Skip to content

Operator terminal ​

Русская версия

Use operatorTerminal to find an operation, inspect its documents and instructions, choose a material context, start or pause work, and register good items. The header, work area, command rail and sectioned footer describe the same selected operation. The demonstration supports training commands. With a configured WorkOrderOperation source, the same buttons send the commands of the workflow API; another source only reads.

The command, material and instruction walkthrough below describes the demonstration. To configure reads of real objects, see Operation source; the commands of a WorkOrderOperation are described in Commands of a WorkOrderOperation.

Open the demonstration ​

Run the isolated panel demo with NUXT_LOCAL_FIXTURE_API_ENABLED=true and NUXT_PUBLIC_API_PREFIX=/local-api. On its login form, enter any non-empty username and password, then choose Терминал оператора · demo in the application list.

Open the operator terminal demo

The application route is /app/local-operator-terminal; its fixture panel ID is local-operator-terminal-panel. Opening the panel requests operations from the same-origin /local-api/terminal/operations route. Wait for the cards before choosing one. No selection from another panel or production credentials are required. If the request fails, check that this is the demo deployment, restore the connection and retry the read.

The server creates 30 operations when its process starts and retains commands and quantities in that process. Reloading the browser or reopening an operation reads this state; it does not reset quantities or the timer. Restarting the demo server restores the initial dataset. Visitors to the same server process share operations, so use an isolated demo process for repeatable scenarios.

Find and open an operation ​

The list screen shows search, filters, operation cards and the command rail, without the operation header and footer. Opening an operation shows its context header above the workspace and the sectioned footer below it; returning to the list removes both.

When an application without child applications has operatorTerminal as its root panel and the terminal configuration passes the check, the application automatically hides its global menu and header and gives the terminal the full browser viewport. The terminal's own operation header and sectioned footer remain visible on the operation screen. This does not switch the browser into its F11 fullscreen mode. Choose Exit to return to the home page and restore the normal application menu and header. Exit is shown in the command rail of the list screen, with or without a selected operation, and next to a configuration error. On the operation screen the rail shows Back to list instead; it only returns to the operation list inside the terminal.

The work command rail contains one Start / Pause button. While work is running it shows Pause; otherwise it shows Start, with availability determined by the quantity and resume rules below. The two commands are never displayed as separate simultaneous rail buttons.

The list shows 20 operations per page. Submit a search with the search button or Enter. What it matches depends on the operation source: the demonstration matches operation code, name, order, workplace, material, batch number or serial number without letter-case sensitivity; a standard request matches the order, the equipment or the item number. A standard request never lists operations in development or scheduling. The Future and Completed toggles include or hide those operations; future operations are included and completed operations hidden by default. Search and filters apply together. Future planned dates do not themselves block Start: the command uses the selected operation's quantities.

Use By date / By priority to sort in ascending order. Changing search, filters or sort requests the list again from the first page. If there are no matches, clear and submit the search or relax a filter.

The page number changes only after its read succeeds. If a page or operation read fails, Refresh state retries that same page or operation. After a failed list read, the previous cards are hidden until a read succeeds, so the list never shows operations that may not match the displayed search, filters or page. Cancelling an open form discards its draft locally without reading the instruction again; cancellation remains disabled while a request is pending.

Each card shows, from top to bottom: the operation's metatype icon and title (cardTitle), the subtitle line (cardSubtitle) when it is configured, the field rows (cardFields), the planned start, and a bottom line with the status, the start-time plate and the open arrow. A check mark marks the selected card. All cards on a list page have the same height: the tallest card sets it. The planned start and the bottom line stay at the bottom of every card, so a shorter card has free space between its field rows and the planned start. The icon has no terminalConfig setting. With a standard request, the terminal reads the metatype named in metaTypeName from /MetaTypes/{metaTypeName} together with each list read and shows its icon; the demonstration returns the icon with each operation. If the metatype has no icon or its read fails, the cards show no icon, and the operations are shown as usual. The terminal does not add the operation code by itself; include it in cardTitle, cardSubtitle or cardFields when operators need it. The demonstration puts the code in cardSubtitle, so the first card shows ОП-001 under the title Сборка корпуса. My operations is visible but disabled; filtering by the signed-in operator is not implemented.

The card title and each card field value show at most two lines; the card subtitle shows one line. A field value that does not fit beside its label moves to its own line under the label. Text that is still longer is cut with an ellipsis, and only cut text gets a tooltip with the full value: point at it with a mouse, or tap it on a touch screen. On a touch screen, tapping cut text only shows the tooltip and does not select the card; tap another part of the card to select it, which also hides the tooltip. Header and footer values are not cut; they wrap onto further lines. In the demonstration, ОП-023 has a long name, order, workplace and material, so its card shows the cutting and its operation screen shows the wrapping. With the default date sort this card is on the second page and is the tallest there, so every card on that page becomes as tall as it; the first page keeps compact cards.

The list request returns each demo operation's plannedStartTime. The card uses this timestamp for its planned-start date, shown as the date and the time separated by a space (for example 28.09 14:30 in Russian), and for the start-time plate: future time ticks down in orange, then changes to green READY (ГОТОВ in Russian) when the planned start arrives. This card countdown measures time until the planned start; the footer timer measures the selected operation's remaining work time. Neither the card countdown nor its color adds a command restriction: Start still follows the quantity rules below.

Select a card's main area for its summary and commands. Use its arrow, or Open in the command rail, to open the workspace. Open is hidden while an operation is open; it is needed only in the list. Back to list clears the operation selection. The header and footer retain the operation context while you change tasks or open forms; the footer's operator section uses the signed-in profile.

