web/front/pages/kompas.vue

196 lines
8.7 KiB
Vue
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.

<script setup lang="ts">
const { sendCommandToPython, isReady, isAvailableOnPlatform, loading } = usePythonBridge()
const {
documents,
selectedTypes,
documentCounts,
filteredDocuments,
documentTypeLabels,
getDocumentLabel,
} = useKompasDocuments()
const {
availableActions,
loadActions
} = useKompasActions()
const selectedAction = ref()
watch(selectedAction, () => {
selectedTypes.value = availableActions.value[selectedAction.value].allowedTypes
})
const resultData = ref<any>(null) // <-- Новое поле для результата
// Синхронизация с КОМПАС
async function syncKompas() {
try {
// Получаем ответ в новом формате: { status, data, error }
const response = await sendCommandToPython('open_kompas')
console.log('Полный ответ от Python:', response)
// Проверяем структуру ответа
if (!response || typeof response !== 'object') {
throw new Error('Некорректный формат ответа: пустой или не объект')
}
if (response.status === 'error') {
throw new Error(response.error || 'Неизвестная ошибка')
}
if (!response.data || !Array.isArray(response.data)) {
throw new Error('Данные от сервера отсутствуют или имеют неверный формат')
}
// Успешно получили документы
documents.value = response.data
loadActions()
console.warn('Документы из КОМПАС:', documents.value)
} catch (err) {
console.error('Ошибка при синхронизации с КОМПАС:', err)
alert(`Не удалось получить список документов из КОМПАС\n(${err.message})`)
}
}
const canRunAction = computed(() => {
return selectedAction.value && filteredDocuments.value.length > 0
})
function updateUIWithResult(data: any) {
resultData.value = data
}
async function runSelectedAction() {
if (!selectedAction.value) {
alert('Выберите действие')
return
}
try {
// Отправляем команду на бэкенд
const result = await sendCommandToPython(selectedAction.value)
console.log('Полный ответ от сервера:', result)
// Проверяем, что результат — это объект и содержит поле status
if (typeof result !== 'object' || result === null) {
// alert('Ошибка: получен некорректный формат данных от сервера')
console.error('Некорректный формат результата:', result)
return
}
// Теперь можно безопасно работать с result.status
if (result.status === 'success') {
// alert(`✅ Действие "${selectedAction.value}" выполнено успешно!`)
updateUIWithResult(result.data) // например, выводим данные в интерфейс
}
else if (result.status === 'error') {
const errorMessage = result.error || 'Неизвестная ошибка'
// alert(`❌ Ошибка при выполнении: ${errorMessage}`)
console.error('Ошибка от сервера:', errorMessage)
}
else {
// alert('⚠️ Не удалось обработать результат от сервера')
console.warn('Неизвестный статус ответа:', result)
}
} catch (err) {
console.error('🚨 Ошибка при выполнении действия:', err)
alert('🔥 Произошла критическая ошибка при выполнении действия')
}
}
</script>
<template>
<div class="flex flex-col gap-4 p-4">
<h1>Компас прослушка событий от Python</h1>
<div v-if="!isAvailableOnPlatform" class="mb-4 p-3 bg-red-100 text-red-800 rounded">
❌ <strong>Мост недоступен на этой платформе.</strong> Возможно, вы запускаете приложение не в Qt/PySide.
</div>
<!-- Статус -->
<div v-if="!isReady && isAvailableOnPlatform"
class="mb-4 p-3 bg-yellow-100 text-yellow-800 rounded flex items-center">
⚠️ <strong class="ml-2">Ещё рано отправлять запросы. Идёт инициализация...</strong>
</div>
<template v-if="isReady && isAvailableOnPlatform">
{{ loading }}
<div>
<!-- Кнопка синхронизации -->
<button @click="syncKompas"
class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded mb-4 transition"
:disabled="loading">
🔁 Синхронизировать КОМПАС
</button>
</div>
<div>
{{ resultData }}
</div>
<!-- Сообщение о пустом списке -->
<div v-if="!documents.length" class="text-gray-500 italic mt-2">
Нет данных о документах. Нажмите "Синхронизировать КОМПАС".
</div>
<template v-else>
<!-- Чекбоксы для фильтрации -->
<div class="mb-4 p-3 bg-gray-100 rounded shadow-sm">
<h3 class="font-medium mb-2">Фильтр по типам:</h3>
<div class="flex flex-wrap gap-4">
<label v-for="(label, code) in documentTypeLabels" :key="code" class="flex items-center gap-1">
<input type="checkbox" :value="Number(code)" v-model="selectedTypes"
:disabled="documentCounts[Number(code)] === 0"
class="form-checkbox h-4 w-4 text-blue-600 disabled:opacity-50" />
<span class="text-sm">
{{ label }} ({{ documentCounts[Number(code)] }})
</span>
</label>
</div>
</div>
<!-- Действия -->
<div class="mb-4 p-3 bg-gray-100 rounded shadow-sm">
<h3 class="font-medium mb-2">Действия:</h3>
<div class="flex flex-col gap-2">
<label v-for="(action, key) in availableActions" :key="key" class="flex items-center gap-2">
<input type="radio" :value="key" v-model="selectedAction"
class="form-radio h-4 w-4 text-blue-600" />
<span class="text-sm">{{ action.label }}</span>
</label>
</div>
<!-- Кнопка выполнения действия -->
<button type="button" @click="runSelectedAction" :disabled="!canRunAction || loading" class="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600
disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none
transition">
✅ Выполнить действие
</button>
</div>
<!-- Грид документов -->
<div v-if="filteredDocuments.length" class="mt-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div v-for="(doc, index) in filteredDocuments" :key="index"
class="border rounded shadow-sm p-4 hover:shadow-md transition-shadow bg-white">
<h3 class="font-medium text-lg">{{ doc.name }}</h3>
<div class="mt-2">
<strong>Тип:</strong> {{ getDocumentLabel(doc.type) }}
</div>
<div class="mt-1">
<strong>Активен:</strong>
<span class="ml-2">
{{ doc.active ? '✅' : '❌' }}
</span>
</div>
<div class="mt-2 text-xs text-gray-500 truncate">
{{ doc.path }}
</div>
</div>
</div>
</template>
</template>
</div>
</template>