Files
protoc-frontend/ARCHITECTURE.md

166 lines
6.2 KiB
Markdown
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.
# Архитектура системы элементов
## Обзор
Система была переработана для обеспечения универсальности и расширяемости. Теперь все элементы регистрируются в едином реестре, что позволяет легко добавлять новые типы элементов без изменения основного кода.
## Структура
### 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`. Для полной миграции рекомендуется перевести все элементы на новую архитектуру.