2026-02-07 18:15:24 +00:00

186 lines
6.0 KiB
JavaScript

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');