124 lines
3.5 KiB
TypeScript
124 lines
3.5 KiB
TypeScript
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
|
||
}
|
||
})
|