const { createApp, ref, onMounted } = Vue; createApp({ setup() { const currentView = ref('channels'); const channels = ref([]); const notifications = ref([]); const showChannelModal = ref(false); const sending = ref(false); const message = ref(null); const channelForm = ref({ name: '', type: 'discord', configJson: '{}', tags: '', is_active: true }); const sendForm = ref({ channels: [], title: '', body: '', priority: 'normal' }); const API_BASE = '/api'; const showMessage = (text, type = 'success') => { message.value = { text, type }; setTimeout(() => message.value = null, 3000); }; const fetchChannels = async () => { try { const res = await fetch(`${API_BASE}/channels`); const data = await res.json(); channels.value = data.channels; } catch (e) { showMessage('获取通道失败', 'error'); } }; const fetchNotifications = async () => { try { const res = await fetch(`${API_BASE}/notifications`); const data = await res.json(); notifications.value = data.notifications; } catch (e) { showMessage('获取历史失败', 'error'); } }; const saveChannel = async () => { try { const config = JSON.parse(channelForm.value.configJson); const tags = channelForm.value.tags.split(',').map(t => t.trim()).filter(t => t); const res = await fetch(`${API_BASE}/channels`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: channelForm.value.name, type: channelForm.value.type, config, tags, is_active: channelForm.value.is_active }) }); if (res.ok) { showMessage('通道创建成功'); showChannelModal.value = false; fetchChannels(); } else { const err = await res.json(); showMessage(err.detail || '创建失败', 'error'); } } catch (e) { showMessage('配置 JSON 格式错误', 'error'); } }; const deleteChannel = async (id) => { if (!confirm('确定删除此通道?')) return; try { const res = await fetch(`${API_BASE}/channels/${id}`, { method: 'DELETE' }); if (res.ok) { showMessage('删除成功'); fetchChannels(); } else { showMessage('删除失败', 'error'); } } catch (e) { showMessage('删除失败', 'error'); } }; const testChannel = async (id) => { try { const res = await fetch(`${API_BASE}/channels/${id}/test`, { method: 'POST' }); if (res.ok) { showMessage('测试消息已发送'); } else { showMessage('测试失败', 'error'); } } catch (e) { showMessage('测试失败', 'error'); } }; const sendNotification = async () => { if (!sendForm.value.body) { showMessage('请输入消息内容', 'error'); return; } if (sendForm.value.channels.length === 0) { showMessage('请至少选择一个通道', 'error'); return; } sending.value = true; try { const res = await fetch(`${API_BASE}/notify`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ channels: sendForm.value.channels, title: sendForm.value.title, body: sendForm.value.body, priority: sendForm.value.priority }) }); if (res.ok) { showMessage('通知发送成功'); sendForm.value = { channels: [], title: '', body: '', priority: 'normal' }; } else { showMessage('发送失败', 'error'); } } catch (e) { showMessage('发送失败', 'error'); } finally { sending.value = false; } }; const formatDate = (dateStr) => { if (!dateStr) return '-'; return new Date(dateStr).toLocaleString('zh-CN'); }; const getStatusClass = (status) => { return { 'px-2 py-1 rounded text-xs': true, 'bg-green-100 text-green-800': status === 'sent', 'bg-red-100 text-red-800': status === 'failed', 'bg-yellow-100 text-yellow-800': status === 'pending' }; }; onMounted(() => { fetchChannels(); fetchNotifications(); }); return { currentView, channels, notifications, showChannelModal, channelForm, sendForm, sending, message, saveChannel, deleteChannel, testChannel, sendNotification, formatDate, getStatusClass }; } }).mount('#app');