From 215e328f170fb92e4cb4c006cf0de7ca53165c3a Mon Sep 17 00:00:00 2001 From: saopig1 <4x7sw862st@gmail.com> Date: Fri, 26 Jun 2026 20:47:34 +0800 Subject: [PATCH] feat(web): admin-only command-permission (adminGroups) settings section --- web/src/views/Settings.vue | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/web/src/views/Settings.vue b/web/src/views/Settings.vue index bc1a0ff..6e04ea0 100755 --- a/web/src/views/Settings.vue +++ b/web/src/views/Settings.vue @@ -504,6 +504,23 @@ + +
+

命令权限

+

+ 限制谁能在 TeamSpeak 聊天里运行管理类命令(stop / clear / remove / move / vol / mode)。 + 填写允许的服务器组 ID(逗号分隔)。留空 = 不限制,所有人可用。如何查看服务器组 ID 见 README。 +

+
+
+ + +
+
+
+

机器人 Profile(TeamSpeak 行为)

@@ -1027,6 +1044,7 @@ async function loadIdleTimeout() { idleTimeout.value = res.data.idleTimeoutMinutes ?? 0; autoPauseOnEmpty.value = res.data.autoPauseOnEmpty ?? false; applyGuestModeFromServer(res.data.guestMode); + applyAdminGroupsFromServer(res.data.adminGroups); } catch { /* ignore */ } } @@ -1092,6 +1110,35 @@ async function saveGuestMode() { } } +// --- Command permissions (admin only) --- +const adminGroupsText = ref(''); +const adminGroupsSaving = ref(false); + +function applyAdminGroupsFromServer(groups: unknown) { + if (Array.isArray(groups)) { + adminGroupsText.value = groups.filter((g) => typeof g === 'number').join(', '); + } +} + +function parseAdminGroups(text: string): number[] { + return text + .split(',') + .map((s) => s.trim()) + .filter((s) => s.length > 0) + .map((s) => Number(s)) + .filter((n) => Number.isInteger(n) && n >= 0); +} + +async function saveAdminGroups() { + adminGroupsSaving.value = true; + try { + const res = await axios.post('/api/bot/settings', { adminGroups: parseAdminGroups(adminGroupsText.value) }); + applyAdminGroupsFromServer(res.data?.adminGroups); + } catch { /* ignore */ } finally { + adminGroupsSaving.value = false; + } +} + // --- Bot Profile config --- interface ProfileConfig { avatarEnabled: boolean;