Эталоны
This commit is contained in:
@@ -3,93 +3,20 @@ import { Button } from '@/component/ui/button'
|
||||
import { Label } from '@/component/ui/label'
|
||||
import { ElementDefinition } from '@/entitiy/element/model/interface'
|
||||
import { CellTarget } from '@/type/template'
|
||||
import { Settings, Weight, Wrench } from 'lucide-react'
|
||||
import { FileText, Settings, Weight } from 'lucide-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useStandards } from './hooks'
|
||||
import { getStandardById } from './mockStandards'
|
||||
import { StandardsEditor } from './StandardsEditor'
|
||||
import { StandardsPreview } from './StandardsPreview'
|
||||
import { StandardsSelector } from './StandardsSelector'
|
||||
|
||||
// Моковые данные для эталонов (такие же как в StandardsSelector)
|
||||
const mockStandards = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'Эталон массы 1 кг',
|
||||
shortName: 'ЭМ-1кг',
|
||||
type: 'Масса',
|
||||
registryNumber: 'ГРСИ 12345-01',
|
||||
range: '0.5-2 кг',
|
||||
accuracy: '±0.001 г',
|
||||
certificateNumber: 'СИ-2024-001',
|
||||
validUntil: '2025-12-31',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Эталон длины 1 м',
|
||||
shortName: 'ЭД-1м',
|
||||
type: 'Длина',
|
||||
registryNumber: 'ГРСИ 12345-02',
|
||||
range: '0.5-2 м',
|
||||
accuracy: '±0.001 мм',
|
||||
certificateNumber: 'СИ-2024-002',
|
||||
validUntil: '2025-06-30',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'Эталон температуры 20°C',
|
||||
shortName: 'ЭТ-20°C',
|
||||
type: 'Температура',
|
||||
registryNumber: 'ГРСИ 12345-03',
|
||||
range: '15-25°C',
|
||||
accuracy: '±0.01°C',
|
||||
certificateNumber: 'СИ-2024-003',
|
||||
validUntil: '2025-03-15',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: 'Эталон давления 1 Па',
|
||||
shortName: 'ЭД-1Па',
|
||||
type: 'Давление',
|
||||
registryNumber: 'ГРСИ 12345-04',
|
||||
range: '0.5-2 Па',
|
||||
accuracy: '±0.001 Па',
|
||||
certificateNumber: 'СИ-2024-004',
|
||||
validUntil: '2025-09-20',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
name: 'Эталон времени 1 с',
|
||||
shortName: 'ЭВ-1с',
|
||||
type: 'Время',
|
||||
registryNumber: 'ГРСИ 12345-05',
|
||||
range: '0.5-2 с',
|
||||
accuracy: '±0.000001 с',
|
||||
certificateNumber: 'СИ-2024-005',
|
||||
validUntil: '2025-12-01',
|
||||
},
|
||||
]
|
||||
|
||||
// Функция для получения данных эталона по ID
|
||||
const getStandardById = (id: string) => {
|
||||
return mockStandards.find(standard => standard.id === id)
|
||||
}
|
||||
|
||||
// Функция для получения типа эталона в сокращенном виде
|
||||
const getStandardTypeBadge = (type: string) => {
|
||||
switch (type) {
|
||||
case 'Манометр грузопоршневой':
|
||||
return 'МГП'
|
||||
case 'Калибратор давления':
|
||||
return 'КД'
|
||||
default:
|
||||
return 'МО'
|
||||
}
|
||||
}
|
||||
|
||||
interface StandardsConfig {
|
||||
sheet: string // Лист Excel
|
||||
startCell: string // Первая ячейка (например "A10")
|
||||
maxItems: number // Обычно 7
|
||||
targetCells: CellTarget[]
|
||||
selectedStandards?: string[] // Выбранные эталоны (ID)
|
||||
}
|
||||
|
||||
export const standardsDefinition: ElementDefinition<StandardsConfig, string[]> =
|
||||
@@ -103,30 +30,30 @@ export const standardsDefinition: ElementDefinition<StandardsConfig, string[]> =
|
||||
startCell: 'A1',
|
||||
maxItems: 7,
|
||||
targetCells: [],
|
||||
selectedStandards: [], // По умолчанию пустой массив
|
||||
},
|
||||
Editor: StandardsEditor,
|
||||
Preview: StandardsPreview,
|
||||
Preview: StandardsPreview, // Использует моки для демонстрации
|
||||
Render: ({ config, value, onChange }) => {
|
||||
const [isStandardsDialogOpen, setIsStandardsDialogOpen] = useState(false)
|
||||
const [selectedStandardIds, setSelectedStandardIds] = useState<string[]>(
|
||||
[]
|
||||
// Инициализируем из config.selectedStandards или value
|
||||
config.selectedStandards || (Array.isArray(value) ? value : [])
|
||||
)
|
||||
|
||||
// Если value содержит названия эталонов, находим соответствующие ID
|
||||
useEffect(() => {
|
||||
if (Array.isArray(value) && value.length > 0) {
|
||||
const ids = value
|
||||
.map(name => {
|
||||
const standard = mockStandards.find(s => s.name === name)
|
||||
return standard?.id || ''
|
||||
})
|
||||
.filter(Boolean)
|
||||
setSelectedStandardIds(ids)
|
||||
}
|
||||
}, [value])
|
||||
// Получаем реальные данные эталонов
|
||||
const { data: standards = [] } = useStandards()
|
||||
|
||||
// Синхронизируем selectedStandardIds с config и value
|
||||
useEffect(() => {
|
||||
const standards =
|
||||
config.selectedStandards || (Array.isArray(value) ? value : [])
|
||||
setSelectedStandardIds(standards)
|
||||
}, [config.selectedStandards, value])
|
||||
|
||||
// Получаем данные выбранных эталонов из реального API
|
||||
const selectedStandardsData = selectedStandardIds
|
||||
.map(id => getStandardById(id))
|
||||
.map(id => standards.find(s => s.id === id))
|
||||
.filter(Boolean)
|
||||
|
||||
return (
|
||||
@@ -148,7 +75,7 @@ export const standardsDefinition: ElementDefinition<StandardsConfig, string[]> =
|
||||
|
||||
<div className="space-y-2">
|
||||
{selectedStandardsData.length > 0 ? (
|
||||
<div className="space-y-1.5">
|
||||
<div className="space-y-1">
|
||||
{selectedStandardsData.map(
|
||||
(standard, index) =>
|
||||
standard && (
|
||||
@@ -156,25 +83,27 @@ export const standardsDefinition: ElementDefinition<StandardsConfig, string[]> =
|
||||
key={standard.id}
|
||||
className="flex items-center gap-2 rounded-md bg-muted/30 p-2 text-sm"
|
||||
>
|
||||
<div className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary/10">
|
||||
<div className="flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-primary/10">
|
||||
<span className="text-xs font-medium text-primary">
|
||||
{index + 1}
|
||||
</span>
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="truncate text-xs font-medium text-foreground">
|
||||
{standard.shortName}
|
||||
{standard.name}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
{standard.accuracy} • {standard.range}
|
||||
<div className="mt-0.5 flex items-center gap-1 text-xs text-muted-foreground">
|
||||
<FileText className="h-2.5 w-2.5" />
|
||||
<span className="hidden text-xs sm:inline">
|
||||
{standard.registry_number}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="shrink-0 text-xs"
|
||||
className="shrink-0 px-1.5 py-0.5 text-xs"
|
||||
>
|
||||
<Wrench className="mr-1 h-3 w-3" />
|
||||
{getStandardTypeBadge(standard.type)}
|
||||
{standard.range}
|
||||
</Badge>
|
||||
</div>
|
||||
)
|
||||
@@ -195,12 +124,10 @@ export const standardsDefinition: ElementDefinition<StandardsConfig, string[]> =
|
||||
value={selectedStandardIds}
|
||||
onChange={standardIds => {
|
||||
setSelectedStandardIds(standardIds)
|
||||
// Преобразуем ID эталонов в их названия для сохранения в ячейки
|
||||
const standardNames = standardIds.map(
|
||||
id => getStandardById(id)?.name || ''
|
||||
)
|
||||
onChange?.(standardNames)
|
||||
// Сохраняем ID эталонов в value для записи в Excel
|
||||
onChange?.(standardIds)
|
||||
}}
|
||||
maxItems={config.maxItems}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
@@ -213,8 +140,13 @@ export const standardsDefinition: ElementDefinition<StandardsConfig, string[]> =
|
||||
// Используем targetCells из конфигурации
|
||||
const cells = cfg.targetCells || []
|
||||
|
||||
// Сопоставляем значения с ячейками
|
||||
const standardNames = Array.isArray(value) ? value : []
|
||||
// Конвертируем ID эталонов в их названия для записи в Excel
|
||||
// Здесь используем моки для быстрого доступа к данным при записи в Excel
|
||||
const standardIds = Array.isArray(value) ? value : []
|
||||
const standardNames = standardIds.map(
|
||||
id => getStandardById(id)?.name || ''
|
||||
)
|
||||
|
||||
return cells.map((target, idx) => ({
|
||||
target,
|
||||
value: standardNames[idx] || '', // Берем значение по индексу или пустую строку
|
||||
|
||||
Reference in New Issue
Block a user