Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kne-components/components-core",
"version": "0.4.74",
"version": "0.4.75",
"files": [
"build"
],
Expand Down
112 changes: 112 additions & 0 deletions src/components/Filter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,7 @@ const {
getFilterValue,
createFilterValueMapper,
pickSelectValues,
useUrlFilterValue,
} = _Filter;
const { useState, useMemo } = React;
const { Space, Card, Divider, Typography, Button, Alert, Tag } = antd;
Expand Down Expand Up @@ -1150,6 +1151,67 @@ mapFilterValue(filterValue, getFilterValue);
{' ' + JSON.stringify(mappedSample, null, 2)}
</pre>
</Card>

{/* ===== useUrlFilterValue ===== */}
<Card title="useUrlFilterValue — 简化版 URL 筛选初始化" size="small">
<Paragraph type="secondary">
基于 useUrlFilter 封装的简化版 Hook,使用 createUrlFilterReader 解析 filterParams[key] 格式,自动解析 label:value,支持单选和多选
</Paragraph>

<Title level={5}>1. 数组形式 — 默认单选</Title>
<pre style={{ background: '#f5f5f5', padding: 8, borderRadius: 4, fontSize: 12 }}>
{&#96;const [filter, setFilter] = useUrlFilterValue(['keyword', 'status']);

// URL: ?filterParams[keyword]=前端开发&filterParams[status]=招聘中:active
// → filter: [
// { name: 'keyword', value: { label: '前端开发', value: '前端开发' } },
// { name: 'status', value: { label: '招聘中', value: 'active' } }
// ]&#96;}
</pre>

<Divider />

<Title level={5}>2. 对象形式 — 多选 + 自定义转换</Title>
<pre style={{ background: '#f5f5f5', padding: 8, borderRadius: 4, fontSize: 12 }}>
{&#96;// { multi: true } 表示多选,value 为数组
// 函数接收解析后的值,返回 filter 项或 null 跳过
const [filter, setFilter] = useUrlFilterValue({
keyword: true, // 单选,默认转换
city: { multi: true }, // 多选
status: (parsed) => parsed // 自定义:直接用解析值
? { name: 'status', value: parsed }
: null
});

// URL: ?filterParams[city]=上海:010,北京:020
// → city 的 value: [{ label: '上海', value: '010' }, { label: '北京', value: '020' }]&#96;}
</pre>

<Divider />

<Title level={5}>对比 useUrlFilter</Title>
<pre style={{ background: '#fff3cd', padding: 8, borderRadius: 4, fontSize: 12 }}>
{&#96;// useUrlFilter(完整控制,需手动解析)
const [filter, setFilter] = useUrlFilter({
readUrlParams: (searchParams) => {
const { takeFilterEntry, getConsumedKeys } = createUrlFilterReader(searchParams);
const keyword = takeFilterEntry('keyword');
const city = takeFilterEntry('city', { multi: true });
return { consumedKeys: getConsumedKeys(), keyword, city };
},
buildFilter: ({ keyword, city }) => [
...(keyword ? [{ name: 'keyword', value: keyword }] : []),
...(city ? [{ name: 'city', value: city }] : []),
]
});

// useUrlFilterValue(等价简化写法)
const [filter, setFilter] = useUrlFilterValue({
keyword: true,
city: { multi: true }
});&#96;}
</pre>
</Card>
</Space>
);
};
Expand Down Expand Up @@ -1901,6 +1963,56 @@ const [filter, setFilter] = useUrlFilter({
});
```

#### useUrlFilterValue

从 URL 参数初始化 Filter 状态的 Hook(简化版)。基于 `useUrlFilter` 封装,使用 `createUrlFilterReader` 解析 `filterParams[key]` 格式的 URL 参数,自动解析 `label:value` 格式,支持单选和多选。

**函数签名:**
```javascript
useUrlFilterValue(mapping): [array, function]
```

**参数说明:**

| 参数名 | 说明 | 类型 | 必填 |
|--------|------|------|------|
| mapping | URL 参数映射配置,支持数组或对象格式 | string[] \| object | 是 |

**mapping 格式:**

- **数组形式**:`['key1', 'key2']`,默认单选,自动创建 `{ name: key, value: { label, value } }` 格式的筛选项
- **对象形式**:`{ key1: true, key2: { multi: true }, key3: fn }`
- 值为 `true`:单选,使用默认转换
- 值为 `{ multi: true }`:多选,value 为 `[{ label, value }, ...]` 数组
- 值为函数:自定义转换,接收解析后的值(单选为 `{ label, value }`,多选为数组),返回 filter 项或 `null`/falsy 跳过

**返回值:**

| 返回值 | 说明 | 类型 |
|--------|------|------|
| [0] | 初始筛选值数组 | array |
| [1] | 设置筛选值的函数 | function |

**示例:**
```javascript
// 数组形式(默认单选)
const [filter, setFilter] = useUrlFilterValue(['keyword', 'status']);
// URL: ?filterParams[keyword]=前端开发&filterParams[status]=招聘中:active
// → filter: [
// { name: 'keyword', value: { label: '前端开发', value: '前端开发' } },
// { name: 'status', value: { label: '招聘中', value: 'active' } }
// ]

// 对象形式(多选 + 自定义转换)
const [filter, setFilter] = useUrlFilterValue({
keyword: true,
city: { multi: true },
status: (parsed) => parsed ? { name: 'status', value: parsed } : null
});
// URL: ?filterParams[city]=上海:010,北京:020
// → city 的 value: [{ label: '上海', value: '010' }, { label: '北京', value: '020' }]
```

#### createUrlParamsReader

创建 URL 参数读取器,自动追踪已消费的参数 key。
Expand Down
50 changes: 50 additions & 0 deletions src/components/Filter/doc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,56 @@ const [filter, setFilter] = useUrlFilter({
});
```

#### useUrlFilterValue

从 URL 参数初始化 Filter 状态的 Hook(简化版)。基于 `useUrlFilter` 封装,使用 `createUrlFilterReader` 解析 `filterParams[key]` 格式的 URL 参数,自动解析 `label:value` 格式,支持单选和多选。

**函数签名:**
```javascript
useUrlFilterValue(mapping): [array, function]
```

**参数说明:**

| 参数名 | 说明 | 类型 | 必填 |
|--------|------|------|------|
| mapping | URL 参数映射配置,支持数组或对象格式 | string[] \| object | 是 |

**mapping 格式:**

- **数组形式**:`['key1', 'key2']`,默认单选,自动创建 `{ name: key, value: { label, value } }` 格式的筛选项
- **对象形式**:`{ key1: true, key2: { multi: true }, key3: fn }`
- 值为 `true`:单选,使用默认转换
- 值为 `{ multi: true }`:多选,value 为 `[{ label, value }, ...]` 数组
- 值为函数:自定义转换,接收解析后的值(单选为 `{ label, value }`,多选为数组),返回 filter 项或 `null`/falsy 跳过

**返回值:**

| 返回值 | 说明 | 类型 |
|--------|------|------|
| [0] | 初始筛选值数组 | array |
| [1] | 设置筛选值的函数 | function |

**示例:**
```javascript
// 数组形式(默认单选)
const [filter, setFilter] = useUrlFilterValue(['keyword', 'status']);
// URL: ?filterParams[keyword]=前端开发&filterParams[status]=招聘中:active
// → filter: [
// { name: 'keyword', value: { label: '前端开发', value: '前端开发' } },
// { name: 'status', value: { label: '招聘中', value: 'active' } }
// ]

// 对象形式(多选 + 自定义转换)
const [filter, setFilter] = useUrlFilterValue({
keyword: true,
city: { multi: true },
status: (parsed) => parsed ? { name: 'status', value: parsed } : null
});
// URL: ?filterParams[city]=上海:010,北京:020
// → city 的 value: [{ label: '上海', value: '010' }, { label: '北京', value: '020' }]
```

#### createUrlParamsReader

创建 URL 参数读取器,自动追踪已消费的参数 key。
Expand Down
62 changes: 62 additions & 0 deletions src/components/Filter/doc/use-url-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const {
getFilterValue,
createFilterValueMapper,
pickSelectValues,
useUrlFilterValue,
} = _Filter;
const { useState, useMemo } = React;
const { Space, Card, Divider, Typography, Button, Alert, Tag } = antd;
Expand Down Expand Up @@ -213,6 +214,67 @@ mapFilterValue(filterValue, getFilterValue);
{' ' + JSON.stringify(mappedSample, null, 2)}
</pre>
</Card>

{/* ===== useUrlFilterValue ===== */}
<Card title="useUrlFilterValue — 简化版 URL 筛选初始化" size="small">
<Paragraph type="secondary">
基于 useUrlFilter 封装的简化版 Hook,使用 createUrlFilterReader 解析 filterParams[key] 格式,自动解析 label:value,支持单选和多选
</Paragraph>

<Title level={5}>1. 数组形式 — 默认单选</Title>
<pre style={{ background: '#f5f5f5', padding: 8, borderRadius: 4, fontSize: 12 }}>
{`const [filter, setFilter] = useUrlFilterValue(['keyword', 'status']);

// URL: ?filterParams[keyword]=前端开发&filterParams[status]=招聘中:active
// → filter: [
// { name: 'keyword', value: { label: '前端开发', value: '前端开发' } },
// { name: 'status', value: { label: '招聘中', value: 'active' } }
// ]`}
</pre>

<Divider />

<Title level={5}>2. 对象形式 — 多选 + 自定义转换</Title>
<pre style={{ background: '#f5f5f5', padding: 8, borderRadius: 4, fontSize: 12 }}>
{`// { multi: true } 表示多选,value 为数组
// 函数接收解析后的值,返回 filter 项或 null 跳过
const [filter, setFilter] = useUrlFilterValue({
keyword: true, // 单选,默认转换
city: { multi: true }, // 多选
status: (parsed) => parsed // 自定义:直接用解析值
? { name: 'status', value: parsed }
: null
});

// URL: ?filterParams[city]=上海:010,北京:020
// → city 的 value: [{ label: '上海', value: '010' }, { label: '北京', value: '020' }]`}
</pre>

<Divider />

<Title level={5}>对比 useUrlFilter</Title>
<pre style={{ background: '#fff3cd', padding: 8, borderRadius: 4, fontSize: 12 }}>
{`// useUrlFilter(完整控制,需手动解析)
const [filter, setFilter] = useUrlFilter({
readUrlParams: (searchParams) => {
const { takeFilterEntry, getConsumedKeys } = createUrlFilterReader(searchParams);
const keyword = takeFilterEntry('keyword');
const city = takeFilterEntry('city', { multi: true });
return { consumedKeys: getConsumedKeys(), keyword, city };
},
buildFilter: ({ keyword, city }) => [
...(keyword ? [{ name: 'keyword', value: keyword }] : []),
...(city ? [{ name: 'city', value: city }] : []),
]
});

// useUrlFilterValue(等价简化写法)
const [filter, setFilter] = useUrlFilterValue({
keyword: true,
city: { multi: true }
});`}
</pre>
</Card>
</Space>
);
};
Expand Down
4 changes: 3 additions & 1 deletion src/components/Filter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import FilterProvider from './FilterProvider';
import pickSelectValues from "./pickSelectValues";
import createFilterValueMapper from "./createFilterValueMapper";
import useUrlFilter, {createUrlParamsReader, stripConsumedUrlParams} from "./useUrlFilter";
import useUrlFilterValue from "./useUrlFilterValue";
import filterToUrlParams, {parseFilterEntry, takeFilterEntry, createUrlFilterReader} from "./filterToUrlParams";
import filterInterceptors, {singleSelectInterceptor, multiSelectInterceptor} from "./filterInterceptors";