At wide sizes the document and work area appear side by side with a draggable divider. In a narrow terminal, use Document / Work area to show one pane. Opening a form or selecting another operation shows Work area. Switching panes preserves entered quantities and draft material selection; it does not submit a command.

In the same full-screen mode, the application increases the base text size to 16 px, including on desktop screens. Leaving the terminal or switching to an ordinary application restores the default size. An embedded terminal panel does not change the application scale.

On narrow panels, footer sections wrap and the summary scrolls within its own area when necessary. The document region has an accessible name without an extra visible heading. Quantity forms place Start in the footer and good-quantity OK inside the keypad. Serial forms place confirmation above the material list. Enter a quantity or select the required material instances before confirming; Cancel in the footer discards the draft.

Choose the instruction context ​

The demonstration header row Сер. № / № партии shows the serial or batch number. For quantity-based operations (types 0 and 1), it shows the operation's batch/item number as soon as you select the operation. For a serial operation (type 2), it shows — until you confirm an item: choose Item to open the item selector, choose one material card, then Select. The panel requests the current task's instruction for that material GUID. After a successful read, the header shows the item's serial number and the instruction changes with it. Cancel discards the draft choice and retains the previously confirmed context. Reopening the selector starts from the confirmed item. Choosing another operation clears this context.

The item selector chooses one instruction context. The Start and Good forms have separate selections and may choose several eligible materials. Confirming a command does not silently replace the instruction context.

In the demonstration, selecting an instruction task requests its text from the local server. Each task button shows a state icon and the task name in at most two lines. A task in work has a play icon on green, a completed task a check mark on orange, a waiting task a clock and a paused task a pause icon, both in the muted text color; a lock marks a blocked task and an empty circle any other state. A name that does not fit is cut with an ellipsis. The row under the task content repeats the name of the selected task, followed by its state; this row is wider than a button and also shows at most two lines. When the buttons do not fit into one row, scroll the row sideways. Skipped tasks are omitted. Selecting a task does not complete it. While the operation and selected task are in work, use Complete instruction or Complete task to record completion. The server then moves the next waiting task into work. Confirmation applies to the whole operation; selecting a serial context does not make it material-specific. Instruction completion is not a prerequisite for registering good items. Specialized content for other task types, including the measurement form, is not implemented; their active tasks can still be completed in the demo.

Try the work sequence ​

These examples use the seeded initial dataset. Restart the demo process before repeating them.

  1. Find ОП-001 (terminal-001, type 0) and open it. Its plan is 12 items, all queued. Open the demonstration drawing (JPEG) and read an instruction.
  2. Choose Start, enter 3, then Cancel. No command is sent and quantities remain unchanged. Repeat and confirm with the form's Start. The panel sends the command and reads the operation again; wait for 9 queued and 3 in work.
  3. The main button becomes Pause. Press it to freeze the remaining time. It becomes Start again; pressing it resumes the existing work and countdown without asking for another quantity.
  4. Choose Good, enter 2 and press OK inside the keypad. The operation then shows 9 queued, 1 in work and 2 good. This action is also permitted while paused, without completing instructions first.
  5. Register the remaining item in work. With 9 still queued, the operation returns to ready. Start and register those items to complete the operation. Enable Completed to find it in the list.
  6. Reload the browser and reopen the operation. Quantities and remaining time come from the existing server state.

Start requires a positive queued quantity and no items currently in work. Resuming paused work is a separate action behind the same button. Good requires a positive quantity in work; status alone and instruction completion do not add a restriction. Type 1 (ОП-002) uses the same positive-integer quantity entry in this demo. Start quantity cannot exceed queued quantity; good quantity cannot exceed quantity in work.

Enter a quantity with the keyboard or keypad (rows 7–9, 4–6 and 1–3, then zero). Erase removes the last digit. The comma key is disabled because fractional quantities are not supported. Invalid values disable confirmation. The form shows the material and batch/item number so the operator can check what the quantity describes.

For a serial example, open ОП-003 (terminal-003, type 2), initially containing six queued materials. In Start, select two cards and confirm: four remain queued and two enter work. In Good, select one of the materials in work and press Accept: four remain queued, one stays in work and one becomes good. The server changes material statuses by GUID and derives quantities from them. Labels are display values, not command identifiers.

In all serial forms, typing in material search filters visible cards without clearing selected cards. Filtering and selection ignore letter case and leading or trailing spaces: SN-3-001 shows the same cards as SN-3-001. Enter or the search button selects the exact serial match, or the sole visible match if there is no exact match, into the draft. Several non-exact matches require choosing a card; no result or a blank query leaves the draft unchanged. Search never confirms the context or submits a command. Check the selected count, clear the search if needed, then explicitly press Select, Start or Accept. The scanner button is disabled because scanning is not implemented.

Commands are blocked while a request is pending or the operation state is uncertain. After an error, refresh and inspect the quantities before retrying: the write may have succeeded even if its following read failed. If another visitor changed the operation, the server rejects a stale command; review the refreshed state and enter a new command. Retrying a read does not write.

If reading the instruction fails after you confirm a different item, the panel keeps the previously accepted operation, task and serial context, but clears the instruction content. Once the request has ended, Cancel closes the form and clears its quantity and material selection without sending a request. It leaves the error and command block in place; it does not restore the instruction. Press Refresh state to read the operation and its instruction again. This refresh resets the serial context, so select and confirm an item again if needed. Commands become available only after the reads succeed and their usual quantity and task conditions are met. Cancel remains disabled while a request is pending.

