@bit-sun/business-component 4.2.1-alpha.7-longya → 4.2.1-alpha.8
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/.claude/settings.local.json +8 -0
- package/dist/components/Functional/SearchSelect/pagination.d.ts +3 -3
- package/dist/index.esm.js +416 -953
- package/dist/index.js +415 -952
- package/docs/error-record.md +0 -9
- package/package.json +1 -1
- package/src/components/Business/AddSelectBusiness/index.tsx +8 -124
- package/src/components/Business/SearchSelect/BusinessUtils.tsx +12 -106
- package/src/components/Business/columnSettingTable/sulaSettingTable.tsx +1 -1
- package/src/components/Functional/AddSelect/helps.ts +0 -2
- package/src/components/Functional/AddSelect/index.less +0 -17
- package/src/components/Functional/AddSelect/index.tsx +9 -66
- package/src/components/Functional/SearchSelect/index.less +0 -16
- package/src/components/Functional/SearchSelect/index.md +2 -0
- package/src/components/Functional/SearchSelect/index.tsx +65 -77
- package/src/components/Functional/SearchSelect/pagination.ts +4 -4
- package/src/components/Solution/RuleComponent/ruleFiled.js +155 -176
- package/dist/components/Functional/QueryAutoComplete/buildOptions.d.ts +0 -3
- package/dist/components/Functional/QueryAutoComplete/buildOptions.test.d.ts +0 -1
- package/dist/components/Functional/QueryAutoComplete/index.d.ts +0 -23
- package/dist/components/Functional/SearchSelect/currentPageFilter.d.ts +0 -41
- package/docs/superpowers/plans/2026-10-12-IKJX29-sku-name-autocomplete.md +0 -489
- package/docs/superpowers/specs/2026-10-12-IKJX29-sku-name-autocomplete-design.md +0 -115
- package/src/components/Functional/QueryAutoComplete/buildOptions.test.ts +0 -22
- package/src/components/Functional/QueryAutoComplete/buildOptions.ts +0 -17
- package/src/components/Functional/QueryAutoComplete/index.tsx +0 -140
- package/src/components/Functional/SearchSelect/currentPageFilter.ts +0 -135
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export function buildAutoCompleteOptions(
|
|
2
|
-
list: Array<Record<string, any>> | null | undefined,
|
|
3
|
-
mappingTextField = 'name',
|
|
4
|
-
): { value: string }[] {
|
|
5
|
-
if (!Array.isArray(list)) return [];
|
|
6
|
-
const seen = new Set<string>();
|
|
7
|
-
const options: { value: string }[] = [];
|
|
8
|
-
for (const item of list) {
|
|
9
|
-
const text = item?.[mappingTextField];
|
|
10
|
-
if (text == null) continue;
|
|
11
|
-
const value = String(text).trim();
|
|
12
|
-
if (!value || seen.has(value)) continue;
|
|
13
|
-
seen.add(value);
|
|
14
|
-
options.push({ value });
|
|
15
|
-
}
|
|
16
|
-
return options;
|
|
17
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { AutoComplete, Input } from 'antd';
|
|
3
|
-
import { useDebounceFn } from 'ahooks';
|
|
4
|
-
import { stringify } from 'querystring';
|
|
5
|
-
import request from '@/utils/request';
|
|
6
|
-
import { judgeIsRequestError } from '@/utils/requestUtils';
|
|
7
|
-
import { buildAutoCompleteOptions } from './buildOptions';
|
|
8
|
-
|
|
9
|
-
export type QueryAutoCompleteRequestConfig = {
|
|
10
|
-
url: string;
|
|
11
|
-
method?: 'get' | 'GET' | 'post' | 'POST' | 'patch' | 'PATCH' | 'put' | 'PUT';
|
|
12
|
-
otherParams?: Record<string, any>;
|
|
13
|
-
mappingTextField?: string;
|
|
14
|
-
pageSize?: number;
|
|
15
|
-
debounceWait?: number;
|
|
16
|
-
/** 写入查询串的 like 参数名,默认 qp-skuName-like */
|
|
17
|
-
likeParamName?: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type QueryAutoCompleteProps = {
|
|
21
|
-
value?: string;
|
|
22
|
-
onChange?: (value: string) => void;
|
|
23
|
-
onPressEnter?: () => void;
|
|
24
|
-
requestConfig: QueryAutoCompleteRequestConfig;
|
|
25
|
-
placeholder?: string;
|
|
26
|
-
allowClear?: boolean;
|
|
27
|
-
style?: React.CSSProperties;
|
|
28
|
-
disabled?: boolean;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const QueryAutoComplete: React.FC<QueryAutoCompleteProps> = ({
|
|
32
|
-
value,
|
|
33
|
-
onChange,
|
|
34
|
-
onPressEnter,
|
|
35
|
-
requestConfig,
|
|
36
|
-
placeholder = '请输入',
|
|
37
|
-
allowClear = true,
|
|
38
|
-
style,
|
|
39
|
-
disabled,
|
|
40
|
-
}) => {
|
|
41
|
-
const {
|
|
42
|
-
url,
|
|
43
|
-
method = 'get',
|
|
44
|
-
otherParams = {},
|
|
45
|
-
mappingTextField = 'name',
|
|
46
|
-
pageSize = 50,
|
|
47
|
-
debounceWait = 300,
|
|
48
|
-
likeParamName = 'qp-skuName-like',
|
|
49
|
-
} = requestConfig || ({} as QueryAutoCompleteRequestConfig);
|
|
50
|
-
|
|
51
|
-
const [options, setOptions] = useState<{ value: string }[]>([]);
|
|
52
|
-
const seqRef = useRef(0);
|
|
53
|
-
const mountedRef = useRef(true);
|
|
54
|
-
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
mountedRef.current = true;
|
|
57
|
-
return () => {
|
|
58
|
-
mountedRef.current = false;
|
|
59
|
-
seqRef.current += 1;
|
|
60
|
-
};
|
|
61
|
-
}, []);
|
|
62
|
-
|
|
63
|
-
const fetchSuggest = (keyword: string) => {
|
|
64
|
-
const trimmed = (keyword || '').trim();
|
|
65
|
-
if (!url || !trimmed) {
|
|
66
|
-
setOptions([]);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const seq = ++seqRef.current;
|
|
70
|
-
const queryParams = {
|
|
71
|
-
pageSize,
|
|
72
|
-
currentPage: 1,
|
|
73
|
-
...otherParams,
|
|
74
|
-
[likeParamName]: trimmed,
|
|
75
|
-
};
|
|
76
|
-
const qs = stringify(queryParams);
|
|
77
|
-
const fullUrl = `${url}${url.includes('?') ? '&' : '?'}${qs}`;
|
|
78
|
-
const methodName = String(method).toLowerCase();
|
|
79
|
-
const pending =
|
|
80
|
-
['post', 'patch', 'put'].includes(methodName)
|
|
81
|
-
? // 与 SearchSelect 弹窗列表一致:参数在 query,body 为空
|
|
82
|
-
(request as any)[methodName](fullUrl, null)
|
|
83
|
-
: request.get(fullUrl);
|
|
84
|
-
|
|
85
|
-
pending
|
|
86
|
-
.then((result: any) => {
|
|
87
|
-
if (!mountedRef.current || seq !== seqRef.current) return;
|
|
88
|
-
const body = result?.data;
|
|
89
|
-
if (judgeIsRequestError(body)) {
|
|
90
|
-
setOptions([]);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const res = body?.data;
|
|
94
|
-
const list = res?.list || res?.items || (Array.isArray(res) ? res : []);
|
|
95
|
-
// sku 名称:列表列用 skuName,pager 用 name;其它字段(如 itemName)不做跨字段回退
|
|
96
|
-
const primary = buildAutoCompleteOptions(list, mappingTextField);
|
|
97
|
-
if (primary.length) {
|
|
98
|
-
setOptions(primary);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
if (mappingTextField === 'skuName' || mappingTextField === 'name') {
|
|
102
|
-
const fallbackField = mappingTextField === 'skuName' ? 'name' : 'skuName';
|
|
103
|
-
setOptions(buildAutoCompleteOptions(list, fallbackField));
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
setOptions([]);
|
|
107
|
-
})
|
|
108
|
-
.catch(() => {
|
|
109
|
-
if (!mountedRef.current || seq !== seqRef.current) return;
|
|
110
|
-
setOptions([]);
|
|
111
|
-
});
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const { run: debouncedFetch } = useDebounceFn(fetchSuggest, { wait: debounceWait });
|
|
115
|
-
|
|
116
|
-
return (
|
|
117
|
-
<AutoComplete
|
|
118
|
-
value={value}
|
|
119
|
-
options={options}
|
|
120
|
-
onSearch={(text) => {
|
|
121
|
-
debouncedFetch(text);
|
|
122
|
-
}}
|
|
123
|
-
onSelect={(text) => {
|
|
124
|
-
onChange?.(String(text ?? ''));
|
|
125
|
-
}}
|
|
126
|
-
onChange={(next) => onChange?.(next ?? '')}
|
|
127
|
-
disabled={disabled}
|
|
128
|
-
style={{ width: '100%', ...style }}
|
|
129
|
-
>
|
|
130
|
-
<Input
|
|
131
|
-
allowClear={allowClear}
|
|
132
|
-
disabled={disabled}
|
|
133
|
-
placeholder={placeholder}
|
|
134
|
-
onPressEnter={() => onPressEnter?.()}
|
|
135
|
-
/>
|
|
136
|
-
</AutoComplete>
|
|
137
|
-
);
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
export default QueryAutoComplete;
|
|
@@ -1,135 +0,0 @@
|
|
|
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
|
-
});
|