@jctrans-materials/shared 1.0.41-beta.0 → 1.0.41-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,236 +1,499 @@
1
- # 地理位置搜索 SDK
2
-
3
- SDK 提供了一套统一的地理位置(国家、地区、城市、港口、机场、码头等)搜索与查询能力,支持 axios/fetch 双请求适配器、多语言适配、动态配置管理,可快速集成到各类前端项目中。
4
-
5
- ## 特性
6
-
7
- - 🗺️ 覆盖多类型地理实体:国家/地区、省份、城市、港口、机场、码头等
8
- - 🔌 双请求适配器:支持 Axios / Fetch 两种请求方式
9
- - 🌐 多语言适配:自动识别中英文环境,生成对应展示文本
10
- - ⚙️ 动态配置:支持运行时修改请求地址,适配多环境(开发/测试/生产)
11
- - 📦 类型完备:基于 TypeScript 开发,提供完整的类型定义
12
- - 🚀 事件总线:内置全局模态框事件通信能力
1
+ # @jctrans-materials/shared
2
+
3
+ JCTrans 前端共享工具库,为 JCTrans 系列项目提供认证、请求、加密、地理位置搜索、GrowingIO 埋点等基础能力。
4
+
5
+ ## 功能模块
6
+
7
+ | 模块 | 路径 | 说明 |
8
+ |------|------|------|
9
+ | 配置管理 | `config/` | 运行时动态配置(API 地址、AppId 等) |
10
+ | 地理搜索 V1 | `api/baseSearch` | 旧接口搜索(findPageList),使用 appointSearch 结构 |
11
+ | 地理搜索 V2 | `api/searchV2` | 新接口搜索(getLocationOptions),支持 Carrier/Line |
12
+ | 统一类型 | `api/searchTypes` | 搜索模块共享类型定义 |
13
+ | 认证 API | `api/auth` | 登录、注册、第三方登录、密码找回、Session 管理 |
14
+ | 业务 API | `api/common` + `api/applyData` | 验证码、字典、IP 查询、数据上报 |
15
+ | 请求封装 | `utils/request` | Axios/Fetch 双适配器 + 拦截器 |
16
+ | Token 管理 | `utils/storage` | Cookie 凭证存取(Access Token / Refresh Token) |
17
+ | 加密 | `utils/crypto` | AES 加解密(ECB,与后端对齐) |
18
+ | GrowingIO | `utils/gio` | GIO SDK 封装 + v-gio-track 指令支持 |
19
+ | 域名工具 | `utils/domain` | IP 判断、一级域名提取 |
20
+ | AppId/ProjectId | `utils/app` | 跨环境 AppId 和 ProjectId 获取 |
21
+ | 语言 | `utils/lang` | 当前语言获取 |
22
+ | Header 工具 | `utils/header` | HTTP Header 安全处理 |
23
+ | Modal 事件 | `utils/modal` | 全局模态框事件总线 |
24
+ | ClientId | `utils/clientId` | 客户端唯一标识生成与持久化 |
13
25
 
14
26
  ## 安装
15
27
 
16
- ### npm
17
-
18
28
  ```bash
19
- npm install @jctrans-materials/shared --save
29
+ pnpm add @jctrans-materials/shared
20
30
  ```
21
31
 
22
- ### yarn
32
+ **Peer Dependencies:**
23
33
 
24
- ```bash
25
- yarn add @jctrans-materials/shared
34
+ ```json
35
+ {
36
+ "axios": "1.13.2",
37
+ "gio-webjs-sdk": "^4.0.0"
38
+ }
26
39
  ```
27
40
 
28
- ### pnpm
29
-
30
- ```bash
31
- pnpm add @jctrans-materials/shared
32
- ```
41
+ `axios` 为必须依赖,`gio-webjs-sdk` 为可选依赖(仅使用 GIO 埋点时需要)。
33
42
 
34
43
  ## 快速开始
35
44
 
36
- ### 1. 初始化配置(可选)
45
+ ### 1. 初始化配置
37
46
 
38
- 默认使用测试环境地址,可在项目入口处初始化自定义配置:
47
+ 在项目入口调用 `initSharedConfig`,配置 API 域名和路径:
39
48
 
40
49
  ```typescript
