将法律条文查询功能从Mock数据迁移到真实API对接,实现完整的数据加载、查询过滤、分页展示和详情查看流程。
当前LawSearchContent组件使用静态Mock数据,无法满足实际业务需求。需要对接后端API实现:
1. 页面加载时自动获取热门法律法规
2. 动态加载分类统计数据用于筛选器
3. 支持多条件组合查询和分页
4. 点击展开时动态加载法条内容
5. 弹出详情窗口展示完整法律原文
| 场景 | API | 触发时机 | 参数 |
|---|---|---|---|
| 页面初始化 | getHotLaws | useEffect首次加载 | limit=10 |
| 页面初始化 | getCategoryStatistics | useEffect首次加载 | 无 |
| 点击查询按钮 | searchLaws | 用户触发 | keyword, publishStart, publishEnd, lawNatures, authorities, validities, page, size |
| 点击卡片展开 | getLawProvisions | 首次展开时 | law_info_id |
| 点击展开卡片 | getLawOriginalDetail | 弹窗打开时 | law_original_info_id |
// API返回: lawDataList.data.data
{
law_info_id: "xxx", // 法律信息ID(用于getLawProvisions)
law_original_info_id: "yyy", // 法律原文ID(用于getLawOriginalDetail)
title: "中华人民共和国劳动法", // → 法律标题
validity_name: "有效", // → 时效性
law_nature_name: "法律", // → 法律效力位阶
authority_name: "全国人民代表大会", // → 制定机关
publish_time: "2020-05-28", // → 公布日期
implementation_time: "2021-01-01" // → 实施日期
}
// API返回: categoryResponse.data
[
{ code: 101, name: "全国人民代表大会", value: "1", count: 256 },
{ code: 102, name: "法律", value: "1", count: 300 },
{ code: 103, name: "有效", value: "1", count: 500 }
]
// 分组逻辑:
// - code=101 → 制定机关筛选器
// - code=102 → 法律性质筛选器
// - code=103 → 时效性筛选器
// 每组按count降序排列,默认勾选第一项
// 筛选器选中项转换为API参数
const buildSearchParams = () => {
const params = {
page: currentPage,
size: pageSize
};
// 关键词(非空才传)
if (keyword.trim()) {
params.keyword = keyword.trim();
}
// 公布日期(两个都有值才传)
if (publishStart && publishEnd) {
params.publishStart = publishStart; // YYYY-MM-DD格式
params.publishEnd = publishEnd;
}
// 法律性质(多个用逗号拼接)
const selectedNatures = filters.lawNature
.filter(item => item.checked)
.map(item => item.value)
.join(',');
if (selectedNatures) {
params.lawNatures = selectedNatures;
}
// 制定机关(多个用逗号拼接)
const selectedAuthorities = filters.org
.filter(item => item.checked)
.map(item => item.value)
.join(',');
if (selectedAuthorities) {
params.authorities = selectedAuthorities;
}
// 时效性(多个用逗号拼接)
const selectedValidities = filters.validity
.filter(item => item.checked)
.map(item => item.value)
.join(',');
if (selectedValidities) {
params.validities = selectedValidities;
}
return params;
};
从 provision_text (纯文本) 提取章节列表:
const extractChapters = (provisionText) => {
// 1. 定位目录区域
const startMarker = "\n\n目 录\n";
const endMarker = "\n\n第一章 总则\n\n";
const startIndex = provisionText.indexOf(startMarker);
const endIndex = provisionText.indexOf(endMarker);
if (startIndex === -1 || endIndex === -1) {
return []; // 未找到目录标记,返回空数组
}
// 2. 提取目录内容
const tocContent = provisionText.substring(
startIndex + startMarker.length,
endIndex
);
// 3. 按行分割并过滤空行
const lines = tocContent.split('\n').filter(line => line.trim());
// 4. 转换为章节对象
return lines.map((line, index) => ({
id: `chapter-${index + 1}`,
title: line.trim()
}));
};
const [loading, setLoading] = useState(false); // 加载中状态
const [list, setList] = useState([]); // 法律列表
const [filters, setFilters] = useState({ // 筛选器数据
lawNature: [], // 从API加载
org: [], // 从API加载
validity: [] // 从API加载
});
const [activeId, setActiveId] = useState(null); // 当前展开的卡片ID
const [expandedProvisions, setExpandedProvisions] = useState({}); // 已加载的法条内容 {law_info_id: articles}
const [currentPage, setCurrentPage] = useState(1); // 当前页码
const [total, setTotal] = useState(0); // 总记录数
const [pageSize, setPageSize] = useState(10); // 每页数量
web-app/src/components/tools/LawSearchContent.jsx - 主要修改web-app/src/services/LawAPIService.js - 确认API方法签名web-app/src/components/tools/LawDetailContent.jsx - 详情组件修改useEffect(() => {
const loadInitialData = async () => {
setLoading(true);
try {
const [hotLawsRes, categoryRes] = await Promise.all([
LawAPIService.getHotLaws(10),
LawAPIService.getCategoryStatistics()
]);
// 处理法律列表
setList(hotLawsRes.data?.data || []);
setTotal(hotLawsRes.data?.total || 0);
setPageSize(hotLawsRes.data?.size || 10);
// 处理分类统计
const categories = categoryRes.data || [];
setFilters({
lawNature: processCategory(categories, 102),
org: processCategory(categories, 101),
validity: processCategory(categories, 103)
});
} catch (error) {
message.error('数据加载失败,请刷新重试');
} finally {
setLoading(false);
}
};
loadInitialData();
}, []);
const handleSearch = async () => {
setLoading(true);
try {
const params = buildSearchParams();
const response = await LawAPIService.searchLaws(params);
setList(response.data?.data || []);
setTotal(response.data?.total || 0);
setPageSize(response.data?.size || 10);
setCurrentPage(params.page);
// 清空已展开的法条缓存
setExpandedProvisions({});
setActiveId(null);
} catch (error) {
message.error('查询失败,请重试');
} finally {
setLoading(false);
}
};
const handleLawItemClick = async (law) => {
const lawInfoId = law.law_info_id;
if (activeId === lawInfoId) {
// 已展开状态,弹出详情
setSelectedLawId(law.law_original_info_id);
setDetailVisible(true);
} else {
// 首次展开,加载法条内容
setActiveId(lawInfoId);
if (!expandedProvisions[lawInfoId]) {
try {
const response = await LawAPIService.getLawProvisions(lawInfoId);
setExpandedProvisions(prev => ({
...prev,
[lawInfoId]: response.data || []
}));
} catch (error) {
message.error('法条内容加载失败');
}
}
}
};
// LawDetailContent.jsx修改
useEffect(() => {
const loadDetail = async () => {
if (!lawId) return;
setLoading(true);
try {
const response = await LawAPIService.getLawOriginalDetail(lawId);
const detailData = response.data;
// 从provision_text提取章节
const chapters = extractChapters(detailData.provision_text || '');
setLawDetail({
...detailData,
chapters
});
} catch (error) {
message.error('详情加载失败');
} finally {
setLoading(false);
}
};
loadDetail();
}, [lawId]);
document/原型/law_search.htmldocument/原型/law_search_detail.htmlweb-app/src/services/LawAPIService.jsweb-app/src/components/tools/LawSearchContent.jsx