From 88a31d5a960bd10f3799bc00f8aa24461567d06e Mon Sep 17 00:00:00 2001
From: shimai <shimai@example.com>
Date: Tue, 07 Apr 2026 15:23:43 +0800
Subject: [PATCH] Merge branch 'test/tony.cheng/260312' of http://120.79.193.119:9090/r/~chengmw/cloud-melody-front into test/shimai.huang/260309
---
web-app/src/components/tools/LawDetailContent.jsx | 185 +++++++++++++++++++++++++++++++++-------------
1 files changed, 132 insertions(+), 53 deletions(-)
diff --git a/web-app/src/components/tools/LawDetailContent.jsx b/web-app/src/components/tools/LawDetailContent.jsx
index f099af1..587fbdf 100644
--- a/web-app/src/components/tools/LawDetailContent.jsx
+++ b/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>
--
Gitblit v1.8.0