Appearance
Терминал оператора
Панель operatorTerminal позволяет найти операцию, открыть документы и инструкции, выбрать изделие, начать или приостановить работу и зарегистрировать годные. Шапка, рабочая область, команды и секции нижней панели относятся к одной выбранной операции. Демонстрация поддерживает учебные команды. С настроенным источником WorkOrderOperation те же кнопки отправляют команды рабочего процесса в API; другой источник только читает данные.
Дальнейшие действия с командами, материалами и инструкциями описывают демонстрацию. Для подключения чтения реальных объектов см. источник операций, а команды операции WorkOrderOperation описаны в разделе «Команды операции WorkOrderOperation».
Откройте демонстрацию
Запустите изолированную demo-версию панели с NUXT_LOCAL_FIXTURE_API_ENABLED=true и NUXT_PUBLIC_API_PREFIX=/local-api. В форме входа укажите любые непустые логин и пароль, затем выберите в списке приложений Терминал оператора · demo.
Маршрут приложения — /app/local-operator-terminal, идентификатор панели в демонстрационной конфигурации — local-operator-terminal-panel. При открытии панель запрашивает операции по адресу /local-api/terminal/operations на том же сервере. Дождитесь карточек, затем выберите операцию. Выбор в другой панели и производственные учётные данные не нужны. При ошибке проверьте, что открыта demo-версия, восстановите соединение и повторите чтение.
Сервер создаёт 30 операций при запуске процесса и хранит результаты команд в этом процессе. Перезагрузка браузера или повторное открытие операции читает текущее состояние: количества и таймер не сбрасываются. Перезапуск сервера восстанавливает начальные данные. Посетители одного серверного процесса работают с общими операциями; для повторяемой проверки используйте отдельный процесс demo.
Найдите и откройте операцию
Экран списка показывает поиск, фильтры, карточки операций и блок команд, без шапки операции и нижней панели. Когда операция открыта, над рабочей областью появляется шапка с её данными, а под ней — нижняя панель с секциями; возврат к списку убирает и то и другое.
Если корневая панель приложения без дочерних приложений имеет тип operatorTerminal, а конфигурация терминала проходит проверку, приложение автоматически скрывает глобальное меню и шапку и отводит терминалу всё окно браузера. На экране операции собственная шапка операции и секции нижней панели остаются видимыми. Полноэкранный режим браузера по F11 при этом не включается. Нажмите «Выход», чтобы вернуться на главную страницу с обычным меню и шапкой приложения. «Выход» находится в блоке команд на экране списка — с выбранной операцией и без неё — и рядом с ошибкой конфигурации. На экране операции вместо него показана кнопка «К списку»: она возвращает только к списку операций внутри терминала.
В этом же полноэкранном режиме приложение увеличивает базовый размер текста до 16 px, в том числе на настольном экране. После выхода или перехода к обычному приложению возвращается стандартный размер. Вложенная панель терминала сама по себе масштаб приложения не меняет.
В блоке команд работы находится одна кнопка «Старт» / «Пауза». Во время работы она показывает «Паузу», в остальных состояниях — «Старт»; доступность определяется количествами и правилами продолжения работы ниже. Эти команды не показываются двумя отдельными кнопками одновременно.
Список показывает по 20 операций на странице. Подтвердите поиск кнопкой с лупой или Enter. Где ищется значение, зависит от источника операций: демонстрация ищет в коде и названии операции, заказе, рабочем месте, материале, номере партии и серийных номерах без учёта регистра, а стандартный запрос — в заказе, оборудовании и номере изделия. Операции в разработке и в планировании стандартный запрос не показывает никогда. Переключатели «Будущие» и «Выполненные» включают соответствующие операции в список или скрывают их. По умолчанию будущие операции видны, завершённые скрыты. Поиск действует вместе с фильтрами. Будущая плановая дата сама по себе не запрещает «Старт»: команда проверяет количества выбранной операции.
Переключатель «По дате» / «По приоритету» задаёт сортировку по возрастанию. Изменение поиска, фильтра или сортировки повторно запрашивает список с первой страницы. Если совпадений нет, очистите и подтвердите поиск либо измените фильтр.
Номер страницы меняется только после успешного чтения. Если чтение страницы или операции завершилось ошибкой, «Обновить состояние» повторно запрашивает ту же страницу или операцию. После неудачного чтения списка прежние карточки скрываются до успешного чтения, поэтому список не показывает операции, которые могут не соответствовать показанным поиску, фильтрам или странице. Отмена открытой формы удаляет черновик локально без повторного чтения инструкции; во время запроса отмена недоступна.
Карточка показывает сверху вниз: иконку метатипа и заголовок операции (cardTitle), строку подзаголовка (cardSubtitle), если она настроена, строки полей (cardFields), плановый старт и нижнюю строку со статусом, плашкой времени старта и стрелкой открытия. Выбранную карточку отмечает галочка. Все карточки на странице списка одной высоты — её задаёт самая высокая карточка. Плановый старт и нижняя строка всегда остаются внизу карточки, поэтому в более короткой карточке между строками полей и плановым стартом появляется свободное место. Настройки иконки в terminalConfig нет. Для стандартного запроса терминал вместе с каждым чтением списка читает метатип из metaTypeName по адресу /MetaTypes/{metaTypeName} и показывает его иконку; демонстрация возвращает иконку вместе с каждой операцией. Если у метатипа нет иконки или его прочитать не удалось, карточки показываются без иконки, а список операций — как обычно. Сам терминал код операции не добавляет: если он нужен оператору, включите его в cardTitle, cardSubtitle или cardFields. В демонстрации код задан в cardSubtitle, поэтому на первой карточке под заголовком Сборка корпуса видна строка ОП-001. Кнопка «Мои операции» видна, но отключена: фильтрация по вошедшему оператору не реализована.
Заголовок карточки и каждое значение поля карточки занимают не больше двух строк, подзаголовок — одну строку. Если значение не помещается рядом с подписью, оно переходит на отдельную строку под ней. Текст, который не помещается и так, обрезается многоточием, и только у обрезанного текста появляется подсказка с полным значением: наведите на него указатель мыши или коснитесь его на сенсорном экране. На сенсорном экране касание обрезанного текста только показывает подсказку и не выбирает карточку; чтобы выбрать её, коснитесь другого места карточки — подсказка при этом скроется. Значения в шапке и нижней панели не обрезаются, а переносятся на следующие строки. В демонстрации у ОП-023 длинные название, заказ, рабочее место и материал: его карточка показывает обрезку, а экран операции — перенос. При стандартной сортировке по дате эта карточка попадает на вторую страницу и оказывается там самой высокой, поэтому все карточки этой страницы вытягиваются до её высоты, а на первой странице карточки остаются компактными.
В ответе на запрос списка сервер возвращает plannedStartTime каждой демонстрационной операции. По этому значению карточка показывает плановый старт — дату и время через пробел, например 28.09 14:30, — и плашку времени старта: до планового старта время убывает оранжевым, а при его наступлении сменяется зелёным ГОТОВ. Этот отсчёт показывает время до старта; таймер внизу — остаток рабочего времени выбранной операции. Отсчёт карточки и его цвет не добавляют запрета на команды: «Старт» по-прежнему подчиняется описанным ниже правилам количеств.
Нажмите основную область карточки, чтобы выбрать операцию для сводки и команд. Стрелка карточки или кнопка «Открыть» в блоке команд открывает рабочую область. Пока операция открыта, кнопка «Открыть» скрыта: она нужна только в списке. «К списку» снимает выбор операции. Шапка и нижняя панель сохраняют её контекст при переключении задач и открытии форм; сведения об операторе в нижней панели берутся из профиля вошедшего пользователя.
При достаточной ширине документ и рабочая область расположены рядом; разделитель можно перетаскивать. В узком терминале переключатель «Документ» / «Рабочая область» показывает одну область. Открытие формы или выбор другой операции переключает на рабочую область. Переключение областей сохраняет введённое количество и черновой выбор материалов, не отправляя команду.
В узкой панели секции нижней сводки переносятся; при нехватке высоты прокрутите саму сводку. Область документа имеет доступное имя без дополнительного видимого заголовка. При вводе количества кнопка «Старт» находится в нижней строке, а OK для годных — внутри цифровой клавиатуры. В серийных формах подтверждение находится над списком материалов. Перед подтверждением введите количество или выберите нужные экземпляры; «Отмена» в нижней строке отбрасывает ввод.
Выберите изделие для инструкции
Строка шапки «Сер. № / № партии» в демонстрации показывает серийный номер или номер партии. Для операций с количественным учётом (типы 0 и 1) номер партии или изделия из операции виден сразу после выбора операции. Для серийной операции (тип 2) строка показывает —, пока изделие не подтверждено: нажмите «Изделие», выберите одну карточку материала и подтвердите кнопкой «Выбрать». Панель запрашивает инструкцию текущей задачи для GUID этого материала. После успешного чтения шапка показывает серийный номер изделия, и вместе с ним меняется инструкция. «Отмена» отбрасывает черновой выбор и сохраняет ранее подтверждённый контекст. При повторном открытии формы выбрано подтверждённое изделие; переход к другой операции очищает этот выбор.
В этой форме выбирается одно изделие для инструкции. Формы «Старт» и «Годные» имеют отдельный выбор и позволяют отметить несколько подходящих материалов. Подтверждение команды не подменяет изделие, выбранное для инструкции.
В демонстрации выбор задачи с инструкцией запрашивает её текст с локального сервера. Кнопка задачи показывает иконку статуса и название — не больше двух строк. У задачи в работе — значок запуска на зелёном, у завершённой — галочка на оранжевом, у ожидающей — часы, у приостановленной — пауза, обе приглушённого цвета; замок отмечает заблокированную задачу, пустой круг — любой другой статус. Название, которое не помещается, обрезается многоточием. Строка под содержимым задачи повторяет название выбранной задачи и её статус; она шире кнопки и тоже занимает не больше двух строк. Если кнопки не помещаются в одну строку, прокрутите строку вбок. Пропущенные задачи не показываются. Выбор задачи не завершает её. Пока операция и выбранная задача находятся в работе, нажмите «Завершить инструкцию» или «Завершить задачу», чтобы отметить выполнение. Сервер переведёт следующую ожидающую задачу в работу. Подтверждение относится к операции целиком; выбор серийного изделия не делает его поштучным. Завершать инструкции перед регистрацией годных не требуется. Специальное содержимое других типов задач, в том числе форма измерений, не реализовано; при этом их активные задачи можно завершать в демо.
Пройдите рабочий сценарий
Примеры ниже используют начальные демонстрационные данные. Для повторения перезапустите сервер demo.
- Найдите и откройте
ОП-001(terminal-001, тип0). План — 12 изделий, все в очереди. Откройте демонстрационный чертёж (JPEG) и прочитайте инструкцию. - Нажмите «Старт», введите
3, затем «Отмена». Сервер не получает команду, количества не меняются. Повторите ввод и подтвердите кнопкой «Старт» в форме. Панель отправит команду и заново запросит операцию; дождитесь значений 9 в очереди и 3 в работе. - Основная кнопка станет «Пауза». Нажмите её, чтобы остановить отсчёт оставшегося времени. Кнопка снова станет «Старт»; нажатие продолжит текущую работу и отсчёт без повторного ввода количества.
- Нажмите «Годные», введите
2и подтвердите кнопкой OK в цифровой клавиатуре. Операция покажет 9 в очереди, 1 в работе и 2 годных. Это действие разрешено и на паузе; предварительно завершать инструкции не нужно. - Зарегистрируйте оставшееся изделие в работе. Поскольку ещё 9 стоят в очереди, операция вернётся в состояние готовности. Запустите и зарегистрируйте их, чтобы завершить операцию. Включите «Выполненные», чтобы найти её в списке.
- Перезагрузите браузер и вновь откройте операцию. Количества и оставшееся время будут прочитаны из текущего состояния сервера.
«Старт» требует положительного количества в очереди и отсутствия изделий в работе. Продолжение работы на паузе — отдельное действие той же кнопки. «Годные» требует положительного количества в работе; статус сам по себе и выполнение инструкций не добавляют ограничения. Тип 1 (ОП-002) в этом демо использует такой же ввод положительного целого количества. Для старта нельзя указать больше, чем в очереди, а для годных — больше, чем в работе.
Введите количество клавиатурой или экранными кнопками: ряды 7–9, 4–6 и 1–3, затем ноль. Кнопка стирания удаляет последнюю цифру. Кнопка запятой отключена, поскольку дробные количества не поддерживаются. Некорректное значение отключает подтверждение. В форме видны материал и номер партии или изделия, чтобы проверить, к чему относится количество.
Для серийного учёта откройте ОП-003 (terminal-003, тип 2): в начальных данных шесть материалов стоят в очереди. В форме «Старт» выберите две карточки и подтвердите: четыре материала останутся в очереди, два перейдут в работу. В форме «Годные» выберите один из материалов в работе и нажмите «Принять»: останутся четыре в очереди, один в работе и один годный. Сервер меняет статусы по GUID материалов и рассчитывает количества из этих статусов. Видимые номера служат подписями, а не идентификаторами команд.
Во всех серийных формах ввод в поиск фильтрует видимые карточки, сохраняя уже отмеченные. Фильтрация и выбор не учитывают регистр букв и пробелы по краям запроса: SN-3-001 показывает те же карточки, что и SN-3-001. Enter или кнопка поиска добавляет в черновой выбор точное совпадение по серийному номеру; если точного совпадения нет — единственный видимый результат. При нескольких неточных совпадениях выберите карточку вручную; при отсутствии результата или пустом запросе выбор не меняется. Поиск не подтверждает изделие для инструкции и не отправляет команду. Проверьте число выбранных материалов, при необходимости очистите поиск, затем явно нажмите «Выбрать», «Старт» или «Принять». Кнопка сканера отключена: сканирование пока не реализовано.
Панель блокирует команды на время запроса и при неопределённом состоянии операции. После ошибки обновите операцию и проверьте количества перед повтором: запись могла пройти, даже если последующее чтение завершилось ошибкой. Если другой посетитель изменил операцию, сервер отклонит устаревшую команду; проверьте обновлённое состояние и введите команду заново. Повтор чтения не изменяет данные.
Если после подтверждения другого изделия чтение инструкции завершилось ошибкой, панель сохраняет ранее принятую операцию, задачу и серийный контекст, но очищает содержимое инструкции. Когда запрос закончился, «Отмена» закрывает форму и очищает введённое количество и выбор материалов без отправки запроса. Ошибка и блокировка команд сохраняются; содержимое инструкции не восстанавливается. Нажмите «Обновить состояние», чтобы панель повторно прочитала операцию и её инструкцию. Это обновление сбрасывает серийный контекст: при необходимости снова выберите и подтвердите изделие. Команды становятся доступны только после успешного чтения и при выполнении обычных условий по количествам и состоянию задачи. Пока запрос выполняется, «Отмена» остаётся отключённой.
Читайте нижнюю панель и таймер
Для подписи планового старта панель использует общий механизм разбора дат, включая DD.MM.YYYY HH:mm:ss. Даты с Z или смещением часового пояса отображаются в часовом поясе устройства. При отображении даты без зоны сохраняются её календарные поля. Оба отсчёта демо используют часы устройства; разницу с часами сервера панель не компенсирует. Для отсчёта по значениям без часового пояса пока сохраняется зависимость от браузера: производственный контракт времени ещё не согласован. Демонстрация возвращает даты с явно заданной зоной.
По умолчанию внизу пять последовательных секций: сведения об операторе, время, шесть производственных показателей, сведения об операции и оповещения. Сведения об операции — это описание, подпись статуса из { "context": "status" } и номер операции. Показатели — план, очередь, дефект, годные, работа и брак. Дефект и брак здесь показывают значения, но команд для их регистрации нет. В стандартной схеме план бирюзовый, очередь имеет обычный цвет текста, дефект жёлтый, годные и работа зелёные, брак красный.
Таймер показывает оставшееся время со знаком и круговой индикатор. Зелёный означает остаток больше 10%; жёлтый включается после расходования 90% плановой длительности, включая точный остаток 10%. Отрицательный остаток показан красным с подписью «Просрочка». При обычном ходе времени подпись под кругом не показывается; экранный диктор по-прежнему называет значение остатком времени. Пауза останавливает число и сохраняет признак предупреждения или просрочки: просроченный таймер на паузе не становится жёлтым.
В настроенном источнике WorkOrderOperation таймер использует статус, remainingDuration и stateEnteredAt, которые терминал читает вместе с выбранной операцией. remainingDuration — длительность в формате ISO 8601, например PT1H30M. Вне статуса «Работа» таймер показывает её такой, какой её вернул API. В работе он каждую секунду вычитает время, прошедшее с stateEnteredAt, поэтому значение может стать отрицательным: отрицательный остаток показан красным с подписью «Просрочка». Плановой длительности API пока не даёт, поэтому таймер не становится жёлтым, а круг показывает только свою дорожку или, при просрочке, полный красный круг. Таймер показывает — и «Время не определено», пока remainingDuration пуст, а также если у операции в работе нет stateEnteredAt или в нём не указано смещение часового пояса. У другого источника производственного таймера нет.
С источником WorkOrderOperation и включёнными для приложения живыми обновлениями открытая операция следует за сервером без «Обновить состояние»; карточка, только выбранная в списке, — нет. По памятке OperationTimerChanged передаёт статус, stateEnteredAt и remainingDuration вместе после старта, паузы или другой смены статуса на другом терминале; MaterialsLedgerChanged передаёт изменившиеся количества, часто по одному в событии. Когда пришли все три поля таймера, терминал записывает их в открытую операцию без нового запроса и ведёт отсчёт от нового якоря и остатка. Если в событии таймера нет хотя бы одного поля, терминал вместо этого читает операцию по GUID: на WDEV наблюдались события только со state. Частичные события количества меняют только переданные количества. Поля шапки и нижней панели, показывающие поле записи статуса, например state.name, берут значение из события. Если событие передаёт значение, которое терминал не может применить точно, — например, другой атрибут или более глубокий путь статуса вроде поля записи, связанной со статусом, — или события могли потеряться после переподключения, возврата на вкладку либо пропуска в их нумерации, терминал вместо этого снова читает операцию по GUID. В обоих случаях задачи, документы, выбранная задача и экземпляры материала в открытой форме «Старт» или «Годные» остаются прежними. Идущее чтение или команда сначала завершается. События, пришедшие за это время или во время собственного чтения терминала по GUID, не применяются: чтение за это время может оказаться новее них, даже завершившееся до их прихода, поэтому после этой работы терминал ещё раз читает операцию по GUID. Пока терминал показывает ошибку чтения, он ждёт «Обновить состояние». Статусы задач и карточки списка меняются только после «Обновить состояние» или повторного открытия. Живые обновления выключены, пока владелец развёртывания не задаст в окружении процесса панели NUXT_PUBLIC_REALTIME_HUB_URL — адрес хаба уведомлений, полученный от владельца API, вместе с /hubs/notifications; по умолчанию значение пусто, в JSON приложения оно не задаётся. Бэкенд сообщает только о тех изменениях, публикацию которых настроил владелец API; для WorkOrderOperation это уведомления о таймере и количествах.
В демо сервер задаёт plannedDurationSeconds как основу процентного расчёта и сохраняет остаток при паузе, продолжении и перезагрузке браузера. Это демонстрационная модель времени, а не производственное сопоставление нормативов. После запуска свежего процесса ОП-005 находится на паузе с остатком 45 из 600 секунд, ОП-006 просрочена, ОП-007 имеет обычный остаток, а ОП-008 начинается на пороге предупреждения — 60 из 600 секунд. Для работающих операций отсчёт продолжается с момента запуска сервера.
Секция operator показывает три значения из профиля вошедшего пользователя в таких же ячейках, как секция fields из двух столбцов: отображаемое имя на оба столбца, а под ним «Профессия» и «Таб. №». Профиль запрашивает стандартный макет приложения после входа. Терминал берёт из профиля имя; пока запрос не завершился, все три значения показаны прочерком —. С настоящим API терминал затем сам читает профессию и табельный номер — один раз при открытии терминала и снова при смене вошедшего пользователя. У пользователя и его Persona один GUID: табельный номер — itemId Persona, прочитанной по GUID, а профессии приходят по связи ProfessionToPersonaLink от Persona, каждая в виде code профессии и professionLevel связи, например 16015/6. Если профессий несколько, оператор видит первую из ответа API, а остальные перечислены в подсказке к этому значению. Такое значение подчёркнуто точками; подсказка открывается, когда значение получает фокус: при нажатии, щелчке или клавишей Tab. Экранный диктор читает остальные профессии вместе со значением. Если профессии нет, показывается прочерк. Если одно из этих чтений не удалось, обе строки показывают «Ошибка чтения», а операции читаются и показываются как обычно; «Обновить» в панели команд или «Обновить состояние» читает сведения об операторе заново. Локальная демонстрация Persona не читает: её профиль возвращает поля profession и personnelNumber, поэтому в демо показан оператор Иванов И. Ф. с профессией 16015/6 и табельным номером 38475, как в макете. Атрибуты операции секция не читает. Секция оповещений намеренно пуста; работающей ленты уведомлений в демо нет.
Источник операций
panel.request обязателен. Он использует общую структуру запросов Table: metaTypeName с необязательными attributeList, findAttributes и sortParams либо customRequest. Остальные ключи запроса Table, которые терминал не читает, отклоняются; см. ошибки конфигурации. Это настройка чтения, а не адрес команд.
Для чтения WorkOrderOperation задайте в JSON приложения:
json
{"version":"1.0.0","panel":{"id":"operations-read","type":"operatorTerminal","request":{"metaTypeName":"WorkOrderOperation","attributeList":["name","code"],"findAttributes":[],"sortParams":[]}}}operations-read — пример уникального ID панели. Укажите в attributeList атрибуты, которые нужны отображению, по контракту WorkOrderOperation вашей среды — теми же путями через точку, что и в частях отображения. Перед отправкой запроса панель преобразует список так же, как Table: вложенные пути записываются в формате API через вертикальную черту (selectedWorkUnit.name уходит как selectedWorkUnit|name), повторы удаляются. При открытии панель выполняет общий запрос объектов и отображает ответ; выбор карточки повторно читает объект по GUID. findAttributes и sortParams задают фильтрацию и порядок на стороне API; как и в Table, каждый фильтр состоит из field, compareType и value.
Каждое чтение списка по стандартному запросу учитывает также поиск, фильтры и сортировку, выбранные оператором. Панель сохраняет настроенные findAttributes и добавляет к ним условия ниже; API применяет все условия вместе:
- Подтверждённый поиск добавляет условия
CONTAINпоworkOrder,selectedWorkUnit.itemIdиmaterialInstanceItemIdsв одной группе условий, поэтому достаточно совпадения в любом из этих полей. Пробелы в начале и в конце значения панель убирает до отправки; пустой поиск условий не добавляет. - Панель всегда добавляет условия «
state.systemNameне равноinDevelopment» и «state.systemNameне равноinScheduling»: операции в разработке и в планировании ещё не переданы в цех, поэтому список их не показывает. - Когда «Выполненные» выключены — а так и есть по умолчанию, — панель добавляет условие «
state.systemNameне равноcompleted». - Когда «Будущие» выключены, панель добавляет условие «
plannedStartTimeне позже момента чтения». Этот момент берётся по часам устройства и передаётся в UTC. - Первой идёт выбранная сортировка по возрастанию: по
plannedStartTimeили поpriority. НастроенныеsortParamsзатем упорядочивают операции, которые выбранная сортировка считает равными.
Чтение списка завершается ошибкой чтения, если одно из его условий называет атрибут, которого нет у типа из metaTypeName. Чтение с настройками по умолчанию использует state.systemName и plannedStartTime, поиск добавляет workOrder, selectedWorkUnit.itemId и materialInstanceItemIds, сортировка по приоритету — priority. Нестандартный запрос, кроме демонстрационного, возвращает готовые строки, поэтому для него поиск, фильтры и сортировка остаются отключёнными.
Что читает открытая операция
Если задан "metaTypeName": "WorkOrderOperation", то при открытии операции кнопкой «Открыть» или стрелкой на карточке терминал читает больше, чем настроенные атрибуты. Эти чтения терминал выполняет сам, в JSON приложения они не настраиваются:
- Операцию по GUID — с атрибутами из
attributeListи дополнительноstate.systemName,traceabilityType,plannedQty,queuedQty,inWorkQty,pendingQty,scrappedQty,completedQty,remainingDurationиstateEnteredAt. Это чтение выполняется и при простом выборе карточки, поэтому для выбранной операции эти атрибуты запрашиваются, даже если их нет вattributeList. Шапка и нижняя панель показывают их только там, где их использует настроенное поле, а значение, которого нет в ответе API, показывается прочерком. Карточки списка строятся по чтению списка, а оно использует только настроенныйattributeList. API возвращает только те атрибуты, которые названы в чтении: безattributeListу карточек списка атрибутов нет, а у выбранной операции есть только эти десять. - Её рабочий заказ — по связи
WorkOrderToWorkOrderOperationLink, затем задачи — запросомPOST /work-flow/operation/initс рабочим заказом и операцией. Ответ перечисляет задачи, их статусы и следующие задачи каждой из них. Названий задач в ответе нет, поэтому их терминал берёт из связиWorkOrderOperationToWFAtomicTaskInstanceLink. Список задач идёт по этой последовательности: задача стоит после всех задач, которые к ней ведут. Задачи одной параллельной ступени последовательность не упорядочивает, поэтому они идут в порядке ответаinit. На двух операциях WDEV, проверенных в сентябре 2026 года, следующие задачи в ответеinitсовпали со связями задачWFConnectorInstanceLink. Задачи начала и конца графа, типовWFStartTaskInstanceиWFFinishTaskInstance, не показываются: оператор с ними не работает, а на WDEV сервер завершал их сам. В последовательности они по-прежнему участвуют. Кнопка задачи показывает её статус иконкой, а строка под содержимым задачи — подписью статуса выбранной задачи: например,inDevelopment—Разработка(в английском интерфейсе —In development). Терминал вызываетinitпри каждом открытии операции и после каждой команды. В проверках на WDEV в сентябре 2026 годаinitне менял ни операцию, ни её задачи — ни в планировании, ни в готовности, ни в работе, ни на паузе. - Её документы — по связи
ObjectToDataSetLink, по имени, как в панелиfiles. Затем область документа скачивает каждый файл, а имя и тип берёт из/files/{fileGuid}/params.
Если одно из этих чтений не удалось, терминал показывает ошибку чтения; «Обновить состояние» открывает операцию заново. Чтение завершается ошибкой и тогда, когда init отвечает для другой операции или называет задачу, которой нет в связи задач. Чтение названий задач или документов тоже завершается ошибкой, а не неполным списком, если API сообщает больше 100 строк или возвращает ровно 100 строк без общего количества: за ними могут быть ещё строки. Ошибка скачивания документа показывается в области документа. Если API отказал в содержимом файла, сообщение есть только там; при ошибке чтения параметров файла или сбое сети приложение показывает ещё и своё общее уведомление об ошибке запроса. Чтобы прочитать операцию и скачать её документы снова, нажмите «Обновить» в панели команд.
После открытия терминал сам выбирает задачу: ту, что в работе, иначе первую непропущенную в списке. Задачу, которую init помечает isSkipped, терминал считает пропущенной сразу, хотя её состояние остаётся waiting, пока сервер не выставит skipped: с первого чтения она скрыта. Задача в работе или завершённая остаётся видимой, даже если пометка стоит. Если это задача рабочей инструкции (тип WFWorkInstructionTaskInstance в ответе init), терминал сразу читает её текст, иначе — когда вы выберете эту задачу. Текст читается через POST /work-flow/operation/task/content с рабочим заказом, операцией, задачей и пустым params; после подтверждения изделия серийной операции в params передаётся его серийный номер, см. выбор изделия. Простой текст показывается по строкам, текст из редактора инструкций — с его оформлением. Если это чтение не удалось, терминал показывает ошибку чтения; «Обновить состояние» открывает операцию заново, и если задача инструкции после этого не выбрана, выберите её снова. Задача потребления материала (WFMaterialConsumptionTaskInstance) открывает экран потребления, см. задачу потребления материала. Содержимое задач других типов не читается: область задачи показывает их название и сообщает, что содержимое будет добавлено отдельно. Выбор карточки без открытия читает только операцию.
Для другого источника — нестандартного запроса, кроме демонстрационного, или другого metaTypeName — терминал читает только настроенные атрибуты и команд не отправляет; надпись вверху, область документа и область задач сообщают, что документы, задачи и команды пока не подключены.
Команды операции WorkOrderOperation
Если задан "metaTypeName": "WorkOrderOperation", блок команд и область задач отправляют команды рабочего процесса в API для выбранной операции. Каждый запрос содержит рабочий заказ и операцию; в JSON приложения эти запросы не настраиваются. Кнопка доступна только при своём условии:
| Кнопка | Доступна, когда | Запрос |
|---|---|---|
| «Старт» | у операции есть изделия в очереди (queuedQty больше 0) и нет изделий в работе (inWorkQty равно 0) | POST /work-flow/operation/run |
| «Пауза» на месте «Старта» | операция в работе и у неё есть изделия в работе | POST /work-flow/operation/pause |
| «Старт» после паузы | операция на паузе и у неё есть изделия в работе; форма не открывается | POST /work-flow/operation/pause-reset |
| «Годные» | у операции есть изделия в работе | POST /work-flow/operation/complete |
| «Завершить задачу» или «Завершить инструкцию» | выбранная задача в работе; для инструкции — её текст уже прочитан | POST /work-flow/operation/task/complete с задачей |
«Старт» и «Годные» также недоступны, пока traceabilityType операции не равен 0, 1 или 2: терминал не может определить, спрашивать количество или изделия. На «Паузу» и продолжение работы это не влияет.
«Старт» и «Годные» открывают форму на месте задач. При открытии форма читает экземпляры материала, связанные с операцией по WFTagetMaterialInstanceLink:
- Количественный учёт (типы
0и1): форма читает первый связанный экземпляр — партию — и просит целое количество от 1 до очереди операции для «Старта» или до числа изделий в работе для «Годных». Команда передаёт GUID партии и это количество. - Серийный учёт (тип
2): форма показывает карточку каждого связанного экземпляра с егоitemId— для «Старта» только тех, что стоят в очереди (link:queuedQtyбольше 0), для «Годных» — тех, что в работе (link:inWorkQtyбольше 0). Отметьте одну или несколько карточек и подтвердите кнопкой «Старт» или «Принять». Команда передаёт GUID отмеченных экземпляров и количество 0.
Форма показывает экземпляры, прочитанные при её открытии; пока она открыта, терминал их не перечитывает. Если за это время операция изменится в другом месте, карточки могут устареть: нажмите «Отмена» и откройте форму снова, чтобы прочитать экземпляры заново.
Если прочитать экземпляры не удалось, форма остаётся открытой с ошибкой чтения: нажмите «Отмена», затем «Обновить состояние». После успешной команды терминал закрывает форму, заново читает операцию и init и показывает задачи: ту, что в работе, иначе первую непропущенную; после «Паузы», продолжения работы и «Годных» остаётся выбранная задача. Если показана рабочая инструкция, её текст читается снова. Документы повторно не скачиваются. Если нажать «Старт», «Пауза» или «Годные», когда карточка только выбрана в списке, терминал сначала открывает операцию.
API может отклонить команду. Тогда терминал показывает сообщение API над рабочей областью и ничего не меняет; одновременно приложение показывает своё общее уведомление об ошибке запроса. Например, на WDEV «Годные» были отклонены с сообщением Невозможно допустить завершение операции, пока задача операции «Регистрация годных» была в работе; после завершения задач кнопкой «Завершить задачу» те же «Годные» были приняты. После отказа «Отмена» закрывает форму, а «Обновить состояние» заново читает операцию.
Выбор изделия
Для серийной операции (тип 2) кнопка «Изделие» открывает форму выбора. Форма читает все экземпляры материала, связанные с операцией по WFTagetMaterialInstanceLink, и показывает карточку каждого. Выберите одну карточку и нажмите «Выбрать». Если показана рабочая инструкция, терминал сначала заново читает её с params {"mtuItemId": "<itemId>"}; после успешного чтения форма закрывается, а строка шапки «Сер. № / № партии» показывает itemId экземпляра. Если чтение не удалось, терминал показывает ошибку чтения и сохраняет ранее подтверждённое изделие; «Отмена» закрывает форму. Если показана задача другого типа, ничего не читается: форма закрывается, и шапка меняется сразу. Подтверждённое изделие сохраняется при смене задачи и после команд. Открытие другой операции сбрасывает его, и в шапке снова появляется прочерк. «Обновить» и «Обновить состояние» его сохраняют: терминал заново читает операцию и её экземпляры и сбрасывает изделие, только если такого экземпляра в операции больше нет. Выбор изделия команд не отправляет.
Панель запрашивает по 20 объектов и определяет число страниц по pagination.totalRecordCount из ответа API. Для чтения списка терминалу нужны массив data и числовое общее количество. Если количества нет или data равен null, панель показывает ошибку чтения, не подставляя предполагаемое число страниц. Перед повторной попыткой обратитесь к разработчику API для исправления ответа. При чтении выбранного объекта по GUID общее количество не требуется.
Для customRequest поддерживается только GET. Путь dataPath выбирает массив объектов ответа. Каждый объект ответа должен содержать стабильный уникальный идентификатор в поле верхнего уровня, заданном через customRequest.idField; как и в Table, по умолчанию это id. Например, "idField": "objectGuid" выбирает поле objectGuid этого объекта. Идентификатор должен быть непустой строкой или числом; автоматически созданный номер строки не принимается. Если в строке его нет, чтение завершается ошибкой. Строки демонстрации содержат id, поэтому её конфигурация не задаёт idField. Нестандартный источник не включает производственные команды. attributeList, findAttributes и sortParams относятся к стандартному запросу: нестандартное чтение возвращает готовые строки, поэтому рядом с customRequest эти ключи отклоняются, даже если пусты. При выборе объекта из нестандартного источника панель повторно читает коллекцию и находит его по этому идентификатору источника.
Если request отсутствует или неверен, терминал останавливается до чтения данных; см. ошибки конфигурации. Ошибка чтения показывается отдельно; после восстановления доступа повторите чтение кнопкой «Обновить состояние». Отсутствующие атрибуты отображаются прочерками — проверьте attributeList и ответ источника.
Для нестандартного источника общий исполнитель запроса читает массив ответа и делит его в браузере на страницы по 20 строк. Общее количество равно длине этого полного массива. Терминал отклоняет повторяющиеся идентификаторы, в том числе на разных страницах: перед повторной попыткой исправьте данные источника. Атрибуты отображения берутся из исходной строки ответа. Если в ней есть массив fAttributes, терминал использует его; иначе превращает поля строки в атрибуты, сохраняя и реальные поля с именами objectGuid, type, linkedObject или fAttributes. Служебные идентификатор и тип, которые добавляет исполнитель запроса, в атрибуты отображения не попадают.
При преобразовании полей строки поле attributesMap также сохраняется как бизнес-атрибут. Оно не подменяет внутренний индекс, по которому панель находит атрибуты отображения.
Задача потребления материала
Задача типа WFMaterialConsumptionTaskInstance в ответе init открывает экран потребления. Он записывает, какие экземпляры материала оператор израсходовал, и показывает расход рядом с нормой спецификации. Расход всегда относится к одному изделию: номеру партии количественной операции или серийному номеру, который вы подтвердили кнопкой «Изделие» (выбор изделия). Пока серийный номер не подтверждён, экран просит выбрать изделие и ничего не читает. Для количественной операции партия — атрибут операции materialInstanceItemIds, поэтому оставьте его в attributeList: без него экран сообщает, что у операции нет номера партии, и ничего не потребляет.
Состав и прогресс терминал читает у сервера: POST /work-flow/operation/task/content с рабочим заказом, операцией, задачей и params.producedItemId. Запрос повторяется при открытии задачи, смене изделия, смене состояния задачи (например, после паузы) и после каждого действия оператора, принятого сервером или отклонённого им. Терминал ничего не считает сам: норма, потреблённое количество, статус материала и готовность задачи берутся из ответа.
Строка таблицы — один материал спецификации: номер и название, «потреблено из нормы» с единицей, контекст и статус «Собрано» или «Собирается». Контекст показывает, на что идёт расход: «На партию» или «На изделие» — на производимое изделие (норма своя у каждой партии или серийного номера), «На операцию» или «На всю серию» — общая норма операции. Под материалом перечислены потреблённые экземпляры с количеством: тонированные строки со стрелкой и большим отступом, чтобы было видно, к какому материалу они относятся; кнопка слева сворачивает список. Если у операции нет состава материалов, экран пишет об этом: проверьте заказ, потреблять нечего.
Пока задача в работе, оператор делает три действия, и каждое терминал отправляет в POST /MetaMethods/Run:
- Нажатие на поле количества, здесь и при исправлении записи, поднимает калькулятор для сенсорного экрана: цифры, запятая, стирание и «OK»; системная клавиатура не открывается. Калькулятор начинается с пустого значения и показывает текущее количество для справки. Запятая работает один раз, знаков после неё не больше трёх. Физическая клавиатура по-прежнему вводит текст в поле.
- «Потребить»: введите номер экземпляра материала (с клавиатуры или сканером, который вводит текст) и количество, затем нажмите «Потребить» (метод
consume). Количество — положительное число, десятичный разделитель — точка или запятая, не больше трёх знаков. Повторное потребление того же экземпляра для того же изделия суммируется в одну запись. После успеха поля очищаются, а курсор возвращается в поле номера; после отказа введённое остаётся. - Карандаш у экземпляра: исправить запись. В поле записывается новое общее количество, не разница (метод
adjustConsumption). - Корзина у экземпляра: удалить запись после подтверждения «Да» (метод
deleteConsumption). Остаток экземпляра на складе возвращается.
Терминал всегда передаёт изделие; сервер использует его только для материала с расходом на изделие и игнорирует для материала с расходом на операцию. Отказ сервера — превышена норма, не хватает остатка, экземпляр не входит в спецификацию, задача не в работе — показывается его текстом над таблицей, ничего не меняется, и терминал читает задачу заново. Пока задача не в работе, например операция на паузе, поля и кнопки отключены, а экран объясняет причину.
«Завершить задачу» доступна, только когда сервер вернул canComplete: норма набрана для всех изделий, запущенных в операции, а не только для выбранного. Серийный номер, который операция ещё не запустила, сервер принимает, но в готовность задачи не засчитывает; экран предупреждает об этом. Пока норма не набрана, экран перечисляет, чего не хватает по каждому материалу, а кнопка остаётся закрытой: обходного пути в терминале нет. Прямо перед отправкой task/complete терминал ещё раз читает задачу и ничего не отправляет, если другой оператор тем временем отменил расход: сама проверка нормы при завершении на сервере не выполняется. Завершение с отклонением — отдельный сценарий, которого сервер пока не предоставляет. Расход, записанный другим оператором, терминал показывает после следующего чтения задачи: SignalR обновляет только операцию.
Ошибки конфигурации
Перед чтением операций панель проверяет panel.request и panel.terminalConfig. Если хотя бы одно значение неверно, приложение не переходит в полноэкранный режим: меню, шапка с кнопкой редактора приложения и обычный размер текста сохраняются. В области терминала видны только список ошибок и кнопка «Выход»: операции не читаются, команды недоступны. Список сразу показывает все ошибки, у каждой — точный путь в JSON и причину, например panel.request.typeName: параметр не поддерживается терминалом или panel.terminalConfig.cardFields[0].parts[0]: ожидается ровно одно из text, attribute или context: "materialInstance" либо "status".
Панель проверяет:
panel.request: объект ровно с одним из ключейmetaTypeName(непустая строка) илиcustomRequest.customRequest: объект с"method": "GET"и непустымurl;dataPathиidField, если заданы, — непустые строки.attributeList,findAttributesиsortParamsрядом с ним отклоняются, даже если пусты: нестандартное чтение возвращает готовые строки.- Стандартный запрос: каждый элемент
attributeList— непустая строка;findAttributesиsortParams— массивы объектов. Каждый элементfindAttributesпроходит ту же проверку фильтра, что и в Table: элемент без непустогоfieldили с устаревшими ключамиattribute,obj,linkилиcompareотмечается путёмpanel.request.findAttributes[i]с причинойожидается фильтр с непустым field; ключи attribute, obj, link и compare больше не поддерживаются. - Ключи запроса Table, которые терминал не читает, отклоняются:
typeName(используйтеmetaTypeName),filter,getSelectedObjectForEventId,linkName,reverse,linkedAttributeиmethodName. - Структуру отображения:
terminalConfig,cardTitle,cardSubtitle, каждая строка и каждая нижняя секция должны быть объектами;cardFields,headerFields,footerFields,footerSections, каждыйpartsиfieldsкаждой секцииfields— массивами. labelстроки: строка или объект переводов со строковыми значениями. УcardTitleиcardSubtitleподписи нет.- Каждую часть: ровно один из ключей
text(строка),attribute(непустой путь) илиcontext(materialInstanceлибоstatus). Для устаревшей частиfieldпанель сообщает, что нужно указатьattribute. colSpanвfooterFieldsи в нижних секцияхfields, а такжеcolumnsсекцииfields:1,2или3.typeнижней секции:fields,timer,operatorилиnotifications.materialSearchиmaterialScanner:trueилиfalse.
Ключи, не перечисленные здесь, панель не проверяет и не использует; ограничение в один ключ действует только для части. Исправьте все указанные пути в JSON приложения и заново откройте приложение: повтор с той же настройкой не устранит ошибку. «Выход» возвращает на главную страницу.
Минимальная конфигурация демо
Этот пример работает с NUXT_PUBLIC_API_PREFIX=/local-api и включёнными локальными данными:
json
{"version":"1.0.0","panel":{"id":"local-operator-terminal-panel","type":"operatorTerminal","request":{"customRequest":{"method":"GET","url":"/terminal/operations","dataPath":"operations"}}}}Предпросмотр JSON приложения доступен только для чтения. Для проверки изменений отредактируйте jsonData в apps/panel/server/local-fixtures/applications/local-operator-terminal/application.ts, перезапустите demo и вновь откройте приложение. Перезапуск также сбрасывает операции. Настроенный GET проходит через общий исполнитель запросов; учебные команды остаются в защищённых маршрутах /local-api/terminal.
Учебный режим требует, чтобы адрес customRequest без строки запроса равнялся /terminal/operations. Общая проверка демо-режима убирает завершающие слеши из префикса API и принимает /local-api либо префикс, заканчивающийся на /local-api. Например, для /base/local-api среда должна обслуживать учебный API по этому базовому пути. Чтение операций, инструкций и команды используют один префикс. При учебном чтении операций терминал заменяет настроенную строку запроса текущим поиском, фильтрами и выбором операции; другие нестандартные адреса и стандартные источники, кроме WorkOrderOperation, команд не отправляют.
Настройте отображение
Конфигурация терминала
terminalConfig необязателен. Если его не указать, панель использует стандартные заголовок и строки карточки, поля шапки, пять нижних секций, поиск материалов и отключённую кнопку сканера; подзаголовка у карточек в этом случае нет. Настройки определяют отображение и не служат идентификаторами команд.
Заголовок карточки
cardTitle меняет заголовок отдельно от cardFields. По умолчанию это название операции (name); код операции автоматически не выводится. Массив parts объединяет значения и буквальные разделители. Например, { "attribute": "code" }, { "text": " · " } и { "attribute": "name" } дают заголовок первой карточки ОП-001 · Сборка корпуса. В демонстрации в заголовке задан только { "attribute": "name" }, поэтому первая карточка озаглавлена Сборка корпуса, а код операции ОП-001 показан в подзаголовке карточки под этим заголовком и в нижней панели. Заголовок принимает parts и необязательный color; label и colSpan для него не используются. На карточке { "context": "status" } показывает статус операции этой карточки, а { "context": "materialInstance" } всегда показывает —; подробнее — в разделе «Подписи и состав значений». Заголовок занимает не больше двух строк.
Подзаголовок карточки
cardSubtitle необязателен и устроен так же, как cardTitle: упорядоченный массив parts и необязательный color, без label и colSpan. Каждая часть — text, attribute или context, точно как в заголовке: { "context": "status" } показывает статус операции карточки, а { "context": "materialInstance" } — —. Если cardSubtitle не задан, терминал не выводит подзаголовок. Если задан, терминал выводит под заголовком карточки, перед строками полей, мелкую строку приглушённого цвета. Подзаголовок занимает не больше одной строки: более длинный текст терминал обрезает многоточием и, как для другого обрезанного текста карточки, показывает полное значение в подсказке. color меняет цвет только самого значения. Перед чтением операций проверка конфигурации применяет к cardSubtitle те же правила, что и к cardTitle, и указывает ошибки по путям вроде panel.terminalConfig.cardSubtitle.parts. В демонстрации задан { "attribute": "code" }, поэтому на первой карточке под заголовком Сборка корпуса показан ОП-001.
Поля карточки
cardFields заменяет строки сводки в порядке массива. По умолчанию это заказ, рабочее место и материал. Пустой массив скрывает эти строки, сохраняя заголовок карточки и её элементы управления. Каждое значение занимает не больше двух строк; полный текст обрезанного значения показывает подсказка.
Поля шапки
headerFields заменяет строки шапки. По умолчанию это заказ, материал (materialDefinition), серийный номер или номер партии ({ "context": "materialInstance" }) и рабочее место. Пустой массив скрывает настраиваемые строки. Значения шапки не обрезаются: длинный текст переносится. Со стандартным запросом строки по умолчанию показывают значения атрибутов, только если request.attributeList называет workOrder, materialDefinition и selectedWorkUnit.name; значение, которого нет в прочитанной операции, показывается как —.
Секции нижней панели
footerSections заменяет всю последовательность нижних секций. Каждая секция требует type:
fields: требует массивfields;columnsзадаёт 1, 2 или 3 столбца, по умолчанию 1. Ячейки идут в порядке массива. Пустой массив оставляет секцию пустой.operator: показывает имя, профессию и табельный номер вошедшего пользователя из профиля приложения; атрибуты операции здесь не используются. С настоящим API профессию и табельный номер терминал читает из Persona пользователя — подробнее в описании нижней панели выше.timer: показывает описанный выше таймер; массив полей и произвольный порог для него не задаются.notifications: оставляет пустую область оповещений.
Без настройки показываются пять стандартных секций. Значение [] скрывает их все. Явный footerSections, включая [], имеет приоритет над footerFields. Чтобы изменить счётчики с сохранением контекста, скопируйте все пять секций из полного примера и отредактируйте нужные ячейки.
Поля нижней панели
footerFields — сокращённая совместимая настройка для замены только секции счётчиков в стандартной нижней панели. Она действует лишь при отсутствии footerSections. По умолчанию показаны шесть счётчиков. Значение [] оставляет секцию счётчиков пустой, сохраняя оператора, время, операцию и оповещения. Скрытие полей не меняет количества или проверку команд.
Подписи и состав значений
В custom-источнике обычное вложенное значение {"selectedWorkUnit":{"name":"Cell"}} не делает путь selectedWorkUnit.name доступным: терминал показывает прочерк. Разработчик источника должен вернуть атрибуты вложенного объекта в формате {"selectedWorkUnit":{"fAttributes":[{"attributeName":"name","attributeValue":"Cell"}]}}. Когда терминал прочитает такой ответ, общий механизм атрибутов сможет показать Cell по пути selectedWorkUnit.name. Терминал не преобразует вложенный обычный JSON в этот формат автоматически.
Строка поля требует label и parts. label принимает строку или объект переводов, например {"ru":"Операция","en":"Operation"}. Каждая часть содержит ровно один ключ: text для буквального текста, attribute для пути атрибута исходного объекта или context для значения, которое вычисляет сам терминал. context принимает два значения:
materialInstance— серийный номер или номер партии выбранной операции. Вычисляется вheaderFieldsи в строках нижней панели; на карточках всегда показывает—.status— статус операции в виде понятной подписи. Вычисляется везде, где задаются части: на каждой карточке — для операции этой карточки, вheaderFieldsи строках нижней панели — для открытой операции.
Части соединяются по порядку без автоматического разделителя.
Пути вроде name, code и selectedWorkUnit.name разрешаются общим механизмом атрибутов объектов, включая вложенные объекты с fAttributes. Это не выражения JavaScript и не пути к внутренним полям команд. Пустое или отсутствующее значение показывается прочерком; ноль сохраняется. Пустой parts даёт пустое значение. Буквальный text не переводится. Подписи также поддерживают общую запись _t(key); объект переводов использует текущий язык, затем язык приложения по умолчанию.
Старые части { "field": "title" } панель считает ошибкой конфигурации; замените их на { "attribute": "name" }. Для заказа используйте workOrder, для рабочего места — selectedWorkUnit.name, материала — materialDefinition. Для статуса используйте { "context": "status" }: он показывает понятную подпись, например Пауза. Часть { "attribute": "state.systemName" } показывает системное значение как есть, например paused. Эти пути должны присутствовать в ответе источника. Сведения о пользователе задаются отдельной секцией operator, а не выдуманными атрибутами операции. Старые cardTitle.label и cardTitle.colSpan панель не использует; удалите их.
Серийный номер или номер партии
Часть { "context": "materialInstance" } показывает серийный номер или номер партии выбранной операции. Это значение вычисляет сам терминал, а не берёт из одного атрибута:
- Количественный учёт (типы
0и1): атрибут операцииmaterialInstanceItemIds, виден сразу после выбора операции. В демонстрацииОП-001показываетПАРТИЯ-001. - Серийный учёт (тип
2):—, пока оператор не выберет изделие кнопкой «Изделие» и не подтвердит его кнопкой «Выбрать». После успешного чтения инструкции часть показывает серийный номер этого изделия, напримерSN-3-001дляОП-003. Выбор другой операции или «Обновить состояние» сбрасывает подтверждённое изделие, и снова появляется прочерк. - Настроенный источник WorkOrderOperation: при количественном учёте часть показывает
materialInstanceItemIds, поэтому добавьте этот атрибут вattributeList. При серийном учёте ——, пока оператор не подтвердит изделие кнопками «Изделие» и «Выбрать», затемitemIdэтого изделия, напримерСН-2026-000011; см. выбор изделия. У другого стандартного источника выбора изделия нет, и при любом типе учёта часть показываетmaterialInstanceItemIds.
Значение вычисляется в headerFields и в строках нижней панели (секции fields в footerSections или footerFields). Заголовок, подзаголовок и строки карточки не получают этот контекст выбора, поэтому там эта часть всегда показывает —, даже на выбранной карточке; на карточках вычисляется только status. Стандартные headerFields и демонстрация используют её в строке «Сер. № / № партии». Для сравнения: { "attribute": "materialInstanceItemIds" } читает только атрибут и не показывает подтверждённое серийное изделие.
Чтобы повторить номер в нижней панели, добавьте такую строку в массив fields секции fields. Без выбранной операции она показывает —, иначе — то же значение, что и шапка.
json
{"label":{"ru":"Сер. № / № партии","en":"Serial / batch no."},"parts":[{"context":"materialInstance"}]}Статус операции
Часть { "context": "status" } показывает статус операции той же подписью, что и значок статуса в нижней строке карточки: например, Готова, Работа, Пауза или Выполнена (в английском интерфейсе — Ready, In work, Paused, Completed). Терминал берёт значение статуса операции и переводит его на язык интерфейса. Статусы задач получают те же подписи, только идущая работа у задачи — В работе. Кроме семи статусов макета, у терминала есть собственные подписи для этих системных имён: inScheduling — В планировании, inDevelopment — Разработка, inReview — На проверке, obsolete — Устарел, Released — Выпущено, disabled — Недоступен, enabled — Доступен (в английском интерфейсе — Scheduling, In development, In review, Obsolete, Released, Unavailable, Available). Русские подписи повторяют названия, которые эти статусы имели в API 24 сентября 2026 года; если API позже переименует статус, подпись не изменится. Системное имя без подписи в терминале показывается без изменений. В демонстрации это значение возвращает локальный сервер вместе с каждой операцией. В настроенном источнике WorkOrderOperation терминал читает его из state.systemName. Для выбранной операции терминал запрашивает его, даже если его нет в attributeList, поэтому шапка и нижняя панель показывают статус, если API его вернул. Карточки списка используют только настроенный attributeList: добавьте state.systemName туда, иначе на карточке часть покажет —.
В отличие от materialInstance, эта часть вычисляется и на карточках: в заголовке, подзаголовке и строках карточки она показывает статус операции этой карточки. В headerFields и строках нижней панели она показывает статус открытой операции. Демонстрация использует её в строке нижней панели «Статус»: откройте ОП-005, которая в начальных данных стоит на паузе, — строка покажет Пауза. Для сравнения: { "attribute": "state.systemName" } показывает системное значение как есть, например paused.
Цвета и ширина ячеек
color задаёт CSS-цвет значения, включая переменные темы вроде var(--p-green-400); подпись сохраняет обычное оформление. Без настройки значение наследует текущий цвет текста. Цвет не меняет статус или правила проверки.
colSpan принимает 1, 2 или 3, по умолчанию 1. В нижней секции fields ячейка занимает столько столбцов, но не больше её columns. Для заголовка карточки, строк карточек и шапки настройка не влияет на компоновку. В примере описание операции занимает два столбца.
Поиск материалов
materialSearch по умолчанию равен true. Он управляет строкой поиска и кнопкой выбора найденного материала в форме выбора изделия и серийных формах команд. Значение false скрывает оба элемента, сохраняя карточки. Настройка не управляет поиском операций и сканером.
Сканер материалов
materialScanner по умолчанию равен true. Он управляет видимостью отключённой кнопки сканера в серийных формах. Значение false скрывает её независимо от поиска. Включение настройки не включает сканирование.
Полный демонстрационный пример
Этот jsonData совпадает со встроенной конфигурацией: заголовок карточки показывает название операции, подзаголовок — её код, шапка показывает серийный номер или номер партии через { "context": "materialInstance" }, строка нижней панели «Статус» — подпись статуса через { "context": "status" }, все пять нижних секций заданы явно.
json
{
"version": "1.0.0",
"panel": {
"id": "local-operator-terminal-panel",
"type": "operatorTerminal",
"terminalConfig": {
"cardTitle": {
"parts": [
{
"attribute": "name"
}
]
},
"cardSubtitle": {
"parts": [
{
"attribute": "code"
}
]
},
"cardFields": [
{
"label": "Заказ",
"parts": [
{
"attribute": "workOrder"
}
]
},
{
"label": "Рабочее место",
"parts": [
{
"attribute": "selectedWorkUnit.name"
}
]
},
{
"label": "Материал",
"parts": [
{
"attribute": "materialDefinition"
}
]
}
],
"headerFields": [
{
"label": "Заказ",
"parts": [
{
"attribute": "workOrder"
}
]
},
{
"label": "Материал",
"parts": [
{
"attribute": "materialDefinition"
}
]
},
{
"label": "Сер. № / № партии",
"parts": [
{
"context": "materialInstance"
}
]
},
{
"label": "Рабочее место",
"parts": [
{
"attribute": "selectedWorkUnit.name"
}
]
}
],
"footerSections": [
{
"type": "operator"
},
{
"type": "timer"
},
{
"type": "fields",
"columns": 3,
"fields": [
{
"label": "План",
"parts": [
{
"attribute": "plannedQty"
}
],
"color": "var(--p-cyan-400)"
},
{
"label": "Очередь",
"parts": [
{
"attribute": "queuedQty"
}
],
"color": "var(--p-text-color)"
},
{
"label": "Дефект",
"parts": [
{
"attribute": "pendingQty"
}
],
"color": "var(--p-yellow-400)"
},
{
"label": "Годные",
"parts": [
{
"attribute": "completedQty"
}
],
"color": "var(--p-green-400)"
},
{
"label": "Работа",
"parts": [
{
"attribute": "inWorkQty"
}
],
"color": "var(--p-green-400)"
},
{
"label": "Брак",
"parts": [
{
"attribute": "scrappedQty"
}
],
"color": "var(--p-red-400)"
}
]
},
{
"type": "fields",
"columns": 2,
"fields": [
{
"label": "Описание операции",
"parts": [
{
"attribute": "name"
}
],
"colSpan": 2
},
{
"label": "Статус",
"parts": [
{
"context": "status"
}
]
},
{
"label": "№ операции",
"parts": [
{
"attribute": "code"
}
]
}
]
},
{
"type": "notifications"
}
],
"materialSearch": true,
"materialScanner": true
},
"request": {
"customRequest": {
"method": "GET",
"url": "/terminal/operations",
"dataPath": "operations"
}
}
}
}Для проверки вариантов задайте materialSearch: false и оставьте materialScanner: true: поиск исчезнет, отключённый сканер останется. Обратное сочетание оставляет только поиск. Измените color счётчика или columns секции, чтобы проверить оформление. Для проверки footerFields сначала удалите footerSections, затем задайте нужные строки, иначе приоритет останется за секциями. Удаление обеих нижних настроек возвращает стандартную компоновку.
Ограничения и следующий шаг
Источник WorkOrderOperation читает операции, их задачи, рабочие инструкции и документы и отправляет команды старта, паузы, продолжения, регистрации годных и завершения задачи. SignalR обновляет только открытую операцию, но не её задачи и не карточки списка; после собственной команды терминал читает задачи заново. У производственного таймера нет порога предупреждения, потому что API не даёт плановой длительности. Содержимое и условия завершения задач других типов, кроме рабочей инструкции и потребления материала, фиксация отклонения и подтверждения мастера при завершении задачи потребления без нормы, редактирование инструкций, формы измерений, сканирование и команды регистрации брака или дефекта не поддерживаются. В демонстрации просмотр документа показывает общий образец инженерного чертежа в формате JPEG, а не производственную документацию: разные имена и URL операций ведут к одному содержимому.
Используйте демо для проверки процедуры работы оператора с учётом этих ограничений. Для композиции панелей см. общую инструкцию и выбор варианта панели.
Справочник параметров
terminalConfigterminalConfig.cardFieldsterminalConfig.cardFields[].labelterminalConfig.cardFields[].partsterminalConfig.cardFields[].parts[].textterminalConfig.cardFields[].parts[].attributeterminalConfig.cardFields[].parts[].contextterminalConfig.headerFieldsterminalConfig.headerFields[].labelterminalConfig.headerFields[].partsterminalConfig.headerFields[].parts[].textterminalConfig.headerFields[].parts[].attributeterminalConfig.headerFields[].parts[].contextterminalConfig.footerFieldsterminalConfig.footerFields[].labelterminalConfig.footerFields[].partsterminalConfig.footerFields[].parts[].textterminalConfig.footerFields[].parts[].attributeterminalConfig.footerFields[].parts[].contextterminalConfig.materialSearchterminalConfig.cardTitleterminalConfig.cardTitle.partsterminalConfig.cardTitle.parts[].textterminalConfig.cardTitle.parts[].attributeterminalConfig.cardTitle.parts[].contextterminalConfig.cardTitle.colorterminalConfig.cardSubtitleterminalConfig.cardSubtitle.partsterminalConfig.cardSubtitle.parts[].textterminalConfig.cardSubtitle.parts[].attributeterminalConfig.cardSubtitle.parts[].contextterminalConfig.cardSubtitle.colorterminalConfig.cardFields[].colorterminalConfig.cardFields[].colSpanterminalConfig.headerFields[].colorterminalConfig.headerFields[].colSpanterminalConfig.footerFields[].colorterminalConfig.footerFields[].colSpanterminalConfig.footerSections[].fields[].labelterminalConfig.footerSections[].fields[].partsterminalConfig.footerSections[].fields[].parts[].textterminalConfig.footerSections[].fields[].parts[].attributeterminalConfig.footerSections[].fields[].parts[].contextterminalConfig.footerSections[].fields[].colorterminalConfig.footerSections[].fields[].colSpanterminalConfig.footerSectionsterminalConfig.footerSections[].typeterminalConfig.footerSections[].columnsterminalConfig.footerSections[].fieldsterminalConfig.materialScanner