@bit-sun/business-component 4.2.1-alpha.8 → 4.2.1-alpha.8-longya

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.
@@ -50,3 +50,12 @@
50
50
  - 原因:当前 `distribution-front` 本地依赖环境没有生成 `umi-test` 可执行文件。
51
51
  - 处理:不下载或改动依赖,改为执行与目标测试一致的源码静态断言,并确认旧服务适配引用已清零。
52
52
  - 后续规则:消费端依赖未完整安装时,不宣称测试套件通过;应明确区分正式测试结果和等价静态验证结果。
53
+
54
+ ## 2026-08-19 SKU 选择器多值查询
55
+
56
+ ### 测试断言残留旧参数转换方案
57
+
58
+ - 现象:提交前复跑 SKU 选择器测试时,多值查询转换断言失败。
59
+ - 原因:查询配置已直接切换为批量参数,测试和任务记录仍保留单值精确参数转批量参数的旧方案。
60
+ - 修正:删除不再使用的转换断言,按两个弹窗当前的批量查询参数更新任务记录。
61
+ - 后续规则:查询参数方案调整后必须重新读取最终配置并复跑测试,禁止沿用中间方案的断言和完成记录。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bit-sun/business-component",
3
- "version": "4.2.1-alpha.8",
3
+ "version": "4.2.1-alpha.8-longya",
4
4
  "scripts": {
5
5
  "start": "dumi dev",
6
6
  "docs:build": "dumi build",
@@ -13,6 +13,7 @@ import { tableColumnsImage } from '@/components/Business/BsSulaQueryTable/utils'
13
13
  import { getSkuImg } from '@/utils/TableUtils';
14
14
  import { judgeIsRequestError } from '@/utils/requestUtils';
15
15
  import { getEmployeeId } from '@/utils/LocalstorageUtils';
16
+ import { SEARCH_SELECT_MODAL_PAGE_SIZE_OPTIONS, SEARCH_SELECT_MODAL_DEFAULT_PAGE_SIZE } from '@/components/Functional/SearchSelect/pagination';
16
17
  // import { getCurrentTargetBgId } from '@/utils/LocalstorageUtils';
17
18
 
18
19
  function handleSelectColumn(c: any, parentProps: any) {
@@ -152,17 +153,46 @@ export const AddSkuSelect = (parProps: any) => {
152
153
  ]),
153
154
  {
154
155
  title: 'SKU名称',
155
- width: 200,
156
+ width: 300,
156
157
  ellipsis: {
157
158
  showTitle: false,
158
159
  },
159
160
  render: (text: any) => (
160
161
  <Tooltip placement="topLeft" title={text}>
161
- {text}
162
+ <span
163
+ style={{
164
+ display: 'block',
165
+ overflow: 'hidden',
166
+ textOverflow: 'ellipsis',
167
+ whiteSpace: 'nowrap',
168
+ }}
169
+ >
170
+ {text}
171
+ </span>
162
172
  </Tooltip>
163
173
  ),
164
174
  dataIndex: 'name',
165
175
  },
176
+ {
177
+ title: '龙牙款号',
178
+ width: 150,
179
+ dataIndex: 'longyaStyleCode',
180
+ },
181
+ {
182
+ title: '龙牙品号',
183
+ width: 150,
184
+ dataIndex: 'longyaPinCode',
185
+ },
186
+ {
187
+ title: '颜色名称',
188
+ width: 140,
189
+ dataIndex: 'colorName',
190
+ },
191
+ {
192
+ title: '尺码名称',
193
+ width: 140,
194
+ dataIndex: 'sizeName',
195
+ },
166
196
  {
167
197
  title: '图片',
168
198
  dataIndex: 'itemUrl',
@@ -237,17 +267,46 @@ export const AddSkuSelect = (parProps: any) => {
237
267
  },
238
268
  {
239
269
  title: 'SKU名称',
240
- width: 200,
270
+ width: 300,
241
271
  ellipsis: {
242
272
  showTitle: false,
243
273
  },
244
274
  render: (text: any) => (
245
275
  <Tooltip placement="topLeft" title={text}>
246
- {text}
276
+ <span
277
+ style={{
278
+ display: 'block',
279
+ overflow: 'hidden',
280
+ textOverflow: 'ellipsis',
281
+ whiteSpace: 'nowrap',
282
+ }}
283
+ >
284
+ {text}
285
+ </span>
247
286
  </Tooltip>
248
287
  ),
249
288
  dataIndex: 'name',
250
289
  },
290
+ {
291
+ title: '龙牙款号',
292
+ width: 150,
293
+ dataIndex: 'longyaStyleCode',
294
+ },
295
+ {
296
+ title: '龙牙品号',
297
+ width: 150,
298
+ dataIndex: 'longyaPinCode',
299
+ },
300
+ {
301
+ title: '颜色名称',
302
+ width: 140,
303
+ dataIndex: 'colorName',
304
+ },
305
+ {
306
+ title: '尺码名称',
307
+ width: 140,
308
+ dataIndex: 'sizeName',
309
+ },
251
310
  {
252
311
  title: '图片',
253
312
  dataIndex: 'itemUrl',
@@ -380,6 +439,8 @@ export const AddSkuSelect = (parProps: any) => {
380
439
  },
381
440
  { name: 'qp-itemCode-like', label: '款号(SPU)', type: 'multipleQueryInput', },
382
441
  { name: 'qp-skuName-like', label: 'SKU名称' },
442
+ { name: 'qp-longyaStyleCode-in', label: '龙牙款号', type: 'multipleQueryInput' },
443
+ { name: 'qp-longyaPinCode-in', label: '龙牙品号', type: 'multipleQueryInput' },
383
444
  { name: 'qp-externalCode-like', label: '外部SPU编码' },
384
445
  ...(isNoUseItemBarcode ? []: [
385
446
  { name: 'qp-code-in', label: '商品条码', field: {
@@ -433,7 +494,7 @@ export const AddSkuSelect = (parProps: any) => {
433
494
  'ctl-withAuth': true
434
495
  },
435
496
  resType: 'list',
436
- resPosition: isNoUseItemBarcode ? 4 : 5,
497
+ resPosition: mTpTableSearchForm.findIndex((item: any) => item.name === 'qp-brandId-in'),
437
498
  resKeyValue: ['id','name']
438
499
  },
439
500
  {
@@ -443,10 +504,15 @@ export const AddSkuSelect = (parProps: any) => {
443
504
  currentPage: 1,
444
505
  },
445
506
  resType: 'treeList',
446
- resPosition: isNoUseItemBarcode ? 5 : 6
507
+ resPosition: mTpTableSearchForm.findIndex((item: any) => item.name === 'qp-categoryId-in')
447
508
  },
448
509
  ]
449
510
  const mTpPromiseLoadList = handleFormSearchSourceLoad(initialPromiseLoadList, parProps);
511
+ const topTablePagination = parProps?.pagination || {};
512
+ const pageSizeOptions = Array.from(new Set([
513
+ ...SEARCH_SELECT_MODAL_PAGE_SIZE_OPTIONS,
514
+ ...(topTablePagination.pageSizeOptions || []),
515
+ ].map((option) => String(option)))).sort((left, right) => Number(left) - Number(right));
450
516
 
451
517
  const props = {
452
518
  buttonText: parProps.buttonText || '新增',
@@ -486,7 +552,12 @@ export const AddSkuSelect = (parProps: any) => {
486
552
  tableColumns: mTpTableColumn,
487
553
  selectColumn: mTpSelectColumn,
488
554
  promiseLoadList: mTpPromiseLoadList,
489
- topTablePagination: parProps?.pagination || {},
555
+ topTablePagination: {
556
+ ...topTablePagination,
557
+ pageSize: topTablePagination.pageSize ?? SEARCH_SELECT_MODAL_DEFAULT_PAGE_SIZE,
558
+ showSizeChanger: topTablePagination.showSizeChanger ?? true,
559
+ pageSizeOptions,
560
+ },
490
561
  }
491
562
 
492
563
  return (
@@ -399,6 +399,16 @@ export function commonFun (type?: string, prefixUrl: any, parentProps?:any) {
399
399
  },
400
400
  }
401
401
  } },
402
+ {
403
+ name: 'qp-styleCode-in',
404
+ label: '龙牙款号',
405
+ type: 'multipleQueryInput',
406
+ },
407
+ {
408
+ name: 'qp-pinCode-in',
409
+ label: '龙牙品号',
410
+ type: 'multipleQueryInput',
411
+ },
402
412
  // { name: 'qp-eancode-in', label: '商品条码', field: {
403
413
  // type: 'multipleQueryInput',
404
414
  // props: {
@@ -480,9 +490,9 @@ export function commonFun (type?: string, prefixUrl: any, parentProps?:any) {
480
490
  'qp-labelType-eq': 1,
481
491
  },getQueryHeadersItem(queryHeaderParams,'qp-itemLabelId-in')),
482
492
  ]).then((x: any)=>{
483
- formatSource(x,0, 3, tableSearchForm,['id','name'])
484
- formatTreeDataSource(x,1, 4, tableSearchForm)
485
- formatSource(x,2, 6, tableSearchForm,['id','name'])
493
+ formatSource(x,0, getFieldIndex(tableSearchForm, 'brandId'), tableSearchForm,['id','name'])
494
+ formatTreeDataSource(x,1, getFieldIndex(tableSearchForm, 'categoryId'), tableSearchForm)
495
+ formatSource(x,2, getFieldIndex(tableSearchForm, 'itemLabelId'), tableSearchForm,['id','name'])
486
496
  })
487
497
  modalTableProps = {
488
498
  modalTableTitle: '选择SKU',
@@ -492,60 +502,101 @@ export function commonFun (type?: string, prefixUrl: any, parentProps?:any) {
492
502
  {
493
503
  title: '序号',
494
504
  dataIndex: 'keyIndex',
505
+ width: 60,
495
506
  defaultSort: 0,
496
507
  },
497
508
  {
498
- title: 'SKU编码',
499
- dataIndex: 'skuCode',
500
- defaultSort: 2,
509
+ title: '图片',
510
+ dataIndex: 'itemUrl',
511
+ width: 60,
512
+ defaultSort: 1,
513
+ render: (text: any,record: any) => tableColumnsImage(getSkuImg(record), { width: 16, height: 16 }),
501
514
  },
502
515
  {
503
516
  title: 'SKU名称',
504
517
  dataIndex: 'skuName',
518
+ width: 200,
519
+ defaultSort: 2,
520
+ ellipsis: {
521
+ showTitle: false,
522
+ },
523
+ render: (text: any) => handleTextOverflow(text, 200),
524
+ },
525
+ {
526
+ title: '颜色名称',
527
+ dataIndex: 'colorName',
528
+ width: 140,
505
529
  defaultSort: 3,
506
530
  },
507
531
  {
508
- title: '图片',
509
- dataIndex: 'itemUrl',
510
- defaultSort: 1,
511
- render: (text: any,record: any) => tableColumnsImage(getSkuImg(record), { width: 16, height: 16 }),
532
+ title: '尺码名称',
533
+ dataIndex: 'sizeName',
534
+ width: 100,
535
+ defaultSort: 4,
536
+ },
537
+ {
538
+ title: 'SKU编码',
539
+ dataIndex: 'skuCode',
540
+ width: 160,
541
+ defaultSort: 5,
542
+ },
543
+ {
544
+ title: '龙牙款号',
545
+ dataIndex: 'styleCode',
546
+ width: 160,
547
+ defaultSort: 6,
548
+ },
549
+ {
550
+ title: '龙牙品号',
551
+ dataIndex: 'pinCode',
552
+ width: 160,
553
+ defaultSort: 7,
512
554
  },
513
555
  {
514
556
  title: '商品条码',
515
557
  dataIndex: 'eancode',
558
+ width: 140,
516
559
  },
517
560
  {
518
561
  title: 'SKC编码',
519
562
  dataIndex: 'skcCode',
563
+ width: 140,
520
564
  },
521
565
  {
522
566
  title: '所属SPU名称',
523
567
  dataIndex: 'itemName',
568
+ width: 160,
524
569
  },
525
570
  {
526
571
  title: '所属SPU编码',
527
572
  dataIndex: 'itemCode',
573
+ width: 140,
528
574
  },
529
575
  {
530
576
  title: '外部编码',
531
577
  dataIndex: 'externalCode',
578
+ width: 140,
532
579
  },
533
580
  {
534
581
  title: '规格',
535
582
  dataIndex: 'propertyNameAndValue',
583
+ width: 140,
536
584
  },
537
585
  {
538
586
  title: '类目',
539
587
  dataIndex: 'categoryName',
588
+ width: 120,
540
589
  },
541
590
  {
542
591
  title: '品类',
543
592
  dataIndex: 'className',
593
+ width: 120,
544
594
  },
545
595
  {
546
596
  title: '品牌',
547
597
  dataIndex: 'brandName',
548
- defaultSort: 4,
598
+ width: 120,
599
+ defaultSort: 8,
549
600
  },
550
601
  ],
551
602
  ...modalTableBusProps
@@ -1286,14 +1337,13 @@ export function commonFun (type?: string, prefixUrl: any, parentProps?:any) {
1286
1337
  ]).then((x: any)=>{
1287
1338
  const channelDisabledJude = (data: any) => data['parentCode'] === '0'; // 所属销售渠道 树节点不能点判断
1288
1339
  const areaDisabledJude = (data: any) => data['parent'] === '0'; // 所属营销区域 树节点不能点判断
1289
- formatTreeDataSource(x, 0, 4, tableSearchForm, ['code','name'], 'channelInfoSon', channelDisabledJude)
1290
- formatTreeDataSource(x, 1, 5, tableSearchForm, ['code', 'name'], 'children', areaDisabledJude)
1340
+ formatTreeDataSource(x, 0, getFieldIndex(tableSearchForm, 'qp-channelCode-in'), tableSearchForm, ['code','name'], 'channelInfoSon', channelDisabledJude)
1341
+ formatTreeDataSource(x, 1, getFieldIndex(tableSearchForm, 'qp-refCode-in'), tableSearchForm, ['code', 'name'], 'children', areaDisabledJude)
1291
1342
  })
1292
1343
  tableSearchForm = [
1293
1344
  { name: 'realWarehouseName*multiInput', label: '逻辑仓名称', type: 'multipleQueryInput' },
1294
1345
  { name: 'realWarehouseCode*multiInput', label: '逻辑仓编码', type: 'multipleQueryInput' },
1295
1346
  { name: 'qp-realWarehouseType-eq', type: 'select', label: '逻辑仓类型', initialSource: getDictionarySource('SC00004') },
1296
- { name: 'belongArea', field: {type: 'select', props: {mode: 'multiple',}}, label: '管理大区', initialSource: getDictionarySource('BUSINESS_belongArea'), },
1297
1347
  {
1298
1348
  name: 'qp-channelCode-in', type: 'treeSelect', label: '销售渠道', field: {
1299
1349
  type: 'treeSelect',
@@ -485,4 +485,4 @@ export default class ColumnSettingSulaTable extends React.Component {
485
485
  )
486
486
  }
487
487
 
488
- }
488
+ }
@@ -39,6 +39,7 @@ export const loadSelectSource = (url: string, params?: any) => {
39
39
  };
40
40
 
41
41
  export const formatSource = (reData: any, position: number, changePosition: number,changeSearchForm: any,resKeyValue=['code', 'name']) => {
42
+ if (!Array.isArray(changeSearchForm) || !changeSearchForm[changePosition]) return;
42
43
  const data = reData && reData[position]?.data;
43
44
  const list = Array.isArray(data) ? data :(data?.items || data?.list || data?.children || []);
44
45
  const formatData = list?.length ? list.map((v: any) => ({ text: v[resKeyValue[1]], value: v[resKeyValue[0]] })) : [];
@@ -58,6 +59,7 @@ export const mapSearchTree = (treeDataItem: any, resKeyValue: any) => {
58
59
  };
59
60
  };
60
61
  export const formatTreeDataSource = (reData: any, position: number, changePosition: number,changeSearchForm: any,resKeyValue=['id', 'name']) => {
62
+ if (!Array.isArray(changeSearchForm) || !changeSearchForm[changePosition]?.field?.props) return;
61
63
  const data = reData && reData[position]?.data;
62
64
  const formatData = (data &&
63
65
  Array.isArray(data) &&
@@ -127,6 +127,23 @@
127
127
  }
128
128
  }
129
129
 
130
+ .search_select_current_page_filter_column {
131
+ min-width: 140px;
132
+
133
+ .ant-table-filter-column {
134
+ min-width: 108px;
135
+ }
136
+
137
+ .ant-table-column-title {
138
+ min-width: 64px;
139
+ white-space: nowrap;
140
+ }
141
+
142
+ .ant-table-filter-trigger {
143
+ flex: 0 0 32px;
144
+ }
145
+ }
146
+
130
147
  .ant-modal-body {
131
148
  padding: 10px;
132
149
  }
@@ -16,6 +16,8 @@ import { handleAntdColumnsSpecialParams, uuid, parseWidth } from '@/utils/utils'
16
16
  import { judgeIsRequestError } from '@/utils/requestUtils';
17
17
  import { getItemDefaultWidth, noEmptyArray } from '@/components/Business/columnSettingTable/utils';
18
18
  import { getSelectDataList, loadSelectSource, formatFormSourceList } from './helps';
19
+ import { buildCurrentPageFilterColumns, markCurrentPageFilterByDataIndex } from '../SearchSelect/currentPageFilter';
20
+ import { SEARCH_SELECT_MODAL_DEFAULT_PAGE_SIZE } from '../SearchSelect/pagination';
19
21
 
20
22
  interface SearchFormItem {
21
23
  name: string;
@@ -98,7 +100,7 @@ const AddSelect = (props: any) => {
98
100
  const selectMode = selectProps?.mode // 设定当前选择器 为单选或者多选模式 无设定为单选模式(默认)
99
101
  const initVal = value || (selectMode ? [] : null);
100
102
  const pageSize = 100 // 下拉框默认分页 条数
101
- const tableInitPageSize = modalTableProps?.topTablePagination?.pageSize || 10 // 弹框默认分页 条数
103
+ const tableInitPageSize = modalTableProps?.topTablePagination?.pageSize || SEARCH_SELECT_MODAL_DEFAULT_PAGE_SIZE // 弹框默认分页 条数
102
104
  const currentPage = 1
103
105
 
104
106
  const [fetching, setFetching] = useState(false);
@@ -111,6 +113,7 @@ const AddSelect = (props: any) => {
111
113
  const [caretLeftFlag, setCaretLeftFlag] = useState(true);
112
114
  const [tableData, setTableData] = useState([]);
113
115
  const [tablePagination, setTablePagination] = useState({ total: 0, size: "small", current: 1, pageSize: tableInitPageSize, ...(modalTableProps?.topTablePagination) })
116
+ const [currentPageFilters, setCurrentPageFilters] = useState({});
114
117
  const [selectedRowKeys, setSelectedRowKeys] = useState([]);
115
118
  const [tableFormParams, setTableFormParams] = useState({});
116
119
  const [confirmLoading, setConfirmLoading] = useState(false);
@@ -671,7 +674,8 @@ const AddSelect = (props: any) => {
671
674
  source = Array.isArray(source) ? _.uniqBy(source, 'value') : [];
672
675
 
673
676
  setTableData(source)
674
- setTablePagination({ ...tablePagination, total: Number(res?.total || res?.totalCount || source.length), pageSize: Number(res?.size || res?.pageSize || (params?.pageSize || pageSize)), current: Number(res?.page || res?.currentPage || (params?.currentPage || currentPage)) })
677
+ setCurrentPageFilters({})
678
+ setTablePagination((previousPagination) => ({ ...previousPagination, total: Number(res?.total || res?.totalCount || source.length), pageSize: Number(res?.size || res?.pageSize || (params?.pageSize || pageSize)), current: Number(res?.page || res?.currentPage || (params?.currentPage || currentPage)) }))
675
679
  })
676
680
  .catch((err: any) => { setFetching(false) });
677
681
  }
@@ -699,6 +703,7 @@ const AddSelect = (props: any) => {
699
703
 
700
704
  const showModal = () => {
701
705
  // getData({ pageSize: tableInitPageSize, currentPage: 1 }, 2)
706
+ setCurrentPageFilters({});
702
707
  setIsModalVisible(true);
703
708
  // 回显
704
709
  if (value) {
@@ -777,6 +782,7 @@ const AddSelect = (props: any) => {
777
782
  const handleCancel = () => {
778
783
  form.resetFields();
779
784
  setTableFormParams({});
785
+ setCurrentPageFilters({});
780
786
  setIsModalVisible(false);
781
787
  setTableData([])
782
788
  onCancelCallback && onCancelCallback();
@@ -789,26 +795,39 @@ const AddSelect = (props: any) => {
789
795
  form.validateFields()
790
796
  .then(() => {
791
797
  const params = form.getFieldsValue();
798
+ const currentTablePageSize = businessType === 'sku'
799
+ ? Number(tablePagination?.pageSize || tableInitPageSize)
800
+ : tableInitPageSize;
792
801
  setTableFormParams(params);
793
- getData({ ...params, pageSize: tableInitPageSize }, 2)
802
+ setCurrentPageFilters({});
803
+ getData({ ...params, pageSize: currentTablePageSize, currentPage: 1 }, 2)
794
804
  })
795
805
  }
796
806
 
797
807
  const onResetTable = () => {
798
808
  form.resetFields();
799
809
  setTableFormParams({});
810
+ setCurrentPageFilters({});
800
811
  form.validateFields()
801
812
  .then(() => {
802
- getData({ pageSize: tableInitPageSize, currentPage: 1 }, 2)
813
+ const currentTablePageSize = businessType === 'sku'
814
+ ? Number(tablePagination?.pageSize || tableInitPageSize)
815
+ : tableInitPageSize;
816
+ getData({ pageSize: currentTablePageSize, currentPage: 1 }, 2)
803
817
  })
804
818
  .catch(() => {
805
819
  setTableData([]);
806
820
  })
807
821
  }
808
822
 
809
- const handleTableChange = (pagination) => {
810
- // 设置分页tablePagination
811
- setTablePagination({ ...tablePagination, ...pagination })
823
+ const handleTableChange = (pagination, filters, sorter, extra) => {
824
+ if (extra?.action === 'filter') {
825
+ setCurrentPageFilters(filters || {});
826
+ return;
827
+ }
828
+
829
+ setCurrentPageFilters({});
830
+ setTablePagination((previousPagination) => ({ ...previousPagination, ...pagination }))
812
831
  getData({ ...tableFormParams, pageSize: pagination.pageSize, currentPage: pagination.current }, 2)
813
832
  }
814
833
 
@@ -1042,12 +1061,33 @@ const AddSelect = (props: any) => {
1042
1061
  return ({ ...item })
1043
1062
  })
1044
1063
  handleColumns(showToChooseCol, [],(res)=> setShowToChooseColumnsCallback(res));
1064
+ const currentPageTableColumns = buildCurrentPageFilterColumns(
1065
+ businessType === 'sku'
1066
+ ? markCurrentPageFilterByDataIndex(showToChooseCol)
1067
+ : showToChooseCol,
1068
+ tableData,
1069
+ currentPageFilters,
1070
+ );
1045
1071
  let showSelectedCol = showColumns.map((item: any) => {
1046
1072
  handleAntdColumnsSpecialParams(item);
1047
1073
  return ({ ...item })
1048
1074
  })
1049
1075
  handleColumns(showSelectedCol, [],(res)=> setShowColumnsCallback(res));
1050
1076
 
1077
+ // sku 上表勿用 scroll.x=max-content:会按当前页单元格内容重算列宽,分页切换时 SKU名称等列会忽宽忽窄
1078
+ const sumColumnScrollX = (columns: any[], extraWidth = 0) => {
1079
+ const sum = (columns || []).reduce((total: number, col: any) => {
1080
+ if (typeof col?.width === 'number') return total + col.width;
1081
+ if (typeof col?.width === 'string') {
1082
+ const parsed = parseFloat(col.width);
1083
+ return Number.isFinite(parsed) ? total + parsed : total;
1084
+ }
1085
+ return total;
1086
+ }, extraWidth);
1087
+ return sum > extraWidth ? sum : undefined;
1088
+ };
1089
+ const skuTopTableScrollX = sumColumnScrollX(currentPageTableColumns, selectMode ? 60 : 0);
1090
+
1051
1091
  const selectLength = isAllowRepeatedSelect ? (popvalue?.length || 0) : (selectedRowKeys?.length || 0)
1052
1092
  return (
1053
1093
  <div className={'add_select'}>
@@ -1127,14 +1167,19 @@ const AddSelect = (props: any) => {
1127
1167
  <Table
1128
1168
  size='small'
1129
1169
  rowSelection={rowSelection}
1130
- columns={showToChooseCol}
1170
+ columns={currentPageTableColumns}
1131
1171
  dataSource={tableData}
1172
+ getPopupContainer={(triggerNode) =>
1173
+ modalTableProps?.getFilterPopupContainer?.(triggerNode) || document.body
1174
+ }
1132
1175
  pagination={tablePagination}
1133
1176
  loading={fetching}
1134
1177
  onChange={handleTableChange}
1135
1178
  rowKey={mappingValueField}
1136
1179
  rowClassName={'row-class'}
1137
- scroll={{ y: 500 }}
1180
+ scroll={businessType === 'sku'
1181
+ ? { x: skuTopTableScrollX || true, y: 500 }
1182
+ : { y: 500 }}
1138
1183
  components={{
1139
1184
  header: {
1140
1185
  cell: ResizeableTitle,
@@ -0,0 +1,135 @@
1
+ export interface CurrentPageFilterColumn {
2
+ dataIndex?: string;
3
+ currentPageFilter?: boolean;
4
+ children?: CurrentPageFilterColumn[];
5
+ [key: string]: any;
6
+ }
7
+
8
+ export interface CurrentPageFilterOption {
9
+ text: string;
10
+ value: string;
11
+ }
12
+
13
+ /**
14
+ * SKU 选择弹框「当前页列筛选」默认字段(合并 BusinessSearchSelect / AddSkuSelect 命名)。
15
+ * Functional 层按 dataIndex 命中自动开启,业务列不必再散标 currentPageFilter。
16
+ */
17
+ export const SKU_CURRENT_PAGE_FILTER_DATA_INDEXES = [
18
+ 'skuCode',
19
+ 'skuName',
20
+ 'name',
21
+ 'itemName',
22
+ 'itemCode',
23
+ 'styleCode',
24
+ 'pinCode',
25
+ 'longyaStyleCode',
26
+ 'longyaPinCode',
27
+ 'colorName',
28
+ 'sizeName',
29
+ ];
30
+
31
+ /**
32
+ * 按 dataIndex 白名单为表格列打上 currentPageFilter。
33
+ *
34
+ * @param columns 原始表格列
35
+ * @param dataIndexes 需要开启当前页筛选的字段
36
+ * @returns 已标记的表格列
37
+ */
38
+ export const markCurrentPageFilterByDataIndex = (
39
+ columns: CurrentPageFilterColumn[] = [],
40
+ dataIndexes: string[] = SKU_CURRENT_PAGE_FILTER_DATA_INDEXES,
41
+ ): CurrentPageFilterColumn[] =>
42
+ columns.map((column) =>
43
+ dataIndexes.includes(column?.dataIndex as string)
44
+ ? { ...column, currentPageFilter: true, width: column.width || 140 }
45
+ : column,
46
+ );
47
+
48
+ /**
49
+ * 从当前页数据中提取指定字段的筛选项,过滤空值后按名称去重、排序。
50
+ *
51
+ * @param dataSource 当前页表格数据
52
+ * @param dataIndex 作为筛选值的数据字段
53
+ * @returns 当前页可用的筛选项
54
+ */
55
+ export const getCurrentPageFilterOptions = (
56
+ dataSource: any[] = [],
57
+ dataIndex?: string,
58
+ ): CurrentPageFilterOption[] => {
59
+ if (!dataIndex) {
60
+ return [];
61
+ }
62
+
63
+ const optionMap = new Map<string, CurrentPageFilterOption>();
64
+ dataSource.forEach((record: any) => {
65
+ const rawValue = record?.[dataIndex];
66
+ if (rawValue === null || rawValue === undefined) {
67
+ return;
68
+ }
69
+
70
+ const value = String(rawValue).trim();
71
+ if (!value || optionMap.has(value)) {
72
+ return;
73
+ }
74
+
75
+ optionMap.set(value, { text: value, value });
76
+ });
77
+
78
+ return Array.from(optionMap.values()).sort((left, right) =>
79
+ left.text.localeCompare(right.text, 'zh-CN', { numeric: true }),
80
+ );
81
+ };
82
+
83
+ /**
84
+ * 为声明了 currentPageFilter 的表格列注入当前页筛选能力。
85
+ *
86
+ * @param columns 原始表格列
87
+ * @param dataSource 当前页表格数据
88
+ * @param filteredValues 当前已选筛选值
89
+ * @param enabled 是否启用筛选;已选结果表仅移除内部配置,不启用筛选
90
+ * @returns 可直接传给 Ant Design Table 的表格列
91
+ */
92
+ export const buildCurrentPageFilterColumns = (
93
+ columns: CurrentPageFilterColumn[] = [],
94
+ dataSource: any[] = [],
95
+ filteredValues: Record<string, any[] | null> = {},
96
+ enabled = true,
97
+ ): CurrentPageFilterColumn[] =>
98
+ columns.map((column: CurrentPageFilterColumn) => {
99
+ const { currentPageFilter, children, ...columnProps } = column;
100
+ const nextColumn = {
101
+ ...columnProps,
102
+ ...(children?.length
103
+ ? {
104
+ children: buildCurrentPageFilterColumns(
105
+ children,
106
+ dataSource,
107
+ filteredValues,
108
+ enabled,
109
+ ),
110
+ }
111
+ : {}),
112
+ };
113
+
114
+ if (!currentPageFilter || !enabled || !column.dataIndex) {
115
+ return nextColumn;
116
+ }
117
+
118
+ const dataIndex = column.dataIndex;
119
+ const currentPageFilterClassName = [
120
+ columnProps.className,
121
+ 'search_select_current_page_filter_column',
122
+ ]
123
+ .filter(Boolean)
124
+ .join(' ');
125
+ return {
126
+ ...nextColumn,
127
+ width: columnProps.width || 140,
128
+ className: currentPageFilterClassName,
129
+ filters: getCurrentPageFilterOptions(dataSource, dataIndex),
130
+ filterSearch: true,
131
+ filteredValue: filteredValues[dataIndex] || null,
132
+ onFilter: (filterValue: any, record: any) =>
133
+ String(record?.[dataIndex] ?? '') === String(filterValue),
134
+ };
135
+ });