shimai
9 days ago 88a31d5a960bd10f3799bc00f8aa24461567d06e
web-app/src/components/tools/LawDetailContent.jsx
@@ -1,17 +1,105 @@
import React, { useState, useEffect } from 'react';
import { mockLawDetail } from '../../mocks/lawMocks';
import { Spin, message } from 'antd';
import LawAPIService from '../../services/LawAPIService';
import './LawDetailContent.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;
  }
};
/**
 * 从 provision_text 中提取章节列表
 * @param {string} provisionText - 法律原文纯文本
 * @returns {Array} 章节对象数组 [{id, title}, ...]
 */
const extractChapters = (provisionText) => {
  if (!provisionText) return [];
  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) {
    console.warn('未找到章节目录标记,跳过章节提取');
    return [];
  }
  const tocContent = provisionText.substring(
    startIndex + startMarker.length,
    endIndex
  );
  const lines = tocContent.split('\n').filter(line => line.trim());
  return lines.map((line, index) => ({
    id: `chapter-${index + 1}`,
    title: line.trim()
  }));
};
const LawDetailContent = ({ lawId }) => {
  const [activeChapter, setActiveChapter] = useState('chapter1');
  const [loading, setLoading] = useState(false);
  const [activeChapter, setActiveChapter] = useState(null);
  const [lawDetail, setLawDetail] = useState(null);
  const [chapters, setChapters] = useState([]);
  useEffect(() => {
    // 模拟根据 lawId 获取详情
    setLawDetail(mockLawDetail);
    const loadDetail = async () => {
      if (!lawId) return;
      setLoading(true);
      try {
        const response = await LawAPIService.getLawOriginalDetail(lawId);
        const detailData = response.data;
        // 从 provision_text 提取章节
        const extractedChapters = extractChapters(detailData.provision_text || '');
        setLawDetail(detailData);
        setChapters(extractedChapters);
        // 设置默认激活第一个章节
        if (extractedChapters.length > 0) {
          setActiveChapter(extractedChapters[0].id);
        }
      } catch (error) {
        message.error('详情加载失败');
        console.error('详情加载失败:', error);
      } finally {
        setLoading(false);
      }
    };
    loadDetail();
  }, [lawId]);
  if (!lawDetail) return <div className="law-detail-loading">加载中...</div>;
  if (loading) {
    return (
      <div className="law-detail-loading" style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '400px' }}>
        <Spin size="large" tip="加载中..." />
      </div>
    );
  }
  if (!lawDetail) {
    return <div className="law-detail-loading">暂无数据</div>;
  }
  const handleChapterClick = (chapterId) => {
    setActiveChapter(chapterId);
@@ -24,80 +112,71 @@
  return (
    <div className="law-detail-modal-body">
      {/* 章节导航 */}
      <div className="law-detail-chapter-nav">
        <h3 className="law-detail-chapter-nav-title">
          <i className="fas fa-list-ol"></i>
          章节导航
        </h3>
        <div className="law-detail-chapter-list">
          {lawDetail.chapters.map((chapter) => (
            <a
              key={chapter.id}
              href={`#${chapter.id}`}
              className={`law-detail-chapter-link ${activeChapter === chapter.id ? 'active' : ''}`}
              onClick={(e) => {
                e.preventDefault();
                handleChapterClick(chapter.id);
              }}
            >
              {chapter.title}
            </a>
          ))}
      {chapters.length > 0 && (
        <div className="law-detail-chapter-nav">
          <h3 className="law-detail-chapter-nav-title">
            <i className="fas fa-list-ol"></i>
            章节导航
          </h3>
          <div className="law-detail-chapter-list">
            {chapters.map((chapter) => (
              <a
                key={chapter.id}
                href={`#${chapter.id}`}
                className={`law-detail-chapter-link ${activeChapter === chapter.id ? 'active' : ''}`}
                onClick={(e) => {
                  e.preventDefault();
                  handleChapterClick(chapter.id);
                }}
              >
                {chapter.title}
              </a>
            ))}
          </div>
        </div>
      </div>
      )}
      {/* 法律详情容器 */}
      <div className="law-detail-main-container">
        <div className="law-detail-header">
          <h2 className="law-detail-title">{lawDetail.lawName}</h2>
          <h2 className="law-detail-title">{lawDetail.title || '未命名法律'}</h2>
          <div className="law-detail-meta-grid">
            <div className="law-detail-meta-item">
              <span className="law-detail-meta-label">时效性:</span>
              <span className="law-detail-meta-value status-effective">{lawDetail.status}</span>
              <span className="law-detail-meta-value status-effective">{lawDetail.validity_name || '其他'}</span>
            </div>
            <div className="law-detail-meta-item">
              <span className="law-detail-meta-label">法律效力位阶:</span>
              <span className="law-detail-meta-value">{lawDetail.effectLevel}</span>
              <span className="law-detail-meta-value">{lawDetail.law_nature_name || '-'}</span>
            </div>
            <div className="law-detail-meta-item">
              <span className="law-detail-meta-label">制定机关:</span>
              <span className="law-detail-meta-value">{lawDetail.org}</span>
              <span className="law-detail-meta-value">{lawDetail.authority_name || '-'}</span>
            </div>
            <div className="law-detail-meta-item">
              <span className="law-detail-meta-label">公布日期:</span>
              <span className="law-detail-meta-value">{lawDetail.publishDate}</span>
              <span className="law-detail-meta-value">{formatDate(lawDetail.publish_time)}</span>
            </div>
            <div className="law-detail-meta-item">
              <span className="law-detail-meta-label">实施日期:</span>
              <span className="law-detail-meta-value">{lawDetail.effectiveDate}</span>
              <span className="law-detail-meta-value">{formatDate(lawDetail.implementation_time)}</span>
            </div>
          </div>
        </div>
        <div className="law-detail-content-area">
          {lawDetail.chapters.map((chapter) => (
            <div className="law-detail-chapter-section" id={chapter.id} key={chapter.id}>
              <h3 className="law-detail-chapter-title">
                <i className="fas fa-bookmark"></i>
                {chapter.title}
              </h3>
              <div className="law-detail-articles-container">
                {chapter.articles.map((article, index) => (
                  <div className="law-detail-article-item" key={index}>
                    <div className="law-detail-article-number">{article.number}</div>
                    <div className="law-detail-article-content">
                      {article.content.split('\n').map((line, i) => (
                        <React.Fragment key={i}>
                          {line}
                          {i < article.content.split('\n').length - 1 && <br />}
                        </React.Fragment>
                      ))}
                    </div>
                  </div>
                ))}
              </div>
          {lawDetail.provision_text ? (
            <div className="law-detail-provision-text">
              {lawDetail.provision_text.split('\n').map((line, index) => (
                <React.Fragment key={index}>
                  {line}
                  {index < lawDetail.provision_text.split('\n').length - 1 && <br />}
                </React.Fragment>
              ))}
            </div>
          ))}
          ) : (
            <div className="law-detail-no-content">暂无详细内容</div>
          )}
        </div>
      </div>
    </div>