diff --git a/web/html/form/client.html b/web/html/form/client.html
index 908f28d2..3cc13b89 100644
--- a/web/html/form/client.html
+++ b/web/html/form/client.html
@@ -13,7 +13,19 @@
-
+
+
+ [[ email ]]
+
+
@@ -169,4 +181,4 @@
-{{end}}
\ No newline at end of file
+{{end}}
diff --git a/web/html/inbounds.html b/web/html/inbounds.html
index b945da90..f0298a8a 100644
--- a/web/html/inbounds.html
+++ b/web/html/inbounds.html
@@ -741,6 +741,9 @@
showAlert: false,
ipLimitEnable: false,
pageSize: 0,
+ isAdmin: {{if .is_admin}}true{{else}}false{{end}},
+ currentUsername: {{ printf "%q" .current_username }},
+ clientEmailOptions: [],
},
methods: {
loading(spinning = true) {
@@ -798,6 +801,18 @@
this.ipLimitEnable = ipLimitEnable;
}
},
+ async getClientEmailOptions() {
+ if (this.isAdmin) {
+ const msg = await HttpUtil.get('/panel/api/users/list');
+ if (msg.success && Array.isArray(msg.obj)) {
+ this.clientEmailOptions = msg.obj
+ .map(user => user?.username || '')
+ .filter(Boolean);
+ return;
+ }
+ }
+ this.clientEmailOptions = this.currentUsername ? [this.currentUsername] : [];
+ },
setInbounds(dbInbounds) {
this.inbounds.splice(0);
this.dbInbounds.splice(0);
@@ -1587,6 +1602,7 @@
}
this.loading();
this.getDefaultSettings();
+ this.getClientEmailOptions();
// Initial data fetch
this.getDBInbounds().then(() => {
@@ -1697,4 +1713,4 @@
},
});
-{{ template "page/body_end" .}}
\ No newline at end of file
+{{ template "page/body_end" .}}
diff --git a/web/html/modals/client_modal.html b/web/html/modals/client_modal.html
index 8b57b8b2..33246e35 100644
--- a/web/html/modals/client_modal.html
+++ b/web/html/modals/client_modal.html
@@ -118,8 +118,20 @@
set delayedExpireDays(days) {
this.client.expiryTime = -86400000 * days;
},
+ get emailOptions() {
+ const options = Array.isArray(app.clientEmailOptions) ? [...app.clientEmailOptions] : [];
+ const email = this.client?.email;
+ if (email && !options.includes(email)) {
+ options.unshift(email);
+ }
+ return options;
+ },
},
methods: {
+ filterEmailOption(input, option) {
+ const value = String(option.componentOptions?.propsData?.value || '').toLowerCase();
+ return value.includes(String(input || '').toLowerCase());
+ },
async getDBClientIps(email) {
const msg = await HttpUtil.post(`/panel/api/inbounds/clientIps/${email}`);
if (!msg.success) {
diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml
index f6cf88cf..047ba4a7 100644
--- a/web/translation/translate.en_US.toml
+++ b/web/translation/translate.en_US.toml
@@ -241,6 +241,7 @@
"delDepletedClientsTitle" = "Delete Depleted Clients"
"delDepletedClientsContent" = "Are you sure you want to delete all the depleted clients?"
"email" = "Email"
+"emailSelectPlaceholder" = "Type an email or select a user from the list"
"emailDesc" = "Please provide a unique email address."
"IPLimit" = "IP Limit"
"IPLimitDesc" = "Disables inbound if the count exceeds the set value. (0 = disable)"
diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml
index 33ebd14c..73d71b60 100644
--- a/web/translation/translate.zh_CN.toml
+++ b/web/translation/translate.zh_CN.toml
@@ -241,6 +241,7 @@
"delDepletedClientsTitle" = "删除流量耗尽的客户端"
"delDepletedClientsContent" = "确定要删除所有流量耗尽的客户端吗?"
"email" = "电子邮件"
+"emailSelectPlaceholder" = "可输入邮箱,也可从用户列表中选择"
"emailDesc" = "电子邮件必须完全唯一"
"IPLimit" = "IP 限制"
"IPLimitDesc" = "如果数量超过设置值,则禁用入站流量。(0 = 禁用)"