@pnt-team/pnt-component-frontend 0.0.41 → 0.0.45
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/lib/cjs/components/PntBusinessSelect/index.d.ts +172 -0
- package/lib/cjs/components/PntBusinessSelect/index.js +243 -0
- package/lib/cjs/components/PntBusinessSelect/index.scss +3 -0
- package/lib/cjs/components/PntGeneralLayout/index.d.ts +1 -1
- package/lib/cjs/components/PntSecureBox/index.d.ts +23 -8
- package/lib/cjs/components/PntSecureBox/index.js +3 -1
- package/lib/cjs/hooks/useHighSecurity.d.ts +8 -9
- package/lib/cjs/hooks/useHighSecurity.js +14 -7
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.js +3 -0
- package/lib/esm/components/PntBusinessSelect/index.d.ts +172 -0
- package/lib/esm/components/PntBusinessSelect/index.js +229 -0
- package/lib/esm/components/PntBusinessSelect/index.scss +3 -0
- package/lib/esm/components/PntGeneralLayout/index.d.ts +1 -1
- package/lib/esm/components/PntSecureBox/index.d.ts +23 -8
- package/lib/esm/components/PntSecureBox/index.js +3 -1
- package/lib/esm/hooks/useHighSecurity.d.ts +8 -9
- package/lib/esm/hooks/useHighSecurity.js +14 -7
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +6 -4
- package/lib/umd/pnt-component-frontend.min.css +1 -1
- package/lib/umd/pnt-component-frontend.min.js +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { BusinessSelectListBody, BusinessSelectListResponse } from "../../api/types";
|
|
2
|
+
import type { commonEesType } from "../../utils/request";
|
|
3
|
+
import React, { FC } from 'react';
|
|
4
|
+
import type { SelectValue, TdSelectProps } from 'tdesign-react/es/select/type';
|
|
5
|
+
import './index.scss';
|
|
6
|
+
/** 业务列表请求函数:返回 commonEesType 结构,code === 0 视为成功 */
|
|
7
|
+
export type BusinessSelectFetcher = (params: BusinessSelectListBody) => Promise<commonEesType<BusinessSelectListResponse>>;
|
|
8
|
+
/** 下拉场景 */
|
|
9
|
+
type Scene = 'default' | 'sdk' | 'compliance_age' | 'custom_region';
|
|
10
|
+
/** 标签格式 */
|
|
11
|
+
type LabelFormat = 'name' | 'name_en' | 'name_id' | 'name_en_id';
|
|
12
|
+
interface PntBusinessSelectProps {
|
|
13
|
+
/**
|
|
14
|
+
* 业务列表请求函数
|
|
15
|
+
* @description 不传时使用组件库内置的 `businessSelectList` API(对接 `/api/business/select/list`);
|
|
16
|
+
* 需要覆盖时传入自定义请求函数(如各项目自己的 http 封装)
|
|
17
|
+
*/
|
|
18
|
+
fetcher?: BusinessSelectFetcher;
|
|
19
|
+
/**
|
|
20
|
+
* 当前选中值
|
|
21
|
+
* @description 单选为 string,多选为 string[]
|
|
22
|
+
*/
|
|
23
|
+
value?: SelectValue;
|
|
24
|
+
/**
|
|
25
|
+
* 值变化回调
|
|
26
|
+
*/
|
|
27
|
+
onChange?: TdSelectProps['onChange'];
|
|
28
|
+
/**
|
|
29
|
+
* 是否多选
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
multiple?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* 下拉场景
|
|
35
|
+
* @description 后端按场景返回默认字段集
|
|
36
|
+
* @default 'default'
|
|
37
|
+
*/
|
|
38
|
+
scene?: Scene;
|
|
39
|
+
/**
|
|
40
|
+
* 业务状态筛选
|
|
41
|
+
* @description 3-线上运营,4-接入中,5-中途结项,6-已下线
|
|
42
|
+
*/
|
|
43
|
+
statuses?: number[];
|
|
44
|
+
/**
|
|
45
|
+
* 业务类型筛选
|
|
46
|
+
* @description 1-正式业务,2-测试业务
|
|
47
|
+
*/
|
|
48
|
+
businessTypes?: number[];
|
|
49
|
+
/**
|
|
50
|
+
* 业务接入类型筛选
|
|
51
|
+
* @description 1-纯SDK,2-LI PASS,3-工作室品牌账号
|
|
52
|
+
*/
|
|
53
|
+
businessAccessMethod?: number;
|
|
54
|
+
/**
|
|
55
|
+
* 标签格式
|
|
56
|
+
* @description name-中文名,name_en-英文名,name_id-中文名(ID),name_en_id-英文名(ID)
|
|
57
|
+
* @default 'name'
|
|
58
|
+
*/
|
|
59
|
+
labelFormat?: LabelFormat;
|
|
60
|
+
/**
|
|
61
|
+
* 占位提示文案
|
|
62
|
+
*/
|
|
63
|
+
placeholder?: string;
|
|
64
|
+
/**
|
|
65
|
+
* 是否禁用整个选择器
|
|
66
|
+
* @default false
|
|
67
|
+
*/
|
|
68
|
+
disabled?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* 是否可清除
|
|
71
|
+
* @default true
|
|
72
|
+
*/
|
|
73
|
+
clearable?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* 是否可远程搜索
|
|
76
|
+
* @default true
|
|
77
|
+
*/
|
|
78
|
+
filterable?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* 多选时最大可选数量
|
|
81
|
+
*/
|
|
82
|
+
max?: number;
|
|
83
|
+
/**
|
|
84
|
+
* 每页条数
|
|
85
|
+
* @default 20
|
|
86
|
+
*/
|
|
87
|
+
pageSize?: number;
|
|
88
|
+
/**
|
|
89
|
+
* 搜索防抖延迟(毫秒)
|
|
90
|
+
* @default 400
|
|
91
|
+
*/
|
|
92
|
+
searchDebounce?: number;
|
|
93
|
+
/**
|
|
94
|
+
* 多选时最少折叠数量
|
|
95
|
+
* @description 超过此数量的选中项将折叠显示,透传至 TDesign Select
|
|
96
|
+
*/
|
|
97
|
+
minCollapsedNum?: number;
|
|
98
|
+
/**
|
|
99
|
+
* 折叠项自定义渲染
|
|
100
|
+
* @description 透传至 TDesign Select collapsedItems
|
|
101
|
+
*/
|
|
102
|
+
collapsedItems?: TdSelectProps['collapsedItems'];
|
|
103
|
+
/**
|
|
104
|
+
* 弹层属性透传
|
|
105
|
+
* @description 会与组件内部 onScrollToBottom 合并;常用 attach(挂载容器)、overlayClassName 等
|
|
106
|
+
*/
|
|
107
|
+
popupProps?: Partial<TdSelectProps['popupProps']>;
|
|
108
|
+
/**
|
|
109
|
+
* 自定义类名
|
|
110
|
+
*/
|
|
111
|
+
className?: string;
|
|
112
|
+
/**
|
|
113
|
+
* 自定义样式
|
|
114
|
+
*/
|
|
115
|
+
style?: React.CSSProperties;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 业务选择器组件
|
|
119
|
+
* @description 统一业务下拉选择器,内置对接后端通用接口 `/api/business/select/list`,
|
|
120
|
+
* 支持远程搜索、滚动分页加载、多选、场景化禁用(合规场景 creatable 字段)。
|
|
121
|
+
* 默认使用组件库内置 `businessSelectList` API,无需传 fetcher 即可工作;
|
|
122
|
+
* 各项目如需覆盖请求逻辑,传入自定义 `fetcher` 即可。
|
|
123
|
+
*
|
|
124
|
+
* @param {PntBusinessSelectProps} props - 组件属性
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```tsx
|
|
128
|
+
* import { PntBusinessSelect } from '@pnt-team/pnt-component-frontend';
|
|
129
|
+
*
|
|
130
|
+
* // 最简用法(内置 fetcher,无需传)
|
|
131
|
+
* <PntBusinessSelect
|
|
132
|
+
* value={gameId}
|
|
133
|
+
* onChange={(v) => setGameId(v as string)}
|
|
134
|
+
* />
|
|
135
|
+
*
|
|
136
|
+
* // SDK 定制场景 + 名称带 ID
|
|
137
|
+
* <PntBusinessSelect
|
|
138
|
+
* scene="sdk"
|
|
139
|
+
* labelFormat="name_id"
|
|
140
|
+
* value={gameId}
|
|
141
|
+
* onChange={(v) => setGameId(v as string)}
|
|
142
|
+
* />
|
|
143
|
+
*
|
|
144
|
+
* // 合规年龄场景(自动禁用 creatable=false 的业务)
|
|
145
|
+
* <PntBusinessSelect
|
|
146
|
+
* scene="compliance_age"
|
|
147
|
+
* value={gameId}
|
|
148
|
+
* onChange={(v) => setGameId(v as string)}
|
|
149
|
+
* />
|
|
150
|
+
*
|
|
151
|
+
* // 多选 + 状态过滤
|
|
152
|
+
* <PntBusinessSelect
|
|
153
|
+
* multiple
|
|
154
|
+
* statuses={[3, 4]}
|
|
155
|
+
* labelFormat="name_id"
|
|
156
|
+
* value={gameIds}
|
|
157
|
+
* onChange={(v) => setGameIds(v as string[])}
|
|
158
|
+
* />
|
|
159
|
+
*
|
|
160
|
+
* // 注入自定义 fetcher(覆盖内置 API)
|
|
161
|
+
* import http from '@/utils/request';
|
|
162
|
+
* <PntBusinessSelect
|
|
163
|
+
* fetcher={(params) => http.post('/api/business/select/list', params)}
|
|
164
|
+
* value={gameId}
|
|
165
|
+
* onChange={(v) => setGameId(v as string)}
|
|
166
|
+
* />
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* @returns {ReactElement} 业务选择器组件
|
|
170
|
+
*/
|
|
171
|
+
declare const PntBusinessSelect: FC<PntBusinessSelectProps>;
|
|
172
|
+
export default PntBusinessSelect;
|
|
@@ -0,0 +1,243 @@
|
|
|
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/components/PntBusinessSelect/index.tsx
|
|
20
|
+
var PntBusinessSelect_exports = {};
|
|
21
|
+
__export(PntBusinessSelect_exports, {
|
|
22
|
+
default: () => PntBusinessSelect_default
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(PntBusinessSelect_exports);
|
|
25
|
+
var import_api = require("../../api");
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
var import_tdesign_react = require("tdesign-react");
|
|
28
|
+
var import_index = require("./index.scss");
|
|
29
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
30
|
+
var PntBusinessSelect = (props) => {
|
|
31
|
+
const {
|
|
32
|
+
fetcher,
|
|
33
|
+
value,
|
|
34
|
+
onChange,
|
|
35
|
+
multiple = false,
|
|
36
|
+
scene = "default",
|
|
37
|
+
statuses,
|
|
38
|
+
businessTypes,
|
|
39
|
+
businessAccessMethod,
|
|
40
|
+
labelFormat = "name",
|
|
41
|
+
placeholder,
|
|
42
|
+
disabled,
|
|
43
|
+
clearable = true,
|
|
44
|
+
filterable = true,
|
|
45
|
+
max,
|
|
46
|
+
pageSize = 20,
|
|
47
|
+
searchDebounce = 400,
|
|
48
|
+
minCollapsedNum,
|
|
49
|
+
collapsedItems,
|
|
50
|
+
popupProps,
|
|
51
|
+
className,
|
|
52
|
+
style
|
|
53
|
+
} = props;
|
|
54
|
+
const requestFn = (0, import_react.useCallback)(
|
|
55
|
+
(params) => (fetcher || import_api.businessSelectList)(params),
|
|
56
|
+
[fetcher]
|
|
57
|
+
);
|
|
58
|
+
const [options, setOptions] = (0, import_react.useState)(
|
|
59
|
+
[]
|
|
60
|
+
);
|
|
61
|
+
const [loading, setLoading] = (0, import_react.useState)(false);
|
|
62
|
+
const [keyword, setKeyword] = (0, import_react.useState)("");
|
|
63
|
+
const [pageNum, setPageNum] = (0, import_react.useState)(1);
|
|
64
|
+
const [total, setTotal] = (0, import_react.useState)(0);
|
|
65
|
+
const debounceRef = (0, import_react.useRef)();
|
|
66
|
+
const loadingRef = (0, import_react.useRef)(false);
|
|
67
|
+
const selectedItemsRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
|
|
68
|
+
const buildParams = (0, import_react.useCallback)(
|
|
69
|
+
(kw, page) => ({
|
|
70
|
+
keyword: kw || void 0,
|
|
71
|
+
pageNum: page,
|
|
72
|
+
pageSize,
|
|
73
|
+
scene,
|
|
74
|
+
statuses,
|
|
75
|
+
business_types: businessTypes,
|
|
76
|
+
business_access_method: businessAccessMethod
|
|
77
|
+
}),
|
|
78
|
+
[scene, statuses, businessTypes, businessAccessMethod, pageSize]
|
|
79
|
+
);
|
|
80
|
+
const fetchData = (0, import_react.useCallback)(
|
|
81
|
+
async (kw, page, append) => {
|
|
82
|
+
var _a;
|
|
83
|
+
if (loadingRef.current)
|
|
84
|
+
return;
|
|
85
|
+
loadingRef.current = true;
|
|
86
|
+
setLoading(true);
|
|
87
|
+
try {
|
|
88
|
+
const res = await requestFn(buildParams(kw, page));
|
|
89
|
+
if (res.code === 0 && res.data) {
|
|
90
|
+
const newList = res.data.list || [];
|
|
91
|
+
setOptions((prev) => append ? [...prev, ...newList] : newList);
|
|
92
|
+
setTotal(((_a = res.data.pagination) == null ? void 0 : _a.total) || 0);
|
|
93
|
+
setPageNum(page);
|
|
94
|
+
}
|
|
95
|
+
} finally {
|
|
96
|
+
loadingRef.current = false;
|
|
97
|
+
setLoading(false);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
[requestFn, buildParams]
|
|
101
|
+
);
|
|
102
|
+
const handleSearch = (0, import_react.useCallback)(
|
|
103
|
+
(val) => {
|
|
104
|
+
setKeyword(val);
|
|
105
|
+
if (debounceRef.current)
|
|
106
|
+
clearTimeout(debounceRef.current);
|
|
107
|
+
debounceRef.current = setTimeout(() => {
|
|
108
|
+
fetchData(val, 1, false);
|
|
109
|
+
}, searchDebounce);
|
|
110
|
+
},
|
|
111
|
+
[fetchData, searchDebounce]
|
|
112
|
+
);
|
|
113
|
+
const handleScrollToBottom = (0, import_react.useCallback)(() => {
|
|
114
|
+
if (!loadingRef.current && options.length < total) {
|
|
115
|
+
fetchData(keyword, pageNum + 1, true);
|
|
116
|
+
}
|
|
117
|
+
}, [options.length, total, keyword, pageNum, fetchData]);
|
|
118
|
+
const handlePopupVisibleChange = (0, import_react.useCallback)(
|
|
119
|
+
(visible) => {
|
|
120
|
+
if (!visible && keyword) {
|
|
121
|
+
setKeyword("");
|
|
122
|
+
fetchData("", 1, false);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
[keyword, fetchData]
|
|
126
|
+
);
|
|
127
|
+
(0, import_react.useEffect)(() => {
|
|
128
|
+
fetchData("", 1, false);
|
|
129
|
+
}, [fetchData]);
|
|
130
|
+
(0, import_react.useEffect)(() => {
|
|
131
|
+
const selectedValues = Array.isArray(value) ? value : value ? [value] : [];
|
|
132
|
+
options.forEach((item) => {
|
|
133
|
+
if (item.game_id && selectedValues.includes(item.game_id)) {
|
|
134
|
+
selectedItemsRef.current.set(item.game_id, item);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}, [options, value]);
|
|
138
|
+
(0, import_react.useEffect)(() => {
|
|
139
|
+
return () => {
|
|
140
|
+
if (debounceRef.current)
|
|
141
|
+
clearTimeout(debounceRef.current);
|
|
142
|
+
};
|
|
143
|
+
}, []);
|
|
144
|
+
const formatLabel = (0, import_react.useCallback)(
|
|
145
|
+
(item) => {
|
|
146
|
+
const name = item.name || "";
|
|
147
|
+
const nameEn = item.name_en || "";
|
|
148
|
+
const gameId = item.game_id || "";
|
|
149
|
+
switch (labelFormat) {
|
|
150
|
+
case "name_en":
|
|
151
|
+
return nameEn || name;
|
|
152
|
+
case "name_id":
|
|
153
|
+
return `${name}(${gameId})`;
|
|
154
|
+
case "name_en_id":
|
|
155
|
+
return `${nameEn}(${gameId})`;
|
|
156
|
+
default:
|
|
157
|
+
return name;
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
[labelFormat]
|
|
161
|
+
);
|
|
162
|
+
const isOptionDisabled = (0, import_react.useCallback)(
|
|
163
|
+
(item) => {
|
|
164
|
+
if (scene === "compliance_age" || scene === "custom_region") {
|
|
165
|
+
return !item.creatable;
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
},
|
|
169
|
+
[scene]
|
|
170
|
+
);
|
|
171
|
+
const selectOptions = (0, import_react.useMemo)(() => {
|
|
172
|
+
const map = /* @__PURE__ */ new Map();
|
|
173
|
+
options.forEach((item) => {
|
|
174
|
+
if (item.game_id) {
|
|
175
|
+
map.set(item.game_id, {
|
|
176
|
+
label: formatLabel(item),
|
|
177
|
+
value: item.game_id,
|
|
178
|
+
disabled: isOptionDisabled(item),
|
|
179
|
+
name: item.name,
|
|
180
|
+
name_en: item.name_en,
|
|
181
|
+
game_id: item.game_id
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
const selectedValues = Array.isArray(value) ? value : value ? [value] : [];
|
|
186
|
+
selectedValues.forEach((id) => {
|
|
187
|
+
if (!map.has(id)) {
|
|
188
|
+
const item = selectedItemsRef.current.get(id);
|
|
189
|
+
if (item) {
|
|
190
|
+
map.set(id, {
|
|
191
|
+
label: formatLabel(item),
|
|
192
|
+
value: id,
|
|
193
|
+
disabled: isOptionDisabled(item),
|
|
194
|
+
name: item.name,
|
|
195
|
+
name_en: item.name_en,
|
|
196
|
+
game_id: item.game_id
|
|
197
|
+
});
|
|
198
|
+
} else {
|
|
199
|
+
map.set(id, { label: id, value: id, disabled: false });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
return Array.from(map.values());
|
|
204
|
+
}, [options, value, formatLabel, isOptionDisabled]);
|
|
205
|
+
const localFilter = (0, import_react.useCallback)(
|
|
206
|
+
(filterWord, option) => {
|
|
207
|
+
if (!filterWord)
|
|
208
|
+
return true;
|
|
209
|
+
const kw = filterWord.toLowerCase();
|
|
210
|
+
const opt = option;
|
|
211
|
+
return ((opt == null ? void 0 : opt.name) || "").toLowerCase().includes(kw) || ((opt == null ? void 0 : opt.name_en) || "").toLowerCase().includes(kw) || ((opt == null ? void 0 : opt.game_id) || "").includes(kw);
|
|
212
|
+
},
|
|
213
|
+
[]
|
|
214
|
+
);
|
|
215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
216
|
+
import_tdesign_react.Select,
|
|
217
|
+
{
|
|
218
|
+
value,
|
|
219
|
+
onChange,
|
|
220
|
+
options: selectOptions,
|
|
221
|
+
filterable,
|
|
222
|
+
filter: filterable ? localFilter : void 0,
|
|
223
|
+
onSearch: filterable ? handleSearch : void 0,
|
|
224
|
+
loading: loading && options.length === 0,
|
|
225
|
+
multiple,
|
|
226
|
+
max,
|
|
227
|
+
clearable,
|
|
228
|
+
disabled,
|
|
229
|
+
placeholder,
|
|
230
|
+
minCollapsedNum,
|
|
231
|
+
collapsedItems,
|
|
232
|
+
onPopupVisibleChange: handlePopupVisibleChange,
|
|
233
|
+
panelBottomContent: options.length > 0 && loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tdesign_react.Loading, { loading: true, size: "small" }) : null,
|
|
234
|
+
popupProps: {
|
|
235
|
+
...popupProps,
|
|
236
|
+
onScrollToBottom: handleScrollToBottom
|
|
237
|
+
},
|
|
238
|
+
className: className ? `pnt-business-select ${className}` : "pnt-business-select",
|
|
239
|
+
style
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
var PntBusinessSelect_default = PntBusinessSelect;
|
|
@@ -41,13 +41,18 @@ interface PntSecureBoxProps {
|
|
|
41
41
|
pageId?: string;
|
|
42
42
|
/**
|
|
43
43
|
* 高敏数据请求函数
|
|
44
|
-
* @description
|
|
44
|
+
* @description 不传时使用组件库内置的 `businessGameInfoHighSecurityDecrypt` API
|
|
45
|
+
* (对接 `/api/v3/business/game_info/high-security-decrypt`);
|
|
46
|
+
* 需要覆盖时传入自定义请求函数(如各项目自己的 http 封装)
|
|
45
47
|
*/
|
|
46
|
-
fetcher
|
|
48
|
+
fetcher?: HighSecurityFetcher;
|
|
47
49
|
}
|
|
48
50
|
/**
|
|
49
51
|
* 高敏信息展示统一组件
|
|
50
|
-
* @description
|
|
52
|
+
* @description 用于统一处理和展示高敏信息,支持脱敏显示和按需获取真实数据。
|
|
53
|
+
* 默认使用组件库内置 `businessGameInfoHighSecurityDecrypt` API,无需传 fetcher 即可工作;
|
|
54
|
+
* 各项目如需覆盖请求逻辑,传入自定义 `fetcher` 即可。
|
|
55
|
+
*
|
|
51
56
|
* @param {PntSecureBoxProps} props - 组件属性
|
|
52
57
|
* @param {string} props.dataKey - 高敏信息的唯一标识 key
|
|
53
58
|
* @param {string} props.dataValue - 高敏信息的实际值
|
|
@@ -56,22 +61,32 @@ interface PntSecureBoxProps {
|
|
|
56
61
|
* @param {(content: string) => React.ReactNode} props.renderDom - 自定义渲染函数
|
|
57
62
|
* @param {string} [props.viewText] - 自定义查看按钮文案
|
|
58
63
|
* @param {string} [props.pageId] - 页面 ID
|
|
59
|
-
* @param {HighSecurityFetcher} props.fetcher -
|
|
64
|
+
* @param {HighSecurityFetcher} [props.fetcher] - 高敏数据请求函数(可选,不传用内置 API)
|
|
60
65
|
*
|
|
61
66
|
* @example
|
|
62
67
|
* ```tsx
|
|
63
|
-
* import http from '@/utils/request';
|
|
64
68
|
* import { PntSecureBox } from '@pnt-team/pnt-component-frontend';
|
|
65
69
|
*
|
|
70
|
+
* // 最简用法(内置 API,无需传 fetcher)
|
|
66
71
|
* <PntSecureBox
|
|
67
72
|
* dataKey="userPhone"
|
|
68
|
-
* dataValue="
|
|
69
|
-
* env=
|
|
73
|
+
* dataValue="_high_security_:AAAA...:6542"
|
|
74
|
+
* env={2}
|
|
70
75
|
* gameId={12345}
|
|
71
|
-
* fetcher={(params) => http.post('/api/v3/business/game_info/high-security-decrypt', params).then(r => r.data)}
|
|
72
76
|
* renderDom={(content) => <span>{content}</span>}
|
|
73
77
|
* viewText="查看"
|
|
74
78
|
* />
|
|
79
|
+
*
|
|
80
|
+
* // 注入自定义 fetcher(覆盖内置 API)
|
|
81
|
+
* import http from '@/utils/request';
|
|
82
|
+
* <PntSecureBox
|
|
83
|
+
* dataKey="userPhone"
|
|
84
|
+
* dataValue="_high_security_:AAAA...:6542"
|
|
85
|
+
* env={2}
|
|
86
|
+
* gameId={12345}
|
|
87
|
+
* fetcher={(params) => http.post('/api/v3/business/game_info/high-security-decrypt', params)}
|
|
88
|
+
* renderDom={(content) => <span>{content}</span>}
|
|
89
|
+
* />
|
|
75
90
|
* ```
|
|
76
91
|
*
|
|
77
92
|
* @returns {ReactElement} 高敏信息展示组件
|
|
@@ -22,6 +22,7 @@ __export(PntSecureBox_exports, {
|
|
|
22
22
|
default: () => PntSecureBox_default
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(PntSecureBox_exports);
|
|
25
|
+
var import_api = require("../../api");
|
|
25
26
|
var import_useHighSecurity = require("../../hooks/useHighSecurity");
|
|
26
27
|
var import_utils = require("../../utils");
|
|
27
28
|
var import_index = require("./index.scss");
|
|
@@ -37,7 +38,8 @@ var PntSecureBox = (prop) => {
|
|
|
37
38
|
pageId,
|
|
38
39
|
fetcher
|
|
39
40
|
} = prop;
|
|
40
|
-
const
|
|
41
|
+
const requestFn = fetcher || import_api.businessGameInfoHighSecurityDecrypt;
|
|
42
|
+
const { securityData, requestSecurityData } = (0, import_useHighSecurity.useHighSecurity)(requestFn);
|
|
41
43
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pnt-secure-box", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
42
44
|
renderDom(
|
|
43
45
|
(0, import_utils.isSecurityData)(dataValue) ? securityData[dataKey] || "******" : dataValue
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { BusinessGameInfoHighSecurityDecryptBody, BusinessGameInfoHighSecurityDecryptResponse } from "../api/types";
|
|
2
|
+
import type { commonEesType } from "../utils/request";
|
|
3
|
+
/** 高敏数据请求参数(组件层友好命名) */
|
|
2
4
|
export interface HighSecurityRequestParams {
|
|
3
5
|
/** 游戏 ID */
|
|
4
6
|
gameId: string | number;
|
|
@@ -12,14 +14,11 @@ export interface HighSecurityRequestParams {
|
|
|
12
14
|
value: string;
|
|
13
15
|
}>;
|
|
14
16
|
}
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
value: string;
|
|
21
|
-
}>;
|
|
22
|
-
}>;
|
|
17
|
+
/**
|
|
18
|
+
* 高敏数据请求函数:返回 commonEesType 结构,code === 0 视为成功
|
|
19
|
+
* 不传时使用组件库内置的 `businessGameInfoHighSecurityDecrypt` API
|
|
20
|
+
*/
|
|
21
|
+
export type HighSecurityFetcher = (params: BusinessGameInfoHighSecurityDecryptBody) => Promise<commonEesType<BusinessGameInfoHighSecurityDecryptResponse>>;
|
|
23
22
|
/**
|
|
24
23
|
* 高敏数据解锁 Hook(PntSecureBox 内部依赖)
|
|
25
24
|
* @internal 不对外导出,归 PntSecureBox 组件内部使用
|
|
@@ -40,14 +40,21 @@ var useHighSecurity = (fetcher) => {
|
|
|
40
40
|
env,
|
|
41
41
|
pageId
|
|
42
42
|
}) => {
|
|
43
|
-
const
|
|
44
|
-
gameId,
|
|
43
|
+
const body = {
|
|
44
|
+
game_id: Number(gameId),
|
|
45
45
|
env: Number(env),
|
|
46
|
-
|
|
47
|
-
param
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
page_id: pageId || location.pathname,
|
|
47
|
+
param: param.map(
|
|
48
|
+
(i) => ({
|
|
49
|
+
key: i.key,
|
|
50
|
+
value: i.value
|
|
51
|
+
})
|
|
52
|
+
)
|
|
53
|
+
};
|
|
54
|
+
const result = await fetcher(body);
|
|
55
|
+
if (result.code === 0 && result.data) {
|
|
56
|
+
const data = result.data;
|
|
57
|
+
data.forEach((item) => {
|
|
51
58
|
securityCache.set(item.key, item.value);
|
|
52
59
|
});
|
|
53
60
|
setSecurityData(Object.fromEntries(securityCache));
|
package/lib/cjs/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { default as PntImagePreview } from './components/PntImagePreview';
|
|
2
|
+
export { default as PntBusinessSelect } from './components/PntBusinessSelect';
|
|
2
3
|
export { default as PntSecureBox } from './components/PntSecureBox';
|
|
3
4
|
export { default as PntGeneralLayout } from './components/PntGeneralLayout';
|
package/lib/cjs/index.js
CHANGED
|
@@ -29,16 +29,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
// src/index.ts
|
|
30
30
|
var src_exports = {};
|
|
31
31
|
__export(src_exports, {
|
|
32
|
+
PntBusinessSelect: () => import_PntBusinessSelect.default,
|
|
32
33
|
PntGeneralLayout: () => import_PntGeneralLayout.default,
|
|
33
34
|
PntImagePreview: () => import_PntImagePreview.default,
|
|
34
35
|
PntSecureBox: () => import_PntSecureBox.default
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(src_exports);
|
|
37
38
|
var import_PntImagePreview = __toESM(require("./components/PntImagePreview"));
|
|
39
|
+
var import_PntBusinessSelect = __toESM(require("./components/PntBusinessSelect"));
|
|
38
40
|
var import_PntSecureBox = __toESM(require("./components/PntSecureBox"));
|
|
39
41
|
var import_PntGeneralLayout = __toESM(require("./components/PntGeneralLayout"));
|
|
40
42
|
// Annotate the CommonJS export names for ESM import in node:
|
|
41
43
|
0 && (module.exports = {
|
|
44
|
+
PntBusinessSelect,
|
|
42
45
|
PntGeneralLayout,
|
|
43
46
|
PntImagePreview,
|
|
44
47
|
PntSecureBox
|