跳至主要內容

船舶 Profile 與統一資料模型

統一資料模型將船舶 Profile 串接至航次、作業事件、來源報告、欄位擷取證據、人工審查與不可 變更的 audit history。

本頁定義 domain model。Endpoint 的 request 與 response schema 仍以自動產生的 API Reference 為準。

Entity 關係​

Vessel
└── Trip
└── HaulEvent
└── SourceReport
└── ExtractedField
├── Confidence
├── ReviewStatus
└── AuditLog

一艘 Vessel 可以有多個 Trip。Trip 包含依時間排序的 HaulEvent 或其他作業事件。 SourceReport 記錄匯入或產生資訊的來源。每個 ExtractedField 都會保留來源位置、標準化值、 Confidence、ReviewStatus 與 AuditLog。

Entity 定義​

Vessel​

單一漁船的穩定 Profile,保存跨 Trip 與報告仍然有效的識別資料與描述欄位。

Trip​

單一 Vessel 的一段有明確範圍的航次,將出港與返港資訊連接至航次期間產生的事件與報告。

HaulEvent​

Trip 中具有開始與結束時間的作業事件。eventType 用來區分 haul、set、catch、transit 或 其他控制類型,並共用同一套來源追蹤模型。

SourceReport​

用來產生標準化資料的來源文件、電子表單、錄影群組或機器產生報告。它會記錄來源型別、 關聯對象、時間範圍、版本與處理狀態。

ExtractedField​

從 SourceReport 擷取或投影出的單一欄位,保存原始值、標準化值、來源位置、擷取方式、 Confidence 與 ReviewStatus。

Confidence​

附加於擷取值的模型或規則判斷。score 必須介於 0 到 1;level 使用 low、 medium 或 high,讓審查流程採用一致的判斷。

ReviewStatus​

擷取值目前的人工審查狀態:pending、in_review、accepted、corrected 或 rejected。修正值不會覆蓋原始擷取結果。

AuditLog​

記錄重要變更或審查決策的 append-only 資料。它會保存變更內容、原因、時間,以及執行操作 的授權使用者或服務,但不會保存憑證。

Field dictionary|欄位字典​

Vessel​

欄位型別必填說明
vesselIdstring是穩定的 Fishtube 船舶識別碼。
namestring是組織內唯一的船舶顯示名稱。
registrationNumberstring 或 null否可取得時使用的官方登記號碼。
flagStatestring 或 null否受控制的船旗國代碼。
organizationIdstring是擁有船舶 Profile 的 tenant。
createdAt、updatedAtISO-8601 datetime是Profile lifecycle 時間。

Trip​

欄位型別必填說明
tripIdstring是穩定的航次識別碼。
vesselIdstring是所屬 Vessel。
tripNumberstring 或 null否業者或主管機關的航次編號。
departedAt、returnedAtISO-8601 datetime 或 null否航次開始與結束時間。
departurePort、returnPortstring 或 null否受控制的港口參照。
statusenum是planned、active、completed 或 cancelled。

HaulEvent​

欄位型別必填說明
eventIdstring是穩定的作業事件識別碼。
tripIdstring是所屬 Trip。
eventTypeenum是set、haul、catch、transit 或其他控制類型。
startedAt、endedAtISO-8601 datetime是事件開始與結束時間。
locationobject 或 null否可取得時保存經緯度。
sourceReportIdsstring array是支援此事件的 SourceReport。

SourceReport​

欄位型別必填說明
sourceReportIdstring是穩定的來源報告識別碼。
tripId、eventIdstring 或 null否關聯的 Trip 與 HaulEvent。
sourceTypeenum是observer_form、edge_recording、ai_analysis 或 import。
sourceReferencestring是不含機密的文件、segment 或錄影群組參照。
capturedAtISO-8601 datetime是來源所代表的時間。
versionstring是來源 schema 或文件版本。
processingStatusenum是received、processing、ready 或 failed。

ExtractedField​

