feat(设备管理): 添加Spark设备发现与状态管理功能

实现Bonjour服务发现过滤和Spark设备状态管理,包括:
- 在BonjourView中添加对polygence-spark类型设备的过滤
- 创建spark store用于管理设备列表和选中设备状态
- 支持设备URL自动生成和持久化存储
This commit is contained in:
houakang
2026-04-12 12:51:53 +08:00
parent 8b145d79d3
commit 9710da8b3d
2 changed files with 66 additions and 2 deletions

View File

@@ -0,0 +1,55 @@
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
const STORAGE_KEY = 'selected_spark_device';
export const useSparkStore = defineStore('spark', () => {
// 运行时发现的设备列表(动态,不持久化)
const devices = ref([]);
// 当前选中的设备,启动时从 localStorage 恢复
const selectedDevice = ref(JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null'));
// 选中设备的完整 URL优先取 IPv4 地址
const selectedDeviceUrl = computed(() => {
if (!selectedDevice.value) return null;
const { addresses, port, referer } = selectedDevice.value;
// 优先找 IPv4不含冒号的地址
const ipv4 = addresses?.find((a) => !a.includes(':'));
// 兜底用 referer.addressmDNS 响应来源 IP
const ip = ipv4 || referer?.address;
return ip ? `http://${ip}:${port}` : null;
});
// 更新设备列表(由 BonjourView 调用)
function setDevices(list) {
devices.value = list;
// 如果之前选中的设备还在列表里,用最新数据刷新它
if (selectedDevice.value) {
const fresh = list.find((d) => d.name === selectedDevice.value.name);
if (fresh) selectDevice(fresh);
}
}
// 选中某台设备,并持久化到 localStorage
function selectDevice(device) {
selectedDevice.value = device;
localStorage.setItem(STORAGE_KEY, JSON.stringify(device));
}
// 清除选中
function clearSelectedDevice() {
selectedDevice.value = null;
localStorage.removeItem(STORAGE_KEY);
}
return {
devices,
selectedDevice,
selectedDeviceUrl,
setDevices,
selectDevice,
clearSelectedDevice,
};
});

View File

@@ -1,15 +1,22 @@
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { Search, Refresh } from '@element-plus/icons-vue';
import { useSparkStore } from '@/stores/spark';
const sparkStore = useSparkStore();
const services = ref([]);
const loading = ref(false);
let unsubscribe = null;
const filterServices = (list) => list.filter((s) => s.type === 'polygence-spark');
const fetchServices = async () => {
loading.value = true;
try {
services.value = await window.bonjour.getServices();
const all = await window.bonjour.getServices();
const filtered = filterServices(all);
services.value = filtered;
sparkStore.setDevices(filtered);
} catch (error) {
console.error('Failed to fetch bonjour services:', error);
} finally {
@@ -20,7 +27,9 @@ const fetchServices = async () => {
onMounted(() => {
fetchServices();
unsubscribe = window.bonjour.onServicesUpdated((updatedServices) => {
services.value = updatedServices;
const filtered = filterServices(updatedServices);
services.value = filtered;
sparkStore.setDevices(filtered);
});
});