@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 CHANGED
@@ -1,103 +1,166 @@
1
- ## @flatbiz/device
1
+ # @flatbiz/device
2
2
 
3
- 增强 H5 设备信息采集能力:`deviceInfo` 支持自定义/自动获取 IP、屏幕分辨率字符串,并合并 UA 解析结果;`deviceId` 通过 cookie + localStorage 持久化,并支持主域与子域共享。
3
+ H5 设备信息 SDK,提供两个核心能力:
4
4
 
5
- ### Breaking Changes
5
+ | API | 作用 | 返回值 |
6
+ | --- | --- | --- |
7
+ | `deviceInfo` | 采集设备指纹与 UA 信息 | `Promise<FlatbizDevice>` |
8
+ | `reportDeviceInfo` | 采集后上报业务接口 | `Promise<boolean>` |
6
9
 
7
- - **`deviceInfo` 改为异步 API**:由同步函数改为 `async`,返回 `Promise<FlatbizDevice>`,调用方需使用 `await deviceInfo()` 或 `.then()`
8
- - **移除 `utils` 模块**:`getDeviceId` 统一从 `helper-get-deviceId` 导出,不再通过 `src/utils.ts`
10
+ > 仅支持浏览器环境。非浏览器调用时:`deviceInfo` 返回 `{}`,`reportDeviceInfo` 返回 `false`。
9
11
 
10
- ### Features
12
+ ---
11
13
 
12
- - 新增 **`DeviceInfoOptions`** 可选参数:
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
- ### `deviceInfo()` 返回字段
16
+ ```bash
17
+ yarn add @flatbiz/device
18
+ # 或
19
+ npm i @flatbiz/device
20
+ ```
23
21
 
24
- **H5 终端(`FlatbizDeviceInfo`)**
22
+ ---
25
23
 
26
- - `ip`、`deviceId`、`language`
27
- - `screenWidth`、`screenHeight`、`screenSize`、`screenDensity`
28
- - `networkType`、`timezone`、`timezoneOffset`、`systemDate`、`systemTime`
29
- - `colorDepth`、`touchSupport`、`plugins`、`pluginNum`、`cookiesEnable`
24
+ ## 1. `deviceInfo` — 采集设备信息
30
25
 
31
- **UA 解析(`FlatbizUaParserResult`)**
26
+ 异步采集 H5 终端信息与 UA 解析结果,并持久化 `deviceId`(Cookie + localStorage,支持主域/子域共享)。
32
27
 
33
- - `userAgent`、`browserName`、`browserVersion`
34
- - `engineName`、`engineVersion`
35
- - `osName`、`osVersion`、`cpuModel`
36
- - `deviceType`、`deviceVendor`、`deviceModel`
28
+ ### 快速接入
37
29
 
38
- ### deviceId 与 Cookie
30
+ ```ts
31
+ import { deviceInfo } from '@flatbiz/device';
39
32
 
40
- `deviceInfo()` 内部会调用 `getDeviceId()` 生成/读取设备 ID。存储与同步规则如下。
33
+ // 最简用法
34
+ const info = await deviceInfo();
41
35
 
42
- #### 存储键
36
+ // 推荐:由服务端下发 IP
37
+ const info2 = await deviceInfo({ ip: '203.0.113.1' });
43
38
 
44
- | 介质 | Key | 说明 |
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
- 1. **Cookie 有值**:返回该 ID,并写入/覆盖 localStorage
52
- 2. **Cookie 无、localStorage 有**:返回 localStorage 中的 ID,并回写 Cookie
53
- 3. **都没有**:生成新 ID(16 位类 UUID),同时写入 Cookie 与 localStorage
45
+ console.log(info.deviceId, info.screenSize, info.browserName);
46
+ ```
54
47
 
55
- #### Cookie 属性
48
+ ### 入参 `DeviceInfoOptions`
56
49
 
57
- 通过 `js-cookie` 写入,默认属性:
50
+ 全部可选。
58
51
 
59
- | 属性 | | 说明 |
60
- | --- | --- | --- |
61
- | `expires` | `1`(约 1 天) | 过期后续访问会重新走生成/回写逻辑 |
62
- | `path` | `/` | 整站路径可访问 |
63
- | `sameSite` | `Lax` | 常规同站导航可携带 |
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
- #### 跨子域共享(`domain`)
58
+ ### 出参 `FlatbizDevice`
67
59
 
68
- 使用 [psl](https://www.npmjs.com/package/psl) 解析当前 `location.hostname` 的注册域,并设置为带前缀点的根域,例如:
60
+ 返回值为 `Partial<FlatbizDeviceInfo> & Partial<FlatbizUaParserResult>`。异常或非浏览器环境返回 `{}`。
69
61
 
70
- - `example.com` → `domain=.example.com`
71
- - `www.example.com` → `domain=.example.com`
72
- - `api.example.com` → `domain=.example.com`
62
+ #### 终端字段(`FlatbizDeviceInfo`)
73
63
 
74
- 因此在同一注册域下,主域与各子域可共享同一个 `deviceId`(localStorage 仍按源隔离,跨域依赖 Cookie)。
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
- 以下场景**不设置** `domain`(仅当前 host 生效):
101
+ ### `deviceId` 说明(简要)
77
102
 
78
- - `localhost`
79
- - IP 地址(如 `127.0.0.1`)
80
- - 无法解析出注册域的 hostname
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
- - 浏览器禁用 Cookie 时,仍可能依赖 localStorage;返回字段 `cookiesEnable` 可反映 Cookie 是否启用
85
- - Cookie 约 24 小时过期后,若 localStorage 仍有值,会按优先级回写新 Cookie,**ID 保持不变**
110
+ ## 2. `reportDeviceInfo` 上报设备信息
86
111
 
87
- ### Usage
112
+ 内部先重置并缓存 `eventId`,再调用 `deviceInfo()`,按 `isProd` 选择上报地址 `POST`,将设备指纹(含 `eventId`)与业务埋点一并上报。
113
+
114
+ ### 快速接入
88
115
 
89
116
  ```ts
90
- import { deviceInfo } from '@flatbiz/device';
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
- // 自定义 IP(推荐由服务端下发)
93
- const info = await deviceInfo({ ip: '203.0.113.1' });
135
+ ```
94
136
 
95
- // 自动获取公网 IP
96
- const info2 = await deviceInfo({ autoGetIp: true });
137
+ ### 入参 `ReportDeviceInfoOptions`
97
138
 
98
- // 调试模式
99
- const info3 = await deviceInfo({ isDebug: true });
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;
@@ -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
- export {};
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 = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flatbiz/device",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "homepage": "https://gitlab.itcjf.com/flatjs/flat-biz-devkit",
5
5
  "repository": {
6
6
  "type": "git",