欄位型別必填說明
extractedFieldIdstring是穩定的擷取值識別碼。
sourceReportIdstring是產生此值的 SourceReport。
fieldKeystring是穩定的欄位字典 key。
rawValueany 或 null否來源中原本呈現的值。
normalizedValueany 或 null否依欄位字典標準化後的值。
sourcePointerobject是Page、segment、camera、timestamp 或 JSON path 來源。
extractionMethodenum是manual、rule、ocr 或 model。
confidenceConfidence是信心評估。
reviewStatusReviewStatus是目前審查狀態。

Confidence​

欄位型別必填說明
scorenumber是包含 0 與 1 的數值範圍。
levelenum是low、medium 或 high。
methodstring是規則、模型或人工判斷方式。
modelVersionstring 或 null否適用時保存產生結果的模型版本。

ReviewStatus​

欄位型別必填說明
statusenum是pending、in_review、accepted、corrected 或 rejected。
reviewedValueany 或 null否不覆蓋來源資料的接受或修正值。
reasonCodestring 或 null否修正或拒絕的控制原因。
reviewedBy、reviewedAtstring/datetime 或 null否授權審查者與決策時間。

AuditLog​

欄位型別必填說明
auditLogIdstring是穩定的 audit event 識別碼。
entityType、entityIdstring是被變更的 entity。
actionstring是例如 field.corrected 的重要操作。
actorType、actorIdstring是授權使用者或服務參照。
occurredAtISO-8601 datetime是不可變更的事件時間。
reasonCodestring 或 null否受控制的業務原因。
changesobject是已去除機密的前後值或變更欄位名稱。
correlationIdstring是Request 或 workflow correlation 參照。

範例 JSON​

{
"vessel": {
"vesselId": "vessel_demo_001",
"name": "Example Vessel 01",
"registrationNumber": null,
"flagState": "TW",
"organizationId": "organization_demo_001",
"createdAt": "2026-07-01T08:00:00Z",
"updatedAt": "2026-07-28T04:00:00Z"
},
"trip": {
"tripId": "trip_demo_001",
"vesselId": "vessel_demo_001",
"tripNumber": "DEMO-2026-001",
"departedAt": "2026-07-20T00:00:00Z",
"returnedAt": null,
"departurePort": "PORT_DEMO_A",
"returnPort": null,
"status": "active"
},
"haulEvent": {
"eventId": "event_demo_001",
"tripId": "trip_demo_001",
"eventType": "haul",
"startedAt": "2026-07-27T02:10:00Z",
"endedAt": "2026-07-27T02:42:00Z",
"location": {
"latitude": 23.5,
"longitude": 121.0
},
"sourceReportIds": ["source_report_demo_001"]
},
"sourceReport": {
"sourceReportId": "source_report_demo_001",
"tripId": "trip_demo_001",
"eventId": "event_demo_001",
"sourceType": "ai_analysis",
"sourceReference": "recording_group_demo_001",
"capturedAt": "2026-07-27T02:20:14Z",
"version": "1.0",
"processingStatus": "ready"
},
"extractedFields": [
{
"extractedFieldId": "field_demo_001",
"sourceReportId": "source_report_demo_001",
"fieldKey": "catch.species_code",
"rawValue": "YFT",
"normalizedValue": "YFT",
"sourcePointer": {
"segmentId": "segment_demo_001",
"cameraId": "camera_demo_01",
"timestampSeconds": 614
},
"extractionMethod": "model",
"confidence": {
"score": 0.94,
"level": "high",
"method": "object_detection",
"modelVersion": "demo-model-1.0"
},
"reviewStatus": {
"status": "accepted",
"reviewedValue": "YFT",
"reasonCode": null,
"reviewedBy": "reviewer_demo_001",
"reviewedAt": "2026-07-28T03:45:00Z"
}
}
],
"auditLogs": [
{
"auditLogId": "audit_demo_001",
"entityType": "ExtractedField",
"entityId": "field_demo_001",
"action": "field.accepted",
"actorType": "user",
"actorId": "reviewer_demo_001",
"occurredAt": "2026-07-28T03:45:00Z",
"reasonCode": null,
"changes": {
"reviewStatus": {
"before": "pending",
"after": "accepted"
}
},
"correlationId": "request_demo_001"
}
]
}