41
- import { initSharedConfig } from "@jctrans-materials/shared";
50
+ import { initSharedConfig, initCommonKeys } from "@jctrans-materials/shared";
42
51
 
43
- // 初始化自定义配置
44
52
  initSharedConfig({
45
- prefixPath: "https://api-production.jctrans.com", // 生产环境域名
46
- searchPath: "/system/dms/fr/aggr/getLocationOptions", // 接口路径
53
+ prefixPath: "https://api-production.jctrans.com",
54
+ searchPath: "/system/dms/fr/aggr/getLocationOptions",
55
+ oldSearchPath: "/system/dms/fr/aggr/findPageList",
56
+ carrierPath: "/system/dms/carrier/findAllList",
57
+ linePath: "/system/dms/fr/line/findAllList",
58
+ allLinePath: "/system/dms/fr/line/findAllListByCountry",
59
+ appId: "YOUR_APP_ID",
60
+ commonKeys: {
61
+ TokenKey: "CUSTOM-TOKEN-KEY", // 可选:自定义 Cookie key
62
+ },
47
63
  });
48
64
  ```
49
65
 
50
- ### 2. 切换请求适配器(可选)
66
+ ### 2. 切换请求适配器
51
67
 
52
- 默认使用 Axios 适配器,可切换为 Fetch:
68
+ 默认使用 Fetch 适配器(浏览器环境自动检测),可手动切换:
53
69
 
54
70
  ```typescript
55
71
  import { createRequest } from "@jctrans-materials/shared";
56
72
 
57
- // 切换为 Fetch 适配器
58
- createRequest("fetch", {
59
- fetch: window.fetch, // 可传入自定义 fetch 实现(如 node-fetch)
60
- });
73
+ // 切换为 Axios
74
+ createRequest("axios");
75
+
76
+ // 切换为 Fetch(可传入自定义实现,如 Nuxt 的 $fetch)
77
+ createRequest("fetch", { fetch: $fetch });
61
78
  ```
62
79
 
63
- ### 3. 基础使用示例
80
+ ### 3. 地理位置搜索
64
81
 
65
- #### 搜索国家
82
+ #### V2 接口(推荐)
66
83
 
67
84
  ```typescript
68
- import { searchCountryByName } from "@jctrans-materials/shared";
85
+ import { locationSearchV2 } from "@jctrans-materials/shared";
69
86
 
