|
|
|
@@ -0,0 +1,155 @@
|
|
|
|
|
export const PRODUCT_NAME = '虫虫出海'
|
|
|
|
|
|
|
|
|
|
const MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER)
|
|
|
|
|
|
|
|
|
|
function quoteUnsafeIntegerTokens(source: string) {
|
|
|
|
|
let output = ''
|
|
|
|
|
let index = 0
|
|
|
|
|
let inString = false
|
|
|
|
|
let escaped = false
|
|
|
|
|
|
|
|
|
|
while (index < source.length) {
|
|
|
|
|
const character = source[index]
|
|
|
|
|
|
|
|
|
|
if (inString) {
|
|
|
|
|
output += character
|
|
|
|
|
if (escaped) escaped = false
|
|
|
|
|
else if (character === '\\') escaped = true
|
|
|
|
|
else if (character === '"') inString = false
|
|
|
|
|
index += 1
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (character === '"') {
|
|
|
|
|
inString = true
|
|
|
|
|
output += character
|
|
|
|
|
index += 1
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (character === '-' || (character >= '0' && character <= '9')) {
|
|
|
|
|
const token = source.slice(index).match(/^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/)?.[0]
|
|
|
|
|
if (token) {
|
|
|
|
|
const isInteger = !token.includes('.') && !/[eE]/.test(token)
|
|
|
|
|
if (isInteger && (BigInt(token) > MAX_SAFE_INTEGER || BigInt(token) < -MAX_SAFE_INTEGER)) output += JSON.stringify(token)
|
|
|
|
|
else output += token
|
|
|
|
|
index += token.length
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
output += character
|
|
|
|
|
index += 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return output
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function parseJsonWithSafeIntegers(source: string) {
|
|
|
|
|
return JSON.parse(quoteUnsafeIntegerTokens(source)) as unknown
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function parseApiJsonResponse(data: unknown) {
|
|
|
|
|
if (typeof data !== 'string') return data
|
|
|
|
|
const trimmed = data.trim()
|
|
|
|
|
if (!trimmed || (!trimmed.startsWith('{') && !trimmed.startsWith('['))) return data
|
|
|
|
|
try {
|
|
|
|
|
return parseJsonWithSafeIntegers(data)
|
|
|
|
|
} catch {
|
|
|
|
|
return data
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type AppCode = 'admin' | 'client'
|
|
|
|
|
|
|
|
|
|
export interface CurrentUser {
|
|
|
|
|
id: string
|
|
|
|
|
name: string
|
|
|
|
|
account: string
|
|
|
|
|
tenantName?: string
|
|
|
|
|
roles: string[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface NavigationItem {
|
|
|
|
|
path: string
|
|
|
|
|
title: string
|
|
|
|
|
permission?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ApiResponse<T> {
|
|
|
|
|
code: number
|
|
|
|
|
message: string
|
|
|
|
|
data: T
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const FIRST_LEG_ORDER_STATUSES = [
|
|
|
|
|
{ code: 'DRAFT', label: '草稿' },
|
|
|
|
|
{ code: 'PENDING_REVIEW', label: '待审核' },
|
|
|
|
|
{ code: 'ACCEPTED', label: '已受理' },
|
|
|
|
|
{ code: 'BOOKED', label: '已订舱' },
|
|
|
|
|
{ code: 'IN_TRANSIT', label: '运输中' },
|
|
|
|
|
{ code: 'COMPLETED', label: '已完成' },
|
|
|
|
|
{ code: 'CANCELLED', label: '已取消' },
|
|
|
|
|
] as const
|
|
|
|
|
|
|
|
|
|
export type FirstLegOrderStatus = (typeof FIRST_LEG_ORDER_STATUSES)[number]['code']
|
|
|
|
|
export type FirstLegOrderStatusLabel = (typeof FIRST_LEG_ORDER_STATUSES)[number]['label']
|
|
|
|
|
|
|
|
|
|
export const FIRST_LEG_TRANSPORT_MODES = [
|
|
|
|
|
{ code: 'FCL', label: '海运整箱 FCL' },
|
|
|
|
|
{ code: 'LCL', label: '海运拼箱 LCL' },
|
|
|
|
|
{ code: 'AIR', label: '空运' },
|
|
|
|
|
{ code: 'ROAD', label: '陆运' },
|
|
|
|
|
] as const
|
|
|
|
|
|
|
|
|
|
export type FirstLegTransportMode = (typeof FIRST_LEG_TRANSPORT_MODES)[number]['code']
|
|
|
|
|
export type FirstLegTransportModeLabel = (typeof FIRST_LEG_TRANSPORT_MODES)[number]['label']
|
|
|
|
|
|
|
|
|
|
export type PlatformWarehouseStatus = 'ACTIVE' | 'INACTIVE'
|
|
|
|
|
|
|
|
|
|
export interface PlatformReceivingWarehouse {
|
|
|
|
|
id: string
|
|
|
|
|
code: string
|
|
|
|
|
name: string
|
|
|
|
|
province: string
|
|
|
|
|
city: string
|
|
|
|
|
address: string
|
|
|
|
|
contactName: string
|
|
|
|
|
contactPhone: string
|
|
|
|
|
businessHours: string
|
|
|
|
|
status: PlatformWarehouseStatus
|
|
|
|
|
remark: string
|
|
|
|
|
updatedAt: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PlatformReceivingWarehouseSnapshot {
|
|
|
|
|
id: string
|
|
|
|
|
code: string
|
|
|
|
|
name: string
|
|
|
|
|
province: string
|
|
|
|
|
city: string
|
|
|
|
|
address: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function createPlatformReceivingWarehouseSnapshot(
|
|
|
|
|
warehouse: PlatformReceivingWarehouse,
|
|
|
|
|
): PlatformReceivingWarehouseSnapshot {
|
|
|
|
|
return {
|
|
|
|
|
id: warehouse.id,
|
|
|
|
|
code: warehouse.code,
|
|
|
|
|
name: warehouse.name,
|
|
|
|
|
province: warehouse.province,
|
|
|
|
|
city: warehouse.city,
|
|
|
|
|
address: warehouse.address,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// API 接入前供 Admin 与 Client 静态原型共用,不能作为服务端真实仓库数据。
|
|
|
|
|
export const DEMO_PLATFORM_RECEIVING_WAREHOUSES: readonly PlatformReceivingWarehouse[] = [
|
|
|
|
|
{ id: 'WH001', code: 'CN-YW-01', name: '义乌仓', province: '浙江省', city: '义乌市', address: '北苑街道演示物流园 1 号库', contactName: '仓库客服', contactPhone: '0579-****001', businessHours: '周一至周六 08:30-18:00', status: 'ACTIVE', remark: '支持普通货物收货。', updatedAt: '2026-07-28 10:20' },
|
|
|
|
|
{ id: 'WH002', code: 'CN-SZ-01', name: '深圳仓', province: '广东省', city: '深圳市', address: '盐田区演示物流园 2 号库', contactName: '仓库客服', contactPhone: '0755-****002', businessHours: '周一至周六 08:30-18:00', status: 'ACTIVE', remark: '华南区域主要收货仓。', updatedAt: '2026-07-28 10:20' },
|
|
|
|
|
{ id: 'WH003', code: 'CN-QD-01', name: '青岛仓', province: '山东省', city: '青岛市', address: '黄岛区演示物流园 3 号库', contactName: '仓库客服', contactPhone: '0532-****003', businessHours: '周一至周五 09:00-17:30', status: 'ACTIVE', remark: '', updatedAt: '2026-07-28 10:20' },
|
|
|
|
|
{ id: 'WH004', code: 'CN-SH-01', name: '上海仓', province: '上海市', city: '上海市', address: '浦东新区演示物流园 4 号库', contactName: '仓库客服', contactPhone: '021-****004', businessHours: '周一至周六 08:30-18:00', status: 'ACTIVE', remark: '华东区域综合收货仓。', updatedAt: '2026-07-28 10:20' },
|
|
|
|
|
{ id: 'WH005', code: 'CN-NB-01', name: '宁波仓', province: '浙江省', city: '宁波市', address: '北仑区演示物流园 5 号库', contactName: '仓库客服', contactPhone: '0574-****005', businessHours: '周一至周六 08:30-18:00', status: 'ACTIVE', remark: '临近宁波港。', updatedAt: '2026-07-28 10:20' },
|
|
|
|
|
{ id: 'WH006', code: 'CN-XM-01', name: '厦门仓', province: '福建省', city: '厦门市', address: '湖里区演示物流园 6 号库', contactName: '仓库客服', contactPhone: '0592-****006', businessHours: '周一至周五 09:00-17:30', status: 'INACTIVE', remark: '静态演示:暂停接收新订单。', updatedAt: '2026-07-28 10:20' },
|
|
|
|
|
]
|