|
|
@@ -0,0 +1,147 @@
|
|
|
+import React, { useState } from 'react';
|
|
|
+import { useQuery } from '@tanstack/react-query';
|
|
|
+import { dashClient } from '@/client/api';
|
|
|
+
|
|
|
+// 导入基础组件
|
|
|
+import Icon from './components/Icon';
|
|
|
+import ReportHeader from './components/ReportHeader';
|
|
|
+import BaseContainer from './components/BaseContainer';
|
|
|
+import GridBackground from './components/GridBackground';
|
|
|
+import BackgroundOverlay from './components/BackgroundOverlay';
|
|
|
+
|
|
|
+// 导入数据模块组件
|
|
|
+import AssetMetrics from './components/AssetMetrics';
|
|
|
+import ProfitMetrics from './components/ProfitMetrics';
|
|
|
+import IncomeMetrics from './components/IncomeMetrics';
|
|
|
+import DebtRatioMetrics from './components/DebtRatioMetrics';
|
|
|
+
|
|
|
+// 导入弹窗组件
|
|
|
+import VariationModal from './components/VariationModal';
|
|
|
+
|
|
|
+// API 响应类型定义
|
|
|
+interface FinancialDataItem {
|
|
|
+ id: number;
|
|
|
+ year: number;
|
|
|
+ assetTotal?: number; // 资产总额(单位:元)
|
|
|
+ assetNet?: number; // 资产净额(单位:元)
|
|
|
+ profitTotal?: number; // 利润总额(单位:元)
|
|
|
+ profitNet?: number; // 净利润(单位:元)
|
|
|
+ income?: number; // 收入(单位:元)
|
|
|
+ assetLiabilityRatio?: number; // 资产负债率(单位:%)
|
|
|
+ dataDeadline: string;
|
|
|
+ createTime: string;
|
|
|
+ updateTime: string;
|
|
|
+}
|
|
|
+
|
|
|
+interface FinancialOutlookData {
|
|
|
+ code: 200;
|
|
|
+ msg: '查询成功';
|
|
|
+ rows: Array<{
|
|
|
+ assetTotalNet: FinancialDataItem[];
|
|
|
+ profitTotalNet: FinancialDataItem[];
|
|
|
+ incomeStatement: FinancialDataItem[];
|
|
|
+ assetLiabilityRatio: FinancialDataItem[];
|
|
|
+ }>;
|
|
|
+}
|
|
|
+
|
|
|
+const FinancialDashboard: React.FC = () => {
|
|
|
+ const [isModalOpen, setIsModalOpen] = useState(false);
|
|
|
+
|
|
|
+ // 使用真实API调用获取财务数据
|
|
|
+ const { data: financialData, isLoading, error } = useQuery({
|
|
|
+ queryKey: ['financial-outlook'],
|
|
|
+ queryFn: async () => {
|
|
|
+ const response = await dashClient.outlook.$get();
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('Failed to fetch financial data');
|
|
|
+ }
|
|
|
+ return response.json() as Promise<FinancialOutlookData>;
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ const handleOpenModal = () => {
|
|
|
+ setIsModalOpen(true);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleCloseModal = () => {
|
|
|
+ setIsModalOpen(false);
|
|
|
+ };
|
|
|
+
|
|
|
+ if (isLoading) {
|
|
|
+ return (
|
|
|
+ <div className="w-screen h-screen bg-gray-900 flex items-center justify-center">
|
|
|
+ <div className="text-white text-xl">加载中...</div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (error) {
|
|
|
+ return (
|
|
|
+ <div className="w-screen h-screen bg-gray-900 flex items-center justify-center">
|
|
|
+ <div className="text-white text-xl">数据加载失败</div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="relative w-[1920px] h-[1080px] overflow-hidden bg-gray-900">
|
|
|
+ {/* 背景层 */}
|
|
|
+ <BackgroundOverlay />
|
|
|
+ <GridBackground />
|
|
|
+
|
|
|
+ {/* 主内容区域 */}
|
|
|
+ <div className="relative z-10 w-full h-full p-8">
|
|
|
+ {/* 报表头部 */}
|
|
|
+ <ReportHeader title="财务数据可视化大屏" />
|
|
|
+
|
|
|
+ {/* 数据模块网格布局 */}
|
|
|
+ <div className="grid grid-cols-2 grid-rows-2 gap-6 mt-8 h-[calc(100%-120px)]">
|
|
|
+ {/* 左上:资产负债率模块 */}
|
|
|
+ <div className="relative">
|
|
|
+ <BaseContainer>
|
|
|
+ <AssetMetrics data={financialData?.rows[0]?.assetTotalNet} />
|
|
|
+ </BaseContainer>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 右上:收入模块 */}
|
|
|
+ <div className="relative">
|
|
|
+ <BaseContainer>
|
|
|
+ <IncomeMetrics data={financialData?.rows[0]?.incomeStatement} />
|
|
|
+ </BaseContainer>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 左下:利润总额与净利润模块 */}
|
|
|
+ <div className="relative">
|
|
|
+ <BaseContainer>
|
|
|
+ <ProfitMetrics data={financialData?.rows[0]?.profitTotalNet} />
|
|
|
+ </BaseContainer>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 右下:资产负债率(百分比)模块 */}
|
|
|
+ <div className="relative">
|
|
|
+ <BaseContainer>
|
|
|
+ <DebtRatioMetrics data={financialData?.rows[0]?.assetLiabilityRatio} />
|
|
|
+ </BaseContainer>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 浮动按钮 */}
|
|
|
+ <button
|
|
|
+ onClick={handleOpenModal}
|
|
|
+ className="absolute bottom-8 right-8 w-16 h-16 bg-blue-600 rounded-full flex items-center justify-center shadow-lg hover:bg-blue-700 transition-colors z-20"
|
|
|
+ >
|
|
|
+ <Icon />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 变动幅度弹窗 */}
|
|
|
+ <VariationModal
|
|
|
+ isOpen={isModalOpen}
|
|
|
+ onClose={handleCloseModal}
|
|
|
+ data={financialData?.rows[0]}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export default FinancialDashboard;
|