The planned-start label uses the panel's shared date parser, including DD.MM.YYYY HH:mm:ss. Timestamps with Z or an offset are displayed in the device's timezone. Dates without a zone retain their calendar fields for display. Both demo countdowns use the device clock; the panel does not compensate for a difference from the server clock. Countdown interpretation of values without a timezone remains browser-dependent pending a production time contract; the demo supplies absolute timestamps.

The default footer has five ordered sections: operator details, time, six production counts, operation details and notifications. Operation details show the description, the status label from { "context": "status" } and the operation number. Counts show plan, queued, pending/defect, good, in work and scrap; pending/defect and scrap are display values without recording commands. In the default color scheme, plan is cyan, queued uses the normal text color, pending/defect is yellow, good and in work are green, and scrap is red.

The timer shows signed remaining time and a circular indicator. Green means more than 10% remains; yellow starts when 90% of the planned duration has elapsed, including exactly 10% remaining. Negative remaining time is red and labeled overdue. While time runs normally, no caption appears under the ring; screen readers still announce it as remaining time. Pause freezes the number and preserves its warning/overdue classification; pause does not turn overdue time yellow.

With a configured WorkOrderOperation source, the timer uses the status, remainingDuration and stateEnteredAt that the terminal reads with the selected operation. remainingDuration is an ISO 8601 duration such as PT1H30M. Outside In work the timer shows it as the API returns it. In work it subtracts the time elapsed since stateEnteredAt every second, so the value can become negative: negative time is red and labeled overdue. The API gives no planned total yet, so the timer never turns yellow and the ring shows only its track, or a full red ring when overdue. The timer shows — and Time unavailable while remainingDuration is empty, and when an operation in work has no stateEnteredAt or has one without a time zone offset. Another source has no production timer.

With a WorkOrderOperation source and live updates enabled for the application, the opened operation follows the server without Refresh state; a card only selected in the list does not. The timer guide specifies that OperationTimerChanged carries the status, stateEnteredAt and remainingDuration together after a start, pause or other status change elsewhere; MaterialsLedgerChanged carries the quantities that changed, often one quantity per event. When all three timer fields arrive, the terminal writes them into the opened operation without another request and counts from the new anchor and remainder. A timer event missing any of the three fields triggers a read by GUID instead; WDEV has sent state-only timer events. Partial quantity events still replace only the quantities they carry. Header and footer fields that show a field of the status record, such as state.name, take the value from the event. If an event carries a value the terminal cannot apply exactly, for example another attribute or a deeper status path such as a field of a record linked to the status, or if events may have been missed after a reconnect, a return to the tab or a gap in their numbering, the terminal reads the operation again by GUID instead. In both cases the tasks, documents, chosen task and the material instances of an open Start or Good form stay as they were. A read or command in progress finishes first. The events received meanwhile, or during the terminal's own read by GUID, are not applied: a read made meanwhile may be newer than them, even one finished before they arrived, so the terminal reads the operation by GUID once more after that work. While the terminal shows a read error, it waits for Refresh state. Task states and list cards change only after Refresh state or reopening. Live updates are off unless the deployment owner sets NUXT_PUBLIC_REALTIME_HUB_URL in the environment of the panel process to the notification hub URL obtained from the API owner, including /hubs/notifications; the value is empty by default and is not part of the application JSON. The backend reports only the changes that the API owner has set up to publish; for WorkOrderOperation these are the timer and quantity notices.

For this demo, the server supplies plannedDurationSeconds as the percentage baseline and retains the remaining time across pause, resume and browser reload. This is a demonstration time model, not a production mapping to manufacturing durations. On a fresh process, ОП-005 starts paused with 45 of 600 seconds remaining, ОП-006 is overdue, ОП-007 has normal remaining time, and ОП-008 starts at the 60-of-600-second warning threshold. Running examples continue counting down after the server starts.

The operator section shows three values from the signed-in user’s profile in the same cells as a two-column fields section: the display name across both columns and, under it, Profession and Personnel no. (Профессия and Таб. № in Russian). The application's default layout requests that profile after sign-in. The terminal takes the name from the profile; until the request finishes, all three values show —. With a real API, the terminal then reads the profession and personnel number itself, once per opening of the terminal and again when the signed-in user changes. The user and their Persona share one GUID: the personnel number is the Persona itemId, read by GUID, and the professions come through ProfessionToPersonaLink from the Persona, each shown as the profession code and the link's professionLevel, for example 16015/6. An operator with several professions sees the first one in the API response; the others are listed in the tooltip of this value. Such a value is underlined with dots; its tooltip opens when the value receives focus: on a tap, on a click or with the Tab key. Screen readers read the other professions together with the value. An operator without a profession sees —. If one of these reads fails, both rows show Read error (Ошибка чтения), and the operations are read and shown as usual; Refresh in the command rail, or Refresh state, reads the operator details again. The local demo reads no Persona: its profile returns the fields profession and personnelNumber, so the demonstration shows the operator Иванов И. Ф. with profession 16015/6 and personnel number 38475, as in the design mockup. The section does not read operation attributes. The notifications section is intentionally empty; it does not imply a working notification feed.

Operation source ​

panel.request is required. It uses the shared Table request structure: metaTypeName with optional attributeList, findAttributes and sortParams, or customRequest. Other Table request keys that the terminal does not read are rejected; see Configuration errors. This configures reads, not command endpoints.

