Преобразование устаревших данных

Преобразование устаревших данных

- Разработка редактора для преобразования формы опроса на основе ванильного JS в современную структуру-

В этом посте я хотел бы поделиться своим опытом разработки редактора форм опросов, который мы реализовали в недавнем проекте, и его ключевой архитектурой.

1. Фон и проблема

Существующая форма опроса в старой системе была построена на очень традиционном подходе, где использовался Vanilla JS для прямого формирования HTML на экране и поиска DOM на основе уникальных числовых идентификаторов, присвоенных каждому объекту. Эта устаревшая структура не имела проблем с простым рендерингом опроса на экране и ответами на него, но имела одну решающую проблему. Именно Напишите иерархию реальных вопросов и ответовполученные данныеопределитьбыло трудно, Обработка собранных данных для статистики и визуализациидоОченьбыло сложно.

Таким образом, нам нужен был новый редактор форматов, который бы не только просто портировал легаси в React, но и преобразовывал существующие плоские и фрагментарные данные в современную структуру, соответствующую реальной структуре вопросов и ответов (Label, Question, Option).

2. Архитектура компонентов редактора и тщательное разделение интересов

Поскольку это редактор, работающий со сложными данными, самым важным аспектом является строжайшее разделение компонентов, чтобы бизнес-логика и состояние экрана не смешивались на каждом этапе редактирования.Это было.

Весь поток редактирования и переключения вкладок контролируется верхним контейнером TemplateEditorContainer, и под ним расположены независимые компоненты обертки (Wrapper) для каждого этапа.

  • ШАГ 01. ФормаОтображенияЭтап, в котором задаются свойства для элемента наследия, такие как метка, вопрос, ответ
  • ШАГ 02. ФормированиеГруппы: шаг, объединяющий логическую иерархию и группы элементов
  • ШАГ 03. Создание правил: Этап, на который накладываются динамические события и расчетная логика

[Разделение Mapper и Form]Если войти внутрь обертки компонентов на каждом этапе, экран снова будет слева отбоковой панели редактирования (Mapper)и справа отэкран формыКомпонент разделен на View. Mapper абсолютно уникален для каждого STEP, но Form остается простым рендеринговым компонентом, чтобы поддерживать чистоту и повысить повторное использование.

  • MapperЭто интерфейс управления, который изменяет свойства или добавляет действия к элементу.
  • Форма: это главный экран, на котором фактическая анкета визуализируется и можно напрямую щелкать по элементам в редакторе для их выбора.

[Почему это было спроектировано таким образом?]Редактор испытывает много изменений состояния в зависимости от кликов и ввода пользователя. На экране много элементов, и у каждого элемента много уникальных стилей или значений состояния.

Если бы это все обрабатывалось в единственном компоненте или рыхлой структуре, код на этапе 'определения элементов' мог бы случайно вызвать побочные эффекты на этапе 'создания правил', или производительность обработки состояния ухудшилась бы, и экран рисковал бы зависнуть.

На каждом этапе редактирования (STEP 01~03) была выбрана полностью независимая обертка-компонента, в которой совмещаются Mapper и Form, что позволяет полностью предотвратить вмешательство логики домена конкретного этапа в другие этапы. Благодаря этому удалось снизить сложность кода и значительно повысить его поддерживаемость и стабильность рендеринга.

Кроме того, поток данных оптимизирован на этапы: изменение элемента (React State) → применение (удержание промежуточного состояния с помощью React Hook Form) → сохранение (преобразование значений RHF для передачи в соответствии с API сервера), а подкомпоненты были тщательно разделены с учетом повторного использования, и через useCallback и memo была предотвращена ненужная перерендеринга, которая нагружала бы тяжелые экраны.

3. Процесс структурирования данных на этапе 3

Процесс преобразования зависимых от DOM данных прошлого в структурированные статистические данные делится на три основных этапа.

