feat(设备管理): 添加Spark设备发现与状态管理功能
实现Bonjour服务发现过滤和Spark设备状态管理,包括: - 在BonjourView中添加对polygence-spark类型设备的过滤 - 创建spark store用于管理设备列表和选中设备状态 - 支持设备URL自动生成和持久化存储
This commit is contained in:
55
src/renderer/stores/spark.js
Normal file
55
src/renderer/stores/spark.js
Normal 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.address(mDNS 响应来源 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,
|
||||
};
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user