show results
This commit is contained in:
parent
9c025628ff
commit
289e256286
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<h2 class="text-xl font-bold mb-4">Результаты сохранения в IGES</h2>
|
||||||
|
|
||||||
|
<table class="min-w-full border-collapse mt-4">
|
||||||
|
<thead class="bg-gray-100">
|
||||||
|
<tr>
|
||||||
|
<th class="border px-4 py-2 text-left">Документ</th>
|
||||||
|
<th class="border px-4 py-2 text-left">Файл</th>
|
||||||
|
<th class="border px-4 py-2 text-left">Успешно</th>
|
||||||
|
<th class="border px-4 py-2 text-left">Ошибка</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="file in files" :key="file.timestamp" class="hover:bg-gray-50">
|
||||||
|
<td class="border px-4 py-2">{{ file.document_name }}</td>
|
||||||
|
<td class="border px-4 py-2">
|
||||||
|
<a :href="`file://${file.file}`" target="_blank">{{ file.file }}</a>
|
||||||
|
</td>
|
||||||
|
<td class="border px-4 py-2">
|
||||||
|
<span :class="file.success ? 'text-green-500' : 'text-red-500'">
|
||||||
|
{{ file.success ? '✅ Да' : '❌ Нет' }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td class="border px-4 py-2">
|
||||||
|
{{ file.error || '-' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
files: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,37 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps({
|
||||||
|
caption: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
labelKey: {
|
||||||
|
type: String,
|
||||||
|
default: 'Ключ'
|
||||||
|
},
|
||||||
|
labelValue: {
|
||||||
|
type: String,
|
||||||
|
default: 'Значение'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<table class="min-w-full mt-4 border-collapse">
|
||||||
|
<caption v-if="caption" class="caption-top font-medium text-left">{{ caption }}</caption>
|
||||||
|
<thead class="bg-gray-100">
|
||||||
|
<tr>
|
||||||
|
<th class="border px-4 py-2 text-left">{{ labelKey }}</th>
|
||||||
|
<th class="border px-4 py-2 text-left">{{ labelValue }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(value, key) in items" :key="key">
|
||||||
|
<td class="border px-4 py-2">{{ key }}</td>
|
||||||
|
<td class="border px-4 py-2">{{ value }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="item" class="p-4">
|
||||||
|
<h3 class="text-xl font-bold mb-2">{{ item.name }}</h3>
|
||||||
|
<p>Количество элементов: {{ item.elements_count }}</p>
|
||||||
|
<p>Количество гибов: {{ item.bends_count }}</p>
|
||||||
|
|
||||||
|
<!-- Имя -->
|
||||||
|
<TableItem caption="По названию:" :items="item.statistics.Name" label-key="Название" label-value="Количество" />
|
||||||
|
|
||||||
|
<!-- Материал -->
|
||||||
|
<TableItem caption="По материалу:" :items="item.statistics.Material" label-key="Материал"
|
||||||
|
label-value="Количество" />
|
||||||
|
|
||||||
|
<!-- Площадь -->
|
||||||
|
<TableItem caption="Площадь материалов:" :items="item.statistics.Area" label-key="Материал"
|
||||||
|
label-value="Площадь (м²)" />
|
||||||
|
|
||||||
|
<!-- Сварки -->
|
||||||
|
<TableItem caption="Сварные швы:" :items="item.statistics.Welding" label-key="Имя сварки"
|
||||||
|
label-value="Длина (мм)" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -21,7 +21,9 @@ watch(selectedAction, () => {
|
||||||
selectedTypes.value = availableActions.value[selectedAction.value].allowedTypes
|
selectedTypes.value = availableActions.value[selectedAction.value].allowedTypes
|
||||||
})
|
})
|
||||||
|
|
||||||
const resultData = ref<any>(null) // <-- Новое поле для результата
|
const statsData = ref(null)
|
||||||
|
const filesData = ref(null)
|
||||||
|
const resultData = ref(null)
|
||||||
|
|
||||||
// Синхронизация с КОМПАС
|
// Синхронизация с КОМПАС
|
||||||
async function syncKompas() {
|
async function syncKompas() {
|
||||||
|
@ -52,15 +54,44 @@ async function syncKompas() {
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Ошибка при синхронизации с КОМПАС:', err)
|
console.error('Ошибка при синхронизации с КОМПАС:', err)
|
||||||
alert(`Не удалось получить список документов из КОМПАС\n(${err.message})`)
|
alert(`Не удалось получить список документов из КОМПАС\n(${err})`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const canRunAction = computed(() => {
|
const canRunAction = computed(() => {
|
||||||
return selectedAction.value && filteredDocuments.value.length > 0
|
return selectedAction.value && filteredDocuments.value.length > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
function updateUIWithResult(data: any) {
|
function updateUIWithResult(data: any, action: any) {
|
||||||
|
// Обнуляем предыдущие данные
|
||||||
|
statsData.value = null
|
||||||
|
filesData.value = null
|
||||||
|
resultData.value = null
|
||||||
|
|
||||||
|
// Сохраняем сырые данные на случай непредвиденного типа действия
|
||||||
resultData.value = data
|
resultData.value = data
|
||||||
|
|
||||||
|
if (!data || !data.result || !Array.isArray(data.result)) {
|
||||||
|
console.warn('Некорректный формат данных')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(action)
|
||||||
|
console.warn(JSON.stringify(data))
|
||||||
|
switch (action) {
|
||||||
|
case 'stats':
|
||||||
|
// Для статистики
|
||||||
|
statsData.value = data
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'iges':
|
||||||
|
// Для файлов IGES
|
||||||
|
filesData.value = data
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn(`Неизвестное действие: ${action}`)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runSelectedAction() {
|
async function runSelectedAction() {
|
||||||
|
@ -71,6 +102,11 @@ async function runSelectedAction() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Отправляем команду на бэкенд
|
// Отправляем команду на бэкенд
|
||||||
|
// Обнуляем предыдущие данные
|
||||||
|
statsData.value = null
|
||||||
|
filesData.value = null
|
||||||
|
resultData.value = null
|
||||||
|
|
||||||
const result = await sendCommandToPython(selectedAction.value)
|
const result = await sendCommandToPython(selectedAction.value)
|
||||||
|
|
||||||
console.log('Полный ответ от сервера:', result)
|
console.log('Полный ответ от сервера:', result)
|
||||||
|
@ -85,7 +121,7 @@ async function runSelectedAction() {
|
||||||
// Теперь можно безопасно работать с result.status
|
// Теперь можно безопасно работать с result.status
|
||||||
if (result.status === 'success') {
|
if (result.status === 'success') {
|
||||||
// alert(`✅ Действие "${selectedAction.value}" выполнено успешно!`)
|
// alert(`✅ Действие "${selectedAction.value}" выполнено успешно!`)
|
||||||
updateUIWithResult(result.data) // например, выводим данные в интерфейс
|
updateUIWithResult(result.data, selectedAction.value) // например, выводим данные в интерфейс
|
||||||
}
|
}
|
||||||
else if (result.status === 'error') {
|
else if (result.status === 'error') {
|
||||||
const errorMessage = result.error || 'Неизвестная ошибка'
|
const errorMessage = result.error || 'Неизвестная ошибка'
|
||||||
|
@ -115,7 +151,6 @@ async function runSelectedAction() {
|
||||||
⚠️ <strong class="ml-2">Ещё рано отправлять запросы. Идёт инициализация...</strong>
|
⚠️ <strong class="ml-2">Ещё рано отправлять запросы. Идёт инициализация...</strong>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="isReady && isAvailableOnPlatform">
|
<template v-if="isReady && isAvailableOnPlatform">
|
||||||
{{ loading }}
|
|
||||||
<div>
|
<div>
|
||||||
<!-- Кнопка синхронизации -->
|
<!-- Кнопка синхронизации -->
|
||||||
<button @click="syncKompas"
|
<button @click="syncKompas"
|
||||||
|
@ -125,49 +160,49 @@ async function runSelectedAction() {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
{{ resultData }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Сообщение о пустом списке -->
|
<!-- Сообщение о пустом списке -->
|
||||||
<div v-if="!documents.length" class="text-gray-500 italic mt-2">
|
<div v-if="!documents.length" class="text-gray-500 italic mt-2">
|
||||||
Нет данных о документах. Нажмите "Синхронизировать КОМПАС".
|
Нет данных о документах. Нажмите "Синхронизировать КОМПАС".
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<!-- Чекбоксы для фильтрации -->
|
<!-- Фильтры и действия в одной строке -->
|
||||||
<div class="mb-4 p-3 bg-gray-100 rounded shadow-sm">
|
<div class="grid grid-cols-2 gap-6">
|
||||||
<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">
|
<div class="mb-4 p-3 bg-gray-100 rounded shadow-sm">
|
||||||
<h3 class="font-medium mb-2">Действия:</h3>
|
<h3 class="font-medium mb-2">Фильтр по типам:</h3>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-wrap gap-4">
|
||||||
<label v-for="(action, key) in availableActions" :key="key" class="flex items-center gap-2">
|
<label v-for="(label, code) in documentTypeLabels" :key="code"
|
||||||
<input type="radio" :value="key" v-model="selectedAction"
|
class="flex items-center gap-1">
|
||||||
class="form-radio h-4 w-4 text-blue-600" />
|
<input type="checkbox" :value="Number(code)" v-model="selectedTypes"
|
||||||
<span class="text-sm">{{ action.label }}</span>
|
:disabled="documentCounts[Number(code)] === 0"
|
||||||
</label>
|
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>
|
||||||
<!-- Кнопка выполнения действия -->
|
|
||||||
<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
|
<!-- Действия -->
|
||||||
|
<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
|
disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none
|
||||||
transition">
|
transition">
|
||||||
✅ Выполнить действие
|
✅ Выполнить действие
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</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-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"
|
<div v-for="(doc, index) in filteredDocuments" :key="index"
|
||||||
|
@ -178,18 +213,20 @@ async function runSelectedAction() {
|
||||||
<strong>Тип:</strong> {{ getDocumentLabel(doc.type) }}
|
<strong>Тип:</strong> {{ getDocumentLabel(doc.type) }}
|
||||||
</div>
|
</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">
|
<div class="mt-2 text-xs text-gray-500 truncate">
|
||||||
{{ doc.path }}
|
{{ doc.path }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<template v-if="filesData">
|
||||||
|
<TableFiles :files="(filesData as any).result" />
|
||||||
|
</template>
|
||||||
|
<template v-if="statsData">
|
||||||
|
<TableStats v-for="item in (statsData as any).result" :key="item.name" :item="item" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue