chore: vendor shared package for standalone build
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
"preview": "vite preview --port 4173"
|
"preview": "vite preview --port 4173"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chongchong/shared": "link:../../packages/shared",
|
"@chongchong/shared": "link:./shared",
|
||||||
"@lucide/vue": "^1.27.0",
|
"@lucide/vue": "^1.27.0",
|
||||||
"axios": "^1.18.1",
|
"axios": "^1.18.1",
|
||||||
"element-plus": "^2.14.3",
|
"element-plus": "^2.14.3",
|
||||||
|
|||||||
Generated
+2
-2
@@ -9,8 +9,8 @@ importers:
|
|||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@chongchong/shared':
|
'@chongchong/shared':
|
||||||
specifier: link:../../packages/shared
|
specifier: link:./shared
|
||||||
version: link:../../packages/shared
|
version: link:./shared
|
||||||
'@lucide/vue':
|
'@lucide/vue':
|
||||||
specifier: ^1.27.0
|
specifier: ^1.27.0
|
||||||
version: 1.27.0(vue@3.5.40(typescript@5.9.3))
|
version: 1.27.0(vue@3.5.40(typescript@5.9.3))
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Shared Package Instructions
|
||||||
|
|
||||||
|
## 项目定位
|
||||||
|
|
||||||
|
- 本包提供跨应用共享的 TypeScript 类型、常量、轻量工具和可复用资源。
|
||||||
|
- 当前公共能力包括产品名称、用户模型、导航模型、API 响应模型和头程订单状态常量。
|
||||||
|
- 只有具有明确跨项目语义,或已经被两个或以上项目稳定复用的能力才进入本包;单一应用的页面状态、UI 组件和临时业务逻辑留在对应项目。尚无消费者的契约型导出必须标记为暂定,并有对应 API 或产品决策依据。
|
||||||
|
|
||||||
|
## 公共 API 与依赖边界
|
||||||
|
|
||||||
|
- `src/index.ts` 是当前唯一公共入口。新增导出应有清晰命名和稳定语义,不让消费者依赖未导出的内部实现。
|
||||||
|
- 公共类型保持平台无关,不依赖 DOM、Vue、微信、uni-app 或 Node 专属运行时,除非任务明确改变本包定位。
|
||||||
|
- 不在共享类型中编码客户端鉴权结论;租户隔离、权限和数据合法性仍由 `services/api` 最终校验。
|
||||||
|
- 避免以“复用”为由建立宽泛的万能类型。优先使用小而明确的模型,并区分请求、响应、领域状态和展示模型。
|
||||||
|
- 新增依赖前先确认原生 TypeScript 能力或现有依赖无法满足需求;本包不应成为所有应用依赖的重量级入口。
|
||||||
|
|
||||||
|
## 兼容性与变更原则
|
||||||
|
|
||||||
|
- 修改导出名称、字段类型、枚举值或常量语义前,搜索所有消费者并评估兼容性。
|
||||||
|
- 优先采用向后兼容的新增;删除或破坏性修改必须同步更新全部消费者,并在交付说明中明确迁移影响。
|
||||||
|
- API 契约文档是服务端落地后的唯一权威来源;共享包只映射经确认的客户端模型,不反向定义服务端行为。API 尚未落地前,`ApiResponse` 和订单状态等无消费者导出视为暂定,不得当作已发布契约。
|
||||||
|
- 状态码、权限码和业务常量应有唯一来源,不在多个应用中复制维护相同列表。
|
||||||
|
|
||||||
|
## 质量门禁
|
||||||
|
|
||||||
|
- 当前包未声明独立的安装、测试、类型检查或构建脚本,不得声称这些检查已在本包内通过。
|
||||||
|
- 变更公共导出后,至少运行现有消费者的类型检查;当前直接消费者包括 `apps/admin-web` 和 `apps/client-web`。
|
||||||
|
- 若新增本包自己的质量脚本,应同步更新 `package.json`、`README.md` 和本文件,并为公共工具及兼容性边界增加测试。
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# 共享模块
|
||||||
|
|
||||||
|
用于存放跨应用共享的类型定义、常量、工具和可复用资源。
|
||||||
|
|
||||||
|
当前已提供产品名称、用户模型、导航模型、API 响应模型,以及经一期产品决策确认的头程订单状态与运输方式常量。
|
||||||
|
|
||||||
|
当前还提供平台收货仓模型、订单仓库快照模型和供 Admin、Client 静态原型共用的演示仓库数据。订单仓库快照在下单时复制仓库 ID、编码、名称及国内地址,避免仓库主数据后续改名或停用影响历史订单展示;真实仓库列表、状态、下单可用性和快照持久化最终由服务端 API 保证。
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "@chongchong/shared",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
".": "./src/index.ts"
|
||||||
|
},
|
||||||
|
"types": "./src/index.ts"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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' },
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user