diff --git a/front/composables/useKompasActions.ts b/front/composables/useKompasActions.ts index 840c560..30cdc4b 100644 --- a/front/composables/useKompasActions.ts +++ b/front/composables/useKompasActions.ts @@ -4,26 +4,33 @@ const availableActions = ref(null) /** * Загружает список действий с бэкенда */ async function loadActions() { - loading.value = true + if (!isReady.value) { + console.warn('Bridge не готов') + return + } + error.value = null + try { - const actions = await sendCommandToPython<{ - [key: string]: { label: string; allowed_types: number[] } + // Отправляем команду и ожидаем ответ в новом формате + const response = await sendCommandToPython<{ + status: 'success' | 'error' + data: Record | null + error: string | null }>('get_available_actions') - if (actions) { - // Преобразуем все ключи `allowed_types` → `allowedTypes` + if (response.status === 'success' && response.data) { + // Преобразуем данные const convertedActions: Record = {} - for (const key in actions) { - const { label, allowed_types } = actions[key] + for (const key in response.data) { + const { label, allowed_types } = response.data[key] convertedActions[key] = { label, allowedTypes: allowed_types @@ -31,18 +38,18 @@ export function useKompasActions() { } availableActions.value = convertedActions + } else { + throw new Error(response.error || 'Неизвестная ошибка') } } catch (err: any) { console.error('Ошибка при получении действий:', err) error.value = 'Не удалось загрузить список действий' - } finally { - loading.value = false } } + return { availableActions, - loading, error, loadActions, } diff --git a/front/composables/usePythonBridge.ts b/front/composables/usePythonBridge.ts index 80163de..071b833 100644 --- a/front/composables/usePythonBridge.ts +++ b/front/composables/usePythonBridge.ts @@ -1,4 +1,4 @@ -import { ref, onMounted } from 'vue' +// composables/usePythonBridge.ts declare global { interface Window { @@ -12,29 +12,25 @@ declare global { new(transport: any, ready: (channel: any) => void): void } } - -interface PythonEvent { - type: string - data: any -} - -const pyjs = ref(null) -const isReady = ref(false) - -// Хранилище обработчиков событий -const pythonEventHandlers = new Map void>>() - -function receiveFromPython(eventType: string, data: any) { - console.warn("🟢 Event from Python:", eventType, data) - - const handlers = pythonEventHandlers.get(eventType) || [] - handlers.forEach(handler => handler(data)) -} - export function usePythonBridge() { + const pyjs = useState('bridge_pyjs', () => null) + const isReady = useState('bridge_ready', () => false) + const isAvailableOnPlatform = useState('bridge_av', () => false) + const loading = useState('bridge_loading', () => false) + + // Хранилище обработчиков событий + const pythonEventHandlers = new Map void>>() + + function receiveFromPython(eventType: string, data: any) { + console.warn("🟢 Event from Python:", eventType, data) + const handlers = pythonEventHandlers.get(eventType) || [] + handlers.forEach(handler => handler(data)) + } + function setupQWebChannel() { if (window.QWebChannel && window.qt && window.qt.webChannelTransport) { new window.QWebChannel(window.qt.webChannelTransport, function (channel) { + isAvailableOnPlatform.value = true isReady.value = true pyjs.value = channel.objects.pyjs @@ -47,6 +43,7 @@ export function usePythonBridge() { } }) } else { + isAvailableOnPlatform.value = false console.error('Qt WebChannel недоступен') } } @@ -55,24 +52,34 @@ export function usePythonBridge() { command: string, data: Record = {} ): Promise { - return new Promise((resolve, reject) => { - if (!isReady.value) { - reject(new Error('Мост еще не готов')) - return - } + if (!isReady.value) { + throw new Error('Мост еще не готов') + } - if (!pyjs.value || !pyjs.value.callFromJS) { - reject(new Error('Python недоступен')) - return - } + if (!pyjs.value || !pyjs.value.callFromJS) { + throw new Error('Python недоступен') + } - pyjs.value.callFromJS(command, JSON.stringify(data), (result: string) => { + loading.value = true + + return new Promise((resolve, reject) => { + setTimeout(() => { try { - resolve(JSON.parse(result)) - } catch (e) { - reject(e) + pyjs.value.callFromJS(command, JSON.stringify(data), (result: string) => { + try { + const parsed = JSON.parse(result) + resolve(parsed) + } catch (e) { + reject(e) + } finally { + loading.value = false + } + }) + } catch (err) { + reject(err) + loading.value = false } - }) + }, 300) }) } @@ -96,7 +103,7 @@ export function usePythonBridge() { } const checkBridge = () => { - if (window.QWebChannel && window.qt?.webChannelTransport) { + if (import.meta.client && window.QWebChannel && window.qt?.webChannelTransport) { setupQWebChannel() } @@ -107,12 +114,16 @@ export function usePythonBridge() { } } - onMounted(() => { + // Вызываем один раз при первом монтировании + if (!isReady.value) { checkBridge() - }) + } return { + pyjs, isReady, + isAvailableOnPlatform, + loading, sendCommandToPython, onPythonEvent, offPythonEvent, diff --git a/front/pages/kompas.vue b/front/pages/kompas.vue index 44173f7..6f82bc1 100644 --- a/front/pages/kompas.vue +++ b/front/pages/kompas.vue @@ -1,6 +1,6 @@ @@ -72,20 +106,29 @@ async function runSelectedAction() {