From 0fe0e973e67acd7ed6885295b41fec84be0aa7e5 Mon Sep 17 00:00:00 2001 From: saopig1 <4x7sw862st@gmail.com> Date: Thu, 25 Jun 2026 12:20:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(web/settings):=20admin-only=20=E6=B8=B8?= =?UTF-8?q?=E5=AE=A2=E6=A8=A1=E5=BC=8F=20section=20(toggles=20+=20bot=20sc?= =?UTF-8?q?ope)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/Settings.vue | 100 +++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/web/src/views/Settings.vue b/web/src/views/Settings.vue index cd0fbf1..bc1a0ff 100755 --- a/web/src/views/Settings.vue +++ b/web/src/views/Settings.vue @@ -455,6 +455,55 @@ + + + 游客模式 + 开启后,访客无需登录即可进入并点歌(默认关闭)。游客永远无法查看或修改设置。下面逐项决定游客可用的能力。 + + + + 允许游客访问 + 登录页会出现「以游客身份进入」。关闭后所有游客会话立即失效。 + + + + + + 游客权限 + + + + {{ f.label }} + + + + + + 可控制的机器人 + + + 全部机器人 + + + + + {{ bot.name }} + + 还没有机器人。 + + + + + + {{ guestSaving ? '保存中…' : '保存' }} + + + + 机器人 Profile(TeamSpeak 行为) @@ -977,6 +1026,7 @@ async function loadIdleTimeout() { const res = await axios.get('/api/bot/settings'); idleTimeout.value = res.data.idleTimeoutMinutes ?? 0; autoPauseOnEmpty.value = res.data.autoPauseOnEmpty ?? false; + applyGuestModeFromServer(res.data.guestMode); } catch { /* ignore */ } } @@ -992,6 +1042,56 @@ async function saveAutoPause() { } catch { /* ignore */ } } +// --- Guest mode (admin only) --- +const GUEST_FLAGS: { token: string; label: string }[] = [ + { token: 'addToQueue', label: '添加到队列末尾' }, + { token: 'playNext', label: '添加到下一首' }, + { token: 'playNow', label: '立即播放(不清空队列)' }, + { token: 'skip', label: '跳过当前歌曲' }, + { token: 'transport', label: '暂停/继续/进度/音量' }, + { token: 'removeClear', label: '移除/清空队列' }, + { token: 'playMode', label: '切换播放模式 / FM' }, +]; +const guestMode = reactive<{ enabled: boolean; botsAll: boolean; selectedBotIds: string[]; permissions: Record }>({ + enabled: false, + botsAll: true, + selectedBotIds: [], + permissions: { addToQueue: true, playNext: false, playNow: false, skip: false, transport: false, removeClear: false, playMode: false }, +}); +const guestSaving = ref(false); + +function applyGuestModeFromServer(gm: any) { + if (!gm) return; + guestMode.enabled = Boolean(gm.enabled); + guestMode.botsAll = gm.bots === 'all'; + guestMode.selectedBotIds = Array.isArray(gm.bots) ? [...gm.bots] : []; + for (const f of GUEST_FLAGS) { + guestMode.permissions[f.token] = Boolean(gm.permissions?.[f.token]); + } +} + +function toggleGuestBot(id: string, checked: boolean) { + const has = guestMode.selectedBotIds.includes(id); + if (checked && !has) guestMode.selectedBotIds.push(id); + else if (!checked && has) guestMode.selectedBotIds = guestMode.selectedBotIds.filter((b) => b !== id); +} + +async function saveGuestMode() { + guestSaving.value = true; + try { + const res = await axios.post('/api/bot/settings', { + guestMode: { + enabled: guestMode.enabled, + bots: guestMode.botsAll ? 'all' : [...guestMode.selectedBotIds], + permissions: { ...guestMode.permissions }, + }, + }); + applyGuestModeFromServer(res.data?.guestMode); + } catch { /* ignore */ } finally { + guestSaving.value = false; + } +} + // --- Bot Profile config --- interface ProfileConfig { avatarEnabled: boolean;
开启后,访客无需登录即可进入并点歌(默认关闭)。游客永远无法查看或修改设置。下面逐项决定游客可用的能力。