feat: 初始版本,支持配置和连接多个 MQTT 服务器,支持配置订阅的主题列表,支持消息历史记录

This commit is contained in:
2026-07-18 19:23:50 +08:00
parent d0bbd32d08
commit 32643c2518
17 changed files with 2931 additions and 34 deletions
+238
View File
@@ -0,0 +1,238 @@
import { ref, computed } from 'vue'
// 全局状态(单例)
const servers = ref([])
const activeServerId = ref(null)
const messages = ref([])
const publishHistory = ref([])
const loading = ref(false)
// 清理函数集合
let cleanupFns = []
function setupListeners() {
// 清理旧监听器
cleanupFns.forEach((fn) => fn())
cleanupFns = []
cleanupFns.push(
window.api.onStatusChange((data) => {
const srv = servers.value.find((s) => s.id === data.id)
if (srv) {
srv.status = data.status
if (data.status === 'disconnected') {
srv.topics.forEach((t) => {
t.subscribed = false
})
}
}
})
)
cleanupFns.push(
window.api.onMessage((data) => {
if (data.serverId === activeServerId.value) {
messages.value.unshift(data.message)
if (messages.value.length > 500) messages.value.pop()
}
})
)
cleanupFns.push(
window.api.onSubscriptionChange((data) => {
if (data.serverId === activeServerId.value) {
const srv = servers.value.find((s) => s.id === data.serverId)
if (srv) {
const t = srv.topics.find((t) => t.topic === data.topic || t.id === data.topicId)
if (t) {
t.subscribed = data.subscribed
if (data.topic && data.topic !== t.topic) {
t.topic = data.topic
}
}
}
}
})
)
}
export function useMqttStore() {
const activeServer = computed(
() => servers.value.find((s) => s.id === activeServerId.value) || null
)
const connectedServers = computed(() => servers.value.filter((s) => s.status === 'connected'))
const totalTopics = computed(() =>
servers.value.reduce((sum, s) => sum + (s.topics?.length || 0), 0)
)
const subscribedTopics = computed(() =>
servers.value.reduce((sum, s) => sum + (s.topics?.filter((t) => t.subscribed)?.length || 0), 0)
)
const totalMessages = computed(() => messages.value.length)
// ==================== 初始化 ====================
async function init() {
loading.value = true
try {
const data = await window.api.getServers()
servers.value = data
if (data.length > 0 && !activeServerId.value) {
activeServerId.value = data[0].id
}
setupListeners()
} catch (e) {
console.error('初始化失败:', e)
} finally {
loading.value = false
}
}
// ==================== 服务器管理 ====================
function setActiveServer(id) {
activeServerId.value = id
// 切换时刷新消息
refreshMessages()
refreshPublishHistory()
}
async function addServer(config) {
const server = await window.api.addServer(config)
servers.value.push(server)
if (!activeServerId.value) {
activeServerId.value = server.id
}
return server
}
async function updateServer(id, config) {
const result = await window.api.updateServer(id, config)
if (result) {
const idx = servers.value.findIndex((s) => s.id === id)
if (idx !== -1) {
servers.value[idx] = { ...servers.value[idx], ...result }
}
}
return result
}
async function deleteServer(id) {
await window.api.deleteServer(id)
servers.value = servers.value.filter((s) => s.id !== id)
if (activeServerId.value === id) {
activeServerId.value = servers.value.length > 0 ? servers.value[0].id : null
}
}
async function connectServer(id) {
return await window.api.connect(id)
}
async function disconnectServer(id) {
await window.api.disconnect(id)
}
// ==================== 主题管理 ====================
async function addTopic(serverId, topic, qos) {
const result = await window.api.addTopic(serverId, topic, qos)
if (result) {
const srv = servers.value.find((s) => s.id === serverId)
if (srv) {
srv.topics.push({ topic, qos, subscribed: false })
}
}
return result
}
async function removeTopic(serverId, topic) {
await window.api.removeTopic(serverId, topic)
const srv = servers.value.find((s) => s.id === serverId)
if (srv) {
srv.topics = srv.topics.filter((t) => t.topic !== topic)
}
}
async function subscribeTopic(serverId, topic) {
return await window.api.subscribe(serverId, topic)
}
async function unsubscribeTopic(serverId, topic) {
return await window.api.unsubscribe(serverId, topic)
}
async function subscribeAllTopics(serverId) {
return await window.api.subscribeAll(serverId)
}
async function updateTopic(serverId, topicId, topic, qos) {
return await window.api.updateTopic(serverId, topicId, topic, qos)
}
// ==================== 消息发布 ====================
async function publishMessage(serverId, topic, payload, opts) {
const result = await window.api.publish(serverId, topic, payload, opts)
if (result && serverId === activeServerId.value) {
refreshPublishHistory()
}
return result
}
// ==================== 消息管理 ====================
async function refreshMessages() {
if (!activeServerId.value) return
messages.value = await window.api.getMessages(activeServerId.value)
}
async function refreshPublishHistory() {
if (!activeServerId.value) return
publishHistory.value = await window.api.getPublishHistory(activeServerId.value)
}
async function clearMessages() {
if (!activeServerId.value) return
await window.api.clearMessages(activeServerId.value)
messages.value = []
}
async function clearPublishHistory() {
if (!activeServerId.value) return
await window.api.clearPublishHistory(activeServerId.value)
publishHistory.value = []
}
return {
// 状态
servers,
activeServerId,
activeServer,
messages,
publishHistory,
loading,
// 计算属性
connectedServers,
totalTopics,
subscribedTopics,
totalMessages,
// 方法
init,
setActiveServer,
addServer,
updateServer,
deleteServer,
connectServer,
disconnectServer,
addTopic,
removeTopic,
subscribeTopic,
unsubscribeTopic,
subscribeAllTopics,
updateTopic,
publishMessage,
refreshMessages,
refreshPublishHistory,
clearMessages,
clearPublishHistory
}
}