You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

531 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/** 前端类型定义 — 与 PRD / API 契约一致 */
import type { Priority1DisplayLine } from "@/modules/priority1/quote-storage";
import type { FlockDisplayLine } from "@/modules/flock/quote-storage";
export type QuotePageStatus =
| "idle"
| "resolving_address"
| "validating"
| "processing"
| "success"
| "fallback"
| "manual_followup"
| "error"
| "expired";
export type DataPageStatus = "loading" | "success" | "empty" | "error";
/** MotherShip 已知 Tab;API 可能出现未注册的新 service_level */
export type KnownServiceLevel = "standard" | "guaranteed" | "dedicated";
export type ServiceLevel = KnownServiceLevel | (string & {});
export type RateOption = "lowest" | "fastest" | "bestValue" | (string & {});
export type UnitWeight = "lb" | "kg";
export type UnitDim = "in" | "cm";
export type DisplayUnit = "imperial" | "metric";
export type CargoType =
| "general_freight"
| "machinery"
| "furniture"
| "electronics"
| "building_materials"
| "auto_parts"
| "food_nonperishable"
| "apparel"
| "other";
export interface AddressInput {
street: string;
city: string;
state: string;
zip: string;
place_id: string;
formatted_address: string;
selected_from_suggestions: boolean;
mothership_option_id?: string;
mothership_display_label?: string;
selected_from_mothership?: boolean;
}
export interface MothershipAddressCandidate {
option_id: string;
display_label: string;
formatted_address: string;
street: string;
city: string;
state: string;
zip: string;
selectable?: boolean;
unavailable_reason?: string;
}
export interface MothershipCandidatesResult {
pickup_candidates: MothershipAddressCandidate[];
delivery_candidates: MothershipAddressCandidate[];
requires_selection: boolean;
quote_session_id?: string;
}
export interface QuoteRequestBody {
request_id: string;
customer_id: string;
business_customer_id?: string;
/** ccnew 登录账号;缺 BC 时后端反查加价客户 */
business_user_account?: string;
pickup_address: AddressInput;
delivery_address: AddressInput;
weight: { value: number; unit: UnitWeight };
dimensions: {
length: number;
width: number;
height: number;
unit: UnitDim;
};
pallet_count: number;
cargo_type: CargoType;
service_level?: ServiceLevel;
rate_option?: RateOption;
display_unit?: DisplayUnit;
quote_session_id?: string;
/** MotherShip 登录态:提货附加服务 id(cfs/liftgate/…) */
pickup_accessorials?: string[];
/** MotherShip 登录态:派送附加服务 id */
delivery_accessorials?: string[];
/** MotherShip 登录态:可提货日期 YYYY-MM-DD */
ready_date?: string;
/** MotherShip 登录态:可提货时刻,如 3:00 PM */
ready_time?: string;
/** MotherShip 登录态:多行货物(与官网 cargo-add-button 对应) */
cargo_lines?: Array<{
cargo_type: string;
quantity: number;
weight_lb: number;
length_in: number;
width_in: number;
height_in: number;
}>;
/** MotherShip 登录态:二级 Details 补充字段 */
mothership_details?: {
pickup: {
company_name?: string;
suite?: string;
contact_first?: string;
contact_last?: string;
contact_email?: string;
contact_phone?: string;
reference?: string;
notes?: string;
opens_at?: string;
closes_at?: string;
};
delivery: {
company_name?: string;
suite?: string;
contact_first?: string;
contact_last?: string;
contact_email?: string;
contact_phone?: string;
reference?: string;
notes?: string;
opens_at?: string;
closes_at?: string;
};
request_delivery_appointment?: boolean;
fba_number?: string;
fba_po_number?: string;
cargo?: Array<{
piece_count_type?: string;
piece_count_qty?: number;
description?: string;
nmfc?: string;
hazmat?: boolean;
alcohol?: boolean;
tobacco?: boolean;
}>;
};
/** 结账:指定承运商子串 */
preferred_carrier?: string;
/** 结账:保障方案 */
coverage?: "basic" | "freight_protect";
/** 结账:FreightProtect 货值 USD */
cargo_value_usd?: number;
}
export type QuoteStatus = "processing" | "done" | "failed" | "expired";
export type SourceType = "rpa" | "cache" | "stale";
export interface QuoteItem {
service_level: ServiceLevel;
rate_option: RateOption;
carrier: string;
transit_days: string;
transit_description: string;
raw_freight: number;
surcharges: number;
raw_total: number;
markup_percent: number;
markup_amount: number;
final_total: number;
breakdown: Array<{ item: string; amount: number }>;
}
export type Priority1QuoteLineDetail = Priority1DisplayLine;
export interface Priority1QuotePayload {
display_mode: "ltl_cards" | "ftl_calendar";
lines: Priority1DisplayLine[];
shipment_meta?: {
shipment_type?: string;
pickup_date?: string;
commodity?: string;
origin_zip?: string;
destination_zip?: string;
weight_lb?: number;
};
}
export interface FlockQuotePayload {
reference?: string | null;
lines: FlockDisplayLine[];
shipment_meta?: {
pickup_date?: string;
origin_zip?: string;
destination_zip?: string;
total_weight_lb?: number;
pallet_count?: number;
};
}
export interface QuoteDetail {
quote_id: string;
request_id: string;
status: QuoteStatus;
valid_until?: string | null;
source_type?: SourceType | null;
is_realtime?: boolean;
confidence_score?: number | null;
currency: string;
quotes?: QuoteItem[];
priority1?: Priority1QuotePayload;
flock?: FlockQuotePayload;
error_code?: string | null;
error_message?: string | null;
/** Flock RPA 执行阶段(processing 时由 Worker 回写) */
rpa_stage?: string | null;
rpa_stage_label?: string | null;
/** MotherShip 登录态:首价后二级刷价 hold */
refine_hold?: {
available: boolean;
quote_session_id: string;
decision_deadline_ms: number;
total_deadline_ms: number;
decision_remaining_ms: number;
total_remaining_ms: number;
} | null;
/** MotherShip 登录态:fill-only 结账进度(脱敏,无 screenshot_path) */
ms_checkout?: {
status: "processing" | "done" | "failed";
stage?: string | null;
selected_carrier?: string | null;
selected_total?: number | null;
coverage?: "basic" | "freight_protect" | null;
cargo_value_usd?: number | null;
message?: string | null;
} | null;
/** Flock 登录态:fill-only 结账进度(脱敏) */
flock_checkout?: {
status: "processing" | "done" | "failed";
stage?: string | null;
preferred_tier?: "flock_direct" | "standard" | null;
selected_total?: number | null;
message?: string | null;
} | null;
/** Flock:选档后三档灵活性价 / 承运商列表 */
flock_pricing_options?: {
status: "processing" | "done" | "failed";
preferred_tier: "flock_direct" | "standard";
options: Array<{
key: "2_day" | "1_day" | "none";
label: string;
rateUsd: number;
pickupWindow?: string;
deliverBy?: string;
}>;
options_type?: "flexibility" | "carriers";
carrier_options?: Array<{
carrierName: string;
transitDays: string;
pickupDate?: string;
deliveryEstimate?: string;
rateUsd: number;
label: string;
}>;
message?: string | null;
} | null;
/** Flock 登录态:首价后二级填写 hold(60s/5min) */
flock_hold?: {
available: boolean;
quote_session_id: string;
decision_deadline_ms: number;
total_deadline_ms: number;
decision_remaining_ms: number;
total_remaining_ms: number;
status?: string;
} | null;
/** 首价同步带回的 Direct/Standard 三档灵活性价 */
flock_flexibility_by_tier?: Partial<
Record<
"flock_direct" | "standard",
Array<{
key: "2_day" | "1_day" | "none";
label: string;
rateUsd: number;
pickupWindow?: string;
deliverBy?: string;
}>
>
> | null;
/** 首价同步带回的 Standard 承运商列表 */
flock_carriers_by_tier?: Partial<
Record<
"flock_direct" | "standard",
Array<{
carrierName: string;
transitDays: string;
pickupDate?: string;
deliveryEstimate?: string;
rateUsd: number;
label: string;
}>
>
> | null;
}
export interface CreateQuoteResult {
quote_id: string;
status: "processing" | "done";
}
/** Priority1 模拟填表提交体 */
export interface Priority1QuoteRequestBody {
request_id: string;
customer_id: string;
business_customer_id?: string;
priority1_input: Record<string, unknown>;
}
/** Flock Freight 查价提交体 */
export interface FlockQuoteRequestBody {
request_id: string;
customer_id: string;
business_customer_id?: string;
flock_input: Record<string, unknown>;
}
export type HostCustomerStatus = "active" | "disabled";
export type ServiceApiKeySummary = {
key_id: string;
key_prefix: string;
is_active: boolean;
permissions: string[];
created_at: string;
};
export type HostCustomerRecord = {
customer_id: string;
name: string;
status: HostCustomerStatus;
remark: string | null;
embed_password_set: boolean;
active_api_key: string | null;
created_at: string;
updated_at: string;
api_keys: ServiceApiKeySummary[];
};
export type CreateHostCustomerResponse = HostCustomerRecord & {
api_key: string;
};
export type MarkupType = "percent" | "fixed";
export interface MarkupConfig {
customer_id: string;
business_customer_id?: string | null;
/** 客户代码 */
business_customer_code?: string | null;
/** 客户名称 */
business_customer_name?: string | null;
markup_type: MarkupType;
markup_percent: number;
markup_fixed_amount: number | null;
operator_id: string;
remark: string | null;
updated_at: string;
}
export type AlertType =
| "PRICE_DEVIATION"
| "STALE_FALLBACK"
| "RPA_FAILED"
| "RPA_CAPTCHA"
| "STRUCT_CHANGE"
| "SESSION_EXPIRED"
| "SECURITY"
| "MANUAL_FALLBACK";
export interface AlertRecord {
id: string;
alert_type: AlertType;
quote_id: string | null;
cargo_hash: string | null;
detail_json: Record<string, unknown> | null;
status: "open" | "resolved";
resolver_id: string | null;
resolved_at: string | null;
created_at: string;
root_cause?: string;
customer_id?: string | null;
pickup_customer?: string;
pickup_selected?: string;
delivery_customer?: string;
delivery_selected?: string;
cargo_summary?: string;
}
export type QuoteQueryOutcome = "processing" | "success" | "failed" | "stale";
export interface QuoteQueryLogQuotePreview {
carrier: string;
service_level: string;
rate_option: string;
final_total: number | null;
}
export interface QuoteQueryLogRecord {
quote_id: string;
request_id: string;
customer_id: string;
business_customer_id?: string | null;
outcome: QuoteQueryOutcome;
failure_reason: string | null;
error_code: string | null;
source_type: string | null;
tier_count: number | null;
pickup_customer: string;
pickup_selected: string;
delivery_customer: string;
delivery_selected: string;
cargo_summary: string;
quotes?: QuoteQueryLogQuotePreview[];
quoted_carrier?: string | null;
quoted_total?: number | null;
created_at: string;
completed_at: string | null;
}
export type BusinessCustomerStatus = "active" | "disabled";
export interface BusinessCustomerRecord {
customer_id: string;
business_customer_id: string;
name: string;
external_code: string | null;
status: BusinessCustomerStatus;
remark: string | null;
user_count?: number;
created_at: string;
updated_at: string;
}
export interface BusinessCustomerUserRecord {
customer_id: string;
business_customer_id: string;
external_user_id: string;
account: string;
display_name: string | null;
email: string | null;
mobile: string | null;
main_external_user_id: string | null;
status: "active" | "inactive";
business_customer_code?: string | null;
business_customer_name?: string;
created_at: string;
updated_at: string;
}
export type ErrorCode =
| "VALIDATION_FAILED"
| "UNAUTHORIZED"
| "FORBIDDEN"
| "QUOTE_NOT_FOUND"
| "RATE_LIMITED"
| "QUOTE_UNAVAILABLE"
| "QUOTE_TIMEOUT"
| "INTERNAL_ERROR";
export interface ApiOk<T> {
code: 0;
message: string;
data: T;
}
export interface ApiErr {
code: ErrorCode | string;
message: string;
data: null;
}
export type ApiResponse<T> = ApiOk<T> | ApiErr;
export interface AdminUser {
user_id: string;
role: "admin";
}
export interface LoginResponse {
token: string;
user: AdminUser;
}
export interface PaginatedResult<T> {
list: T[];
total: number;
page: number;
size: number;
}
export interface MetricsDashboard {
api_success_rate: number;
rpa_success_rate: number;
realtime_rate: number;
cache_hit_rate: number;
p95_latency_ms: number;
queue_depth: number;
open_alerts_count: number;
}
export interface RpaStatus {
workers: Array<{
worker_id: string;
last_seen_ms: number | null;
paused_seconds: number;
online: boolean;
}>;
queue_depth: number;
circuit_open: boolean;
success_rate_24h: number;
}
export interface QueueStats {
queue_name: string;
waiting: number;
active: number;
delayed: number;
failed: number;
completed: number;
depth: number;
}