архитектура добавления элементов, список эталонов

This commit is contained in:
2025-07-18 07:45:43 +03:00
parent dfb4d377d0
commit 7cf319f25d
36 changed files with 2100 additions and 123 deletions

166
ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,166 @@
# Архитектура системы элементов
## Обзор
Система была переработана для обеспечения универсальности и расширяемости. Теперь все элементы регистрируются в едином реестре, что позволяет легко добавлять новые типы элементов без изменения основного кода.
## Структура
### 1. Реестр элементов (`src/lib/element-registry.ts`)
Центральный реестр, который содержит все определения элементов:
```typescript
export interface ElementDefinition<Config = any, Value = any> {
type: ElementType; // Уникальный тип элемента
label: string; // Человекочитаемое имя
icon: ReactNode; // Иконка для UI
Editor: React.FC<{ config: Config; onChange(c: Config): void }>;
Preview: React.FC<{ config: Config }>;
Render: React.FC<{ config: Config; value: Value; onChange?(v: Value): void }>;
defaultConfig: Config; // Конфигурация по умолчанию
mapToCells?(config: Config): CellTarget[]; // Маппинг на ячейки Excel
}
```
### 2. Базовые элементы (`src/components/BasicElements/`)
Стандартные элементы формы:
- `TextElement.tsx` - текстовое поле
- `SelectElement.tsx` - выпадающий список
- `NumberElement.tsx` - числовое поле
- `DateElement.tsx` - поле даты
- `TextareaElement.tsx` - многострочный текст
- `CheckboxElement.tsx` - чекбокс
- `RadioElement.tsx` - радиокнопки
### 3. Специальные элементы (`src/components/StandardsElement/`)
Сложные элементы с собственной логикой:
- `StandardsDialog.tsx` - диалог выбора эталонов
- `StandardsEditor.tsx` - редактор настроек
- `StandardsPreview.tsx` - превью элемента
- `definition.tsx` - определение элемента
## Как добавить новый элемент
### 1. Создать компоненты
```typescript
// MyElement/MyElementEditor.tsx
export const MyElementEditor: React.FC<{ config: MyConfig; onChange: (config: MyConfig) => void }> = ({ config, onChange }) => {
// Логика редактирования
};
// MyElement/MyElementPreview.tsx
export const MyElementPreview: React.FC<{ config: MyConfig }> = ({ config }) => {
// Логика превью
};
// MyElement/MyElementRender.tsx
export const MyElementRender: React.FC<{ config: MyConfig; value: string; onChange?: (value: string) => void }> = ({ config, value, onChange }) => {
// Логика рендеринга
};
```
### 2. Создать определение
```typescript
// MyElement/definition.tsx
export const myElementDefinition: ElementDefinition<MyConfig, string> = {
type: "my_element",
label: "Мой элемент",
icon: <MyIcon className="h-4 w-4" />,
defaultConfig: {
// конфигурация по умолчанию
},
Editor: MyElementEditor,
Preview: MyElementPreview,
Render: MyElementRender,
mapToCells: (config) => {
// логика маппинга на ячейки Excel
return [];
},
};
```
### 3. Зарегистрировать в реестре
```typescript
// src/lib/element-registry-init.ts
import { myElementDefinition } from "@/components/MyElement/definition";
export function initializeElementRegistry() {
// ... существующие элементы
registerElement("my_element", myElementDefinition);
}
```
### 4. Добавить тип в types/template.ts
```typescript
export type ElementType =
| 'text' | 'select' | 'radio' | 'checkbox' | 'number'
| 'textarea' | 'date' | 'standards'
| 'my_element'; // <-- новый тип
```
## Особенности элемента "Измерительные эталоны"
### Конфигурация
```typescript
interface StandardsConfig {
registryNumber: string; // ГРСИ
sheet: string; // Лист Excel
startCell: string; // Первая ячейка (например "A10")
maxItems: number; // Обычно 7
targetCells: CellTarget[];
}
```
### Логика маппинга
Элемент автоматически генерирует ячейки для записи выбранных эталонов:
```typescript
mapToCells: (cfg) => {
const res: CellTarget[] = [];
const parsed = parseCellAddress(cfg.startCell);
if (!parsed) return res;
const { column, row } = parsed;
// Генерируем ячейки вертикально (A1, A2, A3...)
for (let i = 0; i < cfg.maxItems; i++) {
res.push({
sheet: cfg.sheet,
cell: `${column}${row + i}`,
displayName: `Эталон ${i + 1}`,
});
}
return res;
}
```
### Ограничения
- Максимум 7 эталонов (настраивается)
- Автоматическое заполнение только выбранных позиций
- Оставшиеся ячейки остаются пустыми
## Преимущества новой архитектуры
1. **Расширяемость**: Добавление новых элементов требует минимальных изменений
2. **Универсальность**: Единый интерфейс для всех элементов
3. **Типобезопасность**: TypeScript обеспечивает корректность типов
4. **Модульность**: Каждый элемент самодостаточен
5. **Переиспользование**: Компоненты можно использовать в разных контекстах
## Миграция
Старые элементы продолжают работать через fallback-логику в `ElementConstructor.tsx`. Для полной миграции рекомендуется перевести все элементы на новую архитектуру.