diff --git a/packages/pro/search/demo/Parser.md b/packages/pro/search/demo/Parser.md new file mode 100644 index 000000000..615e02f57 --- /dev/null +++ b/packages/pro/search/demo/Parser.md @@ -0,0 +1,6 @@ +--- +order: 50 +title: + zh: 使用 `useParser` 解析搜索值 + en: Parse search value using `useParser` +--- diff --git a/packages/pro/search/demo/Parser.vue b/packages/pro/search/demo/Parser.vue new file mode 100644 index 000000000..abb040f4e --- /dev/null +++ b/packages/pro/search/demo/Parser.vue @@ -0,0 +1,305 @@ + + + + + diff --git a/packages/pro/search/index.ts b/packages/pro/search/index.ts index 1d0923e91..c02a66933 100644 --- a/packages/pro/search/index.ts +++ b/packages/pro/search/index.ts @@ -14,6 +14,7 @@ const IxProSearch = ProSearch as unknown as ProSearchComponent const IxProSearchShortcut = ProSearchShortcut as unknown as ProSearchShortcutComponent export { IxProSearch, IxProSearchShortcut } +export { useParser } from './src/useParser' export type { ProSearchSize, @@ -29,3 +30,5 @@ export type { SearchItemCreateContext, SearchItemConfirmContext, } from './src/types' + +export type { ParserContext, ParseResult } from './src/useParser' diff --git a/packages/pro/search/src/ProSearch.tsx b/packages/pro/search/src/ProSearch.tsx index 1ef249e49..74cc0948c 100644 --- a/packages/pro/search/src/ProSearch.tsx +++ b/packages/pro/search/src/ProSearch.tsx @@ -46,6 +46,7 @@ export default defineComponent({ () => !!props.searchFields?.some(field => !!field.quickSelect && !field.multiple), ) + const searchFields = computed(() => props.searchFields ?? []) const quickSelectOverlayOpened = computed(() => quickSelectActive.value && overlayOpened.value) const elementRef = ref() @@ -54,7 +55,7 @@ export default defineComponent({ const searchValueContext = useSearchValues(props) const { searchValues } = searchValueContext - const resolvedSearchFieldsContext = useResolvedSearchFields(props, mergedPrefixCls, dateConfig) + const resolvedSearchFieldsContext = useResolvedSearchFields(searchFields, mergedPrefixCls, dateConfig) const { fieldKeyMap } = resolvedSearchFieldsContext const searchStateContext = useSearchStates(props, fieldKeyMap, searchValueContext) const { searchStates, initSearchStates, clearSearchState, updateSearchValues, isSegmentVisible } = diff --git a/packages/pro/search/src/composables/useResolvedSearchFields.ts b/packages/pro/search/src/composables/useResolvedSearchFields.ts index 36170c902..12de6ef76 100644 --- a/packages/pro/search/src/composables/useResolvedSearchFields.ts +++ b/packages/pro/search/src/composables/useResolvedSearchFields.ts @@ -5,7 +5,7 @@ * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE */ -import type { ProSearchProps, ResolvedSearchField, SearchField, Segment } from '../types' +import type { ResolvedSearchField, SearchField, Segment } from '../types' import type { VKey } from '@idux/cdk/utils' import type { DateConfig } from '@idux/components/config' @@ -26,13 +26,13 @@ export interface ResolvedSearchFieldsContext { } export function useResolvedSearchFields( - props: ProSearchProps, + searchFields: ComputedRef, mergedPrefixCls: ComputedRef, dateConfig: DateConfig, ): ResolvedSearchFieldsContext { const resolvedSearchFields = computed( () => - props.searchFields?.map(searchField => { + searchFields.value.map(searchField => { return { ...searchField, segments: [ diff --git a/packages/pro/search/src/composables/useSearchStates.ts b/packages/pro/search/src/composables/useSearchStates.ts index 99dbed69b..9a6321697 100644 --- a/packages/pro/search/src/composables/useSearchStates.ts +++ b/packages/pro/search/src/composables/useSearchStates.ts @@ -12,7 +12,9 @@ import { type ComputedRef, type Ref, computed, ref, toRaw } from 'vue' import { isEqual, isNil } from 'lodash-es' -import { type VKey, callEmit, convertArray } from '@idux/cdk/utils' +import { type VKey, callEmit } from '@idux/cdk/utils' + +import { generateSegmentStates } from '../utils' export interface SearchState { key: VKey @@ -443,24 +445,6 @@ function createStateKeyGetter() { } } -function generateSegmentStates( - searchField: ResolvedSearchField, - searchValue?: Omit, -): SegmentState[] { - const segments = searchField.segments - const hasOperators = searchField.operators && searchField.operators.length > 0 - const operator = searchValue?.operator ?? searchField.operators?.find(op => op === searchField.defaultOperator) - const value = searchValue?.value ?? searchField.defaultValue - const valueArr = segments.length > (hasOperators ? 2 : 1) ? convertArray(value) : [value] - const segmentValues = hasOperators ? [operator, ...valueArr] : valueArr - - return segments.map((segment, idx) => ({ - name: segment.name, - value: segmentValues[idx], - input: segment.format(segmentValues[idx], []), - })) -} - function compareSearchValues(newSearchValues: SearchValue[] | undefined, oldSearchValues: SearchValue[] | undefined) { if (!newSearchValues && !oldSearchValues) { return true diff --git a/packages/pro/search/src/useParser.ts b/packages/pro/search/src/useParser.ts new file mode 100644 index 000000000..7adec45d0 --- /dev/null +++ b/packages/pro/search/src/useParser.ts @@ -0,0 +1,57 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import type { SearchField, SearchValue, SegmentState } from './types' +import type { VKey } from '@idux/cdk/utils' + +import { type Ref, computed } from 'vue' + +import { useDateConfig } from '@idux/components/config' + +import { useResolvedSearchFields } from './composables/useResolvedSearchFields' +import { generateSegmentStates } from './utils' + +export interface ParseResult { + key: VKey + label?: string + segments: SegmentState[] +} + +export interface ParserContext { + parse: (searchValues: SearchValue[]) => ParseResult[] +} + +export function useParser(searchFields: Ref | SearchField[]): ParserContext { + const dateConfig = useDateConfig() + const { fieldKeyMap } = useResolvedSearchFields( + computed(() => ('value' in searchFields ? searchFields.value : searchFields)), + computed(() => '__pro-search-parser__'), + dateConfig, + ) + + const parse = (searchValues: SearchValue[]) => { + return searchValues + .map(value => { + const field = fieldKeyMap.value.get(value.key) + + if (field) { + return { + key: value.key, + label: field.label, + segments: generateSegmentStates(field, value), + } + } + + return + }) + .filter(Boolean) as ParseResult[] + } + + return { + parse, + } +} diff --git a/packages/pro/search/src/utils/generateSegmentStates.ts b/packages/pro/search/src/utils/generateSegmentStates.ts new file mode 100644 index 000000000..3e3202689 --- /dev/null +++ b/packages/pro/search/src/utils/generateSegmentStates.ts @@ -0,0 +1,28 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import type { ResolvedSearchField, SearchValue, SegmentState } from '../types' + +import { convertArray } from '@idux/cdk/utils' + +export function generateSegmentStates( + searchField: ResolvedSearchField, + searchValue?: Omit, +): SegmentState[] { + const segments = searchField.segments + const hasOperators = searchField.operators && searchField.operators.length > 0 + const operator = searchValue?.operator ?? searchField.operators?.find(op => op === searchField.defaultOperator) + const value = searchValue?.value ?? searchField.defaultValue + const valueArr = segments.length > (hasOperators ? 2 : 1) ? convertArray(value) : [value] + const segmentValues = hasOperators ? [operator, ...valueArr] : valueArr + + return segments.map((segment, idx) => ({ + name: segment.name, + value: segmentValues[idx], + input: segment.format(segmentValues[idx], []), + })) +} diff --git a/packages/pro/search/src/utils/index.ts b/packages/pro/search/src/utils/index.ts index be026cd43..650831d08 100644 --- a/packages/pro/search/src/utils/index.ts +++ b/packages/pro/search/src/utils/index.ts @@ -9,3 +9,4 @@ export * from './getSelectableCommonParams' export * from './RenderIcon' export * from './selectData' export * from './measureTextWidth' +export * from './generateSegmentStates'