Expand All @@ -20,6 +21,7 @@ Filter.FilterProvider = FilterProvider;
Filter.pickSelectValues = pickSelectValues;
Filter.createFilterValueMapper = createFilterValueMapper;
Filter.useUrlFilter = useUrlFilter;
Filter.useUrlFilterValue = useUrlFilterValue;
Filter.createUrlParamsReader = createUrlParamsReader;
Filter.stripConsumedUrlParams = stripConsumedUrlParams;
Filter.filterToUrlParams = filterToUrlParams;
Expand All @@ -30,7 +32,7 @@ Filter.filterInterceptors = filterInterceptors;
Filter.singleSelectInterceptor = singleSelectInterceptor;
Filter.multiSelectInterceptor = multiSelectInterceptor;
export default Filter;
export {fields, getFilterValue, useFilter, withFilterValue, SearchInput, FilterProvider, pickSelectValues, createFilterValueMapper, useUrlFilter, createUrlParamsReader, stripConsumedUrlParams, filterToUrlParams, parseFilterEntry, takeFilterEntry, createUrlFilterReader, filterInterceptors, singleSelectInterceptor, multiSelectInterceptor};
export {fields, getFilterValue, useFilter, withFilterValue, SearchInput, FilterProvider, pickSelectValues, createFilterValueMapper, useUrlFilter, useUrlFilterValue, createUrlParamsReader, stripConsumedUrlParams, filterToUrlParams, parseFilterEntry, takeFilterEntry, createUrlFilterReader, filterInterceptors, singleSelectInterceptor, multiSelectInterceptor};
export {default as AdvancedFilter, advancedFields} from "./AdvancedFilter";
export {default as FilterValueDisplay} from "./FilterValueDisplay";
export {default as FilterItem} from "./FilterItem";
Expand Down
Loading