Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
authorMHSanaei <mc.sanaei@gmail.com>2023-02-20 20:29:55 +0300
committerMHSanaei <mc.sanaei@gmail.com>2023-02-20 20:29:55 +0300
commitadd853fadaebeed99d2eadcf6ec2fa9396bf6ccd (patch)
treed55598f4ef7d0b812ff9a721a72aad7b2a298ded /web
parentd4c8b926d3a35e8b632ddd290599d3b344e13fc3 (diff)
update pack 3
user pass will be generated randomly upgrade all dependencies move add client buttom
Diffstat (limited to 'web')
-rw-r--r--web/assets/js/util/utils.js2
-rw-r--r--web/html/xui/form/protocol/trojan.html213
-rw-r--r--web/html/xui/form/protocol/vless.html64
-rw-r--r--web/html/xui/form/protocol/vmess.html67
-rw-r--r--web/html/xui/inbound_modal.html22
-rw-r--r--web/job/stats_notify_job.go2
-rw-r--r--web/service/inbound.go20
-rw-r--r--web/service/user.go3
-rw-r--r--web/translation/translate.fa_IR.toml2
9 files changed, 164 insertions, 231 deletions
diff --git a/web/assets/js/util/utils.js b/web/assets/js/util/utils.js
index f3a412e5..bb897047 100644
--- a/web/assets/js/util/utils.js
+++ b/web/assets/js/util/utils.js
@@ -179,7 +179,7 @@ class ObjectUtil {
}
}
} else {
- return obj.toString().indexOf(key) >= 0;
+ return obj.toString().toLowerCase().indexOf(key.toLowerCase()) >= 0;
}
return false;
}
diff --git a/web/html/xui/form/protocol/trojan.html b/web/html/xui/form/protocol/trojan.html
index fa5a2032..6d43bc34 100644
--- a/web/html/xui/form/protocol/trojan.html
+++ b/web/html/xui/form/protocol/trojan.html
@@ -1,141 +1,126 @@
{{define "form/trojan"}}
<a-form layout="inline">
+<label>{{ i18n "clients"}} </label>
<a-collapse activeKey="0" v-for="(trojan, index) in inbound.settings.trojans"
:key="`trojan-${index}`">
-
-<a-collapse-panel :class="getHeaderStyle(trojan.email)" :header="getHeaderText(trojan.email)">
- <a-tag v-if="isExpiry(index) || ((getUpStats(trojan.email) + getDownStats(trojan.email)) > trojan.totalGB && trojan.totalGB != 0)" color="red" style="margin-bottom: 10px;display: block;text-align: center;">Account is (Expired|Traffic Ended) And Disabled</a-tag>
- <a-form layout="inline">
+ <a-collapse-panel :class="getHeaderStyle(trojan.email)" :header="getHeaderText(trojan.email)">
+ <a-tag v-if="isExpiry(index) || ((getUpStats(trojan.email) + getDownStats(trojan.email)) > trojan.totalGB && trojan.totalGB != 0)" color="red" style="margin-bottom: 10px;display: block;text-align: center;">Account is (Expired|Traffic Ended) And Disabled</a-tag>
+ <a-form layout="inline">
+ <a-form-item>
+ <span slot="label">
+ Email
+ <a-tooltip>
+ <template slot="title">
+ The Email Must Be Completely Unique
+ </template>
+ <!--Renew Svg Icon-->
+ <svg
+ @click="getNewEmail(trojan)"
+ xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="anticon anticon-question-circle" viewBox="0 0 16 16"> <path d="M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41zm-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9z"/> <path fill-rule="evenodd" d="M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5.002 5.002 0 0 0 8 3zM3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9H3.1z"/> </svg>
+ </a-tooltip>
+ </span>
+ <a-input v-model.trim="trojan.email"></a-input>
+ </a-form-item>
+ </a-form>
+ <a-form-item label="Password">
+ <a-input v-model.trim="trojan.password"></a-input>
+ </a-form-item>
+ <a-form-item v-if="inbound.xtls" label="Flow">
+ <a-select v-model="trojan.flow" style="width: 150px">
+ <a-select-option value="">{{ i18n "none" }}</a-select-option>
+ <a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
+ </a-select>
+ </a-form-item>
<a-form-item>
<span slot="label">
- Email
+ <span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
<a-tooltip>
<template slot="title">
- The Email Must Be Completely Unique
+ 0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
</template>
- <!--Renew Svg Icon-->
- <svg
- @click="getNewEmail(trojan)"
- xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="anticon anticon-question-circle" viewBox="0 0 16 16"> <path d="M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41zm-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9z"/> <path fill-rule="evenodd" d="M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5.002 5.002 0 0 0 8 3zM3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9H3.1z"/> </svg>
+ <a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
</span>
- <a-input v-model.trim="trojan.email"></a-input>
+ <a-input-number v-model="trojan._totalGB" :min="0"></a-input-number>
</a-form-item>
- </a-form>
- <a-form-item label="Password">
- <a-input v-model.trim="trojan.password"></a-input>
- </a-form-item>
- <a-form-item v-if="inbound.xtls" label="Flow">
- <a-select v-model="inbound.settings.trojans[index].flow" style="width: 150px">
- <a-select-option value="" selected>none</a-select-option>
- <a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
- </a-select>
+ <a-form-item>
+ <span slot="label">
+ <span >{{ i18n "pages.inbounds.expireDate" }}</span>
+ <a-tooltip>
+ <template slot="title">
+ <span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
+ </template>
+ <a-icon type="question-circle" theme="filled"></a-icon>
+ </a-tooltip>
+ </span>
+ <a-date-picker :show-time="{ format: 'HH:mm' }" format="YYYY-MM-DD HH:mm"
+ v-model="trojan._expiryTime" style="width: 300px;"></a-date-picker>
</a-form-item>
- <a-form-item>
- <span slot="label">
- <span >{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
- <a-tooltip>
+ <a-form layout="inline">
+ <a-tooltip v-if="trojan._totalGB > 0">
<template slot="title">
- 0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
+ {{ i18n "pages.inbounds.resetTraffic" }}
</template>
- <a-icon type="question-circle" theme="filled"></a-icon>
+ <span style="color: #FF4D4F">
+ <a-icon type="delete" @click="resetClientTraffic(trojan,$event)"></a-icon>
+ </span>
</a-tooltip>
- </span>
- <a-input-number v-model="trojan._totalGB" :min="0"></a-input-number>
- </a-form-item>
- <a-form-item>
- <span slot="label">
- <span >{{ i18n "pages.inbounds.expireDate" }}</span>
- <a-tooltip>
- <template slot="title">
- <span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
- </template>
- <a-icon type="question-circle" theme="filled"></a-icon>
- </a-tooltip>
- </span>
- <a-date-picker :show-time="{ format: 'HH:mm' }" format="YYYY-MM-DD HH:mm"
- v-model="trojan._expiryTime" style="width: 300px;"></a-date-picker>
- </a-form-item>
- <a-form layout="inline">
- <a-tooltip v-if="trojan._totalGB > 0">
- <template slot="title">
- {{ i18n "pages.inbounds.resetTraffic" }}
- </template>
- <span style="color: #FF4D4F">
- <a-icon type="delete" @click="resetClientTraffic(trojan,$event)"></a-icon>
- </span>
- </a-tooltip>
- <a-tag color="blue">[[ sizeFormat(getUpStats(trojan.email)) ]] / [[ sizeFormat(getDownStats(trojan.email)) ]]</a-tag>
- <a-tag v-if="trojan._totalGB > 0" color="red">used : [[ sizeFormat(getUpStats(trojan.email) + getDownStats(trojan.email)) ]]</a-tag>
- <a-tag>
- <svg
- @click="addClient(inbound.protocol,trojan, inbound.settings.trojans)"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 24 24"
- width="24"
- height="24"
- class="ml-2 cursor-pointer"
- >
- <path fill="none" d="M0 0h24v24H0z" />
- <path
- fill="green"
- d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
- />
- </svg>
- </a-tag>
- <a-tag v-show="inbound.settings.trojans.length > 1">
- <svg
- v-show="inbound.settings.trojans.length > 1"
- @click="removeClient(index, inbound.settings.trojans)"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 24 24"
- width="24"
- height="24"
- class="ml-2 cursor-pointer"
- >
- <path fill="none" d="M0 0h24v24H0z" />
- <path
- fill="#EC4899"
- d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
- />
- </svg>
- </a-tag>
- </a-form>
- </a-form>
+ <a-tag color="blue">[[ sizeFormat(getUpStats(trojan.email)) ]] / [[ sizeFormat(getDownStats(trojan.email)) ]]</a-tag>
+ <a-tag v-if="trojan._totalGB > 0" color="red">used : [[ sizeFormat(getUpStats(trojan.email) + getDownStats(trojan.email)) ]]</a-tag>
+ <a-tag v-show="inbound.settings.trojans.length > 1" @click="removeClient(index, inbound.settings.trojans)">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" width="22" height="22" class="mt-2 cursor-pointer">
+ <path fill="none" d="M0 0h24v24H0z" />
+ <path fill="#EC4899"
+ d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
+ />
+ </svg>
+ </a-tag>
+ </a-form>
+ </a-collapse-panel>
+</a-collapse>
+<a-tag @click="addClient(inbound.protocol, inbound.settings.trojans)">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="ml-2 cursor-pointer">
+ <path fill="none" d="M0 0h24v24H0z" />
+ <path fill="green"
+ d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
+ />
+ </svg>
+</a-tag>
+
<a-form layout="inline">
<a-form-item label="Fallbacks">
- <a-row>
- <a-button type="primary" size="small"
- @click="inbound.settings.addTrojanFallback()">
- +
- </a-button>
+ <a-row>
+ <a-button type="primary" size="small"
+ @click="inbound.settings.addTrojanFallback()">
+ +
+ </a-button>
</a-row>
</a-form-item>
</a-form>
<!-- trojan fallbacks -->
<a-form v-for="(fallback, index) in inbound.settings.fallbacks" layout="inline">
-<a-divider>
- fallback[[ index + 1 ]]
- <a-icon type="delete" @click="() => inbound.settings.delTrojanFallback(index)"
- style="color: rgb(255, 77, 79);cursor: pointer;"/>
-</a-divider>
-<a-form-item label="Name">
- <a-input v-model="fallback.name"></a-input>
-</a-form-item>
-<a-form-item label="Alpn">
- <a-input v-model="fallback.alpn"></a-input>
-</a-form-item>
-<a-form-item label="Path">
- <a-input v-model="fallback.path"></a-input>
-</a-form-item>
-<a-form-item label="Dest">
- <a-input v-model="fallback.dest"></a-input>
-</a-form-item>
-<a-form-item label="xVer">
- <a-input type="number" v-model.number="fallback.xver"></a-input>
-</a-form-item>
-<a-divider v-if="inbound.settings.fallbacks.length - 1 === index"/>
+ <a-divider>
+ fallback[[ index + 1 ]]
+ <a-icon type="delete" @click="() => inbound.settings.delTrojanFallback(index)"
+ style="color: rgb(255, 77, 79);cursor: pointer;"/>
+ </a-divider>
+ <a-form-item label="Name">
+ <a-input v-model="fallback.name"></a-input>
+ </a-form-item>
+ <a-form-item label="Alpn">
+ <a-input v-model="fallback.alpn"></a-input>
+ </a-form-item>
+ <a-form-item label="Path">
+ <a-input v-model="fallback.path"></a-input>
+ </a-form-item>
+ <a-form-item label="Dest">
+ <a-input v-model="fallback.dest"></a-input>
+ </a-form-item>
+ <a-form-item label="xVer">
+ <a-input type="number" v-model.number="fallback.xver"></a-input>
+ </a-form-item>
+ <a-divider v-if="inbound.settings.fallbacks.length - 1 === index"/>
</a-form>
{{end}} \ No newline at end of file
diff --git a/web/html/xui/form/protocol/vless.html b/web/html/xui/form/protocol/vless.html
index 5d56fdd3..fc7ffaa6 100644
--- a/web/html/xui/form/protocol/vless.html
+++ b/web/html/xui/form/protocol/vless.html
@@ -1,6 +1,7 @@
{{define "form/vless"}}
<a-form layout="inline">
-<a-collapse activeKey="0" v-for="(vless, index) in inbound.settings.vlesses"
+<label>{{ i18n "clients"}}</label>
+<a-collapse activeKey="0" v-for="(vless, index) in inbound.settings.vlesses"
:key="`vless-${index}`">
<a-collapse-panel :class="getHeaderStyle(vless.email)" :header="getHeaderText(vless.email)">
@@ -26,20 +27,20 @@
<a-form-item label="ID">
<a-input v-model.trim="vless.id"></a-input>
</a-form-item>
- <a-form-item v-if="inbound.xtls" label="flow">
+ <a-form-item v-if="inbound.xtls" label="Flow">
<a-select v-model="inbound.settings.vlesses[index].flow" style="width: 150px">
- <a-select-option value="" selected>none</a-select-option>
+ <a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
- <a-form-item v-else-if="inbound.canEnableTlsFlow()" label="flow" layout="inline">
+ <a-form-item v-else-if="inbound.canEnableTlsFlow()" label="Flow" layout="inline">
<a-select v-model="inbound.settings.vlesses[index].flow" style="width: 150px">
- <a-select-option value="" selected>none</a-select-option>
+ <a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
<a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
- <a-form-item v-if="inbound.tls" label="utls" layout="inline">
- <a-select v-model="inbound.settings.vlesses[index].fingerprint" label="utls" style="width: 150px">
+ <a-form-item v-if="inbound.tls" label="uTLS" layout="inline">
+ <a-select v-model="inbound.settings.vlesses[index].fingerprint" label="uTLS" style="width: 150px">
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
@@ -71,7 +72,7 @@
<a-form layout="inline">
<a-tooltip v-if="vless._totalGB > 0">
<template slot="title">
- {{ i18n "pages.inbounds.resetTraffic" }}
+ {{ i18n "pages.inbounds.resetTraffic" }}
</template>
<span style="color: #FF4D4F">
<a-icon type="delete" @click="resetClientTraffic(vless,$event)"></a-icon>
@@ -79,43 +80,26 @@
</a-tooltip>
<a-tag color="blue">[[ sizeFormat(getUpStats(vless.email)) ]] / [[ sizeFormat(getDownStats(vless.email)) ]]</a-tag>
<a-tag v-if="vless._totalGB > 0" color="red">used : [[ sizeFormat(getUpStats(vless.email) + getDownStats(vless.email)) ]]</a-tag>
- <a-tag>
- <svg
-
- @click="addClient(inbound.protocol,vless, inbound.settings.vlesses)"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 22 22"
- width="22"
- height="22"
- class="mt-2 cursor-pointer"
- >
+
+ <a-tag v-show="inbound.settings.vlesses.length > 1" @click="removeClient(index, inbound.settings.vlesses)">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" width="22" height="22" class="mt-2 cursor-pointer">
<path fill="none" d="M0 0h24v24H0z" />
- <path
- fill="green"
- d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
+ <path fill="#EC4899"
+ d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
/>
</svg>
</a-tag>
- <a-tag v-show="inbound.settings.vlesses.length > 1">
- <svg
- @click="removeClient(index, inbound.settings.vlesses)"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 22 22"
- width="22"
- height="22"
- class="mt-2 cursor-pointer"
- >
- <path fill="none" d="M0 0h24v24H0z" />
- <path
- fill="#EC4899"
- d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
- />
- </svg>
- </a-tag>
</a-form>
-
-
- </a-form>
+ </a-collapse-panel>
+</a-collapse>
+<a-tag @click="addClient(inbound.protocol, inbound.settings.vlesses)">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="ml-2 cursor-pointer">
+ <path fill="none" d="M0 0h24v24H0z" />
+ <path fill="green"
+ d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
+ />
+ </svg>
+</a-tag>
<a-form layout="inline">
<a-form-item label="Fallbacks">
diff --git a/web/html/xui/form/protocol/vmess.html b/web/html/xui/form/protocol/vmess.html
index 9ed444c6..f7050a5e 100644
--- a/web/html/xui/form/protocol/vmess.html
+++ b/web/html/xui/form/protocol/vmess.html
@@ -1,5 +1,6 @@
{{define "form/vmess"}}
<a-form layout="inline">
+<label>{{ i18n "clients"}}</label>
<a-collapse activeKey="0" v-for="(vmess, index) in inbound.settings.vmesses"
:key="`vmess-${index}`">
<a-collapse-panel :class="getHeaderStyle(vmess.email)" :header="getHeaderText(vmess.email)">
@@ -56,7 +57,7 @@
<a-form layout="inline">
<a-tooltip v-if="vmess._totalGB > 0">
<template slot="title">
- {{ i18n "pages.inbounds.resetTraffic" }}
+ {{ i18n "pages.inbounds.resetTraffic" }}
</template>
<span style="color: #FF4D4F">
<a-icon type="delete" @click="resetClientTraffic(vmess,$event)"></a-icon>
@@ -64,56 +65,34 @@
</a-tooltip>
<a-tag color="blue">[[ sizeFormat(getUpStats(vmess.email)) ]] / [[ sizeFormat(getDownStats(vmess.email)) ]]</a-tag>
<a-tag v-if="vmess._totalGB > 0" color="red">used : [[ sizeFormat(getUpStats(vmess.email) + getDownStats(vmess.email)) ]]</a-tag>
- <a-tag>
- <!--Add Svg Icon-->
- <svg
-
- @click="addClient(inbound.protocol,vmess, inbound.settings.vmesses)"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 22 22"
- width="22"
- height="22"
- class="mt-2 cursor-pointer"
- >
- <path fill="none" d="M0 0h24v24H0z" />
- <path
- fill="green"
- d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
- />
- </svg>
+ <a-tag v-show="inbound.settings.vmesses.length > 1" @click="removeClient(index, inbound.settings.vmesses)">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" width="22" height="22" class="mt-2 cursor-pointer">
+ <path fill="none" d="M0 0h24v24H0z" />
+ <path fill="#EC4899"
+ d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
+ />
+ </svg>
</a-tag>
- <a-tag v-show="inbound.settings.vmesses.length > 1">
-
- <!--Remove Svg Icon-->
- <svg
- @click="removeClient(index, inbound.settings.vmesses)"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 22 22"
- width="22"
- height="22"
- class="mt-2 cursor-pointer"
- >
- <path fill="none" d="M0 0h24v24H0z" />
- <path
- fill="#EC4899"
- d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
- />
- </svg>
- </a-tag>
- </a-form>
+ </a-form>
-</a-collapse-panel>
+ </a-collapse-panel>
</a-collapse>
+<a-tag @click="addClient(inbound.protocol, inbound.settings.vmesses)">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="ml-2 cursor-pointer">
+ <path fill="none" d="M0 0h24v24H0z" />
+ <path fill="green"
+ d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
+ />
+ </svg>
+</a-tag>
-</a-form>
-</a-form>
<a-form layout="inline">
-<a-form-item label='{{ i18n "pages.inbounds.disableInsecureEncryption" }}'>
- <a-switch v-model.number="inbound.settings.disableInsecure"></a-switch>
-</a-form-item>
+ <a-form-item label='{{ i18n "pages.inbounds.disableInsecureEncryption" }}'>
+ <a-switch v-model.number="inbound.settings.disableInsecure"></a-switch>
+ </a-form-item>
</a-form>
-{{end}}
+{{end}} \ No newline at end of file
diff --git a/web/html/xui/inbound_modal.html b/web/html/xui/inbound_modal.html
index 4fec0ded..80ea2286 100644
--- a/web/html/xui/inbound_modal.html
+++ b/web/html/xui/inbound_modal.html
@@ -77,7 +77,7 @@
this.inModal.inbound.tls = false;
}
},
- addClient(protocol,value, clients) {
+ addClient(protocol, clients) {
switch (protocol) {
case Protocols.VMESS: return clients.push(new Inbound.VmessSettings.Vmess());
case Protocols.VLESS: return clients.push(new Inbound.VLESSSettings.VLESS());
@@ -88,7 +88,6 @@
removeClient(index, clients) {
clients.splice(index, 1);
},
-
async resetClientTraffic(client,event) {
const msg = await HttpUtil.post('/xui/inbound/resetClientTraffic/'+ client.email);
if (!msg.success) {
@@ -122,7 +121,6 @@
}
}
}
-
},
getDownStats(email) {
clientStats = this.inbound.clientStats
@@ -138,30 +136,18 @@
}
},
isClientEnable(email) {
- clientStats = this.inbound.clientStats
- if(clientStats.length > 0)
- {
- for (const key in clientStats) {
- if (Object.hasOwnProperty.call(clientStats, key)) {
- if(clientStats[key]['email'] == email)
- return clientStats[key]['enable']
-
- }
- }
- }
+ clientStats = this.dbInbound.clientStats ? this.dbInbound.clientStats.find(stats => stats.email === email) : null
+ return clientStats ? clientStats['enable'] : true
},
-
getHeaderText(email) {
if(email == "")
return "Add Client"
return email + (this.isClientEnable(email) == true ? ' Active' : ' Deactive')
},
-
getHeaderStyle(email) {
return (this.isClientEnable(email) == true ? '' : 'deactive-client')
},
-
getNewEmail(client) {
var chars = 'abcdefghijklmnopqrstuvwxyz1234567890';
var string = '';
@@ -175,4 +161,4 @@
});
</script>
-{{end}}
+{{end}} \ No newline at end of file
diff --git a/web/job/stats_notify_job.go b/web/job/stats_notify_job.go
index 92963127..21f61a1e 100644
--- a/web/job/stats_notify_job.go
+++ b/web/job/stats_notify_job.go
@@ -240,7 +240,7 @@ func (j *StatsNotifyJob) getClientUsage(id string) string {
} else {
total = fmt.Sprintf("%s", common.FormatTraffic((traffic.Total)))
}
- output := fmt.Sprintf("💡 Active: %t\r\n📧 Email: %s\r\n🔼 Upload↑: %s\r\n🔽 Download↓: %s\r\n🔄 Total: %s / %s\r\n📅 Expire in: %s\r\n",
+ output := fmt.Sprintf("💡 Active: %t\r\n📧 Email: %s\r\n🔼 Download↑: %s\r\n🔽 Upload↓: %s\r\n🔄 Total: %s / %s\r\n📅 Expire in: %s\r\n",
traffic.Enable, traffic.Email, common.FormatTraffic(traffic.Up), common.FormatTraffic(traffic.Down), common.FormatTraffic((traffic.Up + traffic.Down)),
total, expiryTime)
diff --git a/web/service/inbound.go b/web/service/inbound.go
index dedf76a0..5c1cfedc 100644
--- a/web/service/inbound.go
+++ b/web/service/inbound.go
@@ -238,9 +238,9 @@ func (s *InboundService) AddTraffic(traffics []*xray.Traffic) (err error) {
for _, traffic := range traffics {
if traffic.IsInbound {
err = tx.Where("tag = ?", traffic.Tag).
- UpdateColumn("up", gorm.Expr("up + ?", traffic.Up)).
- UpdateColumn("down", gorm.Expr("down + ?", traffic.Down)).
- Error
+ UpdateColumns(map[string]interface{}{
+ "up": gorm.Expr("up + ?", traffic.Up),
+ "down": gorm.Expr("down + ?", traffic.Down)}).Error
if err != nil {
return
}
@@ -298,11 +298,12 @@ func (s *InboundService) AddClientTraffic(traffics []*xray.ClientTraffic) (err e
}
}
if tx.Where("inbound_id = ?", inbound.Id).Where("email = ?", traffic.Email).
- UpdateColumn("enable", true).
- UpdateColumn("expiry_time", traffic.ExpiryTime).
- UpdateColumn("total", traffic.Total).
- UpdateColumn("up", gorm.Expr("up + ?", traffic.Up)).
- UpdateColumn("down", gorm.Expr("down + ?", traffic.Down)).RowsAffected == 0 {
+ UpdateColumns(map[string]interface{}{
+ "enable": true,
+ "expiry_time": traffic.ExpiryTime,
+ "total": traffic.Total,
+ "up": gorm.Expr("up + ?", traffic.Up),
+ "down": gorm.Expr("down + ?", traffic.Down)}).RowsAffected == 0 {
err = tx.Create(traffic).Error
}
@@ -374,8 +375,7 @@ func (s *InboundService) ResetClientTraffic(clientEmail string) error {
result := db.Model(xray.ClientTraffic{}).
Where("email = ?", clientEmail).
- Update("up", 0).
- Update("down", 0)
+ Updates(map[string]interface{}{"up": 0, "down": 0})
err := result.Error
diff --git a/web/service/user.go b/web/service/user.go
index e4e7572d..6da8bd1e 100644
--- a/web/service/user.go
+++ b/web/service/user.go
@@ -46,8 +46,7 @@ func (s *UserService) UpdateUser(id int, username string, password string) error
db := database.GetDB()
return db.Model(model.User{}).
Where("id = ?", id).
- Update("username", username).
- Update("password", password).
+ Updates(map[string]interface{}{"username": username, "password": password}).
Error
}
diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml
index 76e849b6..7d439fea 100644
--- a/web/translation/translate.fa_IR.toml
+++ b/web/translation/translate.fa_IR.toml
@@ -48,7 +48,7 @@
[menu]
"dashboard" = "وضعیت سیستم"
-"inbounds" = "سروریس ها"
+"inbounds" = "سرویس ها"
"setting" = "تنظیمات پنل"
"logout" = "خروج"
"link" = "دیگر"