@pnt-team/pnt-component-frontend 0.0.91 → 0.0.95
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 +149 -54
- package/lib/cjs/api/cos.d.ts +103 -0
- package/lib/cjs/api/cos.js +137 -0
- package/lib/cjs/components/PntCosUploader/index.d.ts +135 -0
- package/lib/cjs/components/PntCosUploader/index.js +209 -0
- package/lib/cjs/components/PntImage/index.d.ts +9 -3
- package/lib/cjs/components/PntImage/index.js +9 -1
- package/lib/cjs/components/PntSecureBox/index.js +8 -5
- package/lib/cjs/components/PntUpload/index.d.ts +149 -0
- package/lib/cjs/components/PntUpload/index.js +228 -0
- package/lib/cjs/components/PntUpload/index.scss +101 -0
- package/lib/cjs/hooks/useHighSecurity.d.ts +55 -15
- package/lib/cjs/hooks/useHighSecurity.js +168 -35
- package/lib/cjs/index.d.ts +6 -0
- package/lib/cjs/index.js +18 -2
- package/lib/esm/api/cos.d.ts +103 -0
- package/lib/esm/api/cos.js +189 -0
- package/lib/esm/components/PntCosUploader/index.d.ts +135 -0
- package/lib/esm/components/PntCosUploader/index.js +289 -0
- package/lib/esm/components/PntImage/index.d.ts +9 -3
- package/lib/esm/components/PntImage/index.js +22 -3
- package/lib/esm/components/PntSecureBox/index.js +9 -3
- package/lib/esm/components/PntUpload/index.d.ts +149 -0
- package/lib/esm/components/PntUpload/index.js +276 -0
- package/lib/esm/components/PntUpload/index.scss +101 -0
- package/lib/esm/hooks/useHighSecurity.d.ts +55 -15
- package/lib/esm/hooks/useHighSecurity.js +174 -32
- package/lib/esm/index.d.ts +6 -0
- package/lib/esm/index.js +9 -1
- package/lib/umd/pnt-component-frontend.min.css +1 -1
- package/lib/umd/pnt-component-frontend.min.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
PNT 前端业务组件库,基于 [dumi2](https://d.umijs.org/) + [father4](https://github.com/umijs/father) 构建,收敛 PNT 业务项目中高价值的重复组件与 Hook,实现单一来源维护。
|
|
4
4
|
|
|
5
|
+
> 当前版本:**0.0.91** · 组件清单:`PntImage` / `PntBusinessSelect` / `PntSecureBox` / `PntGeneralLayout`
|
|
6
|
+
|
|
5
7
|
## 安装
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -12,11 +14,12 @@ yarn add @pnt-team/pnt-component-frontend
|
|
|
12
14
|
|
|
13
15
|
### 依赖要求(peerDependencies)
|
|
14
16
|
|
|
15
|
-
| 依赖
|
|
16
|
-
|
|
|
17
|
-
| `react`
|
|
18
|
-
| `react-dom`
|
|
19
|
-
| `tdesign-react`
|
|
17
|
+
| 依赖 | 版本要求 | 说明 |
|
|
18
|
+
| --------------------- | ---------- | -------------------------------------- |
|
|
19
|
+
| `react` | `>=16.9.0` | React 核心框架 |
|
|
20
|
+
| `react-dom` | `>=16.9.0` | React DOM 渲染 |
|
|
21
|
+
| `tdesign-react` | `>=1.5.0` | UI 组件库(本组件库基于 TDesign 封装) |
|
|
22
|
+
| `tdesign-icons-react` | `>=0.2.0` | TDesign 图标库 |
|
|
20
23
|
|
|
21
24
|
> ⚠️ 请确保项目中已安装以上依赖,否则组件可能无法正常运行。
|
|
22
25
|
|
|
@@ -36,12 +39,15 @@ import http from '你的项目中的 axios 实例';
|
|
|
36
39
|
```tsx
|
|
37
40
|
import {
|
|
38
41
|
// L1 基础展示组件
|
|
39
|
-
|
|
42
|
+
PntImage,
|
|
40
43
|
// L2 业务复合组件
|
|
41
44
|
PntBusinessSelect,
|
|
42
45
|
PntSecureBox,
|
|
43
46
|
// L3 布局组件
|
|
44
47
|
PntGeneralLayout,
|
|
48
|
+
// 配置
|
|
49
|
+
PntProvider,
|
|
50
|
+
usePntConfig,
|
|
45
51
|
} from '@pnt-team/pnt-component-frontend';
|
|
46
52
|
```
|
|
47
53
|
|
|
@@ -49,29 +55,57 @@ import {
|
|
|
49
55
|
|
|
50
56
|
### L1 基础展示组件
|
|
51
57
|
|
|
52
|
-
####
|
|
58
|
+
#### PntImage — 业务图片组件
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
统一的业务图片组件,单一组件通过 `onRemove` 是否传入自适应「上传预览」与「纯预览」两种模式,避免业务侧维护两套组件(原 UploadImageViewer + BasicImageViewer)。
|
|
55
61
|
|
|
56
62
|
**Props:**
|
|
57
63
|
|
|
58
|
-
| 属性 | 类型
|
|
59
|
-
| ------------ |
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `defaultImg` | `string`
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
64
|
+
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|
|
65
|
+
| ------------ | ------------------------------------ | :--: | -------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
66
|
+
| `src` | `string \| undefined` | ✅ | - | 图片 URL;为空则展示 defaultImg 或内置 uploadImg |
|
|
67
|
+
| `alt` | `string` | ❌ | `''` | alt 文本,纯预览模式建议传入以提升可访问性 |
|
|
68
|
+
| `defaultImg` | `string` | ❌ | 内置 uploadImg | 默认图片(仅上传预览模式生效) |
|
|
69
|
+
| `size` | `'small' \| 'medium' \| 'large'` | ❌ | `'large'` | 快捷正方形尺寸:small=36px、medium=60px、large=136px |
|
|
70
|
+
| `style` | `React.CSSProperties` | ❌ | - | 自定义样式;width/height 优先级高于 size |
|
|
71
|
+
| `loading` | `boolean` | ❌ | `false` | 上传中状态(仅上传预览模式生效) |
|
|
72
|
+
| `onRemove` | `(e: any) => void` | ❌ | - | 删除回调(传入即启用上传预览模式) |
|
|
73
|
+
| `container` | `HTMLElement \| (() => HTMLElement)` | ❌ | - | attach 容器(弹窗场景需要,透传给 tdesign ImageViewer) |
|
|
74
|
+
| `texts` | `PntImageTexts` | ❌ | `{ uploading: '上传中', loading: '加载中', loadFailed: '加载失败' }` | 多语言文案,传入字段覆盖默认中文 |
|
|
75
|
+
|
|
76
|
+
**模式判定规则:**
|
|
77
|
+
|
|
78
|
+
| 模式 | 触发条件 | mask 行为 | loading 占位 | defaultImg | error 占位 |
|
|
79
|
+
| ------------ | --------------- | ------------------------ | ----------------------- | :--------: | ---------- |
|
|
80
|
+
| 上传预览模式 | 传入 `onRemove` | 预览按钮 + 分隔线 + 删除 | "上传中"(LoadingIcon) | ✅ | 不显示 |
|
|
81
|
+
| 纯预览模式 | 不传 `onRemove` | 半透明遮罩 + 点击预览 | "加载中"(ImageIcon) | ❌ | "加载失败" |
|
|
65
82
|
|
|
66
83
|
**示例:**
|
|
67
84
|
|
|
68
85
|
```tsx
|
|
69
|
-
|
|
70
|
-
|
|
86
|
+
// 上传预览模式
|
|
87
|
+
<PntImage
|
|
88
|
+
src={iconUrl}
|
|
71
89
|
loading={uploading}
|
|
72
90
|
defaultImg="/path/to/default.png"
|
|
73
|
-
params={{ style: { width: '200px', height: '200px' } }}
|
|
74
91
|
onRemove={handleRemove}
|
|
92
|
+
size="large"
|
|
93
|
+
/>
|
|
94
|
+
|
|
95
|
+
// 纯预览模式
|
|
96
|
+
<PntImage
|
|
97
|
+
src={url}
|
|
98
|
+
alt="avatar"
|
|
99
|
+
size="medium"
|
|
100
|
+
container={dialogContainer}
|
|
101
|
+
/>
|
|
102
|
+
|
|
103
|
+
// 多语言
|
|
104
|
+
<PntImage
|
|
105
|
+
src={url}
|
|
106
|
+
alt="avatar"
|
|
107
|
+
size="medium"
|
|
108
|
+
texts={{ loading: 'Loading', loadFailed: 'Failed' }}
|
|
75
109
|
/>
|
|
76
110
|
```
|
|
77
111
|
|
|
@@ -81,23 +115,42 @@ import {
|
|
|
81
115
|
|
|
82
116
|
#### PntBusinessSelect — 业务选择器组件
|
|
83
117
|
|
|
84
|
-
统一业务下拉选择器,内置对接后端通用接口 `/api/business/select/list
|
|
118
|
+
统一业务下拉选择器,内置对接后端通用接口 `/api/business/select/list`,支持远程搜索、滚动分页加载、多选、场景化禁用(合规场景 `creatable` 字段)。
|
|
119
|
+
|
|
120
|
+
替代此前 5 个分散的业务 select 接口(`game/list`、`game/list_option`、`compliance-age/game/list`、`biz-list-with-creatable-state`、`sdk_customize/game_list`)。
|
|
85
121
|
|
|
86
122
|
**Props:**
|
|
87
123
|
|
|
88
|
-
| 属性
|
|
89
|
-
|
|
|
90
|
-
| `value`
|
|
91
|
-
| `onChange`
|
|
92
|
-
| `multiple`
|
|
93
|
-
| `scene`
|
|
94
|
-
| `statuses`
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
124
|
+
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|
|
125
|
+
| ---------------------- | ----------------------------------------------------------- | :--: | ----------- | ----------------------------------------------------------------------------------- |
|
|
126
|
+
| `value` | `string \| string[]` | ❌ | - | 当前选中值;单选为 string,多选为 string[] |
|
|
127
|
+
| `onChange` | `(value, context) => void` | ❌ | - | 值变化回调;context.selectedOptions 返回纯业务数据对象 |
|
|
128
|
+
| `multiple` | `boolean` | ❌ | `false` | 是否多选 |
|
|
129
|
+
| `scene` | `'default' \| 'sdk' \| 'compliance_age' \| 'custom_region'` | ❌ | `'default'` | 下拉场景;后端按场景返回默认字段集 |
|
|
130
|
+
| `statuses` | `number[]` | ❌ | - | 业务状态筛选(3-线上运营, 4-接入中, 5-中途结项, 6-已下线) |
|
|
131
|
+
| `businessTypes` | `number[]` | ❌ | - | 业务类型筛选(1-正式业务, 2-测试业务) |
|
|
132
|
+
| `businessAccessMethod` | `number` | ❌ | - | 业务接入类型筛选(1-纯 SDK, 2-LI PASS, 3-工作室品牌账号) |
|
|
133
|
+
| `labelFormat` | `'name' \| 'name_en' \| 'name_id' \| 'name_en_id'` | ❌ | `'name'` | 标签格式 |
|
|
134
|
+
| `labelField` | `string` | ❌ | - | 自定义 label 字段(消费方接口返回字段非标准 name/name_en 时使用) |
|
|
135
|
+
| `optionLabel` | `(item) => ReactNode` | ❌ | - | 自定义选项 label 渲染;优先级高于 labelFormat/labelField |
|
|
136
|
+
| `placeholder` | `string` | ❌ | - | 占位提示文案 |
|
|
137
|
+
| `disabled` | `boolean` | ❌ | `false` | 是否禁用整个选择器 |
|
|
138
|
+
| `clearable` | `boolean` | ❌ | `true` | 是否可清除 |
|
|
139
|
+
| `filterable` | `boolean` | ❌ | `true` | 是否可远程搜索 |
|
|
140
|
+
| `max` | `number` | ❌ | - | 多选时最大可选数量 |
|
|
141
|
+
| `pageSize` | `number` | ❌ | `20` | 每页条数 |
|
|
142
|
+
| `searchDebounce` | `number` | ❌ | `400` | 搜索防抖延迟(毫秒) |
|
|
143
|
+
| `minCollapsedNum` | `number` | ❌ | - | 多选时最少折叠数量;透传至 TDesign Select |
|
|
144
|
+
| `collapsedItems` | `TdSelectProps['collapsedItems']` | ❌ | - | 折叠项自定义渲染;透传至 TDesign Select |
|
|
145
|
+
| `popupProps` | `Partial<TdSelectProps['popupProps']>` | ❌ | - | 弹层属性透传;与内部 onScrollToBottom 合并;常用 attach、overlayClassName |
|
|
146
|
+
| `fields` | `string[]` | ❌ | - | 字段白名单,传给后端 fields 参数;未传时后端按 scene 返回默认字段 |
|
|
147
|
+
| `pagination` | `boolean` | ❌ | `true` | 是否分页;false 时一次性加载全量数据,不远程搜索 |
|
|
148
|
+
| `onLoaded` | `(options) => void` | ❌ | - | 选项加载完成回调;不分页模式下首屏即全量,可复用此数据避免重复请求 |
|
|
149
|
+
| `optionDisabled` | `(item) => boolean` | ❌ | - | 自定义选项禁用逻辑;与合规场景 creatable 判断叠加(任一为 true 即禁用) |
|
|
150
|
+
| `optionTooltip` | `(item) => string` | ❌ | - | 自定义选项 tooltip 内容;返回非空字符串时该选项悬停显示 tooltip,常用于解释禁用原因 |
|
|
151
|
+
| `tooltipPlacement` | `'top' \| 'bottom' \| 'left' \| 'right'` | ❌ | `'top'` | tooltip 位置 |
|
|
152
|
+
| `className` | `string` | ❌ | - | 自定义类名 |
|
|
153
|
+
| `style` | `React.CSSProperties` | ❌ | - | 自定义样式 |
|
|
101
154
|
|
|
102
155
|
**示例:**
|
|
103
156
|
|
|
@@ -111,6 +164,15 @@ import { PntBusinessSelect } from '@pnt-team/pnt-component-frontend';
|
|
|
111
164
|
value={gameId}
|
|
112
165
|
onChange={(v) => setGameId(v as string)}
|
|
113
166
|
/>;
|
|
167
|
+
|
|
168
|
+
// 多选 + 状态过滤
|
|
169
|
+
<PntBusinessSelect
|
|
170
|
+
multiple
|
|
171
|
+
statuses={[3, 4]}
|
|
172
|
+
labelFormat="name_id"
|
|
173
|
+
value={gameIds}
|
|
174
|
+
onChange={(v) => setGameIds(v as string[])}
|
|
175
|
+
/>;
|
|
114
176
|
```
|
|
115
177
|
|
|
116
178
|
---
|
|
@@ -121,15 +183,15 @@ import { PntBusinessSelect } from '@pnt-team/pnt-component-frontend';
|
|
|
121
183
|
|
|
122
184
|
**Props:**
|
|
123
185
|
|
|
124
|
-
| 属性 | 类型 | 必填 | 说明
|
|
125
|
-
| ----------- | -------------------------------------- |
|
|
126
|
-
| `dataKey` | `string` |
|
|
127
|
-
| `dataValue` | `string` |
|
|
128
|
-
| `env` | `string \| number` |
|
|
129
|
-
| `gameId` | `string \| number` |
|
|
130
|
-
| `renderDom` | `(content: string) => React.ReactNode` |
|
|
131
|
-
| `viewText` | `string` |
|
|
132
|
-
| `pageId` | `string` |
|
|
186
|
+
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|
|
187
|
+
| ----------- | -------------------------------------- | :--: | ------------------- | ------------------------------------------------------------ |
|
|
188
|
+
| `dataKey` | `string` | ✅ | - | 高敏信息的唯一标识 key,用于缓存真实值 |
|
|
189
|
+
| `dataValue` | `string` | ✅ | - | 初始显示值,通常为脱敏后的数据(含 `_high_security_:` 前缀) |
|
|
190
|
+
| `env` | `string \| number` | ✅ | - | 环境标识(如 dev / test / production) |
|
|
191
|
+
| `gameId` | `string \| number` | ✅ | - | 游戏 / 业务 ID |
|
|
192
|
+
| `renderDom` | `(content: string) => React.ReactNode` | ✅ | - | 自定义渲染函数,参数为当前显示内容(真实值或脱敏值) |
|
|
193
|
+
| `viewText` | `string` | ❌ | `'View'` | 查看按钮文案 |
|
|
194
|
+
| `pageId` | `string` | ❌ | `location.pathname` | 页面 ID,用于操作日志和权限验证 |
|
|
133
195
|
|
|
134
196
|
**示例:**
|
|
135
197
|
|
|
@@ -146,28 +208,53 @@ import { PntSecureBox } from '@pnt-team/pnt-component-frontend';
|
|
|
146
208
|
/>;
|
|
147
209
|
```
|
|
148
210
|
|
|
211
|
+
**非展示场景(查看 → 复制 / 批量解锁拼装)请用 `useHighSecurity`:**
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { useHighSecurity } from '@pnt-team/pnt-component-frontend';
|
|
215
|
+
|
|
216
|
+
const { securityData, isUnlocked, requestSecurityData, clearSecurityData } =
|
|
217
|
+
useHighSecurity({ gameId, env });
|
|
218
|
+
|
|
219
|
+
// 第一次点击解锁、第二次点击复制;切换业务时 clearSecurityData()
|
|
220
|
+
const res = await requestSecurityData({
|
|
221
|
+
gameId,
|
|
222
|
+
env,
|
|
223
|
+
param: [{ key: 'SDK_KEY', value: cipher }],
|
|
224
|
+
});
|
|
225
|
+
if (res.length) navigator.clipboard.writeText(securityData.SDK_KEY);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
- 模块级缓存按 `gameId + env + key` 复合键隔离,同页多实例共享,同一 key 同页只请求一次;在途并发自动去重
|
|
229
|
+
- 解锁失败返回 `[]` 且不抛错;`env` 必填
|
|
230
|
+
- 另有 `isSecurityData(value)` 导出,用于判断 `_high_security_:` 密文
|
|
231
|
+
|
|
149
232
|
---
|
|
150
233
|
|
|
151
234
|
### L3 布局组件
|
|
152
235
|
|
|
153
236
|
#### PntGeneralLayout — 通用页面布局组件
|
|
154
237
|
|
|
155
|
-
提供标准的「头部 + 子头部 + 内容区 + 底部」页面布局结构,基于 TDesign Layout
|
|
238
|
+
提供标准的「头部 + 子头部 + 内容区 + 底部」页面布局结构,基于 TDesign Layout(flex column)封装,内容区自动填满剩余高度并独立滚动,适用于后台管理系统的列表页、详情页、表单页等场景。
|
|
156
239
|
|
|
157
240
|
**Props:**
|
|
158
241
|
|
|
159
|
-
| 属性 | 类型 | 必填 | 默认值
|
|
160
|
-
| ------------------- | --------------------- |
|
|
161
|
-
| `className` | `string` |
|
|
162
|
-
| `headerTitle` | `ReactNode` |
|
|
163
|
-
| `showBackButton` | `boolean` |
|
|
164
|
-
| `onBackButtonClick` | `() => void` |
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
170
|
-
| `
|
|
242
|
+
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|
|
243
|
+
| ------------------- | --------------------- | :--: | --------- | ---------------------------------------------------------------------------------- |
|
|
244
|
+
| `className` | `string` | ❌ | - | 自定义类名,追加到根元素,常用于页面级样式覆写 |
|
|
245
|
+
| `headerTitle` | `ReactNode` | ❌ | - | 头部标题内容,传入后渲染 Header 区域 |
|
|
246
|
+
| `showBackButton` | `boolean` | ❌ | `false` | 是否显示返回按钮 |
|
|
247
|
+
| `onBackButtonClick` | `() => void` | ❌ | - | 返回按钮点击回调 |
|
|
248
|
+
| `headerBordered` | `boolean` | ❌ | `true` | 是否显示头部底部分割线 |
|
|
249
|
+
| `subHeaderContent` | `ReactNode` | ❌ | - | 子头部内容,位于 Header 下方 |
|
|
250
|
+
| `operation` | `ReactNode` | ❌ | - | 头部右侧操作区,常用于放置按钮组 |
|
|
251
|
+
| `bodyRef` | `Ref<HTMLDivElement>` | ❌ | - | 内容区 ref 引用 |
|
|
252
|
+
| `bodyStyle` | `CSSProperties` | ❌ | - | 内容区自定义样式(内边距、圆角建议优先使用 bodyPadding / cardRadius) |
|
|
253
|
+
| `bodyPadding` | `number \| string` | ❌ | `24` | 内容区内边距;数字按 px 处理,全出血内容可传 `'24px 0'` |
|
|
254
|
+
| `cardRadius` | `number` | ❌ | `4` | 内容区卡片圆角(px),联动 t-card 及其 body |
|
|
255
|
+
| `footerButton` | `'fixed' \| 'auto'` | ❌ | `'fixed'` | fixed:底部按钮统一 36px 高 / 92px 最小宽 / 加粗;auto:不约束按钮尺寸,仅保留间距 |
|
|
256
|
+
| `footer` | `ReactNode` | ❌ | - | 底部内容,传入后渲染 Footer 区域 |
|
|
257
|
+
| `children` | `ReactNode` | ❌ | - | 页面主体内容 |
|
|
171
258
|
|
|
172
259
|
**示例:**
|
|
173
260
|
|
|
@@ -204,6 +291,14 @@ import { PntSecureBox } from '@pnt-team/pnt-component-frontend';
|
|
|
204
291
|
>
|
|
205
292
|
<Detail />
|
|
206
293
|
</PntGeneralLayout>
|
|
294
|
+
|
|
295
|
+
// 适配项目风格(无头部边线 / 全出血内容 / 大圆角卡片 / 底部按钮自适应)
|
|
296
|
+
<PntGeneralLayout
|
|
297
|
+
headerBordered={false}
|
|
298
|
+
bodyPadding="24px 0"
|
|
299
|
+
cardRadius={8}
|
|
300
|
+
footerButton="auto"
|
|
301
|
+
/>
|
|
207
302
|
```
|
|
208
303
|
|
|
209
304
|
---
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { AxiosInstance } from 'axios';
|
|
2
|
+
/**
|
|
3
|
+
* 归一化后的 COS 临时凭证
|
|
4
|
+
* @description 各后端接口字段命名不统一(snake/camel),组件库内部统一为 camelCase
|
|
5
|
+
*/
|
|
6
|
+
export interface NormalizedCosCredential {
|
|
7
|
+
/** COS 存储桶 */
|
|
8
|
+
bucket: string;
|
|
9
|
+
/** COS 地域 */
|
|
10
|
+
region: string;
|
|
11
|
+
/** 临时密钥 ID */
|
|
12
|
+
secretId: string;
|
|
13
|
+
/** 临时密钥 Key */
|
|
14
|
+
secretKey: string;
|
|
15
|
+
/** 临时会话令牌 */
|
|
16
|
+
sessionToken: string;
|
|
17
|
+
/** 凭证生效时间(秒) */
|
|
18
|
+
startTime: number;
|
|
19
|
+
/** 凭证过期时间(秒) */
|
|
20
|
+
expiredTime: number;
|
|
21
|
+
/**
|
|
22
|
+
* 业务路径映射
|
|
23
|
+
* @description 后端按业务类型返回的可写路径 map;消费方按 pathKey 选取
|
|
24
|
+
*/
|
|
25
|
+
path?: Record<string, string>;
|
|
26
|
+
/**
|
|
27
|
+
* 受控目录前缀(SDK 定制场景返回)
|
|
28
|
+
* @description 前端在该前缀下自行拼接文件名;可与 pathKey 继续拼接子目录
|
|
29
|
+
*/
|
|
30
|
+
filePath?: string;
|
|
31
|
+
/**
|
|
32
|
+
* CDN 访问域名(不含尾斜杠)
|
|
33
|
+
* @description SDK 定制场景返回 cdn_url;通用场景无此字段时组件按 COS Location 拼接
|
|
34
|
+
*/
|
|
35
|
+
cosHost?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 通用 COS 凭证响应(snake_case,pnt-tools / account-business)
|
|
39
|
+
*/
|
|
40
|
+
interface SnakeCosCredential {
|
|
41
|
+
bucket: string;
|
|
42
|
+
region: string;
|
|
43
|
+
secret_id: string;
|
|
44
|
+
secret_key: string;
|
|
45
|
+
token: string;
|
|
46
|
+
start_time: number;
|
|
47
|
+
expired_time: number;
|
|
48
|
+
path?: Record<string, string>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 内置业务场景
|
|
52
|
+
* @description 决定走哪个后端凭证接口
|
|
53
|
+
* - default: 通用上传(GET /v2/business/operation/get-cos-temp-token)
|
|
54
|
+
* - default_download: 通用下载/上传(POST /v2/business/operation/get-download-cos-temp-token,snake_case)
|
|
55
|
+
* - sdk_customize: SDK 定制服务(POST /internal/sdk_customize/upload_token,含 cdn_url/file_path)
|
|
56
|
+
* - ai_translate: AI 翻译服务(POST /business/aiTranslate/import/cosToken,camelCase)
|
|
57
|
+
*/
|
|
58
|
+
export type CosScene = 'default' | 'default_download' | 'sdk_customize' | 'ai_translate' | (string & Record<never, never>);
|
|
59
|
+
/**
|
|
60
|
+
* 凭证获取参数
|
|
61
|
+
*/
|
|
62
|
+
export interface GetCosCredentialParams {
|
|
63
|
+
/** 业务场景 */
|
|
64
|
+
scene: CosScene;
|
|
65
|
+
/** 业务类型路径 key(透传到后端 path map 选取;sdk_customize 场景作为受控目录下的子目录) */
|
|
66
|
+
pathKey?: string;
|
|
67
|
+
/**
|
|
68
|
+
* 业务上下文参数(gameId/env/updType 等,按 scene 不同传递)
|
|
69
|
+
* @description default/default_download 场景下 gameId 会自动映射到请求头 x-service-type,
|
|
70
|
+
* 其余字段透传到 query/body;ai_translate 场景整体透传到 body
|
|
71
|
+
*/
|
|
72
|
+
context?: Record<string, string | number>;
|
|
73
|
+
/** 文件大小(字节),后端用于校验配额 */
|
|
74
|
+
contentLength?: number;
|
|
75
|
+
/** 已上传文件 URL/Key(下载场景使用) */
|
|
76
|
+
fileUrl?: string;
|
|
77
|
+
/**
|
|
78
|
+
* 网关 audience
|
|
79
|
+
* @default '/player-network'
|
|
80
|
+
* @description 账号管理等子系统需覆盖为对应 audience(如 '/laas-pnt');
|
|
81
|
+
* 消费方注入的 http 实例若已统一追加 audience,URL 上存在该参数时拦截器不会重复追加
|
|
82
|
+
*/
|
|
83
|
+
audience?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 自定义原始响应归一化函数
|
|
87
|
+
* @description 后端返回字段不符合内置 scene 约定时使用;入参为后端响应的原始 data
|
|
88
|
+
*/
|
|
89
|
+
export type NormalizeCredential = (raw: unknown) => NormalizedCosCredential;
|
|
90
|
+
/**
|
|
91
|
+
* snake_case 凭证归一化(导出供 getCredential 自定义逃生舱复用)
|
|
92
|
+
* @description 消费方自行请求凭证(如项目 http 实例为非标准签名)时,
|
|
93
|
+
* 可在 getCredential 内调用本函数把后端 data 转为组件库统一结构
|
|
94
|
+
*/
|
|
95
|
+
export declare const normalizeSnakeCredential: (raw: SnakeCosCredential) => NormalizedCosCredential;
|
|
96
|
+
/**
|
|
97
|
+
* 获取 COS 临时凭证(按 scene 路由到不同后端接口,内部归一化字段命名)
|
|
98
|
+
* @param http 由 PntProvider 注入的 axios 实例
|
|
99
|
+
* @param params 凭证获取参数
|
|
100
|
+
* @param customNormalize 可选的原始响应自定义归一化
|
|
101
|
+
*/
|
|
102
|
+
export declare const fetchCosCredential: (http: AxiosInstance, params: GetCosCredentialParams, customNormalize?: NormalizeCredential) => Promise<NormalizedCosCredential>;
|
|
103
|
+
export {};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/api/cos.ts
|
|
20
|
+
var cos_exports = {};
|
|
21
|
+
__export(cos_exports, {
|
|
22
|
+
fetchCosCredential: () => fetchCosCredential,
|
|
23
|
+
normalizeSnakeCredential: () => normalizeSnakeCredential
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(cos_exports);
|
|
26
|
+
var normalizeSnake = (raw) => ({
|
|
27
|
+
bucket: raw.bucket,
|
|
28
|
+
region: raw.region,
|
|
29
|
+
secretId: raw.secret_id,
|
|
30
|
+
secretKey: raw.secret_key,
|
|
31
|
+
sessionToken: raw.token,
|
|
32
|
+
startTime: raw.start_time,
|
|
33
|
+
expiredTime: raw.expired_time,
|
|
34
|
+
path: raw.path
|
|
35
|
+
});
|
|
36
|
+
var normalizeSnakeCredential = (raw) => normalizeSnake(raw);
|
|
37
|
+
var normalizeAiTranslate = (raw) => {
|
|
38
|
+
var _a, _b;
|
|
39
|
+
return {
|
|
40
|
+
bucket: raw.bucket || "",
|
|
41
|
+
region: raw.region || "",
|
|
42
|
+
secretId: raw.secretId || "",
|
|
43
|
+
secretKey: raw.secretKey || "",
|
|
44
|
+
sessionToken: raw.token || "",
|
|
45
|
+
startTime: (_a = raw.startTime) != null ? _a : 0,
|
|
46
|
+
expiredTime: (_b = raw.expiredTime) != null ? _b : 0,
|
|
47
|
+
// aiTranslate path 类型为 Record<string, unknown>,这里收窄为 string
|
|
48
|
+
path: raw.path ? Object.fromEntries(
|
|
49
|
+
Object.entries(raw.path).filter(
|
|
50
|
+
(v) => typeof v[1] === "string"
|
|
51
|
+
)
|
|
52
|
+
) : void 0
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
var normalizeSdkCustomize = (raw) => ({
|
|
56
|
+
bucket: raw.bucket,
|
|
57
|
+
region: raw.region,
|
|
58
|
+
secretId: raw.secret_id,
|
|
59
|
+
secretKey: raw.secret_key,
|
|
60
|
+
sessionToken: raw.token,
|
|
61
|
+
startTime: raw.start_time,
|
|
62
|
+
expiredTime: raw.expired_time,
|
|
63
|
+
filePath: raw.file_path,
|
|
64
|
+
cosHost: raw.cdn_url
|
|
65
|
+
});
|
|
66
|
+
var DEFAULT_AUDIENCE = "/player-network";
|
|
67
|
+
var resolveCredential = (res, normalize, customNormalize) => {
|
|
68
|
+
var _a, _b;
|
|
69
|
+
const success = res.code === 0 || res.ret === 0;
|
|
70
|
+
if (!success || res.data === null || typeof res.data === "undefined") {
|
|
71
|
+
throw new Error(
|
|
72
|
+
`[PntCosUploader] 获取 COS 凭证失败: code=${(_a = res.code) != null ? _a : "null"} ret=${(_b = res.ret) != null ? _b : "null"} ${res.msg || ""}`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return customNormalize ? customNormalize(res.data) : normalize(res.data);
|
|
76
|
+
};
|
|
77
|
+
var fetchCosCredential = async (http, params, customNormalize) => {
|
|
78
|
+
const {
|
|
79
|
+
scene,
|
|
80
|
+
context = {},
|
|
81
|
+
contentLength,
|
|
82
|
+
fileUrl,
|
|
83
|
+
audience = DEFAULT_AUDIENCE
|
|
84
|
+
} = params;
|
|
85
|
+
switch (scene) {
|
|
86
|
+
case "default": {
|
|
87
|
+
const { gameId, ...restContext } = context;
|
|
88
|
+
const res = await http.get(`/v2/business/operation/get-cos-temp-token?audience=${audience}`, {
|
|
89
|
+
params: {
|
|
90
|
+
content_length: contentLength,
|
|
91
|
+
...restContext
|
|
92
|
+
},
|
|
93
|
+
headers: gameId !== void 0 ? { "x-service-type": String(gameId) } : void 0
|
|
94
|
+
});
|
|
95
|
+
return resolveCredential(res, normalizeSnake, customNormalize);
|
|
96
|
+
}
|
|
97
|
+
case "default_download": {
|
|
98
|
+
const { gameId, ...restContext } = context;
|
|
99
|
+
const res = await http.post(
|
|
100
|
+
`/v2/business/operation/get-download-cos-temp-token?audience=${audience}`,
|
|
101
|
+
{
|
|
102
|
+
file_url: fileUrl,
|
|
103
|
+
content_length: contentLength,
|
|
104
|
+
...restContext
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
headers: gameId !== void 0 ? { "x-service-type": String(gameId) } : void 0
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
return resolveCredential(res, normalizeSnake, customNormalize);
|
|
111
|
+
}
|
|
112
|
+
case "sdk_customize": {
|
|
113
|
+
const res = await http.post("/internal/sdk_customize/upload_token", {
|
|
114
|
+
content_length: contentLength,
|
|
115
|
+
...context
|
|
116
|
+
});
|
|
117
|
+
return resolveCredential(res, normalizeSdkCustomize, customNormalize);
|
|
118
|
+
}
|
|
119
|
+
case "ai_translate": {
|
|
120
|
+
const res = await http.post("/business/aiTranslate/import/cosToken", {
|
|
121
|
+
contentLength,
|
|
122
|
+
...context
|
|
123
|
+
});
|
|
124
|
+
return resolveCredential(res, normalizeAiTranslate, customNormalize);
|
|
125
|
+
}
|
|
126
|
+
default: {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`[PntCosUploader] 未支持的 scene: ${scene};请通过 getCredential 自定义`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
134
|
+
0 && (module.exports = {
|
|
135
|
+
fetchCosCredential,
|
|
136
|
+
normalizeSnakeCredential
|
|
137
|
+
});
|