Files
Thing/src/stores/processStore.ts
T
2026-08-07 18:09:13 +08:00

124 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { listen, type UnlistenFn } from '@tauri-apps/api/event'
import { moduleRegistry } from '@/modules/registry'
/** 进程状态 */
export type ProcessStatus = 'running' | 'stopped' | 'crashed' | 'starting'
/** 进程信息(与 Rust 端 ProcessInfo 对应) */
export interface ProcessInfo {
id: string
name: string
status: ProcessStatus
pid: number | null
restartCount: number
}
/** 启动进程参数(与 Rust 端 StartProcessParams 对应,camelCase */
export interface StartProcessParams {
id: string
executable: string
args?: string[]
cwd?: string
name: string
restartOnCrash?: boolean
maxRestarts?: number
}
export const useProcessStore = defineStore('process', () => {
/** 所有已知进程的状态映射(key = 模块 ID) */
const processes = ref<Map<string, ProcessInfo>>(new Map())
let unlistenFn: UnlistenFn | null = null
/** 启动进程监听,接收 Rust 端的进程状态变更事件 */
const initListener = async () => {
if (unlistenFn) return
unlistenFn = await listen<ProcessInfo>('process-status-changed', (event) => {
processes.value.set(event.payload.id, event.payload)
})
}
/** 释放进程状态事件监听(应用退出或热重载时调用) */
const destroyListener = () => {
if (unlistenFn) {
unlistenFn()
unlistenFn = null
}
}
/** 通过模块 ID 启动进程(自动从注册表读取进程配置) */
const startByModule = async (moduleId: string): Promise<ProcessInfo> => {
const config = moduleRegistry.getConfig(moduleId)
if (!config?.process) {
throw new Error(`模块 "${moduleId}" 没有进程配置`)
}
const pc = config.process
const params: StartProcessParams = {
id: moduleId,
executable: pc.executable,
args: pc.args,
cwd: pc.cwd,
name: pc.name,
restartOnCrash: pc.restartOnCrash,
maxRestarts: pc.maxRestarts
}
const info = await invoke<ProcessInfo>('process_start', { params })
processes.value.set(moduleId, info)
return info
}
/** 通过模块 ID 停止进程 */
const stopByModule = async (moduleId: string): Promise<void> => {
await invoke('process_stop', { id: moduleId })
processes.value.delete(moduleId)
}
/** 获取单个进程状态(从 Rust 端查询最新值) */
const refreshStatus = async (moduleId: string): Promise<ProcessInfo | null> => {
const info = await invoke<ProcessInfo | null>('process_status', { id: moduleId })
if (info) {
processes.value.set(moduleId, info)
} else {
processes.value.delete(moduleId)
}
return info
}
/** 刷新所有进程状态 */
const refreshAll = async (): Promise<void> => {
const all = await invoke<ProcessInfo[]>('process_all_status')
processes.value.clear()
all.forEach((info) => {
processes.value.set(info.id, info)
})
}
/** 获取进程状态(从本地缓存读取,不触发 Rust 调用) */
const getProcessStatus = (moduleId: string): ProcessInfo | null => {
return processes.value.get(moduleId) ?? null
}
/** 停止所有进程 */
const stopAll = async (): Promise<void> => {
await invoke('process_stop_all')
processes.value.clear()
}
return {
processes,
initListener,
destroyListener,
startByModule,
stopByModule,
refreshStatus,
refreshAll,
getProcessStatus,
stopAll
}
})