To read WorkOrderOperation objects, use this application JSON:

json
{"version":"1.0.0","panel":{"id":"operations-read","type":"operatorTerminal","request":{"metaTypeName":"WorkOrderOperation","attributeList":["name","code"],"findAttributes":[],"sortParams":[]}}}

operations-read is an example unique panel ID. Include the attributes needed by your display in attributeList, using your environment’s WorkOrderOperation contract and the same dotted paths as in display parts. Before sending the request, the panel converts the list as Table does: nested paths use the API pipe format (selectedWorkUnit.name is sent as selectedWorkUnit|name), and duplicates are removed. Opening the panel runs the shared object request and displays its response; selecting a card rereads the object by GUID. findAttributes and sortParams configure API filtering and ordering; as in Table, each filter uses field, compareType and value.

Every list read of a standard request also carries the operator's search, filters and sort. The panel keeps the configured findAttributes and adds these conditions; the API applies all of them together:

  • A submitted search adds CONTAIN conditions on workOrder, selectedWorkUnit.itemId and materialInstanceItemIds in one condition group, so a match in any one of them is enough. The panel removes leading and trailing spaces before sending the value; an empty search adds no condition.
  • The panel always adds state.systemName not equal to inDevelopment and not equal to inScheduling: operations in development or scheduling are not released to the shop floor, so the list never shows them.
  • With Completed off, which is the default, the panel adds state.systemName not equal to completed.
  • With Future off, the panel adds plannedStartTime less than or equal to the moment of the read, taken from the device clock and sent in UTC.
  • The selected sort, plannedStartTime or priority in ascending order, goes first. Configured sortParams then order operations that the selected sort leaves equal.

A list read fails with a read error if one of its conditions names an attribute that the configured metaTypeName lacks. A read with the default controls uses state.systemName and plannedStartTime; a search adds workOrder, selectedWorkUnit.itemId and materialInstanceItemIds; sorting by priority adds priority. A custom request other than the demonstration returns fixed rows, so the search, filter and sort controls stay disabled for it.

What an opened operation reads ​

With "metaTypeName": "WorkOrderOperation", opening an operation with Open or the arrow on its card reads more than the configured attributes. The terminal makes these reads itself; the application JSON configures none of them:

  • The operation by GUID, with the configured attributeList plus state.systemName, traceabilityType, plannedQty, queuedQty, inWorkQty, pendingQty, scrappedQty, completedQty, remainingDuration and stateEnteredAt. This read also runs when you only select a card, so these attributes are requested for the selected operation even when attributeList omits them. The header and footer show them only where their fields use them, and a value missing from the API response shows —. List cards come from the list read, which uses the configured attributeList alone. The API returns only the attributes a read names: without attributeList, list cards have no attributes and the selected operation has only these ten.
  • Its work order through WorkOrderToWorkOrderOperationLink, then its tasks through POST /work-flow/operation/init with the work order and the operation. The answer lists the tasks with their states and the next tasks of each; the task names come from WorkOrderOperationToWFAtomicTaskInstanceLink, because the answer does not contain them. The task list follows this sequence: a task comes after every task that leads to it. The sequence does not order the tasks of one parallel step, so they keep the order of the init answer. On two WDEV operations checked in September 2026, the next tasks in the init answer matched the task links WFConnectorInstanceLink. The start and finish tasks of the graph, types WFStartTaskInstance and WFFinishTaskInstance, are not shown: the operator does not work on them, and on WDEV the server completed them itself. They still take part in the sequence. Each task button shows the task state as an icon; the row under the task content gives the state of the selected task as a label: for example, inDevelopment reads In development (Разработка in Russian). The terminal calls init at every opening and after every command. In checks on WDEV in September 2026, init changed neither the operation nor its tasks for an operation that was being scheduled, ready, in work or paused.
  • Its documents through ObjectToDataSetLink, sorted by name, as in the files panel. The document area then downloads each file and takes its name and type from /files/{fileGuid}/params.

If one of these reads fails, the terminal shows a read error; Refresh state opens the operation again. The read also fails when init answers for another operation or names a task that the task link does not return. A read of task names or documents also fails instead of showing an incomplete list when the API reports more than 100 rows, or returns exactly 100 rows without a total count, because more rows may follow. A failed document download is reported in the document area. When the API refuses the file content, only the document area shows it; a failed read of the file parameters or a network failure also shows the application's general request error notice. Press Refresh in the command rail to read the operation and download its documents again.

After opening, the terminal selects a task itself: the task in work, otherwise the first task in the list that is not skipped. A task that init marks with isSkipped is skipped at once, although its state is still waiting until the server sets skipped; the terminal hides it from the first read. A task in work or completed stays visible even if the mark is set. If that task is the work instruction, type WFWorkInstructionTaskInstance in the init answer, the terminal reads its text at once; otherwise it reads the text when you choose the work instruction task. The text is read through POST /work-flow/operation/task/content with the work order, the operation, the task and empty params; after you confirm an item of a serial operation, params carries its serial number, see Choose an item. Plain text is shown line by line; text saved by the instruction editor keeps its formatting. If this read fails, the terminal shows a read error; Refresh state opens the operation again, and if the work instruction task is not selected then, choose it again. The material consumption task (WFMaterialConsumptionTaskInstance) opens the consumption screen, see Material consumption task. The content of tasks of other types is not read: the task area shows their name and says that their content will be added separately. Selecting a card without opening it reads the operation only.

