fix(file): bind loading evidence to cabinet

This commit is contained in:
2026-08-31 17:33:11 +08:00
parent ba8e3595e4
commit 1288c8937c
10 changed files with 359 additions and 57 deletions
+2 -2
View File
@@ -5,9 +5,9 @@ USE baiyue_file;
CREATE TABLE IF NOT EXISTS file_object (
id BIGINT UNSIGNED NOT NULL COMMENT '文件ID(雪花ID)',
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID和数据隔离键',
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '所有者范围键:0为平台,正整数为客户ID',
business_type VARCHAR(32) NULL COMMENT '关联业务类型',
business_id VARCHAR(64) NULL COMMENT '关联业务逻辑ID',
business_id VARCHAR(64) NULL COMMENT '关联业务逻辑ID;装柜证据固定为物理containerBookingId',
original_name VARCHAR(255) NOT NULL COMMENT '原始文件名',
object_key VARCHAR(512) NOT NULL COMMENT '对象存储键',
storage_provider VARCHAR(32) NOT NULL COMMENT '存储提供方',
@@ -0,0 +1,196 @@
openapi: 3.0.3
info:
title: Loading Evidence File API
version: 1.0.0
description: >-
装柜四步照片与铅封文件只归属物理柜。所有文件固定 ownerScope=PLATFORM、tenantId=0、
businessId=containerBookingId;PDA taskId 仅由 Firstleg 保存为来源和审计,不参与 File 归属。
servers:
- url: /
tags:
- name: LoadingEvidence
paths:
/api/platform/v1/files/loading-evidence/{containerBookingId}:
post:
tags: [LoadingEvidence]
summary: 平台或PDA上传柜级装柜证据
description: 不接受客户ID或入仓单ID;同一文件不得跨containerBookingId复用。
x-required-any-permission:
- platform:firstleg:inbound:loading:edit
- platform:firstleg:pda:work
parameters:
- $ref: '#/components/parameters/ContainerBookingId'
- $ref: '#/components/parameters/EvidenceType'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [file]
properties:
file: {type: string, format: binary}
responses:
'200':
description: 上传结果
content:
application/json:
schema: {$ref: '#/components/schemas/UploadResponse'}
/api/platform/v1/files/loading-evidence/{containerBookingId}/{fileId}:
get:
tags: [LoadingEvidence]
summary: 平台或PDA下载柜级装柜证据
description: 必须同时命中平台所有权、containerBookingId、fileId、LOADING_*类型和ACTIVE状态;响应禁止缓存。
x-required-any-permission:
- platform:firstleg:inbound:loading:view
- platform:firstleg:pda:work
parameters:
- $ref: '#/components/parameters/ContainerBookingId'
- $ref: '#/components/parameters/FileId'
responses:
'200':
description: 文件内容
headers:
Cache-Control:
schema: {type: string, enum: [no-store]}
content:
image/jpeg: {schema: {type: string, format: binary}}
image/png: {schema: {type: string, format: binary}}
image/bmp: {schema: {type: string, format: binary}}
application/octet-stream: {schema: {type: string, format: binary}}
/internal/file/v1/loading-evidence/{containerBookingId}:
post:
tags: [LoadingEvidence]
summary: Firstleg内部上传柜级装柜证据
parameters:
- $ref: '#/components/parameters/InternalToken'
- $ref: '#/components/parameters/OperatorId'
- $ref: '#/components/parameters/ContainerBookingId'
- $ref: '#/components/parameters/EvidenceType'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [file]
properties:
file: {type: string, format: binary}
responses:
'200':
description: 上传结果
content:
application/json:
schema: {$ref: '#/components/schemas/UploadResponse'}
/internal/file/v1/loading-evidence/{containerBookingId}/{fileId}:
get:
tags: [LoadingEvidence]
summary: Firstleg内部校验柜级文件元数据
parameters:
- $ref: '#/components/parameters/InternalToken'
- $ref: '#/components/parameters/ContainerBookingId'
- $ref: '#/components/parameters/FileId'
responses:
'200':
description: 元数据
content:
application/json:
schema: {$ref: '#/components/schemas/MetadataResponse'}
/internal/file/v1/loading-evidence/{containerBookingId}/{fileId}/content:
get:
tags: [LoadingEvidence]
summary: Firstleg内部下载柜级文件
parameters:
- $ref: '#/components/parameters/InternalToken'
- $ref: '#/components/parameters/ContainerBookingId'
- $ref: '#/components/parameters/FileId'
responses:
'200':
description: 文件内容,Cache-Control固定no-store
headers:
Cache-Control:
schema: {type: string, enum: [no-store]}
content:
application/octet-stream: {schema: {type: string, format: binary}}
components:
parameters:
InternalToken:
in: header
name: X-Internal-Service-Token
required: true
schema: {type: string}
OperatorId:
in: header
name: X-Operator-Id
required: true
schema: {$ref: '#/components/schemas/Id'}
ContainerBookingId:
in: path
name: containerBookingId
required: true
schema: {$ref: '#/components/schemas/Id'}
FileId:
in: path
name: fileId
required: true
schema: {$ref: '#/components/schemas/Id'}
EvidenceType:
in: query
name: evidenceType
required: true
schema:
type: string
enum: [PHOTO_STEP_1, PHOTO_STEP_2, PHOTO_STEP_3, PHOTO_STEP_4, SEAL]
schemas:
Id:
type: string
pattern: '^[1-9][0-9]*$'
ApiEnvelope:
type: object
required: [code, message, requestId, traceId, timestamp]
properties:
code: {type: string}
message: {type: string}
requestId: {type: string}
traceId: {type: string}
timestamp: {type: string, format: date-time}
UploadResponse:
allOf:
- $ref: '#/components/schemas/ApiEnvelope'
- type: object
required: [data]
properties:
data: {$ref: '#/components/schemas/UploadResult'}
MetadataResponse:
allOf:
- $ref: '#/components/schemas/ApiEnvelope'
- type: object
required: [data]
properties:
data: {$ref: '#/components/schemas/FileMetadata'}
FileIdentity:
type: object
required: [fileId, ownerScope, tenantId, businessType, businessId, fileName, contentType]
properties:
fileId: {$ref: '#/components/schemas/Id'}
ownerScope: {type: string, enum: [PLATFORM]}
tenantId: {type: string, enum: ['0']}
businessType:
type: string
enum: [LOADING_PHOTO_STEP_1, LOADING_PHOTO_STEP_2, LOADING_PHOTO_STEP_3, LOADING_PHOTO_STEP_4, LOADING_SEAL]
businessId:
allOf:
- $ref: '#/components/schemas/Id'
description: 物理containerBookingId
fileName: {type: string}
contentType: {type: string}
UploadResult:
allOf:
- $ref: '#/components/schemas/FileIdentity'
- type: object
required: [sizeBytes]
properties:
sizeBytes: {type: integer, format: int64, minimum: 1}
FileMetadata:
allOf:
- $ref: '#/components/schemas/FileIdentity'