ШАГ 01. Указать элементы (Mapping) Прежде всего, мы сопоставляем устаревшие данные в плоском (Flat) формате с одной из характеристик: метка (Label), вопрос (Question) или опция (Option). Вопрос — это элемент, который требует прямого ответа от пользователя, а опция имеет фактическое 'значение' этого ответа. Особенно важно, чтобы для получения значений ответов данный элемент был обязательно указан как 'опция', чтобы обеспечить целостность данных.

ШАГ 02. Создание группы (Grouping) Мы объединяем элементы с заданными характеристиками, чтобы создать логическую иерархию. 'Создание группы' объединяет взаимосвязанные вопросы в одну карточку просмотра (секцию), 'группа ответов' объединяет несколько ответов на один вопрос и позволяет назначить действие Radio, которое ранее управлялось полностью на чистом JavaScript, в RadioGroup. Также мы одновременно визуально упорядочиваем элементы, а функция 'однострочное размещение' позволяет задать размещение этих элементов в виде термометра, ползунка или таблицы, тем самым улучшая иерархическую структуру данных, качество интерфейса и удобство использования опроса.

ШАГ 03. Создание правил (Rule Making) Мы добавляем динамические действия (логику) к статичной анкете. Реализована функция 'события' (например, активация поля ввода при выборе другого пункта), которая управляет другими целями в зависимости от изменений базовых элементов, а также функция 'расчета', которая суммирует или начисляет баллы на основе статических и динамических значений определенных ответов.

4. Ключевые неполадки: Смешение двух систем идентификации

Одной из самых проблемных областей в этот проект был Идентификатор (ID) системаЭлементы, пришедшие из устаревшей системы, имели свои уникальные номера (например, formClauSn). Однако в новой современной архитектуре необходим был новый идентификатор (UUID) для идентификации каждого состояния L/Q/O.

Если пользователь изменяет элемент из 'вопроса' на 'метку' в редакторе, то характер элемента изменяется, и ему присваивается новый UUID. В этом случае может возникнуть серьезная проблема, когда существующие 'правила' теряют свои ссылки и перестают работать. Чтобы избежать этого, в редакторе два идентификатора были разделены и использованы в соответствии с назначением.

  1. templateItemIdЭто неизменное значение, основанное на идентификаторе существующей наследственной системы. На этапе назначения элементов (Mapping) и создания правил (Rule) это неизменное значение закреплено в качестве идентификатора, чтобы существующие правила сохранялись, даже если характер элемента изменится.
  2. id (UUID)На этапе создания группы, на котором устанавливается иерархия, я естественным образом использовал UUID в качестве идентификатора, соответствующего новой архитектуре данных.

5. Реализация передачи данных на уровне кода

Чтобы обеспечить плавную обработку данных в соответствии с фронтенд-средой, мы полностью внедрили TypeScript и построили передачу данных на основе пользовательских хуков. При входе в редактор логика функции, которая запрашивает устаревшие данные с бэкенда и преобразует их в удобный для фронтенда формат, выглядит следующим образом.

export const findQuestionnaireEditingViewByQuestionnaireTemplateId = async (payload: {
  questionnaireTemplateId: string;
}): Promise => {
  const url = `${templateLoadResource}/find-questionnaire-template-editing-view-by-questionnaire-template-id/query`;
  const response = await surveyAxios.post(url, payload);
  return transformTemplateTextAlign(response.data);
};

Также при редактировании правил были использованы операции CUD, и для декларативного управления состоянием сервера использовался React Query.

export const useRuleDeleteMutation = (questionnaireTemplateId: string) => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (payload: RemoveItemRuleCommand) => removeItemRule(payload),
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: ruleQueryKeys.list(questionnaireTemplateId),
      });
    },
  });
};

В заключение

Этот проект, который перевел устаревшую форму, застрявшую в манипуляциях с DOM в старомодном JavaScript, в современную архитектуру фронтенда и превратил её в статистически ценные 'данные', был очень интересным вызовом с точки зрения разработки. Надеюсь, этот опыт будет полезным справочным материалом в будущем, когда вы будете выполнять аналогичные миграции или проектировать сложные редакторские представления!

Hazel

Site footer