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';
|
|
/**
|
* 格式化日期为 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 [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 [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 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('');
|
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) => {
|
const newFilters = { ...prev };
|
newFilters[category] = [...prev[category]];
|
newFilters[category][index] = {
|
...newFilters[category][index],
|
checked: !newFilters[category][index].checked,
|
};
|
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 (
|
<div className="law-search-container">
|
{/* 查询条件区域 */}
|
<div className="law-search-query-conditions">
|
<h2 className="law-search-query-title">
|
<i className="fas fa-search"></i>
|
查询条件
|
</h2>
|
<div className="law-search-query-form">
|
<div className="law-search-form-group">
|
<label className="law-search-form-label">关键词</label>
|
<Input
|
value={keyword}
|
onChange={(e) => setKeyword(e.target.value)}
|
placeholder="请输入关键词"
|
/>
|
</div>
|
<div className="law-search-form-group">
|
<label className="law-search-form-label">公布日期</label>
|
<div className="law-search-date-input-group">
|
<DatePicker
|
value={publishStart}
|
onChange={(date) => setPublishStart(date)}
|
placeholder="开始日期"
|
style={{ flex: 1 }}
|
/>
|
<span className="law-search-date-separator">至</span>
|
<DatePicker
|
value={publishEnd}
|
onChange={(date) => setPublishEnd(date)}
|
placeholder="结束日期"
|
style={{ flex: 1 }}
|
/>
|
</div>
|
</div>
|
<div className="law-search-form-group full-width">
|
<div className="law-search-button-group">
|
<Button type="primary" icon={<SearchOutlined />} onClick={handleSearch} loading={loading}>
|
查询
|
</Button>
|
<Button icon={<RedoOutlined />} onClick={handleReset}>
|
重置条件
|
</Button>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
{/* 筛选器区域 */}
|
<div className="law-search-filters-section">
|
<div className="law-search-filters-grid">
|
{/* 法律性质 */}
|
<div className="law-search-filter-category">
|
<h3 className="law-search-filter-title">法律性质</h3>
|
<div className="law-search-filter-list">
|
{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>
|
))
|
) : (
|
<div className="law-search-filter-empty">暂无数据</div>
|
)}
|
</div>
|
</div>
|
|
{/* 制定机关 */}
|
<div className="law-search-filter-category">
|
<h3 className="law-search-filter-title">制定机关</h3>
|
<div className="law-search-filter-list">
|
{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>
|
))
|
) : (
|
<div className="law-search-filter-empty">暂无数据</div>
|
)}
|
</div>
|
</div>
|
|
{/* 时效性 */}
|
<div className="law-search-filter-category">
|
<h3 className="law-search-filter-title">时效性</h3>
|
<div className="law-search-filter-list">
|
{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>
|
))
|
) : (
|
<div className="law-search-filter-empty">暂无数据</div>
|
)}
|
</div>
|
</div>
|
</div>
|
</div>
|
|
{/* 查询结果区域 */}
|
<div className="law-search-results-section">
|
<div className="law-search-results-header">
|
<h2 className="law-search-results-title">查询结果</h2>
|
<div className="law-search-page-info">记录总数:{total}条</div>
|
</div>
|
|
<Spin spinning={loading}>
|
<div className="law-search-laws-list">
|
{list.map((law) => (
|
<div
|
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.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.validity_name || '-'}</span>
|
</div>
|
<div className="law-search-law-meta-item">
|
<i className="fas fa-layer-group"></i>
|
<span>法律效力位阶:{law.law_nature_name || '-'}</span>
|
</div>
|
<div className="law-search-law-meta-item">
|
<i className="fas fa-landmark"></i>
|
<span>制定机关:{law.authority_name || '-'}</span>
|
</div>
|
<div className="law-search-law-meta-item">
|
<i className="far fa-calendar-alt"></i>
|
<span>公布日期:{formatDate(law.publish_time)}</span>
|
</div>
|
<div className="law-search-law-meta-item">
|
<i className="far fa-calendar-check"></i>
|
<span>实施日期:{formatDate(law.implementation_time)}</span>
|
</div>
|
</div>
|
{/* 条文内容 - 仅在选中状态显示 */}
|
{activeId === law.law_info_id && expandedProvisions[law.law_info_id] && expandedProvisions[law.law_info_id].length > 0 && (
|
<div className="law-search-law-content">
|
{expandedProvisions[law.law_info_id].map((article, index) => (
|
<div className="law-search-law-article" key={index}>
|
<span className="law-search-article-number">{article.provision_index || ''}</span>
|
<span>{article.provision_text || ''}</span>
|
</div>
|
))}
|
</div>
|
)}
|
</div>
|
))}
|
</div>
|
</Spin>
|
|
{/* 分页 */}
|
<div className="law-search-pagination">
|
<Pagination
|
current={currentPage}
|
pageSize={pageSize}
|
total={total}
|
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>
|
);
|
};
|
|
export default LawSearchContent;
|