@pnt-team/pnt-component-frontend 0.0.137 → 0.0.138
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/PntRegionSelect/index.scss +2 -2
- package/package.json +1 -1
- package/lib/cjs/api/cos.d.ts +0 -103
- package/lib/cjs/api/cos.js +0 -146
- package/lib/cjs/api/index.d.ts +0 -23
- package/lib/cjs/api/index.js +0 -38
- package/lib/cjs/api/types/index.d.ts +0 -117
- package/lib/cjs/api/types/index.js +0 -17
- package/lib/cjs/assets/css/tdesign-theme.css +0 -584
- package/lib/cjs/assets/images/uploadImg.png +0 -0
- package/lib/cjs/assets/svg/inputSearch.svg +0 -4
- package/lib/cjs/assets/svg/inputTip.svg +0 -5
- package/lib/esm/api/cos.d.ts +0 -103
- package/lib/esm/api/cos.js +0 -189
- package/lib/esm/api/index.d.ts +0 -23
- package/lib/esm/api/index.js +0 -23
- package/lib/esm/api/types/index.d.ts +0 -117
- package/lib/esm/api/types/index.js +0 -1
- package/lib/esm/assets/css/tdesign-theme.css +0 -584
- package/lib/esm/assets/images/uploadImg.png +0 -0
- package/lib/esm/assets/svg/inputSearch.svg +0 -4
- package/lib/esm/assets/svg/inputTip.svg +0 -5
- package/lib/esm/assets/svg/inputWarnTip.svg +0 -5
- package/lib/esm/components/PntBusinessSelect/index.d.ts +0 -192
- package/lib/esm/components/PntBusinessSelect/index.js +0 -513
- package/lib/esm/components/PntBusinessSelect/index.scss +0 -27
- package/lib/esm/components/PntCosUploader/index.d.ts +0 -134
- package/lib/esm/components/PntCosUploader/index.js +0 -300
- package/lib/esm/components/PntGeneralLayout/index.d.ts +0 -114
- package/lib/esm/components/PntGeneralLayout/index.js +0 -103
- package/lib/esm/components/PntGeneralLayout/index.scss +0 -121
- package/lib/esm/components/PntImage/index.d.ts +0 -93
- package/lib/esm/components/PntImage/index.js +0 -200
- package/lib/esm/components/PntImage/index.scss +0 -61
- package/lib/esm/components/PntRegionSelect/ImportDialog.d.ts +0 -29
- package/lib/esm/components/PntRegionSelect/ImportDialog.js +0 -244
- package/lib/esm/components/PntRegionSelect/index.d.ts +0 -39
- package/lib/esm/components/PntRegionSelect/index.js +0 -471
- package/lib/esm/components/PntRegionSelect/index.scss +0 -174
- package/lib/esm/components/PntRegionSelect/types.d.ts +0 -181
- package/lib/esm/components/PntRegionSelect/types.js +0 -77
- package/lib/esm/components/PntSecureBox/index.d.ts +0 -122
- package/lib/esm/components/PntSecureBox/index.js +0 -166
- package/lib/esm/components/PntSecureBox/index.scss +0 -23
- package/lib/esm/components/PntTable/index.d.ts +0 -14
- package/lib/esm/components/PntTable/index.js +0 -404
- package/lib/esm/components/PntTable/index.scss +0 -290
- package/lib/esm/components/PntTable/types.d.ts +0 -250
- package/lib/esm/components/PntTable/types.js +0 -81
- package/lib/esm/components/PntTable/useTableCore.d.ts +0 -38
- package/lib/esm/components/PntTable/useTableCore.js +0 -499
- package/lib/esm/components/PntUpload/index.d.ts +0 -149
- package/lib/esm/components/PntUpload/index.js +0 -276
- package/lib/esm/components/PntUpload/index.scss +0 -101
- package/lib/esm/config.d.ts +0 -97
- package/lib/esm/config.js +0 -60
- package/lib/esm/global.css +0 -2
- package/lib/esm/global.d.ts +0 -39
- package/lib/esm/hooks/useHighSecurity.d.ts +0 -88
- package/lib/esm/hooks/useHighSecurity.js +0 -250
- package/lib/esm/index.d.ts +0 -16
- package/lib/esm/index.js +0 -33
- package/lib/esm/utils/const.d.ts +0 -13
- package/lib/esm/utils/const.js +0 -23
- package/lib/esm/utils/index.d.ts +0 -6
- package/lib/esm/utils/index.js +0 -22
- package/lib/umd/pnt-component-frontend.min.css +0 -1
- package/lib/umd/pnt-component-frontend.min.js +0 -1
|
@@ -1,499 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useTableCore — PntTable 核心逻辑
|
|
3
|
-
*
|
|
4
|
-
* 负责:请求顺序控制、排序三态、筛选草稿/生效分离、多选三态、分页越界校验、7 种状态管理。
|
|
5
|
-
* 纯 React Hook,不依赖 TDesign DOM,方便单测和版本降级。
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
9
|
-
|
|
10
|
-
// ============================================================
|
|
11
|
-
// 内部类型
|
|
12
|
-
// ============================================================
|
|
13
|
-
|
|
14
|
-
// ============================================================
|
|
15
|
-
// 请求顺序控制
|
|
16
|
-
// ============================================================
|
|
17
|
-
|
|
18
|
-
class RequestManager {
|
|
19
|
-
requestIdCounter = 0;
|
|
20
|
-
abortController = null;
|
|
21
|
-
nextId() {
|
|
22
|
-
// 取消上一请求
|
|
23
|
-
if (this.abortController) {
|
|
24
|
-
try {
|
|
25
|
-
this.abortController.abort();
|
|
26
|
-
} catch {
|
|
27
|
-
/* noop */
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
this.abortController = new AbortController();
|
|
31
|
-
return ++this.requestIdCounter;
|
|
32
|
-
}
|
|
33
|
-
isLatest(id) {
|
|
34
|
-
return id === this.requestIdCounter;
|
|
35
|
-
}
|
|
36
|
-
abortCurrent() {
|
|
37
|
-
if (this.abortController) {
|
|
38
|
-
try {
|
|
39
|
-
this.abortController.abort();
|
|
40
|
-
} catch {
|
|
41
|
-
/* noop */
|
|
42
|
-
}
|
|
43
|
-
this.abortController = null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// ============================================================
|
|
49
|
-
// 排序三态循环(TBL-04.01)
|
|
50
|
-
// ============================================================
|
|
51
|
-
|
|
52
|
-
export function cycleSort(currentField, currentDir, targetField) {
|
|
53
|
-
if (currentField !== targetField) {
|
|
54
|
-
// 切换字段:从升序开始,清上一列
|
|
55
|
-
return {
|
|
56
|
-
field: targetField,
|
|
57
|
-
direction: 'asc'
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
// 同字段:三态循环
|
|
61
|
-
if (currentDir === undefined || currentDir === null) return {
|
|
62
|
-
field: targetField,
|
|
63
|
-
direction: 'asc'
|
|
64
|
-
};
|
|
65
|
-
if (currentDir === 'asc') return {
|
|
66
|
-
field: targetField,
|
|
67
|
-
direction: 'desc'
|
|
68
|
-
};
|
|
69
|
-
// 第三态:清除排序
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// ============================================================
|
|
74
|
-
// 分页越界校验(TBL-07.04)
|
|
75
|
-
// ============================================================
|
|
76
|
-
|
|
77
|
-
export function clampPage(page, total, pageSize) {
|
|
78
|
-
const maxPage = Math.max(1, Math.ceil(total / pageSize));
|
|
79
|
-
if (page < 1) return 1;
|
|
80
|
-
if (page > maxPage) return maxPage;
|
|
81
|
-
return page;
|
|
82
|
-
}
|
|
83
|
-
export function validateJumpPage(page, total, pageSize) {
|
|
84
|
-
const maxPage = Math.max(1, Math.ceil(total / pageSize));
|
|
85
|
-
if (!Number.isInteger(page) || page < 1 || page > maxPage) {
|
|
86
|
-
return `请输入 1–${maxPage} 的整数页码`;
|
|
87
|
-
}
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ============================================================
|
|
92
|
-
// 互斥校验(TBL-01.03)
|
|
93
|
-
// ============================================================
|
|
94
|
-
|
|
95
|
-
export function validateColumnConflicts(columns) {
|
|
96
|
-
const errors = [];
|
|
97
|
-
columns.forEach(col => {
|
|
98
|
-
if (col.sort && col.headerFilter) {
|
|
99
|
-
errors.push(`[PntTable] 列 "${col.key}" 同时配置了 sort 和 headerFilter,违反 TBL-01.03 互斥规则。` + ` 如需该字段同时排序+筛选,表头保留 sort,筛选移至 externalFilter(独立查询区)。`);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
return errors;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// ============================================================
|
|
106
|
-
// 核心 Hook
|
|
107
|
-
// ============================================================
|
|
108
|
-
|
|
109
|
-
export function useTableCore(props) {
|
|
110
|
-
const {
|
|
111
|
-
tableId,
|
|
112
|
-
rowKey,
|
|
113
|
-
columns,
|
|
114
|
-
dataMode,
|
|
115
|
-
fetcher,
|
|
116
|
-
data: clientData,
|
|
117
|
-
total: clientTotal,
|
|
118
|
-
initialPage = 1,
|
|
119
|
-
pageSize: initialPageSize = 10,
|
|
120
|
-
businessId,
|
|
121
|
-
env,
|
|
122
|
-
timezone,
|
|
123
|
-
onQueryChange,
|
|
124
|
-
onSelectionChange,
|
|
125
|
-
selectable = false,
|
|
126
|
-
currentPageOnly = true
|
|
127
|
-
} = props;
|
|
128
|
-
const reqMgrRef = useRef(new RequestManager());
|
|
129
|
-
const [requestId, setRequestId] = useState(0);
|
|
130
|
-
const [state, setState] = useState(() => {
|
|
131
|
-
const initialRows = dataMode === 'client' ? clientData ?? [] : [];
|
|
132
|
-
return {
|
|
133
|
-
data: initialRows,
|
|
134
|
-
total: dataMode === 'client' ? clientTotal ?? clientData?.length ?? 0 : 0,
|
|
135
|
-
status: dataMode === 'client' ? initialRows.length === 0 ? 'empty' : 'normal' : 'loading',
|
|
136
|
-
error: null,
|
|
137
|
-
sort: null,
|
|
138
|
-
appliedFilters: {},
|
|
139
|
-
page: initialPage,
|
|
140
|
-
pageSize: initialPageSize,
|
|
141
|
-
selection: new Set()
|
|
142
|
-
};
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// client 模式:props.data 变化时同步行数据,并重算空态
|
|
146
|
-
useEffect(() => {
|
|
147
|
-
if (dataMode !== 'client') return;
|
|
148
|
-
const rows = clientData ?? [];
|
|
149
|
-
setState(prev => {
|
|
150
|
-
const hasAppliedFilter = Object.values(prev.appliedFilters).some(v => v !== undefined && v !== null && v !== '');
|
|
151
|
-
return {
|
|
152
|
-
...prev,
|
|
153
|
-
data: rows,
|
|
154
|
-
total: clientTotal ?? rows.length,
|
|
155
|
-
status: rows.length === 0 ? hasAppliedFilter ? 'empty-with-filter' : 'empty' : 'normal',
|
|
156
|
-
error: null
|
|
157
|
-
};
|
|
158
|
-
});
|
|
159
|
-
}, [dataMode, clientData, clientTotal]);
|
|
160
|
-
const setStatePartial = useCallback(patch => {
|
|
161
|
-
setState(prev => ({
|
|
162
|
-
...prev,
|
|
163
|
-
...patch
|
|
164
|
-
}));
|
|
165
|
-
}, []);
|
|
166
|
-
|
|
167
|
-
// ============================================================
|
|
168
|
-
// 数据获取
|
|
169
|
-
// ============================================================
|
|
170
|
-
|
|
171
|
-
const triggerFetch = useCallback(async (trigger, snapshot) => {
|
|
172
|
-
if (dataMode !== 'server' || !fetcher) return;
|
|
173
|
-
const thisReqId = reqMgrRef.current.nextId();
|
|
174
|
-
const query = {
|
|
175
|
-
query: {},
|
|
176
|
-
// 独立查询区(组件不维护,由业务项目维护并透传)
|
|
177
|
-
filters: snapshot.appliedFilters,
|
|
178
|
-
sort: snapshot.sort,
|
|
179
|
-
page: snapshot.page,
|
|
180
|
-
pageSize: snapshot.pageSize,
|
|
181
|
-
businessId,
|
|
182
|
-
env,
|
|
183
|
-
timezone
|
|
184
|
-
};
|
|
185
|
-
onQueryChange?.(query, {
|
|
186
|
-
tableId,
|
|
187
|
-
trigger,
|
|
188
|
-
requestId: thisReqId
|
|
189
|
-
});
|
|
190
|
-
setStatePartial({
|
|
191
|
-
status: snapshot.page > 1 || requestId > 0 ? 'refreshing' : 'loading'
|
|
192
|
-
});
|
|
193
|
-
try {
|
|
194
|
-
const res = await fetcher(query);
|
|
195
|
-
|
|
196
|
-
// 旧请求晚到 → 丢弃(TBL-09.06)
|
|
197
|
-
if (!reqMgrRef.current.isLatest(thisReqId)) return;
|
|
198
|
-
if (res.noPermission) {
|
|
199
|
-
setStatePartial({
|
|
200
|
-
status: 'no-permission',
|
|
201
|
-
error: null,
|
|
202
|
-
data: [],
|
|
203
|
-
total: 0
|
|
204
|
-
});
|
|
205
|
-
setRequestId(thisReqId);
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
if (res.code !== undefined && res.code !== 0) {
|
|
209
|
-
// 文案由组件层按 locale/texts 兜底,core 只透传原始错误信息
|
|
210
|
-
setStatePartial({
|
|
211
|
-
status: 'error',
|
|
212
|
-
error: res.msg || ''
|
|
213
|
-
});
|
|
214
|
-
setRequestId(thisReqId);
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
const rows = res.rows ?? [];
|
|
218
|
-
setStatePartial({
|
|
219
|
-
data: rows,
|
|
220
|
-
total: res.total ?? rows.length,
|
|
221
|
-
status: rows.length === 0 ? Object.values(snapshot.appliedFilters).some(v => v !== undefined && v !== null && v !== '') ? 'empty-with-filter' : 'empty' : 'normal',
|
|
222
|
-
error: null
|
|
223
|
-
});
|
|
224
|
-
setRequestId(thisReqId);
|
|
225
|
-
} catch (err) {
|
|
226
|
-
if (!reqMgrRef.current.isLatest(thisReqId)) return;
|
|
227
|
-
if (err?.name === 'AbortError') return;
|
|
228
|
-
setStatePartial({
|
|
229
|
-
status: 'error',
|
|
230
|
-
error: err?.message || ''
|
|
231
|
-
});
|
|
232
|
-
setRequestId(thisReqId);
|
|
233
|
-
}
|
|
234
|
-
}, [dataMode, fetcher, tableId, businessId, env, timezone, onQueryChange, requestId, setStatePartial]);
|
|
235
|
-
|
|
236
|
-
// 初始加载
|
|
237
|
-
useEffect(() => {
|
|
238
|
-
if (dataMode === 'server' && fetcher) {
|
|
239
|
-
const page = initialPage;
|
|
240
|
-
const pageSize = state.pageSize;
|
|
241
|
-
setStatePartial({
|
|
242
|
-
page,
|
|
243
|
-
pageSize
|
|
244
|
-
});
|
|
245
|
-
triggerFetch('initial', {
|
|
246
|
-
sort: null,
|
|
247
|
-
appliedFilters: {},
|
|
248
|
-
page,
|
|
249
|
-
pageSize
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
253
|
-
}, [tableId, dataMode]);
|
|
254
|
-
|
|
255
|
-
// ============================================================
|
|
256
|
-
// 排序
|
|
257
|
-
// ============================================================
|
|
258
|
-
|
|
259
|
-
const toggleSort = useCallback(field => {
|
|
260
|
-
if (dataMode !== 'server') return;
|
|
261
|
-
const col = columns.find(c => c.key === field);
|
|
262
|
-
if (!col || col.sort === false) return;
|
|
263
|
-
setState(prev => {
|
|
264
|
-
const newSort = cycleSort(prev.sort?.field ?? null, prev.sort?.direction, field);
|
|
265
|
-
const clearedSelection = currentPageOnly ? new Set() : prev.selection;
|
|
266
|
-
const clearedPage = prev.sort?.field !== field ? prev.page : prev.page; // 换字段才回 1
|
|
267
|
-
const newPage = newSort ? 1 : clearedPage; // 有排序就回 1(TBL-04.05)
|
|
268
|
-
|
|
269
|
-
// 翻页/排序变更回 1 页 + 清勾选
|
|
270
|
-
const next = {
|
|
271
|
-
...prev,
|
|
272
|
-
sort: newSort,
|
|
273
|
-
page: newPage,
|
|
274
|
-
selection: clearedSelection
|
|
275
|
-
};
|
|
276
|
-
if (newSort) {
|
|
277
|
-
triggerFetch('sort', {
|
|
278
|
-
sort: newSort,
|
|
279
|
-
appliedFilters: next.appliedFilters,
|
|
280
|
-
page: newPage,
|
|
281
|
-
pageSize: next.pageSize
|
|
282
|
-
});
|
|
283
|
-
} else if (prev.sort) {
|
|
284
|
-
// 第三态清除排序
|
|
285
|
-
triggerFetch('sort', {
|
|
286
|
-
sort: null,
|
|
287
|
-
appliedFilters: next.appliedFilters,
|
|
288
|
-
page: newPage,
|
|
289
|
-
pageSize: next.pageSize
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
return next;
|
|
293
|
-
});
|
|
294
|
-
}, [dataMode, columns, triggerFetch, currentPageOnly]);
|
|
295
|
-
|
|
296
|
-
// ============================================================
|
|
297
|
-
// 筛选(草稿/生效分离)
|
|
298
|
-
// ============================================================
|
|
299
|
-
|
|
300
|
-
const applyFilters = useCallback(filters => {
|
|
301
|
-
// 归一化:空多选归一为不限(TBL-05.03)
|
|
302
|
-
const normalized = {};
|
|
303
|
-
Object.entries(filters).forEach(([k, v]) => {
|
|
304
|
-
if (Array.isArray(v) && v.length === 0) return;
|
|
305
|
-
if (v === undefined || v === null || v === '') return;
|
|
306
|
-
normalized[k] = v;
|
|
307
|
-
});
|
|
308
|
-
setState(prev => {
|
|
309
|
-
const clearedSelection = currentPageOnly ? new Set() : prev.selection;
|
|
310
|
-
const next = {
|
|
311
|
-
...prev,
|
|
312
|
-
appliedFilters: normalized,
|
|
313
|
-
page: 1,
|
|
314
|
-
// 筛选变更回 1 页(TBL-04.05)
|
|
315
|
-
selection: clearedSelection
|
|
316
|
-
};
|
|
317
|
-
triggerFetch('filter', {
|
|
318
|
-
sort: next.sort,
|
|
319
|
-
appliedFilters: normalized,
|
|
320
|
-
page: 1,
|
|
321
|
-
pageSize: next.pageSize
|
|
322
|
-
});
|
|
323
|
-
return next;
|
|
324
|
-
});
|
|
325
|
-
}, [triggerFetch, currentPageOnly]);
|
|
326
|
-
const resetFilters = useCallback(() => {
|
|
327
|
-
setState(prev => {
|
|
328
|
-
const clearedSelection = currentPageOnly ? new Set() : prev.selection;
|
|
329
|
-
const next = {
|
|
330
|
-
...prev,
|
|
331
|
-
appliedFilters: {},
|
|
332
|
-
page: 1,
|
|
333
|
-
selection: clearedSelection
|
|
334
|
-
};
|
|
335
|
-
triggerFetch('reset', {
|
|
336
|
-
sort: next.sort,
|
|
337
|
-
appliedFilters: {},
|
|
338
|
-
page: 1,
|
|
339
|
-
pageSize: next.pageSize
|
|
340
|
-
});
|
|
341
|
-
return next;
|
|
342
|
-
});
|
|
343
|
-
}, [triggerFetch, currentPageOnly]);
|
|
344
|
-
|
|
345
|
-
// ============================================================
|
|
346
|
-
// 分页
|
|
347
|
-
// ============================================================
|
|
348
|
-
|
|
349
|
-
const setPage = useCallback(page => {
|
|
350
|
-
if (dataMode !== 'server') return;
|
|
351
|
-
setState(prev => {
|
|
352
|
-
const validated = clampPage(page, prev.total, prev.pageSize);
|
|
353
|
-
if (validated === prev.page) return prev;
|
|
354
|
-
const clearedSelection = currentPageOnly ? new Set() : prev.selection;
|
|
355
|
-
const next = {
|
|
356
|
-
...prev,
|
|
357
|
-
page: validated,
|
|
358
|
-
selection: clearedSelection
|
|
359
|
-
};
|
|
360
|
-
triggerFetch('pagination', {
|
|
361
|
-
sort: next.sort,
|
|
362
|
-
appliedFilters: next.appliedFilters,
|
|
363
|
-
page: validated,
|
|
364
|
-
pageSize: next.pageSize
|
|
365
|
-
});
|
|
366
|
-
return next;
|
|
367
|
-
});
|
|
368
|
-
}, [dataMode, triggerFetch, currentPageOnly]);
|
|
369
|
-
const setPageSize = useCallback(size => {
|
|
370
|
-
if (dataMode !== 'server') return;
|
|
371
|
-
setState(prev => {
|
|
372
|
-
if (size === prev.pageSize) return prev;
|
|
373
|
-
const clearedSelection = currentPageOnly ? new Set() : prev.selection;
|
|
374
|
-
// pageSize 变更回 1 页(TBL-07.02)
|
|
375
|
-
const next = {
|
|
376
|
-
...prev,
|
|
377
|
-
pageSize: size,
|
|
378
|
-
page: 1,
|
|
379
|
-
selection: clearedSelection
|
|
380
|
-
};
|
|
381
|
-
triggerFetch('page-size', {
|
|
382
|
-
sort: next.sort,
|
|
383
|
-
appliedFilters: next.appliedFilters,
|
|
384
|
-
page: 1,
|
|
385
|
-
pageSize: size
|
|
386
|
-
});
|
|
387
|
-
return next;
|
|
388
|
-
});
|
|
389
|
-
}, [dataMode, triggerFetch, currentPageOnly]);
|
|
390
|
-
|
|
391
|
-
// ============================================================
|
|
392
|
-
// 多选(三态)
|
|
393
|
-
// ============================================================
|
|
394
|
-
|
|
395
|
-
const toggleRow = useCallback((key, selected) => {
|
|
396
|
-
if (!selectable) return;
|
|
397
|
-
setState(prev => {
|
|
398
|
-
const next = new Set(prev.selection);
|
|
399
|
-
if (selected) next.add(key);else next.delete(key);
|
|
400
|
-
const selArr = Array.from(next);
|
|
401
|
-
onSelectionChange?.(selArr, {
|
|
402
|
-
tableId,
|
|
403
|
-
pageKeys: prev.data.map(r => String(r[rowKey])),
|
|
404
|
-
disabledKeys: [],
|
|
405
|
-
trigger: 'select'
|
|
406
|
-
});
|
|
407
|
-
return {
|
|
408
|
-
...prev,
|
|
409
|
-
selection: next
|
|
410
|
-
};
|
|
411
|
-
});
|
|
412
|
-
}, [selectable, onSelectionChange, tableId, rowKey]);
|
|
413
|
-
const selectAllOnPage = useCallback((rowKeys, disabledKeys) => {
|
|
414
|
-
if (!selectable) return;
|
|
415
|
-
const selectableKeys = rowKeys.filter(k => !disabledKeys.includes(k));
|
|
416
|
-
setState(prev => {
|
|
417
|
-
const allSelected = selectableKeys.every(k => prev.selection.has(k));
|
|
418
|
-
const next = new Set(prev.selection);
|
|
419
|
-
if (allSelected) {
|
|
420
|
-
selectableKeys.forEach(k => next.delete(k));
|
|
421
|
-
} else {
|
|
422
|
-
selectableKeys.forEach(k => next.add(k));
|
|
423
|
-
}
|
|
424
|
-
const selArr = Array.from(next);
|
|
425
|
-
onSelectionChange?.(selArr, {
|
|
426
|
-
tableId,
|
|
427
|
-
pageKeys: rowKeys,
|
|
428
|
-
disabledKeys,
|
|
429
|
-
trigger: allSelected ? 'select-all' : 'select-all'
|
|
430
|
-
});
|
|
431
|
-
return {
|
|
432
|
-
...prev,
|
|
433
|
-
selection: next
|
|
434
|
-
};
|
|
435
|
-
});
|
|
436
|
-
}, [selectable, onSelectionChange, tableId]);
|
|
437
|
-
const clearSelection = useCallback(() => {
|
|
438
|
-
setState(prev => ({
|
|
439
|
-
...prev,
|
|
440
|
-
selection: new Set()
|
|
441
|
-
}));
|
|
442
|
-
onSelectionChange?.([], {
|
|
443
|
-
tableId,
|
|
444
|
-
pageKeys: [],
|
|
445
|
-
disabledKeys: [],
|
|
446
|
-
trigger: 'reset'
|
|
447
|
-
});
|
|
448
|
-
}, [onSelectionChange, tableId]);
|
|
449
|
-
const isAllSelectedOnPage = useCallback((rowKeys, disabledKeys) => {
|
|
450
|
-
const selectableKeys = rowKeys.filter(k => !disabledKeys.includes(k));
|
|
451
|
-
if (selectableKeys.length === 0) return false;
|
|
452
|
-
return selectableKeys.every(k => state.selection.has(k));
|
|
453
|
-
}, [state.selection]);
|
|
454
|
-
const isIndeterminateOnPage = useCallback((rowKeys, disabledKeys) => {
|
|
455
|
-
const selectableKeys = rowKeys.filter(k => !disabledKeys.includes(k));
|
|
456
|
-
if (selectableKeys.length === 0) return false;
|
|
457
|
-
const selectedCount = selectableKeys.filter(k => state.selection.has(k)).length;
|
|
458
|
-
return selectedCount > 0 && selectedCount < selectableKeys.length;
|
|
459
|
-
}, [state.selection]);
|
|
460
|
-
const refresh = useCallback(() => {
|
|
461
|
-
setState(prev => {
|
|
462
|
-
const clearedSelection = currentPageOnly ? new Set() : prev.selection;
|
|
463
|
-
const next = {
|
|
464
|
-
...prev,
|
|
465
|
-
selection: clearedSelection
|
|
466
|
-
};
|
|
467
|
-
triggerFetch('reset', {
|
|
468
|
-
sort: next.sort,
|
|
469
|
-
appliedFilters: next.appliedFilters,
|
|
470
|
-
page: next.page,
|
|
471
|
-
pageSize: next.pageSize
|
|
472
|
-
});
|
|
473
|
-
return next;
|
|
474
|
-
});
|
|
475
|
-
}, [triggerFetch, currentPageOnly]);
|
|
476
|
-
return useMemo(() => ({
|
|
477
|
-
data: state.data,
|
|
478
|
-
total: state.total,
|
|
479
|
-
status: state.status,
|
|
480
|
-
error: state.error,
|
|
481
|
-
sort: state.sort,
|
|
482
|
-
appliedFilters: state.appliedFilters,
|
|
483
|
-
page: state.page,
|
|
484
|
-
pageSize: state.pageSize,
|
|
485
|
-
selection: Array.from(state.selection),
|
|
486
|
-
requestId,
|
|
487
|
-
toggleSort,
|
|
488
|
-
applyFilters,
|
|
489
|
-
resetFilters,
|
|
490
|
-
setPage,
|
|
491
|
-
setPageSize,
|
|
492
|
-
toggleRow,
|
|
493
|
-
selectAllOnPage,
|
|
494
|
-
clearSelection,
|
|
495
|
-
refresh,
|
|
496
|
-
isAllSelectedOnPage,
|
|
497
|
-
isIndeterminateOnPage
|
|
498
|
-
}), [state, requestId, toggleSort, applyFilters, resetFilters, setPage, setPageSize, toggleRow, selectAllOnPage, clearSelection, refresh, isAllSelectedOnPage, isIndeterminateOnPage]);
|
|
499
|
-
}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import type { CosScene } from "../../api/cos";
|
|
2
|
-
import type { FileNameStrategy, PntCosUploadOptions } from "../PntCosUploader";
|
|
3
|
-
import React, { FC } from 'react';
|
|
4
|
-
import './index.scss';
|
|
5
|
-
/**
|
|
6
|
-
* PntUpload 文案集合
|
|
7
|
-
* @description 所有内部展示文案均可通过 texts prop 自定义,用于多语言场景
|
|
8
|
-
*/
|
|
9
|
-
export interface PntUploadTexts {
|
|
10
|
-
/** 上传中文案 */
|
|
11
|
-
uploading?: string;
|
|
12
|
-
/** 上传失败文案 */
|
|
13
|
-
uploadFailed?: string;
|
|
14
|
-
/** 文件大小超出限制文案 */
|
|
15
|
-
sizeInvalid?: string;
|
|
16
|
-
/** 文件类型不支持文案 */
|
|
17
|
-
typeInvalid?: string;
|
|
18
|
-
/** 选择文件文案(无文件时) */
|
|
19
|
-
selectFile?: string;
|
|
20
|
-
/** 重新选择文案(已有文件时,非图片模式) */
|
|
21
|
-
reselect?: string;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* 校验/上传失败阶段
|
|
25
|
-
*/
|
|
26
|
-
export type PntUploadErrorPhase = 'validate' | 'upload';
|
|
27
|
-
export interface PntUploadProps {
|
|
28
|
-
/**
|
|
29
|
-
* 当前已上传文件 URL(受控)
|
|
30
|
-
*/
|
|
31
|
-
value?: string;
|
|
32
|
-
/**
|
|
33
|
-
* 上传成功回调
|
|
34
|
-
* @param fileUrl 上传后的可访问 URL
|
|
35
|
-
* @param cosKey COS 对象 Key
|
|
36
|
-
* @param file 原始文件
|
|
37
|
-
*/
|
|
38
|
-
onChange?: (fileUrl: string, cosKey: string, file: File) => void;
|
|
39
|
-
/**
|
|
40
|
-
* 删除回调
|
|
41
|
-
* @description 由消费方清空 value
|
|
42
|
-
*/
|
|
43
|
-
onRemove?: () => void;
|
|
44
|
-
/**
|
|
45
|
-
* 异常回调(校验失败 / 上传失败)
|
|
46
|
-
* @param err 错误对象(校验失败时 message 为对应文案)
|
|
47
|
-
* @param phase 失败阶段:validate=本地校验,upload=凭证获取或 COS 上传
|
|
48
|
-
* @param file 原始文件
|
|
49
|
-
*/
|
|
50
|
-
onError?: (err: Error, phase: PntUploadErrorPhase, file: File) => void;
|
|
51
|
-
/**
|
|
52
|
-
* 业务场景(透传给 PntCosUploader)
|
|
53
|
-
*/
|
|
54
|
-
scene: CosScene;
|
|
55
|
-
/**
|
|
56
|
-
* 业务类型路径 key(透传给 PntCosUploader)
|
|
57
|
-
*/
|
|
58
|
-
pathKey?: string;
|
|
59
|
-
/**
|
|
60
|
-
* 业务上下文(透传给 PntCosUploader)
|
|
61
|
-
*/
|
|
62
|
-
context?: Record<string, string | number>;
|
|
63
|
-
/**
|
|
64
|
-
* 网关 audience(透传给 PntCosUploader)
|
|
65
|
-
* @default '/player-network'
|
|
66
|
-
*/
|
|
67
|
-
audience?: string;
|
|
68
|
-
/**
|
|
69
|
-
* 文件类型限制
|
|
70
|
-
* @description 支持 MIME('image/png')、通配('image/*')、扩展名('.zip'),可传数组
|
|
71
|
-
*/
|
|
72
|
-
accept?: string | string[];
|
|
73
|
-
/**
|
|
74
|
-
* 文件大小限制(字节)
|
|
75
|
-
*/
|
|
76
|
-
sizeLimit?: number;
|
|
77
|
-
/**
|
|
78
|
-
* 是否为图片预览模式
|
|
79
|
-
* @description true 使用 PntImage 预览;false 使用文件名 + 选择区域
|
|
80
|
-
* @default true
|
|
81
|
-
*/
|
|
82
|
-
imagePreview?: boolean;
|
|
83
|
-
/**
|
|
84
|
-
* 图片预览区样式(imagePreview=true 生效,一般控制宽高)
|
|
85
|
-
*/
|
|
86
|
-
previewStyle?: React.CSSProperties;
|
|
87
|
-
/**
|
|
88
|
-
* 默认占位图(imagePreview=true 生效)
|
|
89
|
-
*/
|
|
90
|
-
defaultImg?: string;
|
|
91
|
-
/**
|
|
92
|
-
* 文件名生成策略(透传给 PntCosUploader)
|
|
93
|
-
* @default 'uuid'
|
|
94
|
-
*/
|
|
95
|
-
fileNameStrategy?: FileNameStrategy;
|
|
96
|
-
/**
|
|
97
|
-
* 是否走 CDN 域名拼接(透传给 PntCosUploader)
|
|
98
|
-
* @default true
|
|
99
|
-
*/
|
|
100
|
-
useCdn?: boolean;
|
|
101
|
-
/**
|
|
102
|
-
* 自定义凭证获取函数(透传给 PntCosUploader)
|
|
103
|
-
*/
|
|
104
|
-
getCredential?: PntCosUploadOptions['getCredential'];
|
|
105
|
-
/**
|
|
106
|
-
* 自定义凭证响应归一化(透传给 PntCosUploader)
|
|
107
|
-
*/
|
|
108
|
-
normalizeCredential?: PntCosUploadOptions['normalizeCredential'];
|
|
109
|
-
/**
|
|
110
|
-
* 多语言文案
|
|
111
|
-
* @description 传入即覆盖默认中文文案;仅对应字段会覆盖,未传字段仍用默认值
|
|
112
|
-
*/
|
|
113
|
-
texts?: PntUploadTexts;
|
|
114
|
-
/**
|
|
115
|
-
* 禁用上传与删除
|
|
116
|
-
* @default false
|
|
117
|
-
*/
|
|
118
|
-
disabled?: boolean;
|
|
119
|
-
/**
|
|
120
|
-
* 自定义样式
|
|
121
|
-
*/
|
|
122
|
-
style?: React.CSSProperties;
|
|
123
|
-
/**
|
|
124
|
-
* 自定义类名
|
|
125
|
-
*/
|
|
126
|
-
className?: string;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* PntUpload 业务上传组件
|
|
130
|
-
* @description 基于 TDesign Upload + PntImage + usePntCosUploader,
|
|
131
|
-
* 内置 COS 凭证获取、直传、进度、校验、错误处理;支持图片预览 / 文件两种模式
|
|
132
|
-
*
|
|
133
|
-
* @example
|
|
134
|
-
* ```tsx
|
|
135
|
-
* <PntUpload
|
|
136
|
-
* scene="default"
|
|
137
|
-
* pathKey="marketing_icon"
|
|
138
|
-
* context={{ gameId }}
|
|
139
|
-
* accept="image/png"
|
|
140
|
-
* sizeLimit={500 * 1024}
|
|
141
|
-
* imagePreview
|
|
142
|
-
* value={iconUrl}
|
|
143
|
-
* onChange={(url) => setIconUrl(url)}
|
|
144
|
-
* onRemove={() => setIconUrl('')}
|
|
145
|
-
* />
|
|
146
|
-
* ```
|
|
147
|
-
*/
|
|
148
|
-
declare const PntUpload: FC<PntUploadProps>;
|
|
149
|
-
export default PntUpload;
|