feat: add Vue.js WebUI — YesPlayMusic-inspired SPA with all pages and components

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
saopig1andClaude Opus 4.6 committed 2026-03-30 00:58:33 +08:00
1 parent 2a966e914c
commit 694e3c953b
25 files changed
+5388 -1

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
import { ref, onUnmounted } from 'vue';
import { usePlayerStore } from '../stores/player.js';
export function useWebSocket() {
const connected = ref(false);
let ws: WebSocket | null = null;
let reconnectTimer: ReturnType<typeof setTimeout> | null = null;
function connect() {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const url = `${protocol}//${window.location.host}/ws`;
ws = new WebSocket(url);
ws.onopen = () => {
connected.value = true;
console.log('WebSocket connected');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
const store = usePlayerStore();
switch (data.type) {
case 'init':
for (const bot of data.bots) {
store.updateBotStatus(bot.id, bot);
}
break;
case 'stateChange':
store.updateBotStatus(data.botId, data.status);
if (data.queue) store.setQueue(data.queue);
break;
case 'botConnected':
store.updateBotStatus(data.botId, data.status);
break;
case 'botDisconnected':
store.removeBotStatus(data.botId);
break;
}
};
ws.onclose = () => {
connected.value = false;
// Reconnect after 3 seconds
reconnectTimer = setTimeout(connect, 3000);
};
ws.onerror = () => {
ws?.close();
};
}
function disconnect() {
if (reconnectTimer) clearTimeout(reconnectTimer);
ws?.close();
}
onUnmounted(disconnect);
return { connected, connect, disconnect };
}