@jctrans-materials/shared 1.0.41-beta.0 → 1.0.41-beta.10
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 +540 -145
- package/dist/index.cjs.js +0 -0
- package/dist/index.d.ts +456 -601
- package/dist/index.esm.js +0 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,236 +1,631 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
+
| 反查回显 | `api/reverseLookup` | 按英文展示名反查实体详情 |
|
|
16
|
+
| DW-SDK | `dw-sdk/` | 数据仓库 GraphQL SDK 统一入口 |
|
|
17
|
+
| 请求封装 | `utils/request` | Axios/Fetch 双适配器 + 拦截器 |
|
|
18
|
+
| Token 管理 | `utils/storage` | Cookie 凭证存取(Access Token / Refresh Token) |
|
|
19
|
+
| 加密 | `utils/crypto` | AES 加解密(ECB,与后端对齐) |
|
|
20
|
+
| GrowingIO | `utils/gio` | GIO SDK 封装 + v-gio-track 指令支持 |
|
|
21
|
+
| 域名工具 | `utils/domain` | IP 判断、一级域名提取 |
|
|
22
|
+
| AppId/ProjectId | `utils/app` | 跨环境 AppId 和 ProjectId 获取 |
|
|
23
|
+
| 语言 | `utils/lang` | 当前语言获取 |
|
|
24
|
+
| Header 工具 | `utils/header` | HTTP Header 安全处理 |
|
|
25
|
+
| Modal 事件 | `utils/modal` | 全局模态框事件总线 |
|
|
26
|
+
| ClientId | `utils/clientId` | 客户端唯一标识生成与持久化 |
|
|
13
27
|
|
|
14
28
|
## 安装
|
|
15
29
|
|
|
16
|
-
### npm
|
|
17
|
-
|
|
18
30
|
```bash
|
|
19
|
-
|
|
31
|
+
pnpm add @jctrans-materials/shared
|
|
20
32
|
```
|
|
21
33
|
|
|
22
|
-
|
|
34
|
+
**Peer Dependencies:**
|
|
23
35
|
|
|
24
|
-
```
|
|
25
|
-
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"axios": "1.13.2",
|
|
39
|
+
"gio-webjs-sdk": "^4.0.0"
|
|
40
|
+
}
|
|
26
41
|
```
|
|
27
42
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
pnpm add @jctrans-materials/shared
|
|
32
|
-
```
|
|
43
|
+
`axios` 为必须依赖,`gio-webjs-sdk` 为可选依赖(仅使用 GIO 埋点时需要)。
|
|
33
44
|
|
|
34
45
|
## 快速开始
|
|
35
46
|
|
|
36
|
-
### 1.
|
|
47
|
+
### 1. 初始化配置
|
|
37
48
|
|
|
38
|
-
|
|
49
|
+
在项目入口调用 `initSharedConfig`,配置 API 域名和路径:
|
|
39
50
|
|
|
40
51
|
```typescript
|
|
41
|
-
import { initSharedConfig } from "@jctrans-materials/shared";
|
|
52
|
+
import { initSharedConfig, initCommonKeys } from "@jctrans-materials/shared";
|
|
42
53
|
|
|
43
|
-
// 初始化自定义配置
|
|
44
54
|
initSharedConfig({
|
|
45
|
-
prefixPath: "https://api-production.jctrans.com",
|
|
46
|
-
searchPath: "/system/dms/fr/aggr/getLocationOptions",
|
|
55
|
+
prefixPath: "https://api-production.jctrans.com",
|
|
56
|
+
searchPath: "/system/dms/fr/aggr/getLocationOptions",
|
|
57
|
+
oldSearchPath: "/system/dms/fr/aggr/findPageList",
|
|
58
|
+
carrierPath: "/system/dms/carrier/findAllList",
|
|
59
|
+
linePath: "/system/dms/fr/line/findAllList",
|
|
60
|
+
allLinePath: "/system/dms/fr/line/findAllListByCountry",
|
|
61
|
+
appId: "YOUR_APP_ID",
|
|
62
|
+
commonKeys: {
|
|
63
|
+
TokenKey: "CUSTOM-TOKEN-KEY", // 可选:自定义 Cookie key
|
|
64
|
+
},
|
|
47
65
|
});
|
|
48
66
|
```
|
|
49
67
|
|
|
50
|
-
### 2.
|
|
68
|
+
### 2. 切换请求适配器
|
|
51
69
|
|
|
52
|
-
默认使用
|
|
70
|
+
默认使用 Fetch 适配器(浏览器环境自动检测),可手动切换:
|
|
53
71
|
|
|
54
72
|
```typescript
|
|
55
73
|
import { createRequest } from "@jctrans-materials/shared";
|
|
56
74
|
|
|
57
|
-
// 切换为
|
|
58
|
-
createRequest("
|
|
59
|
-
|
|
75
|
+
// 切换为 Axios
|
|
76
|
+
createRequest("axios");
|
|
77
|
+
|
|
78
|
+
// 切换为 Fetch(可传入自定义实现,如 Nuxt 的 $fetch)
|
|
79
|
+
createRequest("fetch", { fetch: $fetch });
|
|
80
|
+
|
|
81
|
+
// 切换为 Custom(小程序等非浏览器环境,完全透传)
|
|
82
|
+
createRequest("custom", {
|
|
83
|
+
baseURL: "https://cloudapi-sit2.jctrans.net.cn",
|
|
84
|
+
fetch: async ({ url, method, data, params, headers }) => {
|
|
85
|
+
// 用户自己的请求实现,header/token/返回值完全由你控制
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
wx.request({
|
|
88
|
+
url,
|
|
89
|
+
method: method as any,
|
|
90
|
+
data,
|
|
91
|
+
header: headers,
|
|
92
|
+
success: (res: any) => resolve(res.data),
|
|
93
|
+
fail: reject,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
},
|
|
60
97
|
});
|
|
61
98
|
```
|
|
62
99
|
|
|
63
|
-
|
|
100
|
+
#### ClientId 插件
|
|
64
101
|
|
|
65
|
-
|
|
102
|
+
自动在所有请求 header 中注入客户端唯一标识(`client-uid`),用于无埋点追踪和用户行为分析。
|
|
66
103
|
|
|
67
104
|
```typescript
|
|
68
|
-
import {
|
|
105
|
+
import {
|
|
106
|
+
installClientIdPlugin,
|
|
107
|
+
installFetchClientIdPlugin,
|
|
108
|
+
getOrCreateClientId,
|
|
109
|
+
createRequest,
|
|
110
|
+
} from "@jctrans-materials/shared";
|
|
111
|
+
|
|
112
|
+
// Axios 环境:直接安装插件
|
|
113
|
+
installClientIdPlugin(axiosInstance, {
|
|
114
|
+
headerName: "client-uid", // 可选,默认 'client-uid'
|
|
115
|
+
});
|
|
69
116
|
|
|
70
|
-
//
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
117
|
+
// Fetch 环境:先创建请求实例再安装
|
|
118
|
+
const request = createRequest("fetch", { fetch: customFetch });
|
|
119
|
+
installFetchClientIdPlugin({
|
|
120
|
+
headerName: "client-uid", // 可选,默认 'client-uid'
|
|
74
121
|
});
|
|
75
|
-
|
|
122
|
+
|
|
123
|
+
// 手动获取 clientId
|
|
124
|
+
const cid = getOrCreateClientId(); // 首次调用自动生成并持久化
|
|
76
125
|
```
|
|
77
126
|
|
|
78
|
-
|
|
127
|
+
> **原理**:使用 `nanoid` 生成,完全 SSR 兼容(无 `window`/`document` 依赖)。ClientId 存储在 `localStorage` 中,跨页面共享。
|
|
128
|
+
|
|
129
|
+
### 3. 地理位置搜索
|
|
130
|
+
|
|
131
|
+
#### V2 接口(推荐)
|
|
79
132
|
|
|
80
133
|
```typescript
|
|
81
|
-
import {
|
|
134
|
+
import { locationSearchV2 } from "@jctrans-materials/shared";
|
|
82
135
|
|
|
83
|
-
//
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
136
|
+
// 按名称搜索港口
|
|
137
|
+
const ports = await locationSearchV2.seaport.searchByName({
|
|
138
|
+
keyword: "上海",
|
|
139
|
+
countryId: 1,
|
|
140
|
+
current: 1,
|
|
141
|
+
size: 10,
|
|
142
|
+
});
|
|
87
143
|
|
|
88
|
-
|
|
144
|
+
// 按 ID 查询国家
|
|
145
|
+
const countries = await locationSearchV2.country.getByIds([1, 2, 3]);
|
|
89
146
|
|
|
90
|
-
|
|
91
|
-
|
|
147
|
+
// 获取国家下所有城市
|
|
148
|
+
const cities = await locationSearchV2.city.getCitiesByCountry(1);
|
|
149
|
+
|
|
150
|
+
// 获取城市下的港口/机场
|
|
151
|
+
const children = await locationSearchV2.getChildrenByCity(100, ["Seaport", "Airport"]);
|
|
152
|
+
|
|
153
|
+
// 搜索船公司
|
|
154
|
+
const carriers = await locationSearchV2.carrier.searchShipping({
|
|
155
|
+
keyword: "MAERSK",
|
|
156
|
+
current: 1,
|
|
157
|
+
size: 10,
|
|
158
|
+
});
|
|
92
159
|
|
|
93
|
-
//
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
160
|
+
// 搜索航线
|
|
161
|
+
const lines = await locationSearchV2.line.searchShipping({
|
|
162
|
+
keyword: "AE1",
|
|
163
|
+
current: 1,
|
|
164
|
+
size: 10,
|
|
97
165
|
});
|
|
98
|
-
|
|
166
|
+
|
|
167
|
+
// 通用按类型+ID查询
|
|
168
|
+
const result = await locationSearchV2.searchByIdWithType(100, "City");
|
|
99
169
|
```
|
|
100
170
|
|
|
101
|
-
####
|
|
171
|
+
#### V1 接口(兼容旧项目)
|
|
102
172
|
|
|
103
173
|
```typescript
|
|
104
|
-
import {
|
|
174
|
+
import {
|
|
175
|
+
searchCountryByName,
|
|
176
|
+
searchCityByName,
|
|
177
|
+
searchSeaportByName,
|
|
178
|
+
getById,
|
|
179
|
+
getByIds,
|
|
180
|
+
getCitiesByCountry,
|
|
181
|
+
} from "@jctrans-materials/shared";
|
|
182
|
+
|
|
183
|
+
// 按名称搜索
|
|
184
|
+
const countries = await searchCountryByName("中国");
|
|
185
|
+
|
|
186
|
+
// 按 ID 查询
|
|
187
|
+
const city = await getById("City", 1001);
|
|
188
|
+
const ports = await getByIds("Seaport", [100, 200]);
|
|
105
189
|
|
|
106
|
-
//
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
190
|
+
// 按国家获取城市
|
|
191
|
+
const cities = await getCitiesByCountry(1);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 4. 认证 API
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import {
|
|
198
|
+
loginApi,
|
|
199
|
+
sendEmailCodeApi,
|
|
200
|
+
loginByFacebookApi,
|
|
201
|
+
autoLoginByTGC,
|
|
202
|
+
resetPasswordApi,
|
|
203
|
+
setAuthSessionItems,
|
|
204
|
+
getAuthSessionItems,
|
|
205
|
+
} from "@jctrans-materials/shared";
|
|
206
|
+
|
|
207
|
+
// 登录
|
|
208
|
+
const res = await loginApi({
|
|
209
|
+
username: "user@example.com",
|
|
210
|
+
password: "encrypted_password",
|
|
211
|
+
appId: "ERA",
|
|
212
|
+
code: "",
|
|
213
|
+
uuid: "",
|
|
214
|
+
kick: false,
|
|
215
|
+
redirectPath: "/dashboard",
|
|
216
|
+
activityCode: "",
|
|
217
|
+
referenceUserId: "",
|
|
112
218
|
});
|
|
113
|
-
|
|
219
|
+
|
|
220
|
+
// 发送邮箱验证码
|
|
221
|
+
await sendEmailCodeApi({ target: "user@example.com" });
|
|
222
|
+
|
|
223
|
+
// 第三方登录
|
|
224
|
+
const fbResult = await loginByFacebookApi({ /* oauth data */ });
|
|
225
|
+
|
|
226
|
+
// TGC 自动登录
|
|
227
|
+
await autoLoginByTGC({ toSys: "ERA", path: "/", tgc: "tgc_token" });
|
|
228
|
+
|
|
229
|
+
// 密码找回
|
|
230
|
+
await resetPasswordApi({ account: "user@example.com", password: "new_pwd", code: "123456" });
|
|
231
|
+
|
|
232
|
+
// Session 管理
|
|
233
|
+
setAuthSessionItems({ activityCode: "SUMMER2026", path: "/register" });
|
|
234
|
+
const items = getAuthSessionItems();
|
|
114
235
|
```
|
|
115
236
|
|
|
116
|
-
|
|
237
|
+
### 5. Token 管理
|
|
117
238
|
|
|
118
|
-
|
|
239
|
+
```typescript
|
|
240
|
+
import {
|
|
241
|
+
setTokenAll,
|
|
242
|
+
getToken,
|
|
243
|
+
getRefreshToken,
|
|
244
|
+
getExpiresTimeIn,
|
|
245
|
+
clearAllAuth,
|
|
246
|
+
setRememberMe,
|
|
247
|
+
} from "@jctrans-materials/shared";
|
|
248
|
+
|
|
249
|
+
// 登录成功后保存 Token
|
|
250
|
+
setTokenAll({
|
|
251
|
+
accessToken: "eyJhbGci...",
|
|
252
|
+
expireIn: 86400,
|
|
253
|
+
refreshToken: "refresh_token...",
|
|
254
|
+
refreshTokenExpireIn: 2592000,
|
|
255
|
+
});
|
|
119
256
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
| `initSharedConfig` | 初始化全局配置 | `(newConfig: Partial<SharedConfig>) => void` |
|
|
123
|
-
| `getSharedConfig` | 获取当前配置 | `() => { basePath: string }` |
|
|
124
|
-
| `getIsEn` | 判断当前是否为英文环境 | `() => boolean` |
|
|
257
|
+
// 读取 Token
|
|
258
|
+
const token = getToken();
|
|
125
259
|
|
|
126
|
-
|
|
260
|
+
// 清除所有凭证
|
|
261
|
+
clearAllAuth();
|
|
127
262
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
| `searchByName` | 按名称搜索指定类型地理实体 |
|
|
132
|
-
| `getByIds` | 按类型+ID批量查询 |
|
|
133
|
-
| `getById` | 按类型+单个ID查询 |
|
|
134
|
-
| `getCitiesByCountry` | 获取指定国家下的所有城市 |
|
|
135
|
-
| `getChildrenByCity` | 获取指定城市下的港口/机场 |
|
|
136
|
-
| `searchCountryByName` | 按名称搜索国家 |
|
|
137
|
-
| `searchCityByName` | 按名称搜索城市(支持国家筛选) |
|
|
138
|
-
| `searchSeaportByName` | 按名称搜索港口(支持城市筛选) |
|
|
139
|
-
| `searchAirportByName` | 按名称搜索机场(支持城市筛选) |
|
|
263
|
+
// 记住账号(⚠️ 密码会明文存储在 Cookie 中)
|
|
264
|
+
setRememberMe("user@example.com", "password", true);
|
|
265
|
+
```
|
|
140
266
|
|
|
141
|
-
###
|
|
267
|
+
### 6. 加密
|
|
142
268
|
|
|
143
|
-
|
|
269
|
+
```typescript
|
|
270
|
+
import { encrypt, decrypt, Encrypt, Decrypt } from "@jctrans-materials/shared";
|
|
144
271
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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` | 获取城市下的港口/机场/码头 |
|
|
272
|
+
// camelCase(推荐)
|
|
273
|
+
const encrypted = encrypt("plain_text");
|
|
274
|
+
const decrypted = decrypt(encrypted);
|
|
155
275
|
|
|
156
|
-
|
|
276
|
+
// PascalCase(兼容旧代码)
|
|
277
|
+
const enc = Encrypt("plain_text");
|
|
278
|
+
const dec = Decrypt(enc);
|
|
279
|
+
```
|
|
157
280
|
|
|
158
|
-
|
|
159
|
-
| --------------- | ---------------------------------- |
|
|
160
|
-
| `createRequest` | 创建/切换请求适配器(axios/fetch) |
|
|
161
|
-
| `request` | 全局请求实例(get/post方法) |
|
|
281
|
+
> ⚠️ 加密使用 AES-ECB 模式,密钥与后端对齐。ECB 模式安全性较低(相同明文产生相同密文),仅用于传输层保护,不可用于高安全场景。
|
|
162
282
|
|
|
163
|
-
###
|
|
283
|
+
### 7. GrowingIO 埋点
|
|
164
284
|
|
|
165
|
-
|
|
285
|
+
```typescript
|
|
286
|
+
import { tracker, normalizeClickPageAttrs, GIO_EVENT_CLICK_PAGE } from "@jctrans-materials/shared";
|
|
287
|
+
|
|
288
|
+
// 初始化
|
|
289
|
+
tracker.init("account-id", "datasource-id", {
|
|
290
|
+
debug: true,
|
|
291
|
+
trackPage: true,
|
|
292
|
+
// 性能采集(默认开启首屏加载监控和错误监控,默认关闭网络监控)
|
|
293
|
+
performance: {
|
|
294
|
+
monitor: true, // 首屏加载监控,默认 true
|
|
295
|
+
exception: true, // 错误监控,默认 true
|
|
296
|
+
network: { // 网络监控,不配置则默认关闭
|
|
297
|
+
exclude: /api\.example\.com/, // 排除指定域名的请求
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// 设置用户 ID
|
|
303
|
+
tracker.setUserId("user-123");
|
|
304
|
+
|
|
305
|
+
// 埋点事件
|
|
306
|
+
tracker.track("order_submit", {
|
|
307
|
+
order_type: "freight",
|
|
308
|
+
price: 5000,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// clickPage 事件(自动补齐必填字段)
|
|
312
|
+
const attrs = normalizeClickPageAttrs(GIO_EVENT_CLICK_PAGE, {
|
|
313
|
+
pageCode_var: "HOME",
|
|
314
|
+
pageClickName_var: "search_btn",
|
|
315
|
+
});
|
|
316
|
+
tracker.track(GIO_EVENT_CLICK_PAGE, attrs);
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### 8. Modal 事件总线
|
|
166
320
|
|
|
167
321
|
```typescript
|
|
168
322
|
import { emitter, MODAL_ACTION } from "@jctrans-materials/shared";
|
|
169
323
|
|
|
170
|
-
//
|
|
324
|
+
// 监听
|
|
171
325
|
emitter.on(MODAL_ACTION.Open, () => {
|
|
172
326
|
console.log("模态框已打开");
|
|
173
327
|
});
|
|
174
328
|
|
|
175
|
-
//
|
|
176
|
-
emitter.emit(MODAL_ACTION.Close);
|
|
329
|
+
// 触发
|
|
330
|
+
emitter.emit(MODAL_ACTION.Close, undefined);
|
|
331
|
+
emitter.emit(MODAL_ACTION.Submit, { key: "value" });
|
|
177
332
|
```
|
|
178
333
|
|
|
179
|
-
|
|
334
|
+
### 9. 业务 API
|
|
180
335
|
|
|
181
|
-
|
|
336
|
+
```typescript
|
|
337
|
+
import {
|
|
338
|
+
slideGetApi,
|
|
339
|
+
slideCheckApi,
|
|
340
|
+
findDictApi,
|
|
341
|
+
findPAreaCodeApi,
|
|
342
|
+
getLocalIpDataApi,
|
|
343
|
+
getRedirectPathApi,
|
|
344
|
+
reportNewTypeDataApi,
|
|
345
|
+
} from "@jctrans-materials/shared";
|
|
346
|
+
|
|
347
|
+
// 滑动验证码
|
|
348
|
+
const captcha = await slideGetApi({ clientUid: "xxx", ts: Date.now() });
|
|
349
|
+
const verified = await slideCheckApi({ pointJson: "...", uuid: "..." });
|
|
350
|
+
|
|
351
|
+
// 字典查询
|
|
352
|
+
const dict = await findDictApi({ size: -1 });
|
|
353
|
+
|
|
354
|
+
// 区号列表
|
|
355
|
+
const areaCodes = await findPAreaCodeApi({ size: -1 });
|
|
356
|
+
|
|
357
|
+
// 数据上报
|
|
358
|
+
await reportNewTypeDataApi({
|
|
359
|
+
reportData: "report_content",
|
|
360
|
+
reportType: "City",
|
|
361
|
+
});
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### 10. 反查回显
|
|
365
|
+
|
|
366
|
+
通过英文展示名(nameEnShow)反查实体详情,用于从外部链接或 URL 参数回显数据。
|
|
182
367
|
|
|
183
368
|
```typescript
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
369
|
+
import {
|
|
370
|
+
getAirportByNameEnShow,
|
|
371
|
+
getCountryByNameEnShow,
|
|
372
|
+
getCityByNameEnShow,
|
|
373
|
+
getSeaportByNameEnShow,
|
|
374
|
+
} from "@jctrans-materials/shared";
|
|
375
|
+
|
|
376
|
+
// 按英文展示名查询机场详情
|
|
377
|
+
const airport = await getAirportByNameEnShow("Shanghai Pudong International Airport");
|
|
192
378
|
|
|
193
|
-
//
|
|
194
|
-
|
|
379
|
+
// 按英文展示名查询国家详情
|
|
380
|
+
const country = await getCountryByNameEnShow("China");
|
|
381
|
+
|
|
382
|
+
// 按英文展示名查询城市详情
|
|
383
|
+
const city = await getCityByNameEnShow("Shanghai");
|
|
384
|
+
|
|
385
|
+
// 按英文展示名查询港口详情
|
|
386
|
+
const seaport = await getSeaportByNameEnShow("Shanghai Port");
|
|
195
387
|
```
|
|
196
388
|
|
|
197
|
-
###
|
|
389
|
+
### 11. DW-SDK(数据仓库 GraphQL SDK)
|
|
390
|
+
|
|
391
|
+
对 `@jctrans/dw-sdk` 的零配置封装,自动注入 baseUrl 和 Authorization Token。
|
|
198
392
|
|
|
199
393
|
```typescript
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
394
|
+
import {
|
|
395
|
+
queryOpportunityBoard,
|
|
396
|
+
GraphQLClientError,
|
|
397
|
+
} from "@jctrans-materials/shared";
|
|
398
|
+
import type {
|
|
399
|
+
OpportunityBoardParams,
|
|
400
|
+
BoardQueryResult,
|
|
401
|
+
DateType,
|
|
402
|
+
} from "@jctrans-materials/shared";
|
|
403
|
+
|
|
404
|
+
// 查询商机有效看板数据
|
|
405
|
+
const result = await queryOpportunityBoard({
|
|
406
|
+
compId: 12345,
|
|
407
|
+
dateType: "QUARTER",
|
|
408
|
+
dateValue: "2026-Q2",
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
if (result.success) {
|
|
412
|
+
console.log(result.data.records);
|
|
413
|
+
} else {
|
|
414
|
+
console.error(result.error);
|
|
211
415
|
}
|
|
212
416
|
```
|
|
213
417
|
|
|
214
|
-
|
|
418
|
+
> **原理**:每次调用内部新建 `createDwSdk()` 实例,调用后即销毁,无状态污染。`baseUrl` 自动从 `initSharedConfig` 的 `prefixPath + '/data'` 拼接。
|
|
419
|
+
|
|
420
|
+
## 核心 API 参考
|
|
421
|
+
|
|
422
|
+
### 配置
|
|
423
|
+
|
|
424
|
+
| 方法 | 说明 | 签名 |
|
|
425
|
+
|------|------|------|
|
|
426
|
+
| `initSharedConfig` | 初始化全局配置 | `(config: Partial<SharedConfig>) => void` |
|
|
427
|
+
| `getSharedConfig` | 获取当前配置 | `() => SharedConfig` |
|
|
428
|
+
| `getIsEn` | 判断当前是否英文环境 | `() => boolean` |
|
|
429
|
+
| `initCommonKeys` | 初始化 Cookie Key 配置 | `(keys: Partial<CommonKeysConfig>) => void` |
|
|
430
|
+
|
|
431
|
+
### 搜索 V2(locationSearchV2)
|
|
432
|
+
|
|
433
|
+
| 子模块 | 方法 | 说明 |
|
|
434
|
+
|--------|------|------|
|
|
435
|
+
| `country` | `searchByName` / `getByIds` | 国家 |
|
|
436
|
+
| `region` | `searchByName` / `getByIds` | 地区(复用 Country 接口) |
|
|
437
|
+
| `city` | `searchByName` / `getByIds` / `getCitiesByCountry` | 城市 |
|
|
438
|
+
| `province` | `searchByName` / `getByIds` | 省份 |
|
|
439
|
+
| `continent` | `searchByName` / `getByIds` | 大洲 |
|
|
440
|
+
| `seaport` | `searchByName` / `getByIds` | 港口 |
|
|
441
|
+
| `airport` | `searchByName` / `getByIds` | 机场 |
|
|
442
|
+
| `wharf` | `getByIds` | 码头 |
|
|
443
|
+
| `carrier` | `searchShipping` / `searchAir` / `search` / `getByIds` | 船公司/航空公司 |
|
|
444
|
+
| `line` | `searchShipping` / `searchAir` / `search` / `getByIds` / `searchAllByCountry` | 航线 |
|
|
445
|
+
| — | `searchByName` | 通用按名称搜索 |
|
|
446
|
+
| — | `searchByIdWithType` | 按类型+ID查询任意实体 |
|
|
447
|
+
| — | `getCitiesByCountry` | 国家→城市 |
|
|
448
|
+
| — | `getChildrenByCity` | 城市→港口/机场/码头 |
|
|
449
|
+
|
|
450
|
+
### 搜索 V1(baseSearch)
|
|
451
|
+
|
|
452
|
+
| 方法 | 说明 |
|
|
453
|
+
|------|------|
|
|
454
|
+
| `search` | 通用搜索(支持 keyword + ids + scope) |
|
|
455
|
+
| `searchByName` | 按名称搜索 |
|
|
456
|
+
| `getByIds` / `getById` | 按 ID 查询 |
|
|
457
|
+
| `getCitiesByCountry` | 国家→城市 |
|
|
458
|
+
| `getChildrenByCity` | 城市→港口/机场 |
|
|
459
|
+
| `searchCountryByName` / `searchCityByName` / `searchSeaportByName` / `searchAirportByName` | 按名称快捷搜索 |
|
|
460
|
+
| `getContinent` / `getCountry` / `getCity` / `getProvince` / `getSeaport` / `getAirport` | 按类型获取列表 |
|
|
461
|
+
|
|
462
|
+
### 认证
|
|
463
|
+
|
|
464
|
+
| 方法 | 说明 |
|
|
465
|
+
|------|------|
|
|
466
|
+
| `loginApi` | 账号密码登录 |
|
|
467
|
+
| `loginByEmailOrMobileCodeApi` | 验证码登录 |
|
|
468
|
+
| `loginByQrCode` / `getLoginQrCode` | 扫码登录 |
|
|
469
|
+
| `autoLoginByTGC` | TGC 单点登录 |
|
|
470
|
+
| `loginByFacebookApi` / `loginByLinkedinApi` | 第三方登录 |
|
|
471
|
+
| `sendEmailCodeApi` / `sendMobileCodeApi` | 发送验证码 |
|
|
472
|
+
| `checkEmailCodeApi` / `checkMobileCodeApi` | 校验验证码 |
|
|
473
|
+
| `validateAccountExistApi` | 校验账号是否存在 |
|
|
474
|
+
| `registerApi` / `validateCompanyApi` | 注册 |
|
|
475
|
+
| `resetPasswordApi` / `checkAccountExistsFPApi` / `getMEVCodeApi` | 密码找回 |
|
|
476
|
+
| `setAuthSessionItems` / `getAuthSessionItems` / `resetAuthSessionItems` | Auth Session 管理 |
|
|
477
|
+
| `setGioSessionItems` / `getGioSessionItems` / `resetGioSessionItems` | GIO Session 管理 |
|
|
478
|
+
|
|
479
|
+
### 反查回显
|
|
480
|
+
|
|
481
|
+
| 方法 | 说明 |
|
|
482
|
+
|------|------|
|
|
483
|
+
| `getAirportByNameEnShow` | 按英文展示名查询机场 |
|
|
484
|
+
| `getCountryByNameEnShow` | 按英文展示名查询国家 |
|
|
485
|
+
| `getCityByNameEnShow` | 按英文展示名查询城市 |
|
|
486
|
+
| `getSeaportByNameEnShow` | 按英文展示名查询港口 |
|
|
487
|
+
|
|
488
|
+
### DW-SDK
|
|
489
|
+
|
|
490
|
+
| 方法 | 说明 |
|
|
491
|
+
|------|------|
|
|
492
|
+
| `queryOpportunityBoard` | 查询商机有效看板(分页) |
|
|
493
|
+
|
|
494
|
+
导出类型:`OpportunityBoardParams`, `BoardQueryResult`, `DateType`, `GraphQLClientError`。
|
|
495
|
+
|
|
496
|
+
### Token & Cookie
|
|
497
|
+
|
|
498
|
+
| 方法 | 说明 |
|
|
499
|
+
|------|------|
|
|
500
|
+
| `setTokenAll` | 批量写入所有凭证 |
|
|
501
|
+
| `getToken` / `getRefreshToken` | 读取 Token |
|
|
502
|
+
| `getExpiresTimeIn` | 获取 Token 过期时间戳 |
|
|
503
|
+
| `clearAllAuth` | 清除所有认证 Cookie |
|
|
504
|
+
| `setRememberMe` / `getRememberAccount` | 记住账号 |
|
|
505
|
+
|
|
506
|
+
### 工具
|
|
507
|
+
|
|
508
|
+
| 方法 | 说明 |
|
|
509
|
+
|------|------|
|
|
510
|
+
| `isEmpty` | 判断值是否为空(null/undefined/空字符串/空数组/空对象/空 Map/空 Set)。数字、布尔值等原始类型返回 `false` |
|
|
511
|
+
| `isIpAddress` / `getFirstDomain` | 域名工具 |
|
|
512
|
+
| `getAppId` / `getProjectId` | 跨环境 ID 获取 |
|
|
513
|
+
| `getLanguage` | 获取当前语言 |
|
|
514
|
+
| `getSessionHeaderValue` / `toSafeHeaderValue` | HTTP Header 安全工具 |
|
|
515
|
+
| `encrypt` / `decrypt` | AES 加解密 |
|
|
516
|
+
| `generateClientId` / `getOrCreateClientId` | 客户端唯一标识 |
|
|
517
|
+
| `installClientIdPlugin` | 为 Axios 实例注入 client-uid header |
|
|
518
|
+
| `installFetchClientIdPlugin` | 为 Fetch 请求注入 client-uid header |
|
|
519
|
+
|
|
520
|
+
## 类型定义
|
|
521
|
+
|
|
522
|
+
### LocationType / DisplayInfo
|
|
215
523
|
|
|
216
524
|
```typescript
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
525
|
+
type LocationType =
|
|
526
|
+
| "Continent" | "Country" | "Region" | "Province"
|
|
527
|
+
| "City" | "Seaport" | "Airport"
|
|
528
|
+
| "Street" | "Town" | "Wharf"
|
|
529
|
+
| "Carrier" | "Line";
|
|
530
|
+
|
|
531
|
+
type DisplayInfo = LocationType; // 兼容别名
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### LocationUnifiedItem / UnifiedItem
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
interface LocationUnifiedItem {
|
|
538
|
+
id: number | string;
|
|
539
|
+
type: LocationType;
|
|
540
|
+
nameCn?: string;
|
|
541
|
+
nameEn?: string;
|
|
542
|
+
display?: string; // 适配当前语言的展示文本
|
|
543
|
+
displayEn?: string; // 英文展示
|
|
544
|
+
displayCn?: string; // 中文展示
|
|
545
|
+
code?: string; // 通用代码(Carrier: scacCode, 机场: iataCode)
|
|
546
|
+
scacCode?: string; // Carrier: SCAC 代码
|
|
547
|
+
iataCode?: string; // Airport: IATA 代码
|
|
548
|
+
carrierCode?: string; // Carrier: 船公司代码
|
|
549
|
+
lineType?: string; // Carrier/Line: air | shipping
|
|
550
|
+
country?: Record<string, any>;
|
|
551
|
+
city?: Record<string, any>;
|
|
552
|
+
province?: Record<string, any>;
|
|
553
|
+
continent?: Record<string, any>;
|
|
554
|
+
raw?: any; // 原始后端数据
|
|
220
555
|
}
|
|
556
|
+
|
|
557
|
+
type UnifiedItem = LocationUnifiedItem; // 兼容别名
|
|
221
558
|
```
|
|
222
559
|
|
|
223
|
-
|
|
560
|
+
### BaseResponse
|
|
224
561
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
562
|
+
```typescript
|
|
563
|
+
interface BaseResponse<T = any> {
|
|
564
|
+
records: T[];
|
|
565
|
+
total: number;
|
|
566
|
+
size: number;
|
|
567
|
+
current: number;
|
|
568
|
+
pages?: number;
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
## 架构说明
|
|
573
|
+
|
|
574
|
+
### 请求拦截器
|
|
575
|
+
|
|
576
|
+
请求适配器(Axios / Fetch)共享以下拦截器逻辑:
|
|
577
|
+
|
|
578
|
+
- **buildHeaders** — 统一注入 APP-ID、Accept-Language、pageCode、Authorization、popular-channel
|
|
579
|
+
- **handleTokenRefresh** — Access Token 即将过期时(5 分钟内),自动使用 Refresh Token 刷新
|
|
580
|
+
- **handleResponse** — 登录接口自动同步 Token、验证码接口触发 GIO 埋点、401 触发回调
|
|
581
|
+
|
|
582
|
+
### 多语言判断优先级
|
|
583
|
+
|
|
584
|
+
1. Nuxt `useCookie("jc-language")`
|
|
585
|
+
2. 浏览器 Cookie `jc-language`
|
|
586
|
+
3. Nuxt SSR 请求头中的 Cookie
|
|
587
|
+
|
|
588
|
+
### 实体展示文本规则
|
|
589
|
+
|
|
590
|
+
| 类型 | 格式 | 示例 |
|
|
591
|
+
|------|------|------|
|
|
592
|
+
| 港口/机场/码头 | `名称 (城市, 国家)` | Shanghai (Shanghai, China) |
|
|
593
|
+
| 城市/省份 | `名称 (国家)` | Shanghai (China) |
|
|
594
|
+
| 国家 | `名称 (大洲)` | China (Asia) |
|
|
595
|
+
| 船公司 | `名称 (代码)` | MAERSK (MAEU) |
|
|
596
|
+
| 航线 | `名称 (国家)` | AE1 (China) |
|
|
597
|
+
|
|
598
|
+
## 迁移指南
|
|
599
|
+
|
|
600
|
+
### 从 V1 (baseSearch) 迁移到 V2 (searchV2)
|
|
601
|
+
|
|
602
|
+
V2 是 V1 的超集,所有 V1 函数仍然可用。推荐逐步迁移:
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
// V1 写法
|
|
606
|
+
import { searchCityByName } from "@jctrans-materials/shared";
|
|
607
|
+
const result = await searchCityByName("上海", { countryId: 1 });
|
|
608
|
+
|
|
609
|
+
// V2 等价写法
|
|
610
|
+
import { locationSearchV2 } from "@jctrans-materials/shared";
|
|
611
|
+
const result = await locationSearchV2.city.searchByName({
|
|
612
|
+
keyword: "上海",
|
|
613
|
+
countryId: 1,
|
|
614
|
+
});
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
V2 新增能力:Carrier(船公司/航空公司)、Line(航线)、Province、Continent 命名空间。
|
|
618
|
+
|
|
619
|
+
### crypto 函数名变更
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
// 旧写法(仍然可用)
|
|
623
|
+
import { Encrypt, Decrypt } from "@jctrans-materials/shared";
|
|
624
|
+
|
|
625
|
+
// 新写法(推荐)
|
|
626
|
+
import { encrypt, decrypt } from "@jctrans-materials/shared";
|
|
627
|
+
```
|
|
233
628
|
|
|
234
629
|
## 许可证
|
|
235
630
|
|
|
236
|
-
|
|
631
|
+
MIT
|