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