tony.cheng
2026-03-17 ea12f670293895bc21bf52db1aa3cee9ab454fda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import React, { useState, useRef } from 'react';
import { Spin } from 'antd';
import './App.css';
 
// Context
import { CaseDataProvider, useCaseData } from './contexts/CaseDataContext';
 
// 调解看板组件
import TopSection from './components/dashboard/TopSection';
import MediationProgress from './components/dashboard/MediationProgress';
import TabContainer from './components/dashboard/TabContainer';
import ToolsPanel from './components/dashboard/ToolsPanel';
import FloatingControlPanel from './components/dashboard/FloatingControlPanel';
 
// 弹窗组件
import ToolModal from './components/common/ToolModal';
import OutboundCallWidget from './components/common/OutboundCallWidget';
 
// 工具内容组件
import WageCalculatorContent from './components/tools/WageCalculatorContent';
import LawSearchContent from './components/tools/LawSearchContent';
import CaseSearchContent from './components/tools/CaseSearchContent';
import SimilarCaseContent from './components/tools/SimilarCaseContent';
 
function App() {
  return (
    <CaseDataProvider>
      <AppContent />
    </CaseDataProvider>
  );
}
 
function AppContent() {
  const [activeModal, setActiveModal] = useState(null);
  const { loading, refreshData } = useCaseData();
  
  // TabContainer ref - 用于切换Tab
  const tabContainerRef = useRef(null);
 
  // 工具配置
  const toolConfig = {
    'wage-calculator': {
      title: '欠薪计算器',
      icon: 'fas fa-calculator',
      component: WageCalculatorContent,
    },
    'law-search': {
      title: '法律条文查询',
      icon: 'fas fa-gavel',
      component: LawSearchContent,
    },
    'case-search': {
      title: '典型案例查询',
      icon: 'fas fa-search',
      component: CaseSearchContent,
    },
    'similar-case': {
      title: '类案与法条推荐',
      icon: 'fas fa-balance-scale',
      component: SimilarCaseContent,
    },
  };
 
  const handleToolClick = (toolKey) => {
    setActiveModal(toolKey);
  };
 
  const handleCloseModal = () => {
    setActiveModal(null);
  };
 
  /**
   * 切换Tab页签
   * @param {string} tabKey - Tab键名
   */
  const handleSwitchTab = (tabKey) => {
    if (tabContainerRef.current) {
      tabContainerRef.current.switchTab(tabKey);
    }
  };
 
  /**
   * 刷新案件数据
   */
  const handleRefreshData = () => {
    if (refreshData) {
      refreshData();
    }
  };
 
  const renderModalContent = () => {
    if (!activeModal || !toolConfig[activeModal]) return null;
    const Component = toolConfig[activeModal].component;
    return <Component />;
  };
 
  return (
    <Spin spinning={loading} tip="加载案件数据中...">
      <div className="app">
        {/* Font Awesome CDN */}
        <link
          rel="stylesheet"
          href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
        />
 
        {/* 顶部区域 */}
        <TopSection />
 
        {/* 中间区域 */}
        <section className="middle-section">
          {/* A区域:左侧主要内容 */}
          <div className="area-a">
            {/* AI调解进度 */}
            <MediationProgress />
 
            {/* 选项卡容器 */}
            <TabContainer ref={tabContainerRef} />
          </div>
 
          {/* B区域:右侧工具栏 */}
          <ToolsPanel onToolClick={handleToolClick} />
        </section>
 
        {/* 底部悬浮控制看板 */}
        <FloatingControlPanel />
 
        {/* 工具弹窗 */}
        {activeModal && toolConfig[activeModal] && (
          <ToolModal
            visible={true}
            title={toolConfig[activeModal].title}
            icon={toolConfig[activeModal].icon}
            onClose={handleCloseModal}
          >
            {renderModalContent()}
          </ToolModal>
        )}
 
        {/* 智能外呼通话显示组件 - 默认隐藏,可主动触发显示 */}
        <OutboundCallWidget
          onSwitchTab={handleSwitchTab}
          onRefreshData={handleRefreshData}
        />
      </div>
    </Spin>
  );
}
 
export default App;