For another source, a customRequest other than the demonstration or another metaTypeName, the terminal reads only the configured attributes and sends no commands; a notice at the top, the document area and the task area say that documents, tasks and commands are not connected yet.

Commands of a WorkOrderOperation ​

With "metaTypeName": "WorkOrderOperation", the command rail and the task area send the commands of the workflow API for the selected operation. Each request names the work order and the operation. The application JSON configures none of these requests. A button is enabled only under its condition:

ButtonEnabled whenRequest
Startthe operation has items in the queue (queuedQty above 0) and none in work (inWorkQty is 0)POST /work-flow/operation/run
Pause, shown in place of Startthe operation is in work and has items in workPOST /work-flow/operation/pause
Start after a pausethe operation is paused and has items in work; no form opensPOST /work-flow/operation/pause-reset
Goodthe operation has items in workPOST /work-flow/operation/complete
Complete task or Complete instructionthe selected task is in work; for an instruction, its text has been readPOST /work-flow/operation/task/complete with the task

Start and Good also stay disabled while the operation's traceabilityType is not 0, 1 or 2: the terminal cannot tell whether to ask for a quantity or for items. Pause and resuming do not depend on it.

Start and Good open a form in place of the tasks. On opening, the form reads the material instances linked to the operation through WFTagetMaterialInstanceLink:

  • Quantity traceability (types 0 and 1): the form reads the first linked instance, the batch, and asks for a whole quantity from 1 to the operation's queue for Start or to its items in work for Good. The command sends the batch GUID and this quantity.
  • Serial traceability (type 2): the form shows a card for each linked instance with a queue for Start (link:queuedQty above 0), or with items in work for Good (link:inWorkQty above 0), labeled with its itemId. Choose one or more cards and confirm with Start or Accept. The command sends the GUIDs of the chosen instances and quantity 0.

The form shows the instances it read when it opened; the terminal does not read them again while the form is open. If the operation changes elsewhere meanwhile, the cards may be out of date: press Cancel and open the form again to read them anew.

If the material instance read fails, the form stays open with a read error: press Cancel, then Refresh state. After a successful command, the terminal closes the form, reads the operation and init again and shows the tasks: the task in work, otherwise the first task that is not skipped; after Pause, resuming or Good it keeps the chosen task. It reads a work instruction again when that task is shown. The documents are not downloaded again. Choosing Start, Pause or Good for a card only selected in the list opens the operation first.

The API can refuse a command. The terminal then shows the API message above the workspace and changes nothing; the application also shows its general request error notice. For example, on WDEV Good was refused with Невозможно допустить завершение операции while the operation's task Регистрация годных was in work; after its tasks were completed with Complete task, the same Good was accepted. After a refusal, Cancel closes the form and Refresh state reads the operation again.

Choose an item ​

For a serial operation (type 2), Item opens the item selector. It reads every material instance linked to the operation through WFTagetMaterialInstanceLink and shows a card for each. Choose one card and press Select. If the shown task is a work instruction, the terminal first reads it again with params {"mtuItemId": "<itemId>"}; when the read succeeds, the selector closes and the header row Сер. № / № партии shows the instance's itemId. If the read fails, the terminal shows a read error, and the previously confirmed item stays; Cancel closes the selector. With another task shown, nothing is read: the selector closes and the header changes at once. The confirmed item stays when you change tasks or run a command. Opening another operation clears it, and the header shows — again. Refresh and Refresh state keep it: the terminal reads the operation and its instances again and clears the item only if the operation no longer has that instance. Choosing an item sends no command.

The panel requests 20 objects per page and uses pagination.totalRecordCount from the API response to determine the number of pages. This list reader requires an array in data and a numeric total; missing totals or null data produce a read error instead of a guessed page count. Ask the API provider to correct that response before retrying. Reading a selected object by GUID does not require a pagination total.

Only GET is supported for customRequest. dataPath selects the response array. Each response object must provide a stable unique identifier in the top-level field named by customRequest.idField, which defaults to id as in Table; for example, "idField": "objectGuid" reads the object's objectGuid. The identifier must be a nonempty string or a number; generated row indexes are not accepted. If a row lacks it, the read fails with an error. The demonstration rows contain id, so its configuration omits idField. A custom source does not enable production commands. attributeList, findAttributes and sortParams belong to the standard request: a custom read returns fixed rows, so these keys are rejected next to customRequest, even when empty. Selecting an object from a custom source rereads the collection and finds it by this source identifier.

A missing or invalid request stops the terminal before any read; see Configuration errors. Read failures show a separate error; after restoring access, use Refresh state to retry the read. Missing attributes display dashes: check attributeList and the source response.

For custom reads, the shared request executor reads the response array and divides it into pages of 20 in the browser; the total is the length of that complete array. The terminal rejects repeated source identifiers, including repeats on different pages: correct the source data before retrying. Display attributes come from each original response row. If it contains an fAttributes array, the terminal uses that array; otherwise it uses the row's fields as attributes, including real fields named objectGuid, type, linkedObject or fAttributes. It does not add the executor's generated identity or type as display attributes.

A row field named attributesMap also remains a business attribute when the terminal converts the row's fields. It does not replace the internal index used to find display attributes.

Material consumption task ​

A task of type WFMaterialConsumptionTaskInstance in the init answer opens the consumption screen. It records which material instances the operator consumed and shows the consumption beside the norm of the specification. Consumption always belongs to one item: the batch number of a quantity operation, or the serial number you confirmed with Item (Choose an item). Until a serial number is confirmed, the screen asks you to choose an item and reads nothing. For a quantity operation the batch is the operation attribute materialInstanceItemIds, so keep it in attributeList: without it the screen reports that the operation has no batch number and consumes nothing.

