@flatbiz/device 2.0.3 → 2.0.5
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 +132 -69
- package/dist/constant.d.ts +15 -0
- package/dist/constant.js +29 -0
- package/dist/helpers/helper-event-id.d.ts +11 -0
- package/dist/helpers/helper-event-id.js +64 -0
- package/dist/helpers/helper-report-device-info.d.ts +9 -0
- package/dist/helpers/helper-report-device-info.js +76 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +28 -0
- package/dist/types/types-device.d.ts +6 -0
- package/dist/types/types-options.d.ts +99 -0
- package/dist/types/types-options.js +45 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,103 +1,166 @@
|
|
|
1
|
-
|
|
1
|
+
# @flatbiz/device
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
H5 设备信息 SDK,提供两个核心能力:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
| API | 作用 | 返回值 |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| `deviceInfo` | 采集设备指纹与 UA 信息 | `Promise<FlatbizDevice>` |
|
|
8
|
+
| `reportDeviceInfo` | 采集后上报业务接口 | `Promise<boolean>` |
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
- **移除 `utils` 模块**:`getDeviceId` 统一从 `helper-get-deviceId` 导出,不再通过 `src/utils.ts`
|
|
10
|
+
> 仅支持浏览器环境。非浏览器调用时:`deviceInfo` 返回 `{}`,`reportDeviceInfo` 返回 `false`。
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
---
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
- **`ip`**:传入服务端下发的 IP,优先于自动获取
|
|
14
|
-
- **`autoGetIp`**:为 `true` 时通过 `https://api.ipify.org?format=json` 拉取公网 IP(默认 `false`)
|
|
15
|
-
- **`isDebug`**:为 `true` 时在控制台输出非浏览器环境或解析失败等错误信息(默认 `false`)
|
|
16
|
-
- 新增返回字段 **`ip`**、**`screenSize`**(格式 `{width}x{height}`,如 `390x844`)
|
|
17
|
-
- 非浏览器环境(`typeof window === 'undefined'`)安全返回 `{}`,避免 SSR/Node 直接调用抛错
|
|
18
|
-
- 新增 helpers:`getIp`、`getWindowSize`;`getDeviceId` 独立为 `helper-get-deviceId`
|
|
19
|
-
- **`deviceId` 持久化**:基于 `js-cookie` 写入可跨子域共享的 cookie,并与 localStorage 双向同步
|
|
20
|
-
- 开发体验:补充 Vitest 单元测试(含 jsdom 主域/子域 cookie 共享用例);`yarn demo`(Vite)可本地预览 `public/index.html`
|
|
14
|
+
## 安装
|
|
21
15
|
|
|
22
|
-
|
|
16
|
+
```bash
|
|
17
|
+
yarn add @flatbiz/device
|
|
18
|
+
# 或
|
|
19
|
+
npm i @flatbiz/device
|
|
20
|
+
```
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
---
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
- `screenWidth`、`screenHeight`、`screenSize`、`screenDensity`
|
|
28
|
-
- `networkType`、`timezone`、`timezoneOffset`、`systemDate`、`systemTime`
|
|
29
|
-
- `colorDepth`、`touchSupport`、`plugins`、`pluginNum`、`cookiesEnable`
|
|
24
|
+
## 1. `deviceInfo` — 采集设备信息
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
异步采集 H5 终端信息与 UA 解析结果,并持久化 `deviceId`(Cookie + localStorage,支持主域/子域共享)。
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
- `engineName`、`engineVersion`
|
|
35
|
-
- `osName`、`osVersion`、`cpuModel`
|
|
36
|
-
- `deviceType`、`deviceVendor`、`deviceModel`
|
|
28
|
+
### 快速接入
|
|
37
29
|
|
|
38
|
-
|
|
30
|
+
```ts
|
|
31
|
+
import { deviceInfo } from '@flatbiz/device';
|
|
39
32
|
|
|
40
|
-
|
|
33
|
+
// 最简用法
|
|
34
|
+
const info = await deviceInfo();
|
|
41
35
|
|
|
42
|
-
|
|
36
|
+
// 推荐:由服务端下发 IP
|
|
37
|
+
const info2 = await deviceInfo({ ip: '203.0.113.1' });
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
| Cookie | `flatbiz_device_ftbzdid` | 优先读取;用于跨子域共享 |
|
|
47
|
-
| localStorage | `flatbiz_device_ftbzdid` | Cookie 缺失时的回退;Cookie 有值时会被覆盖 |
|
|
39
|
+
// 自动拉取公网 IP
|
|
40
|
+
const info3 = await deviceInfo({ autoGetIp: true });
|
|
48
41
|
|
|
49
|
-
|
|
42
|
+
// 调试模式(失败时打印日志)
|
|
43
|
+
const info4 = await deviceInfo({ isDebug: true });
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
3. **都没有**:生成新 ID(16 位类 UUID),同时写入 Cookie 与 localStorage
|
|
45
|
+
console.log(info.deviceId, info.screenSize, info.browserName);
|
|
46
|
+
```
|
|
54
47
|
|
|
55
|
-
|
|
48
|
+
### 入参 `DeviceInfoOptions`
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
全部可选。
|
|
58
51
|
|
|
59
|
-
|
|
|
60
|
-
| --- | --- | --- |
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `domain` | 见下 | 主域与子域共享 |
|
|
52
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
53
|
+
| --- | --- | --- | --- |
|
|
54
|
+
| `ip` | `string` | - | 自定义 IP,优先于自动获取(推荐服务端下发) |
|
|
55
|
+
| `autoGetIp` | `boolean` | `false` | 为 `true` 时请求 `https://api.ipify.org?format=json` 获取公网 IP |
|
|
56
|
+
| `isDebug` | `boolean` | `false` | 为 `true` 时在控制台输出错误信息 |
|
|
65
57
|
|
|
66
|
-
|
|
58
|
+
### 出参 `FlatbizDevice`
|
|
67
59
|
|
|
68
|
-
|
|
60
|
+
返回值为 `Partial<FlatbizDeviceInfo> & Partial<FlatbizUaParserResult>`。异常或非浏览器环境返回 `{}`。
|
|
69
61
|
|
|
70
|
-
|
|
71
|
-
- `www.example.com` → `domain=.example.com`
|
|
72
|
-
- `api.example.com` → `domain=.example.com`
|
|
62
|
+
#### 终端字段(`FlatbizDeviceInfo`)
|
|
73
63
|
|
|
74
|
-
|
|
64
|
+
| 字段 | 类型 | 说明 |
|
|
65
|
+
| --- | --- | --- |
|
|
66
|
+
| `ip` | `string` | IP 地址 |
|
|
67
|
+
| `deviceId` | `string` | 设备 ID(持久化,见下文) |
|
|
68
|
+
| `language` | `string` | 系统语言,如 `zh-CN` |
|
|
69
|
+
| `screenWidth` | `number` | 屏幕宽度(px) |
|
|
70
|
+
| `screenHeight` | `number` | 屏幕高度(px) |
|
|
71
|
+
| `screenSize` | `string` | 分辨率,如 `390x844` |
|
|
72
|
+
| `screenDensity` | `number` | 像素密度,如 `2` |
|
|
73
|
+
| `networkType` | `string` | 网络类型,如 `wifi` / `4g` |
|
|
74
|
+
| `timezone` | `string` | 时区,如 `Asia/Shanghai` |
|
|
75
|
+
| `timezoneOffset` | `number` | 时区偏移(分钟) |
|
|
76
|
+
| `systemDate` | `string` | 系统日期 |
|
|
77
|
+
| `systemTime` | `string` | 系统时间 |
|
|
78
|
+
| `colorDepth` | `number` | 颜色深度 |
|
|
79
|
+
| `touchSupport` | `string[]` | 触摸支持信息 |
|
|
80
|
+
| `plugins` | `string[]` | 浏览器插件列表 |
|
|
81
|
+
| `pluginNum` | `number` | 插件数量 |
|
|
82
|
+
| `cookiesEnable` | `boolean` | 是否启用 Cookie |
|
|
83
|
+
| `eventId` | `string` | 事件 ID;仅 `reportDeviceInfo` 生成/重置并缓存,`deviceInfo` 读取当前值(未上报过时可能为空) |
|
|
84
|
+
|
|
85
|
+
#### UA 字段(`FlatbizUaParserResult`)
|
|
86
|
+
|
|
87
|
+
| 字段 | 类型 | 说明 |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| `userAgent` | `string` | 完整 UA |
|
|
90
|
+
| `browserName` | `string` | 浏览器名称 |
|
|
91
|
+
| `browserVersion` | `string` | 浏览器版本 |
|
|
92
|
+
| `engineName` | `string` | 内核名称 |
|
|
93
|
+
| `engineVersion` | `string` | 内核版本 |
|
|
94
|
+
| `osName` | `string` | 操作系统名称 |
|
|
95
|
+
| `osVersion` | `string` | 操作系统版本 |
|
|
96
|
+
| `cpuModel` | `string` | CPU 架构/型号 |
|
|
97
|
+
| `deviceType` | `string` | UA 设备类型,如 `mobile` |
|
|
98
|
+
| `deviceVendor` | `string` | 厂商 |
|
|
99
|
+
| `deviceModel` | `string` | 型号 |
|
|
75
100
|
|
|
76
|
-
|
|
101
|
+
### `deviceId` 说明(简要)
|
|
77
102
|
|
|
78
|
-
- `
|
|
79
|
-
-
|
|
80
|
-
-
|
|
103
|
+
- **存储**:Cookie / localStorage,Key 均为 `flatbiz_device_ftbzdid`
|
|
104
|
+
- **优先级**:Cookie > localStorage > 新生成(生成后同时写入两者)
|
|
105
|
+
- **跨子域**:Cookie 设置 `domain=.注册域`(如 `.example.com`);`localhost` / IP 不设 domain
|
|
106
|
+
- **有效期**:Cookie 约 1 天;过期后若 localStorage 仍有值会回写,**ID 不变**
|
|
81
107
|
|
|
82
|
-
|
|
108
|
+
---
|
|
83
109
|
|
|
84
|
-
|
|
85
|
-
- Cookie 约 24 小时过期后,若 localStorage 仍有值,会按优先级回写新 Cookie,**ID 保持不变**
|
|
110
|
+
## 2. `reportDeviceInfo` — 上报设备信息
|
|
86
111
|
|
|
87
|
-
|
|
112
|
+
内部先重置并缓存 `eventId`,再调用 `deviceInfo()`,按 `isProd` 选择上报地址 `POST`,将设备指纹(含 `eventId`)与业务埋点一并上报。
|
|
113
|
+
|
|
114
|
+
### 快速接入
|
|
88
115
|
|
|
89
116
|
```ts
|
|
90
|
-
import {
|
|
117
|
+
import {
|
|
118
|
+
reportDeviceInfo,
|
|
119
|
+
ReportDeviceType,
|
|
120
|
+
ReportRegionType,
|
|
121
|
+
ReportUserSys,
|
|
122
|
+
} from '@flatbiz/device';
|
|
123
|
+
|
|
124
|
+
await reportDeviceInfo({
|
|
125
|
+
// 由业务侧注入
|
|
126
|
+
signature: '联系负责人获取',
|
|
127
|
+
pageName: 'publicCashier',
|
|
128
|
+
orderNum: 'O20260903001',
|
|
129
|
+
regionType: ReportRegionType.Overseas,
|
|
130
|
+
deviceType: ReportDeviceType.H5,
|
|
131
|
+
userId: 'u1',
|
|
132
|
+
userSys: ReportUserSys.HopeGoo,
|
|
133
|
+
});
|
|
91
134
|
|
|
92
|
-
|
|
93
|
-
const info = await deviceInfo({ ip: '203.0.113.1' });
|
|
135
|
+
```
|
|
94
136
|
|
|
95
|
-
|
|
96
|
-
const info2 = await deviceInfo({ autoGetIp: true });
|
|
137
|
+
### 入参 `ReportDeviceInfoOptions`
|
|
97
138
|
|
|
98
|
-
|
|
99
|
-
|
|
139
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
140
|
+
| --- | --- | --- | --- | --- |
|
|
141
|
+
| `signature` | `string` | 是 | - | 鉴权签名,写入 `X-signature`;为空会 `console.error`(不会写入上报 body) |
|
|
142
|
+
| `pageName` | `ReportPageName` | 是 | - | 采集页面,见枚举表 |
|
|
143
|
+
| `orderNum` | `string` | 是 | - | 项目订单号;|
|
|
144
|
+
| `regionType` | `ReportRegionType` | 是 | - | 区域类型,见枚举表 |
|
|
145
|
+
| `deviceType` | `ReportDeviceType` | 是 | - | 业务侧设备类型,见枚举表 |
|
|
146
|
+
| `userId` | `string` | 否 | - | 用户 ID |
|
|
147
|
+
| `userSys` | `ReportUserSys` | 否 | - | 会员体系,见枚举表 |
|
|
148
|
+
| `eventType` | `string` | 否 | `'pageLoad'` | `pageLoad` / `click` / 自定义 |
|
|
149
|
+
| `isProd` | `boolean` | 否 | `true` | 是否生产环境;决定上报 URL |
|
|
150
|
+
| `isDebug` | `boolean` | 否 | `false` | 失败时打印日志(不会写入上报 body) |
|
|
151
|
+
|
|
152
|
+
#### 枚举
|
|
153
|
+
|
|
154
|
+
| 枚举 | 成员 | 值 | 说明 |
|
|
155
|
+
| --- | --- | --- | --- |
|
|
156
|
+
| `ReportPageName` | `'detail'` / `'order'` / `'publicCashier'` / `'nativeCashier'` | 同左 | 详情 / 创单 / 公共收银台 / 原生收银台 |
|
|
157
|
+
| `ReportUserSys` | `Tongcheng` / `HopeGoo` / `Tabigo` | `'01'` / `'02'` / `'03'` | 同程 / HopeGoo / Tabigo |
|
|
158
|
+
| `ReportRegionType` | `Domestic` / `Overseas` | `'01'` / `'02'` | 国内 / 国外 |
|
|
159
|
+
| `ReportDeviceType` | `PC` / `H5` / `HopeGooApp` / `TabigoApp` | `'1'` / `'3'` / `'4'` / `'5'` | PC / H5 / HopeGoo APP / Tabigo APP |
|
|
160
|
+
|
|
161
|
+
### 出参
|
|
162
|
+
|
|
163
|
+
| 类型 | 说明 |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| `Promise<boolean>` | `true` 上报成功;`false` 失败(网络/HTTP/业务 code/非浏览器等) |
|
|
100
166
|
|
|
101
|
-
// deviceId 已持久化在 cookie / localStorage
|
|
102
|
-
console.log(info.deviceId);
|
|
103
|
-
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** 生产 / 非生产环境设备信息上报地址 */
|
|
2
|
+
export declare const REPORT_DEVICE_INFO_URLS: {
|
|
3
|
+
readonly prod: "https://rcsapi.tcshuke.com/device/collect";
|
|
4
|
+
readonly test: "https://rcsapi.qa.tcshuke.com/device/collect";
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* 组装上报鉴权请求头
|
|
8
|
+
* @param signature 业务侧传入的签名,写入 `X-signature`(勿把密钥写进 npm 包)
|
|
9
|
+
*/
|
|
10
|
+
export declare const getAuthHeaders: (signature?: string) => Record<string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* 获取设备信息上报地址
|
|
13
|
+
* @param isProd 是否生产环境,默认 true
|
|
14
|
+
*/
|
|
15
|
+
export declare const getReportDeviceInfoUrl: (isProd?: boolean) => string;
|
package/dist/constant.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** 生产 / 非生产环境设备信息上报地址 */
|
|
2
|
+
export const REPORT_DEVICE_INFO_URLS = {
|
|
3
|
+
prod: 'https://rcsapi.tcshuke.com/device/collect',
|
|
4
|
+
test: 'https://rcsapi.qa.tcshuke.com/device/collect',
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* 组装上报鉴权请求头
|
|
8
|
+
* @param signature 业务侧传入的签名,写入 `X-signature`(勿把密钥写进 npm 包)
|
|
9
|
+
*/
|
|
10
|
+
export const getAuthHeaders = (signature) => {
|
|
11
|
+
const timestamp = Date.now().toString();
|
|
12
|
+
const requestId = Math.random().toString(36).substring(2, 15);
|
|
13
|
+
if (!signature) {
|
|
14
|
+
console.error('[@flatbiz/device] signature 不能为空,请通过 reportDeviceInfo({ signature }) 传入');
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
'X-app-id': 'cashier',
|
|
18
|
+
'X-requestId': `${requestId}-${timestamp}`,
|
|
19
|
+
'X-timestamp': timestamp,
|
|
20
|
+
'X-signature': signature ?? '',
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* 获取设备信息上报地址
|
|
25
|
+
* @param isProd 是否生产环境,默认 true
|
|
26
|
+
*/
|
|
27
|
+
export const getReportDeviceInfoUrl = (isProd = true) => {
|
|
28
|
+
return isProd ? REPORT_DEVICE_INFO_URLS.prod : REPORT_DEVICE_INFO_URLS.test;
|
|
29
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 读取当前 eventId(不会新建)
|
|
3
|
+
* 仅由 reportDeviceInfo 调用 resetEventId 时生成/重置
|
|
4
|
+
*/
|
|
5
|
+
export declare const getEventId: () => string | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* 生成并缓存新的 eventId(仅应在 reportDeviceInfo 中调用)
|
|
8
|
+
*/
|
|
9
|
+
export declare const resetEventId: () => string;
|
|
10
|
+
/** 测试或内部清理用 */
|
|
11
|
+
export declare const clearEventId: () => void;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const STORAGE_KEY = 'flatbiz_device_eventId';
|
|
2
|
+
let memoryEventId = null;
|
|
3
|
+
const createEventId = () => {
|
|
4
|
+
return 'xxxxxxxx4xxxyxxx'.replace(/[xy]/g, (c) => {
|
|
5
|
+
const r = (Math.random() * 16) | 0;
|
|
6
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
7
|
+
return v.toString(16);
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
const readStorage = () => {
|
|
11
|
+
try {
|
|
12
|
+
if (typeof sessionStorage === 'undefined')
|
|
13
|
+
return null;
|
|
14
|
+
return sessionStorage.getItem(STORAGE_KEY);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const writeStorage = (eventId) => {
|
|
21
|
+
try {
|
|
22
|
+
if (typeof sessionStorage === 'undefined')
|
|
23
|
+
return;
|
|
24
|
+
sessionStorage.setItem(STORAGE_KEY, eventId);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// ignore quota / private mode
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* 读取当前 eventId(不会新建)
|
|
32
|
+
* 仅由 reportDeviceInfo 调用 resetEventId 时生成/重置
|
|
33
|
+
*/
|
|
34
|
+
export const getEventId = () => {
|
|
35
|
+
if (memoryEventId)
|
|
36
|
+
return memoryEventId;
|
|
37
|
+
const cached = readStorage();
|
|
38
|
+
if (cached) {
|
|
39
|
+
memoryEventId = cached;
|
|
40
|
+
return cached;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 生成并缓存新的 eventId(仅应在 reportDeviceInfo 中调用)
|
|
46
|
+
*/
|
|
47
|
+
export const resetEventId = () => {
|
|
48
|
+
const eventId = createEventId();
|
|
49
|
+
memoryEventId = eventId;
|
|
50
|
+
writeStorage(eventId);
|
|
51
|
+
return eventId;
|
|
52
|
+
};
|
|
53
|
+
/** 测试或内部清理用 */
|
|
54
|
+
export const clearEventId = () => {
|
|
55
|
+
memoryEventId = null;
|
|
56
|
+
try {
|
|
57
|
+
if (typeof sessionStorage !== 'undefined') {
|
|
58
|
+
sessionStorage.removeItem(STORAGE_KEY);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// ignore
|
|
63
|
+
}
|
|
64
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FlatbizDevice } from '../types/types-device.js';
|
|
2
|
+
import type { ReportDeviceInfoOptions } from '../types/types-options.js';
|
|
3
|
+
/** 格式化为 yyyy-MM-dd HH:mm:ss */
|
|
4
|
+
export declare const formatCollectTime: (date?: Date) => string;
|
|
5
|
+
/**
|
|
6
|
+
* 将设备信息 + 业务埋点字段上报到业务接口
|
|
7
|
+
* @returns 上报是否成功
|
|
8
|
+
*/
|
|
9
|
+
export declare const reportDeviceInfoRequest: (device: FlatbizDevice, options: ReportDeviceInfoOptions) => Promise<boolean>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { getAuthHeaders, getReportDeviceInfoUrl } from '../constant.js';
|
|
2
|
+
const pad2 = (n) => String(n).padStart(2, '0');
|
|
3
|
+
/** 格式化为 yyyy-MM-dd HH:mm:ss */
|
|
4
|
+
export const formatCollectTime = (date = new Date()) => {
|
|
5
|
+
const y = date.getFullYear();
|
|
6
|
+
const m = pad2(date.getMonth() + 1);
|
|
7
|
+
const d = pad2(date.getDate());
|
|
8
|
+
const hh = pad2(date.getHours());
|
|
9
|
+
const mm = pad2(date.getMinutes());
|
|
10
|
+
const ss = pad2(date.getSeconds());
|
|
11
|
+
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
|
|
12
|
+
};
|
|
13
|
+
const REPORT_SUCCESS_CODE = '0000';
|
|
14
|
+
/** 响应体 DeviceDataResp:code === "0000" 表示成功 */
|
|
15
|
+
const defaultIsSuccess = (_response, data) => {
|
|
16
|
+
if (data && typeof data === 'object' && 'code' in data) {
|
|
17
|
+
return String(data.code) === REPORT_SUCCESS_CODE;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* 将设备信息 + 业务埋点字段上报到业务接口
|
|
23
|
+
* @returns 上报是否成功
|
|
24
|
+
*/
|
|
25
|
+
export const reportDeviceInfoRequest = async (device, options) => {
|
|
26
|
+
const { isDebug = false, isProd = true, signature, ...bizParams } = options;
|
|
27
|
+
try {
|
|
28
|
+
const authHeaders = getAuthHeaders(signature);
|
|
29
|
+
const deviceSdkInfo = { ...device };
|
|
30
|
+
if ('ip' in deviceSdkInfo) {
|
|
31
|
+
delete deviceSdkInfo.ip;
|
|
32
|
+
}
|
|
33
|
+
const response = await fetch(getReportDeviceInfoUrl(isProd), {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: {
|
|
36
|
+
'Content-Type': 'application/json',
|
|
37
|
+
...authHeaders,
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify({
|
|
40
|
+
deviceSdkInfo,
|
|
41
|
+
orderInfo: {
|
|
42
|
+
eventType: 'pageLoad',
|
|
43
|
+
collectTime: formatCollectTime(),
|
|
44
|
+
...bizParams,
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
if (isDebug) {
|
|
50
|
+
console.error('上报设备信息失败', response.status, response.statusText);
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
let data = undefined;
|
|
55
|
+
const contentType = response.headers.get('content-type') || '';
|
|
56
|
+
if (contentType.includes('application/json')) {
|
|
57
|
+
try {
|
|
58
|
+
data = await response.json();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
data = undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const success = defaultIsSuccess(response, data);
|
|
65
|
+
if (!success && isDebug) {
|
|
66
|
+
if (isDebug)
|
|
67
|
+
console.error('上报设备信息业务失败', data);
|
|
68
|
+
}
|
|
69
|
+
return success;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (isDebug)
|
|
73
|
+
console.error('上报设备信息异常', error?.message);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { FlatbizDevice } from './types/types-device.js';
|
|
2
|
-
import type { DeviceInfoOptions } from './types/types-options.js';
|
|
2
|
+
import type { DeviceInfoOptions, ReportDeviceInfoOptions } from './types/types-options.js';
|
|
3
|
+
export type { FlatbizDevice, FlatbizDeviceInfo, FlatbizUaParserResult, } from './types/types-device.js';
|
|
4
|
+
export type { DeviceInfoOptions, DeviceReportAuthInfo, ReportDeviceBizParams, ReportDeviceInfoOptions, ReportPageName, } from './types/types-options.js';
|
|
5
|
+
export { ReportDeviceType, ReportRegionType, ReportUserSys, } from './types/types-options.js';
|
|
3
6
|
/**
|
|
4
7
|
* 获取设备信息
|
|
5
8
|
* @returns FlatbizDevice
|
|
6
9
|
*/
|
|
7
10
|
export declare const deviceInfo: (options?: DeviceInfoOptions) => Promise<FlatbizDevice>;
|
|
11
|
+
/**
|
|
12
|
+
* 上报设备信息
|
|
13
|
+
* 调用时会先重置并缓存 eventId,再采集设备信息并写入 deviceSdkInfo
|
|
14
|
+
*/
|
|
15
|
+
export declare const reportDeviceInfo: (options: ReportDeviceInfoOptions) => Promise<boolean>;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { getDeviceInfoH5 } from './helpers/helper-device-info.js';
|
|
2
|
+
import { getEventId, resetEventId } from './helpers/helper-event-id.js';
|
|
3
|
+
import { reportDeviceInfoRequest } from './helpers/helper-report-device-info.js';
|
|
2
4
|
import { getUaParserResult } from './helpers/helper-ua-parser.js';
|
|
5
|
+
export { ReportDeviceType, ReportRegionType, ReportUserSys, } from './types/types-options.js';
|
|
3
6
|
/**
|
|
4
7
|
* 获取设备信息
|
|
5
8
|
* @returns FlatbizDevice
|
|
@@ -14,9 +17,11 @@ export const deviceInfo = async (options) => {
|
|
|
14
17
|
}
|
|
15
18
|
const deviceInfo = await getDeviceInfoH5({ ip, autoGetIp });
|
|
16
19
|
const uaParserResult = getUaParserResult();
|
|
20
|
+
const eventId = getEventId();
|
|
17
21
|
return {
|
|
18
22
|
...deviceInfo,
|
|
19
23
|
...uaParserResult,
|
|
24
|
+
...(eventId ? { eventId } : {}),
|
|
20
25
|
};
|
|
21
26
|
}
|
|
22
27
|
catch (error) {
|
|
@@ -25,3 +30,26 @@ export const deviceInfo = async (options) => {
|
|
|
25
30
|
return {};
|
|
26
31
|
}
|
|
27
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* 上报设备信息
|
|
35
|
+
* 调用时会先重置并缓存 eventId,再采集设备信息并写入 deviceSdkInfo
|
|
36
|
+
*/
|
|
37
|
+
export const reportDeviceInfo = async (options) => {
|
|
38
|
+
const { isDebug = false } = options || {};
|
|
39
|
+
try {
|
|
40
|
+
if (typeof window === 'undefined') {
|
|
41
|
+
if (isDebug)
|
|
42
|
+
console.error('请在浏览器环境中使用');
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
// 仅在上报时生成/重置 eventId
|
|
46
|
+
resetEventId();
|
|
47
|
+
const info = await deviceInfo({ isDebug });
|
|
48
|
+
return reportDeviceInfoRequest(info, options);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (isDebug)
|
|
52
|
+
console.error('上报设备信息异常', error?.message);
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
@@ -42,6 +42,12 @@ export interface FlatbizDeviceInfo {
|
|
|
42
42
|
pluginNum: number;
|
|
43
43
|
/** 浏览器是否启用 cookies */
|
|
44
44
|
cookiesEnable: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* 事件 ID
|
|
47
|
+
* 仅在调用 reportDeviceInfo 时生成/重置并缓存;
|
|
48
|
+
* deviceInfo 读取当前缓存值一并返回(尚未上报过时可能为空)
|
|
49
|
+
*/
|
|
50
|
+
eventId?: string;
|
|
45
51
|
}
|
|
46
52
|
/**
|
|
47
53
|
* FlatbizUaParserResult
|
|
@@ -20,3 +20,102 @@ export type DeviceInfoOptions = {
|
|
|
20
20
|
*/
|
|
21
21
|
isDebug?: boolean;
|
|
22
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* 鉴权信息:
|
|
25
|
+
* - string:直接作为 `Authorization` 请求头
|
|
26
|
+
* - 对象:`token` 写入 Authorization,`headers` 合并进请求头
|
|
27
|
+
*/
|
|
28
|
+
export type DeviceReportAuthInfo = string | {
|
|
29
|
+
token?: string;
|
|
30
|
+
headers?: Record<string, string>;
|
|
31
|
+
};
|
|
32
|
+
/** 埋点采集页面 */
|
|
33
|
+
export type ReportPageName = 'detail' | 'order' | 'publicCashier' | 'nativeCashier';
|
|
34
|
+
/**
|
|
35
|
+
* 会员体系
|
|
36
|
+
* - 01: 同程会员体系
|
|
37
|
+
* - 02: HopeGoo 会员体系
|
|
38
|
+
* - 03: Tabigo 会员体系
|
|
39
|
+
*/
|
|
40
|
+
export declare enum ReportUserSys {
|
|
41
|
+
/** 同程会员体系 */
|
|
42
|
+
Tongcheng = "01",
|
|
43
|
+
/** HopeGoo 会员体系 */
|
|
44
|
+
HopeGoo = "02",
|
|
45
|
+
/** Tabigo 会员体系 */
|
|
46
|
+
Tabigo = "03"
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 区域类型
|
|
50
|
+
* - 01: 国内
|
|
51
|
+
* - 02: 国外
|
|
52
|
+
*/
|
|
53
|
+
export declare enum ReportRegionType {
|
|
54
|
+
/** 国内 */
|
|
55
|
+
Domestic = "01",
|
|
56
|
+
/** 国外 */
|
|
57
|
+
Overseas = "02"
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 设备类型
|
|
61
|
+
* - 1: PC
|
|
62
|
+
* - 3: H5
|
|
63
|
+
* - 4: HopeGoo APP
|
|
64
|
+
* - 5: Tabigo APP
|
|
65
|
+
*/
|
|
66
|
+
export declare enum ReportDeviceType {
|
|
67
|
+
/** PC */
|
|
68
|
+
PC = "1",
|
|
69
|
+
/** H5 */
|
|
70
|
+
H5 = "3",
|
|
71
|
+
/** HopeGoo APP */
|
|
72
|
+
HopeGooApp = "4",
|
|
73
|
+
/** Tabigo APP */
|
|
74
|
+
TabigoApp = "5"
|
|
75
|
+
}
|
|
76
|
+
/** 上报业务入参(不含设备指纹字段) */
|
|
77
|
+
export type ReportDeviceBizParams = {
|
|
78
|
+
/**
|
|
79
|
+
* 埋点采集页面
|
|
80
|
+
* - detail:产品详情页面
|
|
81
|
+
* - order:创单页面
|
|
82
|
+
* - publicCashier:公共收银台
|
|
83
|
+
* - nativeCashier:原生收银台
|
|
84
|
+
*/
|
|
85
|
+
pageName: ReportPageName;
|
|
86
|
+
/**
|
|
87
|
+
* 项目订单号
|
|
88
|
+
* pageName=detail 时无该字段值
|
|
89
|
+
*/
|
|
90
|
+
orderNum: string;
|
|
91
|
+
/** 区域类型 */
|
|
92
|
+
regionType: ReportRegionType;
|
|
93
|
+
/** 设备类型 */
|
|
94
|
+
deviceType: ReportDeviceType;
|
|
95
|
+
/** 用户 ID */
|
|
96
|
+
userId?: string;
|
|
97
|
+
/** 会员体系 */
|
|
98
|
+
userSys?: ReportUserSys;
|
|
99
|
+
/**
|
|
100
|
+
* 事件类型
|
|
101
|
+
* - pageLoad:页面加载
|
|
102
|
+
* - click:点击事件
|
|
103
|
+
* - 其他:自定义事件
|
|
104
|
+
*/
|
|
105
|
+
eventType?: 'pageLoad' | 'click' | string;
|
|
106
|
+
};
|
|
107
|
+
export type ReportDeviceInfoOptions = Pick<DeviceInfoOptions, 'isDebug'> & ReportDeviceBizParams & {
|
|
108
|
+
/**
|
|
109
|
+
* 鉴权签名,写入请求头 `X-signature`
|
|
110
|
+
* 由业务侧传入
|
|
111
|
+
*/
|
|
112
|
+
signature: string;
|
|
113
|
+
/**
|
|
114
|
+
* 是否生产环境
|
|
115
|
+
* 默认 true
|
|
116
|
+
*
|
|
117
|
+
* - true:使用生产上报地址
|
|
118
|
+
* - false:使用非生产上报地址
|
|
119
|
+
*/
|
|
120
|
+
isProd?: boolean;
|
|
121
|
+
};
|
|
@@ -1 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 会员体系
|
|
3
|
+
* - 01: 同程会员体系
|
|
4
|
+
* - 02: HopeGoo 会员体系
|
|
5
|
+
* - 03: Tabigo 会员体系
|
|
6
|
+
*/
|
|
7
|
+
export var ReportUserSys;
|
|
8
|
+
(function (ReportUserSys) {
|
|
9
|
+
/** 同程会员体系 */
|
|
10
|
+
ReportUserSys["Tongcheng"] = "01";
|
|
11
|
+
/** HopeGoo 会员体系 */
|
|
12
|
+
ReportUserSys["HopeGoo"] = "02";
|
|
13
|
+
/** Tabigo 会员体系 */
|
|
14
|
+
ReportUserSys["Tabigo"] = "03";
|
|
15
|
+
})(ReportUserSys || (ReportUserSys = {}));
|
|
16
|
+
/**
|
|
17
|
+
* 区域类型
|
|
18
|
+
* - 01: 国内
|
|
19
|
+
* - 02: 国外
|
|
20
|
+
*/
|
|
21
|
+
export var ReportRegionType;
|
|
22
|
+
(function (ReportRegionType) {
|
|
23
|
+
/** 国内 */
|
|
24
|
+
ReportRegionType["Domestic"] = "01";
|
|
25
|
+
/** 国外 */
|
|
26
|
+
ReportRegionType["Overseas"] = "02";
|
|
27
|
+
})(ReportRegionType || (ReportRegionType = {}));
|
|
28
|
+
/**
|
|
29
|
+
* 设备类型
|
|
30
|
+
* - 1: PC
|
|
31
|
+
* - 3: H5
|
|
32
|
+
* - 4: HopeGoo APP
|
|
33
|
+
* - 5: Tabigo APP
|
|
34
|
+
*/
|
|
35
|
+
export var ReportDeviceType;
|
|
36
|
+
(function (ReportDeviceType) {
|
|
37
|
+
/** PC */
|
|
38
|
+
ReportDeviceType["PC"] = "1";
|
|
39
|
+
/** H5 */
|
|
40
|
+
ReportDeviceType["H5"] = "3";
|
|
41
|
+
/** HopeGoo APP */
|
|
42
|
+
ReportDeviceType["HopeGooApp"] = "4";
|
|
43
|
+
/** Tabigo APP */
|
|
44
|
+
ReportDeviceType["TabigoApp"] = "5";
|
|
45
|
+
})(ReportDeviceType || (ReportDeviceType = {}));
|