--- name: "search-state-persistence" description: "Search state persistence via tools.router.query. Invoke when implementing search/table pages with SearchForm + Table + pagination that need to preserve query params across refreshes." --- # 搜索状态持久化 通过 `tools.router.query` 实现搜索条件持久化,刷新页面后搜索条件和分页状态保留在 URL 查询参数中。 ## 核心 API ```js import { tools } from "@cqsjjb/jjb-common-lib"; const { router } = tools; ``` `router.query` 是一个响应式对象,对其赋值会同步更新 URL 查询参数。 ## 完整模式 ```jsx import React, { useState, useEffect } from "react"; import { Button, Form, Select, Space, Table, Tag } from "antd"; import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout"; import SearchForm from "~/components/SearchForm"; import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper"; import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd"; import { tools } from "@cqsjjb/jjb-common-lib"; const { router } = tools; const MyPage = (props) => { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); /** 搜索/刷新数据 */ const handleSearch = () => { setLoading(true); // 实际请求... setTimeout(() => setLoading(false), 500); }; /** 重置搜索 */ const handleReset = (values) => { router.query = { ...router.query, ...values, current: 1, size: 10, }; handleSearch(); }; /** 初始化:将 URL 中的查询条件回填到表单 */ useEffect(() => { form.setFieldsValue(router.query); }, []); const columns = [ // ...列定义 ]; return ( , ]} onReset={handleReset} onFinish={(values) => { router.query = { ...router.query, ...values, current: 1, size: 10, }; handleSearch(); }} /> `共 ${total} 条`, current: router.query.current, pageSize: router.query.size, onChange: (page, pageSize) => { router.query = { ...router.query, current: page, size: pageSize, }; handleSearch(); }, }} /> ); }; export default AntdTableFuncControl(MyPage); ``` ## 关键规则 ### 1. 初始化回填 在 `useEffect` 中将 `router.query` 的值回填到表单,确保刷新后表单显示与 URL 一致: ```js useEffect(() => { form.setFieldsValue(router.query); }, []); ``` **注意**:`router.query` 中所有值均为字符串,而 `DatePicker` / `RangePicker` 需要 `dayjs` 对象。当表单包含日期字段时,必须手动转换: ```js useEffect(() => { searchForm.setFieldsValue({ ...router.query, dateRange: router.query.startTime && router.query.endTime ? [dayjs(router.query.startTime), dayjs(router.query.endTime)] : undefined, }); }, []); ``` ### 2. 搜索/重置写入 搜索提交(`onFinish`) 和重置(`onReset`) 时,将表单值与默认分页合并写入 `router.query`: ```js router.query = { ...router.query, ...values, // 表单值 current: 1, // 重置到第一页 pageSize: 10, // 默认页大小 }; ``` ### 3. 翻页写入 分页变化时,仅更新 `current` 和 `pageSize`,保留已有搜索条件: ```js onChange: (page, pageSize) => { router.query = { ...router.query, // 保留已有搜索条件 current: page, pageSize, }; handleSearch(); }; ``` ### 4. 组件装饰器 页面组件必须用 `AntdTableFuncControl` 包裹以支持表格功能: ```js export default AntdTableFuncControl(MyPage); ``` ## 注意事项 - `router.query` 是响应式的:赋值会触发 URL 更新,且刷新后值仍然保留 - `router.query` 中所有值均为字符串类型(URL query 的特性),使用 `current` 和 `pageSize` 时注意隐式类型转换 - 默认值 `current: 1, pageSize: 10` 是约定,可根据实际需求修改 - `onReset` 回调的 `values` 参数是重置后的表单值(所有字段清空/恢复默认后的值)