The terminal reads the specification and the progress from the server: POST /work-flow/operation/task/content with the work order, the operation, the task and params.producedItemId. The request repeats when the task opens, when the item changes, when the task state changes (for example after a pause) and after every operator action, whether the server accepted or refused it. The terminal calculates nothing itself: the norm, the consumed quantity, the material status and the readiness of the task come from the answer.

A table row is one material of the specification: its number and name, the consumed quantity of the norm with its unit, the context, and the status Collected or Collecting. The context shows what the consumption is for: Per batch or Per item is the produced item (each batch or serial number has its own norm), Per operation or Whole series is one norm for the operation. The consumed instances with their quantities are listed under the material on tinted rows with an arrow and a deeper indent, so it is clear which material each belongs to; the button on the left folds the list. If the operation has no material specification, the screen says so: check the order, there is nothing to consume.

While the task is in work, the operator takes three actions, and the terminal sends each through POST /MetaMethods/Run:

  • Tapping the quantity field, here and when correcting a record, raises a calculator for the touch screen: digits, a comma, erase and OK; the system keyboard does not open. It starts empty and shows the current quantity for reference. The comma works once and allows at most three decimals. A physical keyboard still types into the field.
  • Consume: enter the material instance number (by keyboard, or with a scanner that types text) and the quantity, then press Consume (method consume). The quantity is a positive number, the decimal separator is a point or a comma, with at most three decimals. Consuming the same instance for the same item again adds to one record. After success the fields are cleared and the cursor returns to the number field; after a refusal what you entered stays.
  • Pencil at an instance: correct the record. The field takes the new total quantity, not the difference (method adjustConsumption).
  • Trash at an instance: delete the record after you confirm with Yes (method deleteConsumption). The stock of the instance is restored.

The terminal always sends the item; the server uses it for a material consumed on the item and ignores it for a material consumed on the operation. A server refusal — the norm exceeded, not enough stock, an instance outside the specification, a task not in work — is shown in the server's own words above the table, nothing changes, and the terminal reads the task again. While the task is not in work, for example when the operation is paused, the fields and buttons are disabled and the screen says why.

Complete task is available only when the server returns canComplete: the norm is collected for every item started in the operation, not only the chosen one. The server takes a serial number that the operation has not started but does not count it for the readiness of the task; the screen warns about this. While the norm is not collected, the screen lists what is missing for each material and the button stays closed; the terminal has no way around it. Just before it sends task/complete, the terminal reads the task once more and sends nothing if another operator has taken the consumption back meanwhile: the server does not check the norm on completion itself. Completion with a deviation is a separate scenario that the server does not provide yet. Consumption recorded by another operator appears at the next read of the task: SignalR updates only the operation.

Configuration errors ​

Before reading operations, the panel checks panel.request and panel.terminalConfig. If any value is invalid, the application does not switch to full-screen mode: its menu, its header with the application editor button and the normal text size remain. The terminal area shows only the error list and Exit; it reads no operations and offers no commands. The list shows every error at once, each with its exact JSON path and reason, for example panel.request.typeName: this parameter is not supported by the terminal or panel.terminalConfig.cardFields[0].parts[0]: exactly one of text, attribute or context: "materialInstance" or "status" expected.

The check covers:

  • panel.request: an object with exactly one of metaTypeName (a nonempty string) or customRequest.
  • customRequest: an object with "method": "GET" and a nonempty url; dataPath and idField, when present, are nonempty strings. attributeList, findAttributes and sortParams are rejected next to it, even when empty, because a custom read returns fixed rows.
  • Standard request: every attributeList item is a nonempty string; findAttributes and sortParams are arrays of objects. Each findAttributes item passes the same filter check as in Table: an item without a nonblank field, or with the retired attribute, obj, link or compare keys, is reported at panel.request.findAttributes[i] as filter with a non-empty field expected; the attribute, obj, link and compare keys are no longer supported.
  • Table request keys that the terminal does not read are rejected: typeName (use metaTypeName), filter, getSelectedObjectForEventId, linkName, reverse, linkedAttribute and methodName.
  • Display structure: terminalConfig, cardTitle, cardSubtitle, every row and every footer section must be objects; cardFields, headerFields, footerFields, footerSections, every parts and the fields of every fields section must be arrays.
  • Row label: a string or a locale map whose values are strings. cardTitle and cardSubtitle have no label.
  • Every part: exactly one of text (a string), attribute (a nonblank path) or context (materialInstance or status). A retired field part is reported with a request to use attribute.
  • colSpan in footerFields and in footer fields sections, and columns of a fields section: 1, 2 or 3.
  • Footer section type: fields, timer, operator or notifications.
  • materialSearch and materialScanner: true or false.

Keys not listed here are ignored; only a part is limited to a single key. Correct every reported path in the application JSON and reopen the application; retrying with unchanged configuration cannot resolve the error. Exit returns to the home page.

Minimal demo configuration ​

This example requires NUXT_PUBLIC_API_PREFIX=/local-api and enabled local fixtures:

json
{"version":"1.0.0","panel":{"id":"local-operator-terminal-panel","type":"operatorTerminal","request":{"customRequest":{"method":"GET","url":"/terminal/operations","dataPath":"operations"}}}}

