From d100657dacb25df91013ef25432620e6ae10d1f8 Mon Sep 17 00:00:00 2001
From: shimai <shimai@example.com>
Date: Thu, 09 Apr 2026 16:56:44 +0800
Subject: [PATCH] feat:增加白云案件类案数据
---
web-app/src/components/tools/LawSearchContent.jsx | 458 ++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 308 insertions(+), 150 deletions(-)
diff --git a/web-app/src/components/tools/LawSearchContent.jsx b/web-app/src/components/tools/LawSearchContent.jsx
index 24c9420..04ab057 100644
--- a/web-app/src/components/tools/LawSearchContent.jsx
+++ b/web-app/src/components/tools/LawSearchContent.jsx
@@ -1,123 +1,196 @@
-import React, { useState } from 'react';
-import { Input, DatePicker, Button, Pagination, Spin } from 'antd';
+import React, { useState, useEffect } from 'react';
+import { Input, DatePicker, Button, Pagination, Spin, Modal, message } from 'antd';
import { SearchOutlined, RedoOutlined } from '@ant-design/icons';
+import LawAPIService from '../../services/LawAPIService';
+import LawDetailContent from './LawDetailContent';
import './LawSearchContent.css';
-// Mock数据 - 按原型格式
-const mockLawList = [
- {
- id: 'law-001',
- lawName: '中华人民共和国民法典',
- effectLevel: '法律',
- status: '有效',
- org: '全国人民代表大会',
- publishDate: '2020-05-28',
- effectiveDate: '2021-01-01',
- articles: [
- { number: '第五条', content: '民事主体从事民事活动,应当遵循自愿原则,按照自己的意思设立、变更、终止民事法律关系。' },
- { number: '第六条', content: '民事主体从事民事活动,应当遵循公平原则,合理确定各方的权利和义务。' },
- ],
- },
- {
- id: 'law-002',
- lawName: '中华人民共和国劳动法',
- effectLevel: '法律',
- status: '有效',
- org: '全国人民代表大会',
- publishDate: '2018-12-29',
- effectiveDate: '2019-01-01',
- articles: [
- { number: '第五十条', content: '工资应当以货币形式按月支付给劳动者本人。不得克扣或者无故拖欠劳动者的工资。' },
- { number: '第九十一条', content: '用人单位有下列侵害劳动者合法权益情形之一的,由劳动行政部门责令支付劳动者的工资报酬、经济补偿,并可以责令支付赔偿金。' },
- ],
- },
- {
- id: 'law-003',
- lawName: '中华人民共和国劳动合同法',
- effectLevel: '法律',
- status: '有效',
- org: '全国人民代表大会常务委员会',
- publishDate: '2012-12-28',
- effectiveDate: '2013-07-01',
- articles: [
- { number: '第三十条', content: '用人单位应当按照劳动合同约定和国家规定,向劳动者及时足额支付劳动报酬。' },
- ],
- },
- {
- id: 'law-004',
- lawName: '中华人民共和国社会保险法',
- effectLevel: '法律',
- status: '有效',
- org: '全国人民代表大会常务委员会',
- publishDate: '2018-12-29',
- effectiveDate: '2019-01-01',
- articles: [],
- },
- {
- id: 'law-005',
- lawName: '最高人民法院关于审理劳动争议案件适用法律问题的解释(一)',
- effectLevel: '司法解释',
- status: '有效',
- org: '最高人民法院',
- publishDate: '2020-12-29',
- effectiveDate: '2021-01-01',
- articles: [],
- },
-];
-
-// 筛选器配置
-const filterConfig = {
- lawNature: [
- { label: '法律', count: 256, checked: true },
- { label: '法律解释', count: 33, checked: false },
- { label: '有关法律问题和重大问题的决定', count: 12, checked: false },
- { label: '修改、废止的决定', count: 8, checked: false },
- ],
- org: [
- { label: '全国人民代表大会', count: 256, checked: true },
- { label: '全国人民代表大会常务委员会', count: 256, checked: false },
- { label: '国务院', count: 21, checked: false },
- { label: '地方各级人民代表大会', count: 8, checked: false },
- { label: '人民法院', count: 21, checked: false },
- { label: '人民检察院', count: 8, checked: false },
- ],
- validity: [
- { label: '有效', count: 33, checked: true },
- { label: '尚未生效', count: 33, checked: false },
- { label: '已废止', count: 12, checked: false },
- { label: '已修改', count: 21, checked: false },
- { label: '其他', count: 8, checked: false },
- ],
+/**
+ * 格式化日期为 YYYY年MM月DD日 格式
+ * @param {string} dateStr - 日期字符串 YYYY-MM-DD
+ * @returns {string} 格式化后的日期
+ */
+const formatDate = (dateStr) => {
+ if (!dateStr) return '-';
+ try {
+ const date = new Date(dateStr);
+ const year = date.getFullYear();
+ const month = date.getMonth() + 1;
+ const day = date.getDate();
+ return `${year}年${month}月${day}日`;
+ } catch (error) {
+ return dateStr;
+ }
};
/**
* 法条搜索内容组件(用于弹窗内显示)- 与原型 law_search.html 保持一致
+ * 已对接API:getHotLaws, getCategoryStatistics, searchLaws, getLawProvisions
*/
const LawSearchContent = () => {
+ // 基本状态
const [loading, setLoading] = useState(false);
- const [keyword, setKeyword] = useState('民事主体从事民事活动');
- const [list, setList] = useState(mockLawList);
- const [activeId, setActiveId] = useState('law-001');
- const [filters, setFilters] = useState(filterConfig);
+ const [keyword, setKeyword] = useState('');
+ const [publishStart, setPublishStart] = useState(null);
+ const [publishEnd, setPublishEnd] = useState(null);
+
+ // 列表数据
+ const [list, setList] = useState([]);
+ const [total, setTotal] = useState(0);
+ const [pageSize, setPageSize] = useState(10);
const [currentPage, setCurrentPage] = useState(1);
- const pageSize = 10;
- const total = 256;
+
+ // 筛选器数据
+ const [filters, setFilters] = useState({
+ lawNature: [],
+ org: [],
+ validity: []
+ });
+
+ // 展开与详情
+ const [activeId, setActiveId] = useState(null);
+ const [expandedProvisions, setExpandedProvisions] = useState({}); // 缓存已加载的法条内容
+ const [detailVisible, setDetailVisible] = useState(false);
+ const [selectedLawId, setSelectedLawId] = useState(null);
- const handleSearch = () => {
- setLoading(true);
- setTimeout(() => {
- setList(mockLawList);
- setLoading(false);
- }, 300);
+ // 分类统计数据处理函数
+ const processCategory = (data, code) => {
+ return data
+ .filter(item => Number(item.code) === code) // 统一转为数字比较
+ .sort((a, b) => b.count - a.count)
+ .map((item, index) => ({
+ label: item.name,
+ value: item.value,
+ count: item.count,
+ checked: index === 0 // 默认勾选第一项
+ }));
};
+ // 初始化数据加载
+ 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 || [];
+ console.log('分类统计原始数据:', categories);
+
+ const processedFilters = {
+ lawNature: processCategory(categories, 102),
+ org: processCategory(categories, 101),
+ validity: processCategory(categories, 103)
+ };
+
+ console.log('处理后的筛选器数据:', processedFilters);
+ setFilters(processedFilters);
+ } catch (error) {
+ message.error('数据加载失败,请刷新重试');
+ console.error('初始化数据加载失败:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ loadInitialData();
+ }, []);
+
+ // 构建查询参数
+ const buildSearchParams = () => {
+ const params = {
+ page: currentPage,
+ size: pageSize
+ };
+
+ // 关键词(非空才传)
+ if (keyword.trim()) {
+ params.keyword = keyword.trim();
+ }
+
+ // 公布日期(两个都有值才传)
+ if (publishStart && publishEnd) {
+ params.publishStart = publishStart.format('YYYY-MM-DD');
+ params.publishEnd = publishEnd.format('YYYY-MM-DD');
+ }
+
+ // 法律性质(多个用逗号拼接,传名称name)
+ const selectedNatures = filters.lawNature
+ .filter(item => item.checked)
+ .map(item => item.label)
+ .join(',');
+ if (selectedNatures) {
+ params.lawNatures = selectedNatures;
+ }
+
+ // 制定机关(多个用逗号拼接,传名称name)
+ const selectedAuthorities = filters.org
+ .filter(item => item.checked)
+ .map(item => item.label)
+ .join(',');
+ if (selectedAuthorities) {
+ params.authorities = selectedAuthorities;
+ }
+
+ // 时效性(多个用逗号拼接,传名称name)
+ const selectedValidities = filters.validity
+ .filter(item => item.checked)
+ .map(item => item.label)
+ .join(',');
+ if (selectedValidities) {
+ params.validities = selectedValidities;
+ }
+
+ return params;
+ };
+
+ // 查询功能
+ 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);
+
+ // 清空已展开的法条缓存
+ setExpandedProvisions({});
+ setActiveId(null);
+ } catch (error) {
+ message.error('查询失败,请重试');
+ console.error('查询失败:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // 重置条件
const handleReset = () => {
setKeyword('');
- setFilters(filterConfig);
+ setPublishStart(null);
+ setPublishEnd(null);
+ // 重新加载初始化筛选器(每个第一项默认勾选)
+ setFilters(prev => ({
+ lawNature: prev.lawNature.map((item, index) => ({ ...item, checked: index === 0 })),
+ org: prev.org.map((item, index) => ({ ...item, checked: index === 0 })),
+ validity: prev.validity.map((item, index) => ({ ...item, checked: index === 0 }))
+ }));
+ setCurrentPage(1);
};
+ // 切换筛选器
const toggleFilter = (category, index) => {
- setFilters(prev => {
+ setFilters((prev) => {
const newFilters = { ...prev };
newFilters[category] = [...prev[category]];
newFilters[category][index] = {
@@ -126,6 +199,48 @@
};
return newFilters;
});
+ };
+
+ // 点击法律卡片
+ 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);
+ const provisions = response.data || [];
+
+ setExpandedProvisions(prev => ({
+ ...prev,
+ [lawInfoId]: provisions
+ }));
+
+ // 如果法条数据为空,直接打开详情弹窗
+ if (!provisions || provisions.length === 0) {
+ setSelectedLawId(law.law_original_info_id);
+ setDetailVisible(true);
+ }
+ } catch (error) {
+ message.error('法条内容加载失败');
+ console.error('法条加载失败:', error);
+ }
+ }
+ }
+ };
+
+ // 分页切换
+ const handlePageChange = (page) => {
+ setCurrentPage(page);
+ // 重新查询,保持当前筛选条件
+ handleSearch();
};
return (
@@ -148,9 +263,19 @@
<div className="law-search-form-group">
<label className="law-search-form-label">公布日期</label>
<div className="law-search-date-input-group">
- <DatePicker placeholder="开始日期" style={{ flex: 1 }} />
+ <DatePicker
+ value={publishStart}
+ onChange={(date) => setPublishStart(date)}
+ placeholder="开始日期"
+ style={{ flex: 1 }}
+ />
<span className="law-search-date-separator">至</span>
- <DatePicker placeholder="结束日期" style={{ flex: 1 }} />
+ <DatePicker
+ value={publishEnd}
+ onChange={(date) => setPublishEnd(date)}
+ placeholder="结束日期"
+ style={{ flex: 1 }}
+ />
</div>
</div>
<div className="law-search-form-group full-width">
@@ -173,18 +298,24 @@
<div className="law-search-filter-category">
<h3 className="law-search-filter-title">法律性质</h3>
<div className="law-search-filter-list">
- {filters.lawNature.map((item, index) => (
- <div
- key={index}
- className="law-search-filter-item"
- onClick={() => toggleFilter('lawNature', index)}
- >
- <div className={`law-search-filter-checkbox ${item.checked ? 'checked' : ''}`}>
- {item.checked && <i className="fas fa-check"></i>}
+ {filters.lawNature && filters.lawNature.length > 0 ? (
+ filters.lawNature.map((item, index) => (
+ <div
+ key={index}
+ className="law-search-filter-item"
+ onClick={() => toggleFilter('lawNature', index)}
+ >
+ <div className={`law-search-filter-checkbox ${item.checked ? 'checked' : ''}`}>
+ {item.checked && <i className="fas fa-check"></i>}
+ </div>
+ <span>
+ {item.label} ({item.count})
+ </span>
</div>
- <span>{item.label} ({item.count})</span>
- </div>
- ))}
+ ))
+ ) : (
+ <div className="law-search-filter-empty">暂无数据</div>
+ )}
</div>
</div>
@@ -192,18 +323,20 @@
<div className="law-search-filter-category">
<h3 className="law-search-filter-title">制定机关</h3>
<div className="law-search-filter-list">
- {filters.org.map((item, index) => (
- <div
- key={index}
- className="law-search-filter-item"
- onClick={() => toggleFilter('org', index)}
- >
- <div className={`law-search-filter-checkbox ${item.checked ? 'checked' : ''}`}>
- {item.checked && <i className="fas fa-check"></i>}
+ {filters.org && filters.org.length > 0 ? (
+ filters.org.map((item, index) => (
+ <div key={index} className="law-search-filter-item" onClick={() => toggleFilter('org', index)}>
+ <div className={`law-search-filter-checkbox ${item.checked ? 'checked' : ''}`}>
+ {item.checked && <i className="fas fa-check"></i>}
+ </div>
+ <span>
+ {item.label} ({item.count})
+ </span>
</div>
- <span>{item.label} ({item.count})</span>
- </div>
- ))}
+ ))
+ ) : (
+ <div className="law-search-filter-empty">暂无数据</div>
+ )}
</div>
</div>
@@ -211,18 +344,24 @@
<div className="law-search-filter-category">
<h3 className="law-search-filter-title">时效性</h3>
<div className="law-search-filter-list">
- {filters.validity.map((item, index) => (
- <div
- key={index}
- className="law-search-filter-item"
- onClick={() => toggleFilter('validity', index)}
- >
- <div className={`law-search-filter-checkbox ${item.checked ? 'checked' : ''}`}>
- {item.checked && <i className="fas fa-check"></i>}
+ {filters.validity && filters.validity.length > 0 ? (
+ filters.validity.map((item, index) => (
+ <div
+ key={index}
+ className="law-search-filter-item"
+ onClick={() => toggleFilter('validity', index)}
+ >
+ <div className={`law-search-filter-checkbox ${item.checked ? 'checked' : ''}`}>
+ {item.checked && <i className="fas fa-check"></i>}
+ </div>
+ <span>
+ {item.label} ({item.count})
+ </span>
</div>
- <span>{item.label} ({item.count})</span>
- </div>
- ))}
+ ))
+ ) : (
+ <div className="law-search-filter-empty">暂无数据</div>
+ )}
</div>
</div>
</div>
@@ -239,40 +378,40 @@
<div className="law-search-laws-list">
{list.map((law) => (
<div
- key={law.id}
- className={`law-search-law-item ${activeId === law.id ? 'active' : ''}`}
- onClick={() => setActiveId(law.id)}
+ key={law.law_info_id}
+ className={`law-search-law-item ${activeId === law.law_info_id ? 'active' : ''}`}
+ onClick={() => handleLawItemClick(law)}
>
- <h3 className="law-search-law-title">{law.lawName}</h3>
+ <h3 className="law-search-law-title">{law.title}</h3>
<div className="law-search-law-meta">
<div className="law-search-law-meta-item">
<i className="fas fa-check-circle status-valid"></i>
- <span>时效性:{law.status}</span>
+ <span>时效性:{law.validity_name || '-'}</span>
</div>
<div className="law-search-law-meta-item">
<i className="fas fa-layer-group"></i>
- <span>法律效力位阶:{law.effectLevel}</span>
+ <span>法律效力位阶:{law.law_nature_name || '-'}</span>
</div>
<div className="law-search-law-meta-item">
<i className="fas fa-landmark"></i>
- <span>制定机关:{law.org}</span>
+ <span>制定机关:{law.authority_name || '-'}</span>
</div>
<div className="law-search-law-meta-item">
<i className="far fa-calendar-alt"></i>
- <span>公布日期:{law.publishDate}</span>
+ <span>公布日期:{formatDate(law.publish_time)}</span>
</div>
<div className="law-search-law-meta-item">
<i className="far fa-calendar-check"></i>
- <span>实施日期:{law.effectiveDate}</span>
+ <span>实施日期:{formatDate(law.implementation_time)}</span>
</div>
</div>
{/* 条文内容 - 仅在选中状态显示 */}
- {activeId === law.id && law.articles && law.articles.length > 0 && (
+ {activeId === law.law_info_id && expandedProvisions[law.law_info_id] && expandedProvisions[law.law_info_id].length > 0 && (
<div className="law-search-law-content">
- {law.articles.map((article, index) => (
+ {expandedProvisions[law.law_info_id].map((article, index) => (
<div className="law-search-law-article" key={index}>
- <span className="law-search-article-number">{article.number}</span>
- <span>{article.content}</span>
+ <span className="law-search-article-number">{article.provision_index || ''}</span>
+ <span>{article.provision_text || ''}</span>
</div>
))}
</div>
@@ -288,13 +427,32 @@
current={currentPage}
pageSize={pageSize}
total={total}
- onChange={(page) => setCurrentPage(page)}
+ onChange={handlePageChange}
showSizeChanger={false}
showQuickJumper
showTotal={(total, range) => `第 ${range[0]}-${range[1]} 条 / 共 ${total} 条`}
/>
</div>
</div>
+
+ {/* 详情弹窗 */}
+ <Modal
+ title={
+ <div style={{ fontSize: '1.2rem', fontWeight: 600 }}>
+ <i className="fas fa-book" style={{ marginRight: 10, color: '#1a6fb8' }}></i>
+ 法律条文详情
+ </div>
+ }
+ visible={detailVisible}
+ onCancel={() => setDetailVisible(false)}
+ footer={null}
+ width={1000}
+ bodyStyle={{ padding: 0, height: '80vh', overflow: 'hidden' }}
+ centered
+ destroyOnClose
+ >
+ <LawDetailContent lawId={selectedLawId} />
+ </Modal>
</div>
);
};
--
Gitblit v1.8.0