@bit-sun/business-component 4.2.0-alpha.6.8 → 4.2.5-per-alpha.1
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/.umirc.ts +14 -10
- package/dist/components/Business/AddSelectBusiness/index.d.ts +3 -4
- package/dist/components/Business/BsLayouts/Components/AllFunc/drawContent.d.ts +1 -2
- package/dist/components/Business/BsLayouts/Components/ChooseStore/index.d.ts +1 -2
- package/dist/components/Business/BsLayouts/Components/CustomerMenu/MenuSetting/index.d.ts +1 -1
- package/dist/components/Business/BsLayouts/Components/CustomerMenu/MenuSetting/leftTree.d.ts +1 -1
- package/dist/components/Business/BsLayouts/Components/CustomerMenu/MenuSetting/rightTree.d.ts +2 -2
- package/dist/components/Business/BsLayouts/Components/CustomerMenu/globalMenu/DrawContent.d.ts +1 -2
- package/dist/components/Business/BsLayouts/Components/CustomerMenu/globalMenu/customMenuHeader.d.ts +1 -2
- package/dist/components/Business/BsLayouts/Components/CustomerMenu/index.d.ts +1 -1
- package/dist/components/Business/BsLayouts/Components/GlobalHeader/index.d.ts +1 -2
- package/dist/components/Business/BsLayouts/Components/RightContent/LoginModal.d.ts +1 -2
- package/dist/components/Business/BsLayouts/index.d.ts +1 -1
- package/dist/components/Business/BsSulaQueryTable/SearchItemSetting.d.ts +19 -8
- package/dist/components/Business/BsSulaQueryTable/index.d.ts +1 -2
- package/dist/components/Business/BsSulaQueryTable/setting.d.ts +9 -17
- package/dist/components/Business/BsSulaQueryTable/utils.d.ts +14 -15
- package/dist/components/Business/CommodityEntry/index.d.ts +1 -2
- package/dist/components/Business/CommonAlert/index.d.ts +1 -2
- package/dist/components/Business/CommonGuideWrapper/index.d.ts +3 -3
- package/dist/components/Business/DetailPageWrapper/index.d.ts +11 -12
- package/dist/components/Business/HomePageWrapper/index.d.ts +1 -2
- package/dist/components/Business/ItemPropertySelector/index.d.ts +1 -2
- package/dist/components/Business/JsonQueryTable/components/FieldsModifyModal.d.ts +1 -2
- package/dist/components/Business/JsonQueryTable/components/FieldsSettingsTable.d.ts +1 -2
- package/dist/components/Business/JsonQueryTable/components/Formula.d.ts +1 -2
- package/dist/components/Business/JsonQueryTable/components/MaintainOptions.d.ts +1 -2
- package/dist/components/Business/JsonQueryTable/drawer/index.d.ts +1 -2
- package/dist/components/Business/PropertyModal/index.d.ts +1 -2
- package/dist/components/Business/PropertyModal/propertyGroup.d.ts +1 -1
- package/dist/components/Business/SearchSelect/index.d.ts +1 -1
- package/dist/components/Business/StateFlow/index.d.ts +1 -2
- package/dist/components/Business/TreeSearchSelect/index.d.ts +1 -1
- package/dist/components/Business/columnSettingTable/columnSetting.d.ts +6 -6
- package/dist/components/Business/columnSettingTable/components/TableSumComponent.d.ts +1 -2
- package/dist/components/Business/columnSettingTable/index.d.ts +3 -3
- package/dist/components/Business/columnSettingTable/sulaSettingTable.d.ts +3 -3
- package/dist/components/Business/columnSettingTable/utils.d.ts +1 -2
- package/dist/components/Business/moreTreeTable/FixedScrollBar.d.ts +1 -1
- package/dist/components/Common/ParagraphCopier/index.d.ts +1 -1
- package/dist/components/Common/Section/index.d.ts +1 -1
- package/dist/components/Functional/AddSelect/index.d.ts +1 -2
- package/dist/components/Functional/AuthButton/index.d.ts +1 -2
- package/dist/components/Functional/DataImport/index.d.ts +4 -4
- package/dist/components/Functional/DataValidation/index.d.ts +5 -5
- package/dist/components/Functional/ExportFunctions/ExportIcon/index.d.ts +1 -2
- package/dist/components/Functional/QueryMutipleInput/index.d.ts +1 -2
- package/dist/components/Functional/QueryMutipleSelect/index.d.ts +1 -2
- package/dist/components/Functional/SearchSelect/index.d.ts +1 -1
- package/dist/components/Functional/SearchSelect/utils.d.ts +2 -3
- package/dist/components/Functional/TreeSearchSelect/index.d.ts +1 -2
- package/dist/components/Solution/RuleComponent/CustomPlugin/CustomSelector/CustomSelectorModal.d.ts +1 -1
- package/dist/components/Solution/RuleComponent/CustomPlugin/CustomSelector/index.d.ts +1 -2
- package/dist/components/Solution/RuleComponent/Formula.d.ts +1 -2
- package/dist/components/Solution/RuleComponent/InnerSelect.d.ts +1 -2
- package/dist/components/Solution/RuleComponent/RenderCompItem.d.ts +1 -2
- package/dist/components/Solution/RuleSetter/RuleInstance.d.ts +1 -2
- package/dist/components/Solution/RuleSetter/baseRule.d.ts +1 -1
- package/dist/components/Solution/RuleSetter/index.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.esm.js +2298 -1646
- package/dist/index.js +2290 -1640
- package/dist/plugin/TableColumnSetting/index.d.ts +5 -5
- package/dist/utils/TableUtils.d.ts +18 -19
- package/dist/utils/luckysheetLoader.d.ts +21 -0
- package/dist/utils/utils.d.ts +0 -41
- package/package.json +1 -1
- package/src/components/Business/BsLayouts/index.tsx +485 -129
- package/src/components/Business/BsSulaQueryTable/SearchItemSetting.tsx +144 -4
- package/src/components/Business/BsSulaQueryTable/index.md +120 -0
- package/src/components/Business/BsSulaQueryTable/index.tsx +236 -22
- package/src/components/Business/BsSulaQueryTable/setting.tsx +232 -17
- package/src/components/Business/DetailPageWrapper/index.tsx +30 -27
- package/src/components/Business/HomePageWrapper/index.tsx +10 -8
- package/src/components/Business/SearchSelect/BusinessUtils.tsx +27 -214
- package/src/components/Business/columnSettingTable/index.tsx +6 -7
- package/src/components/Business/columnSettingTable/sulaSettingTable.tsx +22 -23
- package/src/components/Functional/DataImport/index.tsx +76 -3
- package/src/components/Functional/DataValidation/index.tsx +81 -3
- package/src/index.ts +0 -2
- package/src/utils/luckysheetLoader.ts +164 -0
- package/src/utils/utils.ts +1 -41
- package/dist/components/Business/SystemLog/index.d.ts +0 -78
- package/src/components/Business/SystemLog/index.md +0 -37
- package/src/components/Business/SystemLog/index.tsx +0 -87
|
@@ -34,14 +34,26 @@ class SearchItemTable extends React.Component {
|
|
|
34
34
|
dataSource: [],
|
|
35
35
|
columns: [],
|
|
36
36
|
sortDataSource: [],
|
|
37
|
-
|
|
38
|
-
searchDataSource:
|
|
39
|
-
onSearchSort:
|
|
37
|
+
visible: false,
|
|
38
|
+
searchDataSource: '',
|
|
39
|
+
onSearchSort: '',
|
|
40
40
|
isDefaultValue: false,
|
|
41
41
|
defaultValue: [],
|
|
42
42
|
bsTableCode: '', //设置table 列的标识
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
// 实例变量声明,用于内存清理
|
|
46
|
+
debounceTimer = null;
|
|
47
|
+
dragContainer = null;
|
|
48
|
+
tableRef = React.createRef();
|
|
49
|
+
sortableContext = null;
|
|
50
|
+
handleGlobalClick = null;
|
|
51
|
+
handleGlobalKeydown = null;
|
|
52
|
+
handleWindowResize = null;
|
|
53
|
+
handleDragStart = null;
|
|
54
|
+
handleDragEnd = null;
|
|
55
|
+
requestController = null;
|
|
56
|
+
|
|
45
57
|
patchUserSearchFieldsConfig = (config) => {
|
|
46
58
|
const { appRequestConfig } = this.props;
|
|
47
59
|
let that = this;
|
|
@@ -199,6 +211,133 @@ class SearchItemTable extends React.Component {
|
|
|
199
211
|
});
|
|
200
212
|
}
|
|
201
213
|
|
|
214
|
+
componentWillUnmount() {
|
|
215
|
+
console.log('[SearchItemTable] 开始清理组件资源');
|
|
216
|
+
|
|
217
|
+
const cleanupTasks = [
|
|
218
|
+
// 取消所有进行中的请求
|
|
219
|
+
() => {
|
|
220
|
+
try {
|
|
221
|
+
if (this.requestControlle) {
|
|
222
|
+
this.requestController.abort();
|
|
223
|
+
this.requestController = null;
|
|
224
|
+
console.log('[SearchItemTable] 请求已取消');
|
|
225
|
+
}
|
|
226
|
+
} catch (error) {
|
|
227
|
+
console.warn('[SearchItemTable] 请求取消失败:', error);
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
// 清理定时器
|
|
232
|
+
() => {
|
|
233
|
+
try {
|
|
234
|
+
if (this.debounceTimer) {
|
|
235
|
+
clearTimeout(this.debounceTimer);
|
|
236
|
+
this.debounceTimer = null;
|
|
237
|
+
console.log('[SearchItemTable] 防抖定时器已清理');
|
|
238
|
+
}
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.warn('[SearchItemTable] 定时器清理失败:', error);
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
// 清理状态引用
|
|
245
|
+
() => {
|
|
246
|
+
try {
|
|
247
|
+
this.setState = () => {
|
|
248
|
+
console.warn('[SearchItemTable] 组件已卸载,忽略setState调用');
|
|
249
|
+
};
|
|
250
|
+
} catch (error) {
|
|
251
|
+
console.warn('[SearchItemTable] setState清理失败:', error);
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
// 清理DOM事件监听器
|
|
256
|
+
() => {
|
|
257
|
+
try {
|
|
258
|
+
if (this.dragContainer) {
|
|
259
|
+
this.dragContainer.removeEventListener('dragstart', this.handleDragStart);
|
|
260
|
+
this.dragContainer.removeEventListener('dragend', this.handleDragEnd);
|
|
261
|
+
this.dragContainer = null;
|
|
262
|
+
console.log('[SearchItemTable] DOM事件监听器已清理');
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.warn('[SearchItemTable] DOM事件清理失败:', error);
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
// 清理全局事件监听器
|
|
270
|
+
() => {
|
|
271
|
+
try {
|
|
272
|
+
if (typeof document !== 'undefined') {
|
|
273
|
+
document.removeEventListener('click', this.handleGlobalClick);
|
|
274
|
+
document.removeEventListener('keydown', this.handleGlobalKeydown);
|
|
275
|
+
window.removeEventListener('resize', this.handleWindowResize);
|
|
276
|
+
}
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.warn('[SearchItemTable] 全局事件清理失败:', error);
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
// 清理Table组件引用
|
|
283
|
+
() => {
|
|
284
|
+
try {
|
|
285
|
+
if (this.tableRef && this.tableRef.current) {
|
|
286
|
+
this.tableRef.current = null;
|
|
287
|
+
}
|
|
288
|
+
} catch (error) {
|
|
289
|
+
console.warn('[SearchItemTable] Table组件清理失败:', error);
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
// 清理react-sortable-hoc相关内存
|
|
294
|
+
() => {
|
|
295
|
+
try {
|
|
296
|
+
if (this.sortableContext) {
|
|
297
|
+
this.sortableContext = null;
|
|
298
|
+
}
|
|
299
|
+
} catch (error) {
|
|
300
|
+
console.warn('[SearchItemTable] sortable-hoc清理失败:', error);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
// 清理localStorage监听器
|
|
305
|
+
() => {
|
|
306
|
+
try {
|
|
307
|
+
if (typeof window !== 'undefined' && window.removeEventListener) {
|
|
308
|
+
window.removeEventListener('storage', this.handleStorageChange);
|
|
309
|
+
}
|
|
310
|
+
} catch (error) {
|
|
311
|
+
console.warn('[SearchItemTable] localStorage监听器清理失败:', error);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
];
|
|
315
|
+
|
|
316
|
+
// 执行清理任务,即使某个任务失败也继续执行其他任务
|
|
317
|
+
let successCount = 0;
|
|
318
|
+
cleanupTasks.forEach((task, index) => {
|
|
319
|
+
try {
|
|
320
|
+
task();
|
|
321
|
+
successCount++;
|
|
322
|
+
} catch (error) {
|
|
323
|
+
console.error(`[SearchItemTable] 清理任务${index + 1}执行失败:`, error);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
console.log(`[SearchItemTable] 组件资源清理完成,成功执行${successCount}/${cleanupTasks.length}个清理任务`);
|
|
328
|
+
|
|
329
|
+
// 最终状态验证
|
|
330
|
+
const finalState = {
|
|
331
|
+
requestCancelled: !this.requestController,
|
|
332
|
+
timerCleared: !this.debounceTimer,
|
|
333
|
+
dragContainerCleared: !this.dragContainer,
|
|
334
|
+
tableRefCleared: !this.tableRef,
|
|
335
|
+
sortableContextCleared: !this.sortableContext
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
console.log('[SearchItemTable] 最终清理状态:', finalState);
|
|
339
|
+
}
|
|
340
|
+
|
|
202
341
|
columns = [
|
|
203
342
|
{
|
|
204
343
|
title: '搜索字段名称',
|
|
@@ -436,12 +575,13 @@ class SearchItemTable extends React.Component {
|
|
|
436
575
|
(item) => item?.label?.indexOf(searchDataSource||'') > -1,
|
|
437
576
|
);
|
|
438
577
|
return (
|
|
439
|
-
<div className={'sort_table_wrapper'}>
|
|
578
|
+
<div data="bssulaquerysearchdatadiv" className={'sort_table_wrapper'}>
|
|
440
579
|
{visible && (
|
|
441
580
|
<Modal
|
|
442
581
|
title="筛选条件设置"
|
|
443
582
|
wrapClassName={'sort_table_wrapper'}
|
|
444
583
|
width={820}
|
|
584
|
+
destroyOnClose={true}
|
|
445
585
|
visible={visible}
|
|
446
586
|
onOk={this.handleOk}
|
|
447
587
|
onCancel={this.handleCancel}
|
|
@@ -92,6 +92,126 @@ export default () => {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
},
|
|
95
|
+
{
|
|
96
|
+
name: 'filterOption1',
|
|
97
|
+
label: '单据号筛选',
|
|
98
|
+
notShowLabel: true,
|
|
99
|
+
field: {
|
|
100
|
+
type: 'input',
|
|
101
|
+
props: {
|
|
102
|
+
options: [
|
|
103
|
+
{
|
|
104
|
+
value: '1',
|
|
105
|
+
text: '单据编号',
|
|
106
|
+
key: 'qp-orderNo-in',
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'filterOption1',
|
|
114
|
+
label: '单据号筛选',
|
|
115
|
+
notShowLabel: true,
|
|
116
|
+
field: {
|
|
117
|
+
type: 'input',
|
|
118
|
+
props: {
|
|
119
|
+
options: [
|
|
120
|
+
{
|
|
121
|
+
value: '1',
|
|
122
|
+
text: '单据编号',
|
|
123
|
+
key: 'qp-orderNo-in',
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'filterOption1',
|
|
131
|
+
label: '单据号筛选',
|
|
132
|
+
notShowLabel: true,
|
|
133
|
+
field: {
|
|
134
|
+
type: 'input',
|
|
135
|
+
props: {
|
|
136
|
+
options: [
|
|
137
|
+
{
|
|
138
|
+
value: '1',
|
|
139
|
+
text: '单据编号',
|
|
140
|
+
key: 'qp-orderNo-in',
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: 'filterOption1',
|
|
148
|
+
label: '单据号筛选',
|
|
149
|
+
notShowLabel: true,
|
|
150
|
+
field: {
|
|
151
|
+
type: 'input',
|
|
152
|
+
props: {
|
|
153
|
+
options: [
|
|
154
|
+
{
|
|
155
|
+
value: '1',
|
|
156
|
+
text: '单据编号',
|
|
157
|
+
key: 'qp-orderNo-in',
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: 'filterOption1',
|
|
165
|
+
label: '单据号筛选',
|
|
166
|
+
notShowLabel: true,
|
|
167
|
+
field: {
|
|
168
|
+
type: 'input',
|
|
169
|
+
props: {
|
|
170
|
+
options: [
|
|
171
|
+
{
|
|
172
|
+
value: '1',
|
|
173
|
+
text: '单据编号',
|
|
174
|
+
key: 'qp-orderNo-in',
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'filterOption1',
|
|
182
|
+
label: '单据号筛选',
|
|
183
|
+
notShowLabel: true,
|
|
184
|
+
field: {
|
|
185
|
+
type: 'input',
|
|
186
|
+
props: {
|
|
187
|
+
options: [
|
|
188
|
+
{
|
|
189
|
+
value: '1',
|
|
190
|
+
text: '单据编号',
|
|
191
|
+
key: 'qp-orderNo-in',
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: 'filterOption1',
|
|
199
|
+
label: '单据号筛选',
|
|
200
|
+
notShowLabel: true,
|
|
201
|
+
field: {
|
|
202
|
+
type: 'input',
|
|
203
|
+
props: {
|
|
204
|
+
options: [
|
|
205
|
+
{
|
|
206
|
+
value: '1',
|
|
207
|
+
text: '单据编号',
|
|
208
|
+
key: 'qp-orderNo-in',
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
|
|
95
215
|
],
|
|
96
216
|
columns: [
|
|
97
217
|
{
|
|
@@ -165,6 +165,20 @@ export default (props: any) => {
|
|
|
165
165
|
const bsTableCode = props?.tableCode || window.location.hash; //设置列字段的唯一标识
|
|
166
166
|
|
|
167
167
|
const rowsRef = useRef<any>(null);
|
|
168
|
+
const sortTableRef = useRef(null);
|
|
169
|
+
const searchTableRef = useRef(null);
|
|
170
|
+
const queryTableRef = useRef(null);
|
|
171
|
+
const exportTableRef = useRef<any>(null);
|
|
172
|
+
|
|
173
|
+
// 定时器引用,用于清理
|
|
174
|
+
const debounceTimer = useRef(null);
|
|
175
|
+
const resizeTimer = useRef(null);
|
|
176
|
+
|
|
177
|
+
// 事件处理函数引用,用于清理
|
|
178
|
+
const handleBeforeUnload = useRef(null);
|
|
179
|
+
const handleGlobalClick = useRef(null);
|
|
180
|
+
const handleGlobalKeydown = useRef(null);
|
|
181
|
+
const handleStorageChange = useRef(null);
|
|
168
182
|
|
|
169
183
|
// 获取 table columns中所有的 key 防止有的地方是 dataindex
|
|
170
184
|
const checkedList = useMemo(
|
|
@@ -277,10 +291,6 @@ export default (props: any) => {
|
|
|
277
291
|
const [showExportColumn, setShowExportColumns] = useState([]); // 导出列字段
|
|
278
292
|
|
|
279
293
|
const [height, setHeight]: any = useState('');
|
|
280
|
-
const sortTableRef = useRef(null);
|
|
281
|
-
const searchTableRef = useRef(null);
|
|
282
|
-
const exportTableRef = useRef<any>(null);
|
|
283
|
-
const queryTableRef = useRef(null);
|
|
284
294
|
|
|
285
295
|
const bsTableCodeExport = `${bsTableCode}___Export`; //设置导出列字段的唯一标识
|
|
286
296
|
|
|
@@ -443,16 +453,211 @@ export default (props: any) => {
|
|
|
443
453
|
setShowSearchFields([...showSearchFields]);
|
|
444
454
|
};
|
|
445
455
|
|
|
456
|
+
// 创建稳定的resize事件处理函数引用
|
|
457
|
+
const handleWindowResize = useCallback(() => {
|
|
458
|
+
watchWinResize();
|
|
459
|
+
}, [watchWinResize]);
|
|
460
|
+
|
|
446
461
|
//组件初始挂载
|
|
447
462
|
useEffect(() => {
|
|
448
|
-
// getTableHeight();
|
|
449
463
|
setInitialTableInfo();
|
|
450
464
|
setInitialSearchFieldsInfo();
|
|
451
|
-
window.addEventListener('resize',
|
|
452
|
-
watchWinResize();
|
|
453
|
-
});
|
|
465
|
+
window.addEventListener('resize', handleWindowResize);
|
|
454
466
|
|
|
455
467
|
setPagePath(pathname); // 做处理,记录当前页面渲染的初始pathname,用于进行判断当前列表页面数据是否需要重新渲染
|
|
468
|
+
}, [handleWindowResize]);
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
// 组件卸载时的完整清理机制
|
|
473
|
+
useEffect(() => {
|
|
474
|
+
return () => {
|
|
475
|
+
// 清理所有定时器
|
|
476
|
+
if (debounceTimer.current) {
|
|
477
|
+
clearTimeout(debounceTimer.current);
|
|
478
|
+
debounceTimer.current = null;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (resizeTimer.current) {
|
|
482
|
+
clearTimeout(resizeTimer.current);
|
|
483
|
+
resizeTimer.current = null;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// 清理所有事件监听器
|
|
487
|
+
window.removeEventListener('resize', handleWindowResize);
|
|
488
|
+
|
|
489
|
+
if (handleBeforeUnload.current) {
|
|
490
|
+
window.removeEventListener('beforeunload', handleBeforeUnload.current);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (handleGlobalClick.current) {
|
|
494
|
+
document.removeEventListener('click', handleGlobalClick.current);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (handleGlobalKeydown.current) {
|
|
498
|
+
document.removeEventListener('keydown', handleGlobalKeydown.current);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
if (handleStorageChange.current) {
|
|
502
|
+
window.removeEventListener('storage', handleStorageChange.current);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// 优化的子组件卸载时序控制
|
|
506
|
+
const cleanupPromises: Promise<void>[] = [];
|
|
507
|
+
const cleanupTimeout = 5000; // 5秒超时保护
|
|
508
|
+
|
|
509
|
+
// 创建清理任务队列,按优先级顺序执行
|
|
510
|
+
const cleanupTasks = [
|
|
511
|
+
// 第一阶段:停止所有活动
|
|
512
|
+
() => {
|
|
513
|
+
return new Promise<void>((resolve) => {
|
|
514
|
+
try {
|
|
515
|
+
// 停止所有定时器和动画
|
|
516
|
+
if (debounceTimer.current) {
|
|
517
|
+
clearTimeout(debounceTimer.current);
|
|
518
|
+
debounceTimer.current = null;
|
|
519
|
+
}
|
|
520
|
+
if (resizeTimer.current) {
|
|
521
|
+
clearTimeout(resizeTimer.current);
|
|
522
|
+
resizeTimer.current = null;
|
|
523
|
+
}
|
|
524
|
+
resolve();
|
|
525
|
+
} catch (error) {
|
|
526
|
+
console.warn('[BsSulaQueryTable] 第一阶段清理错误:', error);
|
|
527
|
+
resolve(); // 即使出错也继续
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
},
|
|
531
|
+
|
|
532
|
+
// 第二阶段:卸载子组件
|
|
533
|
+
() => {
|
|
534
|
+
return new Promise<void>((resolve) => {
|
|
535
|
+
try {
|
|
536
|
+
// 按依赖关系顺序卸载子组件
|
|
537
|
+
const componentCleanupOrder = [
|
|
538
|
+
{ ref: exportTableRef, name: 'ExportTable' },
|
|
539
|
+
{ ref: searchTableRef, name: 'SearchItemTable' },
|
|
540
|
+
{ ref: sortTableRef, name: 'SortableTable' },
|
|
541
|
+
{ ref: queryTableRef, name: 'QueryTable' }
|
|
542
|
+
];
|
|
543
|
+
|
|
544
|
+
componentCleanupOrder.forEach(({ ref, name }) => {
|
|
545
|
+
try {
|
|
546
|
+
if (ref.current) {
|
|
547
|
+
// 调用组件的清理方法
|
|
548
|
+
if (typeof ref.current.componentWillUnmount === 'function') {
|
|
549
|
+
ref.current.componentWillUnmount();
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// 禁用setState防止内存泄漏
|
|
553
|
+
if (ref.current.setState) {
|
|
554
|
+
ref.current.setState = () => {
|
|
555
|
+
console.warn(`[${name}] 组件已卸载,忽略setState调用`);
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// 清理DOM事件监听器
|
|
560
|
+
if (ref.current.removeEventListener) {
|
|
561
|
+
ref.current.removeEventListener('scroll', null);
|
|
562
|
+
ref.current.removeEventListener('click', null);
|
|
563
|
+
ref.current.removeEventListener('resize', null);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
console.log(`[BsSulaQueryTable] ${name} 组件已安全卸载`);
|
|
567
|
+
}
|
|
568
|
+
} catch (componentError) {
|
|
569
|
+
console.warn(`[BsSulaQueryTable] ${name} 卸载失败:`, componentError);
|
|
570
|
+
// 继续处理其他组件
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
resolve();
|
|
575
|
+
} catch (error) {
|
|
576
|
+
console.warn('[BsSulaQueryTable] 第二阶段清理错误:', error);
|
|
577
|
+
resolve();
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
},
|
|
581
|
+
|
|
582
|
+
// 第三阶段:清理全局资源
|
|
583
|
+
() => {
|
|
584
|
+
return new Promise<void>((resolve) => {
|
|
585
|
+
try {
|
|
586
|
+
// 清理全局事件监听器
|
|
587
|
+
window.removeEventListener('resize', handleWindowResize);
|
|
588
|
+
|
|
589
|
+
if (handleBeforeUnload.current) {
|
|
590
|
+
window.removeEventListener('beforeunload', handleBeforeUnload.current);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (handleGlobalClick.current) {
|
|
594
|
+
document.removeEventListener('click', handleGlobalClick.current);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (handleGlobalKeydown.current) {
|
|
598
|
+
document.removeEventListener('keydown', handleGlobalKeydown.current);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (handleStorageChange.current) {
|
|
602
|
+
window.removeEventListener('storage', handleStorageChange.current);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
resolve();
|
|
606
|
+
} catch (error) {
|
|
607
|
+
console.warn('[BsSulaQueryTable] 第三阶段清理错误:', error);
|
|
608
|
+
resolve();
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
];
|
|
613
|
+
|
|
614
|
+
// 执行清理任务队列
|
|
615
|
+
const executeCleanupTasks = async () => {
|
|
616
|
+
for (const task of cleanupTasks) {
|
|
617
|
+
try {
|
|
618
|
+
await Promise.race([
|
|
619
|
+
task(),
|
|
620
|
+
new Promise<void>((_, reject) =>
|
|
621
|
+
setTimeout(() => reject(new Error('清理任务超时')), cleanupTimeout)
|
|
622
|
+
)
|
|
623
|
+
]);
|
|
624
|
+
} catch (error) {
|
|
625
|
+
console.warn('[BsSulaQueryTable] 清理任务执行失败:', error);
|
|
626
|
+
// 继续执行下一个任务
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
// 异步执行清理任务
|
|
632
|
+
executeCleanupTasks().catch(error => {
|
|
633
|
+
console.error('[BsSulaQueryTable] 清理任务队列执行失败:', error);
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
// 清理所有ref引用
|
|
637
|
+
if (rowsRef.current) {
|
|
638
|
+
rowsRef.current = null;
|
|
639
|
+
}
|
|
640
|
+
if (sortTableRef.current) {
|
|
641
|
+
sortTableRef.current = null;
|
|
642
|
+
}
|
|
643
|
+
if (searchTableRef.current) {
|
|
644
|
+
searchTableRef.current = null;
|
|
645
|
+
}
|
|
646
|
+
if (queryTableRef.current) {
|
|
647
|
+
queryTableRef.current = null;
|
|
648
|
+
}
|
|
649
|
+
if (exportTableRef.current) {
|
|
650
|
+
exportTableRef.current = null;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// 最终状态验证
|
|
654
|
+
console.log('[BsSulaQueryTable] 组件卸载流程完成,清理状态:', {
|
|
655
|
+
refsCleared: !rowsRef.current && !sortTableRef.current && !searchTableRef.current,
|
|
656
|
+
timersCleared: !debounceTimer.current && !resizeTimer.current
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
console.log('[BsSulaQueryTable] 主组件及所有子组件已完全卸载,内存已清理');
|
|
660
|
+
};
|
|
456
661
|
}, []);
|
|
457
662
|
|
|
458
663
|
useEffect(() => {
|
|
@@ -489,20 +694,29 @@ export default (props: any) => {
|
|
|
489
694
|
setInitialTableInfo();
|
|
490
695
|
}, [props?.refreshColumns]);
|
|
491
696
|
|
|
492
|
-
const watchWinResize =
|
|
493
|
-
//
|
|
494
|
-
if (
|
|
495
|
-
|
|
496
|
-
// 全屏下按键esc后要执行的动作
|
|
497
|
-
// isFullScreen 为true 此时为全屏状态 false 为非全屏状态
|
|
498
|
-
if (!isFullScreen) {
|
|
499
|
-
// 按下esc键退出全屏
|
|
500
|
-
setIsFnllScreen(false);
|
|
501
|
-
} else {
|
|
502
|
-
setIsFnllScreen(false);
|
|
503
|
-
}
|
|
697
|
+
const watchWinResize = useCallback(() => {
|
|
698
|
+
// 清理之前的定时器
|
|
699
|
+
if (debounceTimer.current) {
|
|
700
|
+
clearTimeout(debounceTimer.current);
|
|
504
701
|
}
|
|
505
|
-
|
|
702
|
+
|
|
703
|
+
// 设置新的定时器
|
|
704
|
+
debounceTimer.current = setTimeout(() => {
|
|
705
|
+
// getTableHeight();
|
|
706
|
+
if (!checkFull()) {
|
|
707
|
+
// addTabsNavStyle(true);
|
|
708
|
+
// 全屏下按键esc后要执行的动作
|
|
709
|
+
// isFullScreen 为true 此时为全屏状态 false 为非全屏状态
|
|
710
|
+
if (!isFullScreen) {
|
|
711
|
+
// 按下esc键退出全屏
|
|
712
|
+
setIsFnllScreen(false);
|
|
713
|
+
} else {
|
|
714
|
+
setIsFnllScreen(false);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
debounceTimer.current = null;
|
|
718
|
+
}, 10);
|
|
719
|
+
}, [isFullScreen]);
|
|
506
720
|
|
|
507
721
|
const setCommonRenderFn = (columns: any[]) => {
|
|
508
722
|
columns.forEach((column) => {
|
|
@@ -962,7 +1176,7 @@ export default (props: any) => {
|
|
|
962
1176
|
);
|
|
963
1177
|
|
|
964
1178
|
return (
|
|
965
|
-
<div id="bs-sula-query-table">
|
|
1179
|
+
<div data="bssulaquerydatadiv" id="bs-sula-query-table">
|
|
966
1180
|
<MemoQueryTable {...memoConfig} />
|
|
967
1181
|
{/* 列设置弹出框表格 */}
|
|
968
1182
|
<SortableTable
|