From 7c387923777605d62bd8c0531bbeb6c108390b3a Mon Sep 17 00:00:00 2001 From: yuWorm Date: Fri, 19 Sep 2025 10:09:28 +0800 Subject: [PATCH] feat: Add search client based on #1978 --- src/app/components/Clients/Search.vue | 42 ++++++++++++++++++++++++++ src/app/components/Panel/head/Boat.vue | 2 +- src/app/pages/index.vue | 1 + src/app/stores/clients.ts | 13 +++++++- src/i18n/locales/en.json | 3 +- src/i18n/locales/zh-CN.json | 3 +- src/i18n/locales/zh-HK.json | 3 +- src/server/api/client/index.get.ts | 15 ++++++--- src/server/utils/WireGuard.ts | 23 ++++++++++++++ 9 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 src/app/components/Clients/Search.vue diff --git a/src/app/components/Clients/Search.vue b/src/app/components/Clients/Search.vue new file mode 100644 index 00000000..d5be2f47 --- /dev/null +++ b/src/app/components/Clients/Search.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/app/components/Panel/head/Boat.vue b/src/app/components/Panel/head/Boat.vue index 9282261d..7bb2cffe 100644 --- a/src/app/components/Panel/head/Boat.vue +++ b/src/app/components/Panel/head/Boat.vue @@ -1,5 +1,5 @@ diff --git a/src/app/pages/index.vue b/src/app/pages/index.vue index 4168eb28..a4f27efe 100644 --- a/src/app/pages/index.vue +++ b/src/app/pages/index.vue @@ -4,6 +4,7 @@ + diff --git a/src/app/stores/clients.ts b/src/app/stores/clients.ts index d1c621ec..ed2f9498 100644 --- a/src/app/stores/clients.ts +++ b/src/app/stores/clients.ts @@ -31,8 +31,13 @@ export const useClientsStore = defineStore('Clients', () => { const clients = ref(null); const clientsPersist = ref>({}); + const searchParams = ref({ + filter: '', + }); + const { data: _clients, refresh: _refresh } = useFetch('/api/client', { method: 'get', + params: searchParams, }); // TODO: rewrite @@ -130,5 +135,11 @@ export const useClientsStore = defineStore('Clients', () => { clients.value = transformedClients ?? null; } - return { clients, clientsPersist, refresh, _clients }; + + function setSearchQuery(filter: string) { + clients.value = null; + searchParams.value.filter = filter; + } + + return { clients, clientsPersist, refresh, _clients, setSearchQuery }; }); diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 73dba722..f76022cc 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -116,7 +116,8 @@ "dnsDesc": "DNS server clients will use (overrides global config)", "notConnected": "Client not connected", "endpoint": "Endpoint", - "endpointDesc": "IP of the client from which the WireGuard connection is established" + "endpointDesc": "IP of the client from which the WireGuard connection is established", + "search": "Search clients..." }, "dialog": { "change": "Change", diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json index 7c95a43b..938f5a16 100644 --- a/src/i18n/locales/zh-CN.json +++ b/src/i18n/locales/zh-CN.json @@ -112,7 +112,8 @@ "persistentKeepaliveDesc": "设置保活数据包的发送间隔(秒)。0表示禁用", "hooks": "钩子脚本", "hooksDescription": "钩子脚本仅在使用wg-quick时有效", - "hooksLeaveEmpty": "如果不使用wg-quick,请留空此字段" + "hooksLeaveEmpty": "如果不使用wg-quick,请留空此字段", + "search": "搜索客户端..." }, "dialog": { "change": "确认修改", diff --git a/src/i18n/locales/zh-HK.json b/src/i18n/locales/zh-HK.json index b2d80cac..41e7001b 100644 --- a/src/i18n/locales/zh-HK.json +++ b/src/i18n/locales/zh-HK.json @@ -113,7 +113,8 @@ "hooks": "掛鉤", "hooksDescription": "掛鉤僅適用於wg-quick", "hooksLeaveEmpty": "僅適用於wg-quick,否則請留空", - "dnsDesc": "客戶端使用的域名系統伺服器(取代全局配置)" + "dnsDesc": "客戶端使用的域名系統伺服器(取代全局配置)", + "search": "搜尋客戶端..." }, "dialog": { "change": "更改", diff --git a/src/server/api/client/index.get.ts b/src/server/api/client/index.get.ts index 296e0003..812cd190 100644 --- a/src/server/api/client/index.get.ts +++ b/src/server/api/client/index.get.ts @@ -1,6 +1,11 @@ -export default definePermissionEventHandler('clients', 'custom', ({ user }) => { - if (user.role === roles.ADMIN) { - return WireGuard.getAllClients(); +export default definePermissionEventHandler( + 'clients', + 'custom', + ({ event, user }) => { + const { filter } = getQuery(event); + if (user.role === roles.ADMIN) { + return WireGuard.filterClients(null, filter as string); + } + return WireGuard.filterClients(user.id, filter as string); } - return WireGuard.getClientsForUser(user.id); -}); +); diff --git a/src/server/utils/WireGuard.ts b/src/server/utils/WireGuard.ts index 034561c4..5044ee06 100644 --- a/src/server/utils/WireGuard.ts +++ b/src/server/utils/WireGuard.ts @@ -134,6 +134,29 @@ class WireGuard { return clients; } + async filterClients(userId: ID | null, filter: string) { + let clients; + if (userId != null) { + await this.getClientsForUser(userId); + } else { + clients = await this.getAllClients(); + } + + if (!clients) { + return []; + } + + if (!filter.trim()) return clients; + + const searchTerm = filter.toLowerCase().trim(); + return clients?.filter((client) => { + const nameMatches = client.name.toLowerCase().includes(searchTerm); + const ipv4Matches = client.ipv4Address.toLowerCase().includes(searchTerm); + const ipv6Matches = client.ipv6Address.toLowerCase().includes(searchTerm); + return nameMatches || ipv4Matches || ipv6Matches; + }); + } + async getClientConfiguration({ clientId }: { clientId: ID }) { const wgInterface = await Database.interfaces.get(); const userConfig = await Database.userConfigs.get();