The application's JSON preview is read-only. Edit jsonData in apps/panel/server/local-fixtures/applications/local-operator-terminal/application.ts, restart the demo and reopen the application to try configuration changes. Restarting also resets seeded operations. The configured GET uses the shared request executor; training commands remain on guarded /local-api/terminal routes.

Training mode requires the configured custom URL, without its query string, to equal /terminal/operations. The shared fixture-mode check removes trailing slashes from the runtime API prefix and accepts /local-api or a prefix ending in /local-api. For example, /base/local-api requires the deployment to serve the fixture API at that base path. Operation reads, instruction reads and commands use that same prefix. For training operation reads, the terminal replaces the configured query string with its current search, filters and selection; other custom URLs and standard sources other than WorkOrderOperation send no commands.

Configure the display ​

Terminal configuration ​

terminalConfig is optional. Omitting it enables the built-in title, card and header rows, five footer sections, material search and the disabled scanner control; cards then have no subtitle line. These are presentation settings and never command identifiers.

Card title ​

cardTitle replaces the card's title separately from cardFields. Its default is the operation name (name); the operation code is not printed automatically. Use ordered parts to concatenate values and literal separators. For example, { "attribute": "code" }, { "text": " · " } and { "attribute": "name" } make the first card read ОП-001 · Сборка корпуса. The demonstration sets only { "attribute": "name" } in the title, so its first card is titled Сборка корпуса; the operation code ОП-001 appears in the card subtitle under that title and in the footer. It accepts parts and optional color; it does not use label or colSpan. On a card, { "context": "status" } shows the status of that card's operation, while { "context": "materialInstance" } always shows —; see Display row labels and parts. The title shows at most two lines.

Card subtitle ​

cardSubtitle is optional and has the same structure as cardTitle: ordered parts and optional color, without label or colSpan. Each part is text, attribute or context, exactly as in the title: { "context": "status" } shows the card's operation status, and { "context": "materialInstance" } shows —. If cardSubtitle is omitted, the terminal renders no subtitle block. If it is present, the terminal renders a small muted line directly under the card title, before the field rows. The subtitle shows at most one line: the terminal cuts longer text with an ellipsis and, as for other cut card text, shows the full value in a tooltip. color replaces the text color of the value only. Before reading operations, the configuration check applies the cardTitle rules to cardSubtitle and reports errors at paths such as panel.terminalConfig.cardSubtitle.parts. The demonstration sets { "attribute": "code" }, so the first card shows ОП-001 under the title Сборка корпуса.

Card fields ​

cardFields replaces summary rows in array order. Omitted: order, workplace and material. An empty array hides these rows while retaining the card title and controls. Each value shows at most two lines; cut text shows its full value in a tooltip.

Header fields ​

headerFields replaces header rows. Omitted: order, material (materialDefinition), serial/batch number ({ "context": "materialInstance" }) and workplace. An empty array hides configurable rows. Header values are not cut; long values wrap. With a standard request, the default rows show attribute values only when request.attributeList names workOrder, materialDefinition and selectedWorkUnit.name; a value missing from the operation read shows —.

footerSections replaces the complete ordered footer. Each section requires type:

  • fields: requires a fields array; columns is 1, 2 or 3 (default 1). Cells follow array order. An empty array leaves an empty section.
  • operator: shows the signed-in user’s name from the application profile and their profession and personnel number, separately from operation attributes. With a real API the terminal reads the profession and personnel number from the user's Persona; see Read the footer and countdown.
  • timer: displays the fixed countdown mechanism described above; no field array or custom threshold is used.
  • notifications: reserves the empty notification area.

Omitted: the five built-in sections. [] hides all footer sections. Supplying footerSections, including [], takes precedence over footerFields. To preserve context while customizing counts, copy all five sections from the complete example and edit only the desired cells.

footerFields is the shorter compatibility setting for replacing only the count section of the default footer. It applies only when footerSections is omitted. Omitted: the six built-in counts. [] leaves the count section empty while preserving operator, timer, operation and notification sections. Hiding fields never changes command validation or quantities.

Display row labels and parts ​

For a custom source, a plain nested value such as {"selectedWorkUnit":{"name":"Cell"}} does not make selectedWorkUnit.name readable: the terminal shows a dash. The source provider must return the nested object's attributes as {"selectedWorkUnit":{"fAttributes":[{"attributeName":"name","attributeValue":"Cell"}]}}. After the terminal reads that response, the shared resolver can display Cell for selectedWorkUnit.name. The terminal does not automatically convert nested plain JSON into this format.

A display row requires label and parts. label accepts a string or a locale map, such as {"ru":"Операция","en":"Operation"}. Each part contains exactly one key: text for literal text, attribute for a path in the original object, or context for a value that the terminal computes itself. context accepts two values:

  • materialInstance: the serial or batch number of the selected operation. It is resolved in headerFields and footer field rows; on cards it always shows —.
  • status: the operation status as a readable label. It is resolved wherever parts are accepted: on each card for that card's operation, and in headerFields and footer field rows for the open operation.

Parts concatenate in order without an automatic separator.

Paths such as name, code and selectedWorkUnit.name use the shared object attribute resolver, including nested objects with fAttributes. They are neither JavaScript expressions nor paths into internal command fields. Missing or empty values show a dash; zero remains zero. Empty parts renders an empty value. Literal text is not translated. Labels also support the shared _t(key) translation syntax; locale maps use the active language and fall back to the application’s default language.