70
- // 搜索名称包含"中国"的国家
71
- const result = await searchCountryByName("中国", {
72
- page: 1,
87
+ // 按名称搜索港口
88
+ const ports = await locationSearchV2.seaport.searchByName({
89
+ keyword: "上海",
90
+ countryId: 1,
91
+ current: 1,
73
92
  size: 10,
74
93
  });
75
- console.log(result.records); // 归一化后的国家列表
94
+
95
+ // 按 ID 查询国家
96
+ const countries = await locationSearchV2.country.getByIds([1, 2, 3]);
97
+
98
+ // 获取国家下所有城市
99
+ const cities = await locationSearchV2.city.getCitiesByCountry(1);
100
+
101
+ // 获取城市下的港口/机场
102
+ const children = await locationSearchV2.getChildrenByCity(100, ["Seaport", "Airport"]);
103
+
104
+ // 搜索船公司
105
+ const carriers = await locationSearchV2.carrier.searchShipping({
106
+ keyword: "MAERSK",
107
+ current: 1,
108
+ size: 10,
109
+ });
110
+
111
+ // 搜索航线
112
+ const lines = await locationSearchV2.line.searchShipping({
113
+ keyword: "AE1",
114
+ current: 1,
115
+ size: 10,
116
+ });
117
+
118
+ // 通用按类型+ID查询
119
+ const result = await locationSearchV2.searchByIdWithType(100, "City");
76
120
  ```
77
121
 
78
- #### 按ID查询城市
122
+ #### V1 接口(兼容旧项目)
79
123
 
80
124
  ```typescript
81
- import { getById } from "@jctrans-materials/shared";
82
-
83
- // 查询 ID 为 1001 的城市
125
+ import {
126
+ searchCountryByName,
127
+ searchCityByName,
128
+ searchSeaportByName,
129
+ getById,
130
+ getByIds,
131
+ getCitiesByCountry,
132
+ } from "@jctrans-materials/shared";
133
+
134
+ // 按名称搜索
135
+ const countries = await searchCountryByName("中国");
136
+
137
+ // 按 ID 查询
84
138
  const city = await getById("City", 1001);
85
- console.log(city); // 城市详情
139
+ const ports = await getByIds("Seaport", [100, 200]);
140
+
141
+ // 按国家获取城市
142
+ const cities = await getCitiesByCountry(1);
86
143
  ```
87
144
 
88
- #### 获取指定国家下的所有城市
145
+ ### 4. 认证 API
89
146
 
90
147
  ```typescript
91
- import { getCitiesByCountry } from "@jctrans-materials/shared";
92
-
93
- // 获取国家 ID 为 1 的所有城市
94
- const cities = await getCitiesByCountry(1, {
95
- page: 1,
96
- size: 100,
148
+ import {
149
+ loginApi,
150
+ sendEmailCodeApi,
151
+ loginByFacebookApi,
152
+ autoLoginByTGC,
153
+ resetPasswordApi,
154
+ setAuthSessionItems,
155
+ getAuthSessionItems,
156
+ } from "@jctrans-materials/shared";
157
+
158
+ // 登录
159
+ const res = await loginApi({
160
+ username: "user@example.com",
161
+ password: "encrypted_password",
162
+ appId: "ERA",
163
+ code: "",
164
+ uuid: "",
165
+ kick: false,
166
+ redirectPath: "/dashboard",
167
+ activityCode: "",
168
+ referenceUserId: "",
97
169
  });
98
- console.log(cities.records);
170
+
171
+ // 发送邮箱验证码
172
+ await sendEmailCodeApi({ target: "user@example.com" });
173
+
174
+ // 第三方登录
175
+ const fbResult = await loginByFacebookApi({ /* oauth data */ });
176
+
177
+ // TGC 自动登录
178
+ await autoLoginByTGC({ toSys: "ERA", path: "/", tgc: "tgc_token" });
179
+
180
+ // 密码找回
181
+ await resetPasswordApi({ account: "user@example.com", password: "new_pwd", code: "123456" });
182
+
183
+ // Session 管理
184
+ setAuthSessionItems({ activityCode: "SUMMER2026", path: "/register" });
185
+ const items = getAuthSessionItems();
99
186
  ```
100
187
 
101
- #### 使用 V2 版本接口(推荐)
188
+ ### 5. Token 管理
102
189
 
103
190
  ```typescript
104
- import { locationSearchV2 } from "@jctrans-materials/shared";
105
-
106
- // 搜索港口
107
- const seaports = await locationSearchV2.seaport.searchByName({
108
- keyword: "上海",
109
- countryId: 1,
110
- current: 1,
111
- size: 10,
191
+ import {
192
+ setTokenAll,
193
+ getToken,
194
+ getRefreshToken,
195
+ getExpiresTimeIn,
196
+ clearAllAuth,
197
+ setRememberMe,
198
+ } from "@jctrans-materials/shared";
199
+
200
+ // 登录成功后保存 Token
201
+ setTokenAll({
202
+ accessToken: "eyJhbGci...",
203
+ expireIn: 86400,
204
+ refreshToken: "refresh_token...",
205
+ refreshTokenExpireIn: 2592000,
112
206
  });
113
- console.log(seaports.records);
207
+
208
+ // 读取 Token
209
+ const token = getToken();
210
+
211
+ // 清除所有凭证
212
+ clearAllAuth();
213
+
214
+ // 记住账号(⚠️ 密码会明文存储在 Cookie 中)
215
+ setRememberMe("user@example.com", "password", true);
114
216
  ```
115
217
 
116
- ## 核心 API 文档
218
+ ### 6. 加密
117
219
 
118
- ### 配置管理
220
+ ```typescript
221
+ import { encrypt, decrypt, Encrypt, Decrypt } from "@jctrans-materials/shared";
119
222
 
120
- | 方法 | 说明 | 类型 |
121
- | ------------------ | ---------------------- | -------------------------------------------- |
122
- | `initSharedConfig` | 初始化全局配置 | `(newConfig: Partial<SharedConfig>) => void` |
123
- | `getSharedConfig` | 获取当前配置 | `() => { basePath: string }` |
124
- | `getIsEn` | 判断当前是否为英文环境 | `() => boolean` |
223
+ // camelCase(推荐)
224
+ const encrypted = encrypt("plain_text");
225
+ const decrypted = decrypt(encrypted);
125
226
 
126
- ### 基础搜索(baseSearch)
227
+ // PascalCase(兼容旧代码)
228
+ const enc = Encrypt("plain_text");
229
+ const dec = Decrypt(enc);
230
+ ```
127
231
 
128
- | 方法 | 说明 |
129
- | --------------------- | ---------------------------------- |
130
- | `search` | 通用搜索接口(支持多条件、多类型) |
131
- | `searchByName` | 按名称搜索指定类型地理实体 |
132
- | `getByIds` | 按类型+ID批量查询 |
133
- | `getById` | 按类型+单个ID查询 |
134
- | `getCitiesByCountry` | 获取指定国家下的所有城市 |
135
- | `getChildrenByCity` | 获取指定城市下的港口/机场 |
136
- | `searchCountryByName` | 按名称搜索国家 |
137
- | `searchCityByName` | 按名称搜索城市(支持国家筛选) |
138
- | `searchSeaportByName` | 按名称搜索港口(支持城市筛选) |
139
- | `searchAirportByName` | 按名称搜索机场(支持城市筛选) |
232
+ > ⚠️ 加密使用 AES-ECB 模式,密钥与后端对齐。ECB 模式安全性较低(相同明文产生相同密文),仅用于传输层保护,不可用于高安全场景。
140
233
 
141
- ### V2 版本搜索(searchV2)
234
+ ### 7. GrowingIO 埋点
142
235
 
143
- `locationSearchV2` 提供更语义化的接口封装:
236
+ ```typescript
237
+ import { tracker, normalizeClickPageAttrs, GIO_EVENT_CLICK_PAGE } from "@jctrans-materials/shared";
144
238
 
145
- | 子模块 | 方法 | 说明 |
146
- | --------- | ---------------------------------------------- | -------------------------- |
147
- | `country` | `searchByName`/`getByIds` | 国家搜索/批量查询 |
148
- | `region` | `searchByName`/`getByIds` | 地区搜索/批量查询 |
149
- | `city` | `searchByName`/`getByIds`/`getCitiesByCountry` | 城市搜索/查询/按国家筛选 |
150
- | `seaport` | `searchByName`/`getByIds` | 港口搜索/批量查询 |
151
- | `airport` | `searchByName`/`getByIds` | 机场搜索/批量查询 |
152
- | `wharf` | `getByIds` | 码头批量查询 |
153
- | - | `searchByIdWithType` | 按类型+ID查询任意地理实体 |
154
- | - | `getChildrenByCity` | 获取城市下的港口/机场/码头 |
239
+ // 初始化
240
+ tracker.init("account-id", "datasource-id", {
241
+ debug: true,
242
+ trackPage: true,
243
+ });
155
244
 
156
- ### 请求适配器
245
+ // 设置用户 ID
246
+ tracker.setUserId("user-123");
157
247
 
158
- | 方法 | 说明 |
159
- | --------------- | ---------------------------------- |
160
- | `createRequest` | 创建/切换请求适配器(axios/fetch) |
161
- | `request` | 全局请求实例(get/post方法) |
248
+ // 埋点事件
249
+ tracker.track("order_submit", {
250
+ order_type: "freight",
251
+ price: 5000,
252
+ });
162
253
 
163
- ### 事件总线
254
+ // clickPage 事件(自动补齐必填字段)
255
+ const attrs = normalizeClickPageAttrs(GIO_EVENT_CLICK_PAGE, {
256
+ pageCode_var: "HOME",
257
+ pageClickName_var: "search_btn",
258
+ });
259
+ tracker.track(GIO_EVENT_CLICK_PAGE, attrs);
260
+ ```
164
261
 
165
- 用于全局模态框交互:
262
+ ### 8. Modal 事件总线
166
263
 
167
264
  ```typescript
168
265
  import { emitter, MODAL_ACTION } from "@jctrans-materials/shared";
169
266
 
170
- // 监听模态框打开事件
267
+ // 监听
171
268
  emitter.on(MODAL_ACTION.Open, () => {
172
269
  console.log("模态框已打开");
173
270
  });
174
271
 
175
- // 触发模态框关闭事件
176
- emitter.emit(MODAL_ACTION.Close);
272
+ // 触发
273
+ emitter.emit(MODAL_ACTION.Close, undefined);
274
+ emitter.emit(MODAL_ACTION.Submit, { key: "value" });
177
275
  ```
178
276
 
179
- ## 关键类型定义
277
+ ### 9. 业务 API
278
+
279
+ ```typescript
280
+ import {
281
+ slideGetApi,
282
+ slideCheckApi,
283
+ findDictApi,
284
+ findPAreaCodeApi,
285
+ getLocalIpDataApi,
286
+ getRedirectPathApi,
287
+ reportNewTypeDataApi,
288
+ } from "@jctrans-materials/shared";
289
+
290
+ // 滑动验证码
291
+ const captcha = await slideGetApi({ clientUid: "xxx", ts: Date.now() });
292
+ const verified = await slideCheckApi({ pointJson: "...", uuid: "..." });
293
+
294
+ // 字典查询
295
+ const dict = await findDictApi({ size: -1 });
296
+
297
+ // 区号列表
298
+ const areaCodes = await findPAreaCodeApi({ size: -1 });
299
+
300
+ // 数据上报
301
+ await reportNewTypeDataApi({
302
+ reportData: "report_content",
303
+ reportType: "City",
304
+ });
305
+ ```
180
306
 
181
- ### 地理实体类型
307
+ ## 核心 API 参考
308
+
309
+ ### 配置
310
+
311
+ | 方法 | 说明 | 签名 |
312
+ |------|------|------|
313
+ | `initSharedConfig` | 初始化全局配置 | `(config: Partial<SharedConfig>) => void` |
314
+ | `getSharedConfig` | 获取当前配置 | `() => SharedConfig` |
315
+ | `getIsEn` | 判断当前是否英文环境 | `() => boolean` |
316
+ | `initCommonKeys` | 初始化 Cookie Key 配置 | `(keys: Partial<CommonKeysConfig>) => void` |
317
+
318
+ ### 搜索 V2(locationSearchV2)
319
+
320
+ | 子模块 | 方法 | 说明 |
321
+ |--------|------|------|
322
+ | `country` | `searchByName` / `getByIds` | 国家 |
323
+ | `region` | `searchByName` / `getByIds` | 地区(复用 Country 接口) |
324
+ | `city` | `searchByName` / `getByIds` / `getCitiesByCountry` | 城市 |
325
+ | `province` | `searchByName` / `getByIds` | 省份 |
326
+ | `continent` | `searchByName` / `getByIds` | 大洲 |
327
+ | `seaport` | `searchByName` / `getByIds` | 港口 |
328
+ | `airport` | `searchByName` / `getByIds` | 机场 |
329
+ | `wharf` | `getByIds` | 码头 |
330
+ | `carrier` | `searchShipping` / `searchAir` / `search` / `getByIds` | 船公司/航空公司 |
331
+ | `line` | `searchShipping` / `searchAir` / `search` / `getByIds` / `searchAllByCountry` | 航线 |
332
+ | — | `searchByName` | 通用按名称搜索 |
333
+ | — | `searchByIdWithType` | 按类型+ID查询任意实体 |
334
+ | — | `getCitiesByCountry` | 国家→城市 |
335
+ | — | `getChildrenByCity` | 城市→港口/机场/码头 |
336
+
337
+ ### 搜索 V1(baseSearch)
338
+
339
+ | 方法 | 说明 |
340
+ |------|------|
341
+ | `search` | 通用搜索(支持 keyword + ids + scope) |
342
+ | `searchByName` | 按名称搜索 |
343
+ | `getByIds` / `getById` | 按 ID 查询 |
344
+ | `getCitiesByCountry` | 国家→城市 |
345
+ | `getChildrenByCity` | 城市→港口/机场 |
346
+ | `searchCountryByName` / `searchCityByName` / `searchSeaportByName` / `searchAirportByName` | 按名称快捷搜索 |
347
+ | `getContinent` / `getCountry` / `getCity` / `getProvince` / `getSeaport` / `getAirport` | 按类型获取列表 |
348
+
349
+ ### 认证
350
+
351
+ | 方法 | 说明 |
352
+ |------|------|
353
+ | `loginApi` | 账号密码登录 |
354
+ | `loginByEmailOrMobileCodeApi` | 验证码登录 |
355
+ | `loginByQrCode` / `getLoginQrCode` | 扫码登录 |
356
+ | `autoLoginByTGC` | TGC 单点登录 |
357
+ | `loginByFacebookApi` / `loginByLinkedinApi` | 第三方登录 |
358
+ | `sendEmailCodeApi` / `sendMobileCodeApi` | 发送验证码 |
359
+ | `checkEmailCodeApi` / `checkMobileCodeApi` | 校验验证码 |
360
+ | `validateAccountExistApi` | 校验账号是否存在 |
361
+ | `registerApi` / `validateCompanyApi` | 注册 |
362
+ | `resetPasswordApi` / `checkAccountExistsFPApi` / `getMEVCodeApi` | 密码找回 |
363
+ | `setAuthSessionItems` / `getAuthSessionItems` / `resetAuthSessionItems` | Auth Session 管理 |
364
+ | `setGioSessionItems` / `getGioSessionItems` / `resetGioSessionItems` | GIO Session 管理 |
365
+
366
+ ### Token & Cookie
367
+
368
+ | 方法 | 说明 |
369
+ |------|------|
370
+ | `setTokenAll` | 批量写入所有凭证 |
371
+ | `getToken` / `getRefreshToken` | 读取 Token |
372
+ | `getExpiresTimeIn` | 获取 Token 过期时间戳 |
373
+ | `clearAllAuth` | 清除所有认证 Cookie |
374
+ | `setRememberMe` / `getRememberAccount` | 记住账号 |
375
+
376
+ ### 工具
377
+
378
+ | 方法 | 说明 |
379
+ |------|------|
380
+ | `isEmpty` | 判断值是否为空(支持 string/array/object/Map/Set) |
381
+ | `isIpAddress` / `getFirstDomain` | 域名工具 |
382
+ | `getAppId` / `getProjectId` | 跨环境 ID 获取 |
383
+ | `getLanguage` | 获取当前语言 |
384
+ | `getSessionHeaderValue` / `toSafeHeaderValue` | HTTP Header 安全工具 |
385
+ | `encrypt` / `decrypt` | AES 加解密 |
386
+ | `generateClientId` / `getOrCreateClientId` | 客户端唯一标识 |
387
+
388
+ ## 类型定义
389
+
390
+ ### LocationType / DisplayInfo
182
391
 
183
392
  ```typescript
184
- // baseSearch 支持的类型
185
- type DisplayInfo =
186
- | "Continent"
187
- | "Country"
188
- | "Province"
189
- | "City"
190
- | "Seaport"
191
- | "Airport";
393
+ type LocationType =
394
+ | "Continent" | "Country" | "Region" | "Province"
395
+ | "City" | "Seaport" | "Airport"
396
+ | "Street" | "Town" | "Wharf"
397
+ | "Carrier" | "Line";
192
398
 
193
- // searchV2 支持的类型(扩展)
194
- type LocationType = DisplayInfo | "Region" | "Street" | "Town" | "Wharf";
399
+ type DisplayInfo = LocationType; // 兼容别名
195
400
  ```
196
401
 
197
- ### 归一化实体结构
402
+ ### LocationUnifiedItem / UnifiedItem
198
403
 
199
404
  ```typescript
200
- interface UnifiedItem {
201
- id: number | string; // 实体ID
202
- type: DisplayInfo; // 实体类型
203
- nameCn?: string; // 中文名称
204
- nameEn?: string; // 英文名称
205
- display?: string; // 适配当前语言的展示文本
206
- continent?: Record<string, any>; // 所属大洲
207
- country?: Record<string, any>; // 所属国家
208
- city?: Record<string, any>; // 所属城市
209
- province?: Record<string, any>; // 所属省份
210
- raw?: any; // 原始后端数据
405
+ interface LocationUnifiedItem {
406
+ id: number | string;
407
+ type: LocationType;
408
+ nameCn?: string;
409
+ nameEn?: string;
410
+ display?: string; // 适配当前语言的展示文本
411
+ displayEn?: string; // 英文展示
412
+ displayCn?: string; // 中文展示
413
+ code?: string; // 通用代码(Carrier: scacCode, 机场: iataCode)
414
+ scacCode?: string; // Carrier: SCAC 代码
415
+ iataCode?: string; // Airport: IATA 代码
416
+ carrierCode?: string; // Carrier: 船公司代码
417
+ lineType?: string; // Carrier/Line: air | shipping
418
+ country?: Record<string, any>;
419
+ city?: Record<string, any>;
420
+ province?: Record<string, any>;
421
+ continent?: Record<string, any>;
422
+ raw?: any; // 原始后端数据
211
423
  }
424
+
425
+ type UnifiedItem = LocationUnifiedItem; // 兼容别名
212
426
  ```
213
427
 
214
- ### 请求配置
428
+ ### BaseResponse
215
429
 
216
430
  ```typescript
217
- interface RequestConfig {
218
- params?: Record<string, any>; // URL参数
219
- headers?: Record<string, string>; // 请求头
431
+ interface BaseResponse<T = any> {
432
+ records: T[];
433
+ total: number;
434
+ size: number;
435
+ current: number;
436
+ pages?: number;
220
437
  }
221
438
  ```
222
439
 
223
- ## 注意事项
440
+ ## 架构说明
441
+
442
+ ### 请求拦截器
443
+
444
+ 请求适配器(Axios / Fetch)共享以下拦截器逻辑:
445
+
446
+ - **buildHeaders** — 统一注入 APP-ID、Accept-Language、pageCode、Authorization、popular-channel
447
+ - **handleTokenRefresh** — Access Token 即将过期时(5 分钟内),自动使用 Refresh Token 刷新
448
+ - **handleResponse** — 登录接口自动同步 Token、验证码接口触发 GIO 埋点、401 触发回调
449
+
450
+ ### 多语言判断优先级
451
+
452
+ 1. Nuxt `useCookie("jc-language")`
453
+ 2. 浏览器 Cookie `jc-language`
454
+ 3. Nuxt SSR 请求头中的 Cookie
455
+
456
+ ### 实体展示文本规则
457
+
458
+ | 类型 | 格式 | 示例 |
459
+ |------|------|------|
460
+ | 港口/机场/码头 | `名称 (城市, 国家)` | Shanghai (Shanghai, China) |
461
+ | 城市/省份 | `名称 (国家)` | Shanghai (China) |
462
+ | 国家 | `名称 (大洲)` | China (Asia) |
463
+ | 船公司 | `名称 (代码)` | MAERSK (MAEU) |
464
+ | 航线 | `名称 (国家)` | AE1 (China) |
465
+
466
+ ## 迁移指南
467
+
468
+ ### 从 V1 (baseSearch) 迁移到 V2 (searchV2)
469
+
470
+ V2 是 V1 的超集,所有 V1 函数仍然可用。推荐逐步迁移:
471
+
472
+ ```typescript
473
+ // V1 写法
474
+ import { searchCityByName } from "@jctrans-materials/shared";
475
+ const result = await searchCityByName("上海", { countryId: 1 });
476
+
477
+ // V2 等价写法
478
+ import { locationSearchV2 } from "@jctrans-materials/shared";
479
+ const result = await locationSearchV2.city.searchByName({
480
+ keyword: "上海",
481
+ countryId: 1,
482
+ });
483
+ ```
484
+
485
+ V2 新增能力:Carrier(船公司/航空公司)、Line(航线)、Province、Continent 命名空间。
486
+
487
+ ### crypto 函数名变更
224
488
 
225
- 1. 接口默认分页:`current=1`(页码)、`size=10`(每页条数)
226
- 2. 多语言判断优先级:Nuxt Cookie > 浏览器 Cookie > Nuxt SSR 上下文
227
- 3. 实体展示文本规则:
228
- - 港口/机场:`名称 (城市, 国家)`
229
- - 城市/省份:`名称 (国家)`
230
- - 国家:`名称 (大洲)`
231
- 4. 请求超时时间(Axios):默认 15000ms
232
- 5. 重复数据:SDK 内部会自动根据 `type + id` 去重
489
+ ```typescript
490
+ // 旧写法(仍然可用)
491
+ import { Encrypt, Decrypt } from "@jctrans-materials/shared";
492
+
493
+ // 新写法(推荐)
494
+ import { encrypt, decrypt } from "@jctrans-materials/shared";
495
+ ```
233
496
 
234
497
  ## 许可证
235
498
 
236
- [MIT](根据实际情况修改)
499
+ MIT
package/dist/index.cjs.js CHANGED
Binary file