chengmw
9 days ago 529af79115af1e72bcd4d9a0dce63bb89cc4a5ab
web-app/src/components/tools/LawSearchContent.jsx
@@ -1,124 +1,194 @@
import React, { useState } from 'react';
import { Input, DatePicker, Button, Pagination, Spin, Modal } 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 [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 pageSize = 10;
  const total = 256;
  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) => {
      const newFilters = { ...prev };
@@ -131,14 +201,46 @@
    });
  };
  const handleLawItemClick = (lawId) => {
    if (activeId === lawId) {
      // 如果已经是激活状态,再次点击弹出详情
      setSelectedLawId(lawId);
  // 点击法律卡片
  const handleLawItemClick = async (law) => {
    const lawInfoId = law.law_info_id;
    if (activeId === lawInfoId) {
      // 已展开状态,弹出详情
      setSelectedLawId(law.law_original_info_id);
      setDetailVisible(true);
    } else {
      setActiveId(lawId);
      // 首次展开,加载法条内容
      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 (
@@ -161,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">
@@ -186,20 +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>
@@ -207,16 +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>
@@ -224,20 +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>
@@ -254,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={() => handleLawItemClick(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>
@@ -303,7 +427,7 @@
            current={currentPage}
            pageSize={pageSize}
            total={total}
            onChange={(page) => setCurrentPage(page)}
            onChange={handlePageChange}
            showSizeChanger={false}
            showQuickJumper
            showTotal={(total, range) => `第 ${range[0]}-${range[1]} 条 / 共 ${total} 条`}