@pnt-team/pnt-component-frontend 0.0.96 → 0.0.99

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.
@@ -4,6 +4,8 @@ import { useCallback, useMemo, useSyncExternalStore } from 'react';
4
4
 
5
5
  /** 单个解锁项 */
6
6
 
7
+ /** 单次请求的接口配置覆盖(优先级 > PntProvider 全局配置) */
8
+
7
9
  /** 高敏数据解锁请求参数(组件层友好命名,库内部转换为后端 snake_case) */
8
10
 
9
11
  /** hook 初始化 scope:传入后 securityData/isUnlocked 自动按该业务+环境过滤 */
@@ -83,7 +85,8 @@ const getDefaultPageId = () => typeof window !== 'undefined' && window.location
83
85
  */
84
86
  export const useHighSecurity = options => {
85
87
  const {
86
- http
88
+ http,
89
+ highSecurity: globalHighSecurity
87
90
  } = usePntConfig();
88
91
  const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
89
92
  const scopeGameId = options?.gameId === undefined ? undefined : String(options.gameId);
@@ -109,23 +112,34 @@ export const useHighSecurity = options => {
109
112
  gameId,
110
113
  env,
111
114
  pageId,
112
- param
115
+ param,
116
+ apiConfig
113
117
  }) => {
114
118
  const gid = String(gameId);
115
- const eid = String(env);
119
+ const eid = String(env ?? 0);
120
+
121
+ // 合并接口配置:单次传入 > PntProvider 全局
122
+ const merged = {
123
+ ...globalHighSecurity,
124
+ ...apiConfig
125
+ };
126
+ const successCodeField = merged.successCodeField || 'code';
116
127
  const result = new Array(param.length);
117
128
  const missing = [];
118
129
  const missingIndexes = [];
119
130
 
120
- // 已缓存的 key 不再请求
131
+ // 已缓存的 key(cacheKey 优先)不再请求
121
132
  param.forEach((item, index) => {
122
- const cached = snapshot.get(buildCacheKey(gid, eid, item.key));
133
+ const storeKey = item.cacheKey || item.key;
134
+ const cached = snapshot.get(buildCacheKey(gid, eid, storeKey));
123
135
  if (cached !== undefined) {
124
136
  result[index] = {
125
137
  key: item.key,
126
- value: cached
138
+ value: cached,
139
+ cacheKey: storeKey
127
140
  };
128
141
  } else {
142
+ // 请求体只用 key/value,不含 cacheKey
129
143
  missing.push({
130
144
  key: item.key,
131
145
  value: item.value
@@ -138,19 +152,27 @@ export const useHighSecurity = options => {
138
152
  }
139
153
  const body = {
140
154
  game_id: Number(gameId),
141
- env: Number(env),
155
+ env: Number(env ?? 0),
142
156
  page_id: pageId || getDefaultPageId(),
143
157
  param: missing
144
158
  };
145
159
 
160
+ // 拼接 URL:decryptUrl 优先;否则用 audience 覆盖默认
161
+ let url = merged.decryptUrl;
162
+ if (!url) {
163
+ const audience = merged.audience || '/laas-pnt';
164
+ url = `/v3/business/game_info/high-security-decrypt?audience=${audience}`;
165
+ }
166
+
146
167
  // 请求级并发去重:同一业务+环境+参数列表指纹在途时复用
147
168
  const requestKey = `${gid}:${eid}:${missing.map(item => `${item.key}\u0001${item.value}`).join('\u0002')}`;
148
169
  const existing = inflightRequests.get(requestKey);
149
170
  if (existing) return existing;
150
171
  const promise = (async () => {
151
172
  try {
152
- const res = await businessGameInfoHighSecurityDecrypt(http, body);
153
- if (res.code === 0 && Array.isArray(res.data)) {
173
+ const res = await businessGameInfoHighSecurityDecrypt(http, body, url);
174
+ const successCode = Number(res[successCodeField] ?? res.code);
175
+ if (successCode === 0 && Array.isArray(res.data)) {
154
176
  // yapi 生成类型为 Record<string, unknown>[],按运行时结构收窄
155
177
  const decrypted = res.data.map(raw => {
156
178
  if (raw && typeof raw === 'object' && 'key' in raw) {
@@ -164,14 +186,24 @@ export const useHighSecurity = options => {
164
186
  }
165
187
  return null;
166
188
  }).filter(item => item !== null);
167
- setEntries(gid, eid, decrypted);
189
+ // 写入缓存时用调用方提供的 cacheKey 映射
190
+ const toStore = decrypted.map(d => {
191
+ const matchIdx = missingIndexes.find(i => param[i].key === d.key);
192
+ const storeKey = matchIdx !== undefined ? param[matchIdx].cacheKey || d.key : d.key;
193
+ return {
194
+ key: d.key,
195
+ value: d.value,
196
+ cacheKey: storeKey
197
+ };
198
+ });
199
+ setEntries(gid, eid, toStore);
168
200
  decrypted.forEach(item => {
169
201
  const index = missingIndexes.find(i => param[i].key === item.key);
170
202
  if (index !== undefined) result[index] = item;
171
203
  });
172
204
  } else {
173
205
  // eslint-disable-next-line no-console
174
- console.warn('[pnt-component-frontend] high-security-decrypt 解锁失败', res?.msg ?? res?.code);
206
+ console.warn('[pnt-component-frontend] high-security-decrypt 解锁失败', res?.msg ?? res[successCodeField]);
175
207
  }
176
208
  } catch (error) {
177
209
  // eslint-disable-next-line no-console
@@ -183,7 +215,7 @@ export const useHighSecurity = options => {
183
215
  })();
184
216
  inflightRequests.set(requestKey, promise);
185
217
  return promise;
186
- }, [http, snapshot]);
218
+ }, [http, snapshot, globalHighSecurity]);
187
219
  const clearSecurityData = useCallback(filter => {
188
220
  clearEntries(filter);
189
221
  }, []);
@@ -1,4 +1,4 @@
1
- export { PntProvider, usePntConfig, type PntConfig, type commonEesType, } from './config';
1
+ export { PntProvider, usePntConfig, type PntConfig, type PntHttpLike, type PntHighSecurityConfig, type commonEesType, } from './config';
2
2
  export { default as PntImage } from './components/PntImage';
3
3
  export { default as PntBusinessSelect } from './components/PntBusinessSelect';
4
4
  export { default as PntSecureBox } from './components/PntSecureBox';
@@ -6,6 +6,6 @@ export { default as PntUpload } from './components/PntUpload';
6
6
  export type { PntUploadErrorPhase, PntUploadProps, PntUploadTexts, } from './components/PntUpload';
7
7
  export { createPntCosUploader, normalizeSnakeCredential, default as usePntCosUploader, type CosScene, type FileNameStrategy, type GetCosCredentialParams, type NormalizeCredential, type NormalizedCosCredential, type PntCosRequestOverrides, type PntCosUploadOptions, type PntCosUploadResult, type PntCosUploader as PntCosUploaderInstance, } from './components/PntCosUploader';
8
8
  export { useHighSecurity } from './hooks/useHighSecurity';
9
- export type { ClearSecurityDataFilter, HighSecurityParamItem, HighSecurityRequestParams, UseHighSecurityOptions, UseHighSecurityResult, } from './hooks/useHighSecurity';
9
+ export type { ClearSecurityDataFilter, HighSecurityApiConfig, HighSecurityParamItem, HighSecurityRequestParams, UseHighSecurityOptions, UseHighSecurityResult, } from './hooks/useHighSecurity';
10
10
  export { isSecurityData } from './utils';
11
11
  export { default as PntGeneralLayout } from './components/PntGeneralLayout';