feat: add user email dropdown for inbound clients

This commit is contained in:
Sora39831 2026-04-04 15:05:37 +08:00
parent 2a9d9a0a6b
commit ec70c4ce07
5 changed files with 45 additions and 3 deletions

View file

@ -13,7 +13,19 @@
<a-icon type="sync" @click="client.email = RandomUtil.randomLowerAndNum(9)"></a-icon> <a-icon type="sync" @click="client.email = RandomUtil.randomLowerAndNum(9)"></a-icon>
</a-tooltip> </a-tooltip>
</template> </template>
<a-input v-model.trim="client.email"></a-input> <a-select
v-model="client.email"
mode="combobox"
show-search
allow-clear
:filter-option="filterEmailOption"
:dropdown-class-name="themeSwitcher.currentTheme"
:not-found-content="emailOptions.length === 0 ? null : undefined"
:placeholder='{{ printf "%q" (i18n "pages.inbounds.emailSelectPlaceholder") }}'>
<a-select-option v-for="email in emailOptions" :key="email" :value="email">
[[ email ]]
</a-select-option>
</a-select>
</a-form-item> </a-form-item>
<a-form-item v-if="inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS"> <a-form-item v-if="inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS">
<template slot="label"> <template slot="label">
@ -169,4 +181,4 @@
<a-input-number v-model.number="client.reset" :min="0"></a-input-number> <a-input-number v-model.number="client.reset" :min="0"></a-input-number>
</a-form-item> </a-form-item>
</a-form> </a-form>
{{end}} {{end}}

View file

@ -741,6 +741,9 @@
showAlert: false, showAlert: false,
ipLimitEnable: false, ipLimitEnable: false,
pageSize: 0, pageSize: 0,
isAdmin: {{if .is_admin}}true{{else}}false{{end}},
currentUsername: {{ printf "%q" .current_username }},
clientEmailOptions: [],
}, },
methods: { methods: {
loading(spinning = true) { loading(spinning = true) {
@ -798,6 +801,18 @@
this.ipLimitEnable = ipLimitEnable; 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) { setInbounds(dbInbounds) {
this.inbounds.splice(0); this.inbounds.splice(0);
this.dbInbounds.splice(0); this.dbInbounds.splice(0);
@ -1587,6 +1602,7 @@
} }
this.loading(); this.loading();
this.getDefaultSettings(); this.getDefaultSettings();
this.getClientEmailOptions();
// Initial data fetch // Initial data fetch
this.getDBInbounds().then(() => { this.getDBInbounds().then(() => {
@ -1697,4 +1713,4 @@
}, },
}); });
</script> </script>
{{ template "page/body_end" .}} {{ template "page/body_end" .}}

View file

@ -118,8 +118,20 @@
set delayedExpireDays(days) { set delayedExpireDays(days) {
this.client.expiryTime = -86400000 * 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: { methods: {
filterEmailOption(input, option) {
const value = String(option.componentOptions?.propsData?.value || '').toLowerCase();
return value.includes(String(input || '').toLowerCase());
},
async getDBClientIps(email) { async getDBClientIps(email) {
const msg = await HttpUtil.post(`/panel/api/inbounds/clientIps/${email}`); const msg = await HttpUtil.post(`/panel/api/inbounds/clientIps/${email}`);
if (!msg.success) { if (!msg.success) {

View file

@ -241,6 +241,7 @@
"delDepletedClientsTitle" = "Delete Depleted Clients" "delDepletedClientsTitle" = "Delete Depleted Clients"
"delDepletedClientsContent" = "Are you sure you want to delete all the depleted clients?" "delDepletedClientsContent" = "Are you sure you want to delete all the depleted clients?"
"email" = "Email" "email" = "Email"
"emailSelectPlaceholder" = "Type an email or select a user from the list"
"emailDesc" = "Please provide a unique email address." "emailDesc" = "Please provide a unique email address."
"IPLimit" = "IP Limit" "IPLimit" = "IP Limit"
"IPLimitDesc" = "Disables inbound if the count exceeds the set value. (0 = disable)" "IPLimitDesc" = "Disables inbound if the count exceeds the set value. (0 = disable)"

View file

@ -241,6 +241,7 @@
"delDepletedClientsTitle" = "删除流量耗尽的客户端" "delDepletedClientsTitle" = "删除流量耗尽的客户端"
"delDepletedClientsContent" = "确定要删除所有流量耗尽的客户端吗?" "delDepletedClientsContent" = "确定要删除所有流量耗尽的客户端吗?"
"email" = "电子邮件" "email" = "电子邮件"
"emailSelectPlaceholder" = "可输入邮箱,也可从用户列表中选择"
"emailDesc" = "电子邮件必须完全唯一" "emailDesc" = "电子邮件必须完全唯一"
"IPLimit" = "IP 限制" "IPLimit" = "IP 限制"
"IPLimitDesc" = "如果数量超过设置值则禁用入站流量。0 = 禁用)" "IPLimitDesc" = "如果数量超过设置值则禁用入站流量。0 = 禁用)"