feat(measure): memorizza tempo di inserimento misura (input_duration_ms)

Colonna nullable su measurements + migration 003, campo opzionale negli
schemi API (create singola e batch), passthrough nel proxy Flask e timer
lato client in task_execute: parte all'attivazione del subtask, si
resetta su auto-advance e navigazione manuale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 14:32:35 +02:00
parent edb7eb382c
commit 3f03ec8ab1
9 changed files with 141 additions and 0 deletions
@@ -729,6 +729,9 @@ function taskExecute() {
// ---- Value from numpad / caliper ----
currentValue: null,
// ---- Input timing (ms spent on the active subtask) ----
inputStartedAt: null,
// ---- Image switching logic ----
get currentSubtaskImage() {
return this.currentSubtask?.image_path || null;
@@ -808,6 +811,7 @@ function taskExecute() {
// ---- Init ----
init() {
this.subtasks.sort((a, b) => (a.order_index || 0) - (b.order_index || 0));
this.inputStartedAt = Date.now();
},
// ---- Check if a subtask has been measured ----
@@ -834,6 +838,9 @@ function taskExecute() {
const pf = this.passFailStatus;
const dev = this.deviation;
const inputDurationMs = this.inputStartedAt !== null
? Math.max(0, Math.round(Date.now() - this.inputStartedAt))
: null;
this.saving = true;
@@ -853,6 +860,7 @@ function taskExecute() {
lot_number: this.lotNumber,
serial_number: this.serialNumber,
input_method: inputMethod || 'manual',
input_duration_ms: inputDurationMs,
}),
});
@@ -911,6 +919,7 @@ function taskExecute() {
// ---- Advance to next unmeasured subtask ----
advanceToNext() {
this.currentValue = null;
this.inputStartedAt = Date.now();
for (let i = this.currentIndex + 1; i < this.totalSubtasks; i++) {
if (!this.isMeasured(this.subtasks[i].id)) {
@@ -932,6 +941,7 @@ function taskExecute() {
this.currentIndex = index;
this.currentValue = null;
this.errorMessage = '';
this.inputStartedAt = Date.now();
}
},