The panel reports old { "field": "title" } parts as configuration errors; replace them with { "attribute": "name" }. Use workOrder for order, selectedWorkUnit.name for workplace and materialDefinition for material. For status, use { "context": "status" } to show a readable label such as Paused; { "attribute": "state.systemName" } shows the raw system name, such as paused. The source response must include those paths. User details belong to the separate operator section, not invented operation attributes. The panel ignores old cardTitle.label and cardTitle.colSpan; remove them.

Serial or batch number ​

{ "context": "materialInstance" } shows the serial or batch number of the selected operation. The terminal computes this value instead of reading one attribute:

  • Quantity traceability (types 0 and 1): the operation attribute materialInstanceItemIds, shown as soon as the operation is selected. In the demonstration, ОП-001 shows ПАРТИЯ-001.
  • Serial traceability (type 2): — until the operator chooses an item with Item and confirms it with Select. After the instruction read succeeds, the part shows that item's serial number, for example SN-3-001 for ОП-003. Selecting another operation or pressing Refresh state clears the confirmed item, and the dash returns.
  • Configured WorkOrderOperation source: quantity traceability shows materialInstanceItemIds, so include this attribute in attributeList. Serial traceability shows — until the operator confirms an item with Item and Select, then that item's itemId, for example СН-2026-000011; see Choose an item. Another standard source has no item choice and shows materialInstanceItemIds for every traceability type.

The part is resolved in headerFields and in footer field rows (fields sections of footerSections, or footerFields). The card title, card subtitle and card rows do not receive this selection context, so this part always shows — there, even on the selected card; only status is resolved on cards. The default headerFields and the demonstration use it for the Сер. № / № партии row. In contrast, { "attribute": "materialInstanceItemIds" } reads only the attribute and never shows the confirmed serial item.

To repeat the number in the footer, add a row like this to the fields array of a fields section. Without a selected operation it shows —; otherwise it shows the same value as the header.

json
{"label":{"ru":"Сер. № / № партии","en":"Serial / batch no."},"parts":[{"context":"materialInstance"}]}

Operation status ​

{ "context": "status" } shows the operation status as the same label as the status badge in the card's bottom line, for example Ready, In work, Paused or Completed (Готова, Работа, Пауза, Выполнена in Russian). The terminal takes the operation's status value and translates it into the interface language. Task states use the same labels; only in Russian a running task reads В работе rather than Работа. Besides the seven mockup states, the terminal has its own labels for these system names: inScheduling — Scheduling (В планировании), inDevelopment — In development (Разработка), inReview — In review (На проверке), obsolete — Obsolete (Устарел), Released — Released (Выпущено), disabled — Unavailable (Недоступен), enabled — Available (Доступен). Their Russian labels repeat the names the API gave these states on 24 September 2026; a later rename in the API does not change them. A system name without a label in the terminal is shown unchanged. In the demonstration, the local server returns this value with each operation. With a configured WorkOrderOperation source, the terminal reads it from state.systemName. For the selected operation the terminal requests it even when attributeList omits it, so the header and footer show the status when the API returns it. List cards use only the configured attributeList: include state.systemName there, otherwise the part on a card shows —.

Unlike materialInstance, this part is resolved on cards: in the card title, card subtitle and card rows it shows the status of that card's operation. In headerFields and in footer field rows it shows the status of the open operation. The demonstration uses it in the footer row Статус: open ОП-005, which starts paused, and the row shows Пауза (Paused in the English interface). In contrast, { "attribute": "state.systemName" } shows the raw system name, such as paused.

Display colors and column spans ​

color sets a field value's CSS color, including theme variables such as var(--p-green-400); labels keep their normal styling. Omitted color inherits the current text color. Color does not change a status or validation rule.

colSpan is 1, 2 or 3 (default 1). In a footer fields section it spans that many columns, clamped to the section's columns. It has no layout effect on the card title, card rows or header rows. The example spans the operation description across two columns.

materialSearch defaults to true. It controls text search and the search-selection button in the serial item selector and serial command forms. Set false to hide both while retaining material cards. It does not control operation-list search or the scanner.

Material scanner ​

materialScanner defaults to true. It controls the visible but disabled scanner button in serial forms. Set false to hide it independently of search. Enabling it does not enable scanning.

Configured demonstration ​

This complete jsonData matches the built-in fixture. Card titles show the operation name, card subtitles show the operation code, the header shows the serial/batch number through { "context": "materialInstance" }, the footer row Статус shows the status label through { "context": "status" }, and all five footer sections are defined explicitly.

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"
      }
    }
  }
}

To try alternatives, set materialSearch: false while retaining materialScanner: true: search disappears and the disabled scanner remains. Reverse the booleans to retain search alone. Change a count's color or a section's columns to see the presentation change. To test footerFields, first remove footerSections, then supply the desired field rows; otherwise the section configuration wins. Omit both footer settings to restore the built-in layout.

Limits and next task ​

The configured WorkOrderOperation source reads operations, their tasks, work instructions and documents and sends the start, pause, resume, good-item and task-completion commands. SignalR updates only the opened operation, not its tasks or the list cards; the terminal reads the tasks again after its own command. The production timer has no warning threshold, because the API gives no planned total. The content and completion conditions of task types other than the work instruction and the material consumption, recording a deviation and a supervisor's confirmation when a consumption task is completed without its norm, editable instructions, measurement forms, scanning, scrap and pending-item commands are unsupported. In the demonstration, the document viewer shows a shared sample engineering drawing (JPEG), not production documentation; operation-specific names and URLs refer to the same image content.

Use the demo to validate the operator procedure with these explicit limits. For panel composition, see the common panel guide and variant selection guide.

Parameter reference ​