396 lines
17 KiB
JavaScript
396 lines
17 KiB
JavaScript
import { useState, useEffect } from 'react'
|
||
import Head from 'next/head'
|
||
import Navbar from '../components/Navbar'
|
||
import Footer from '../components/Footer'
|
||
import TimeRangePicker from '../components/TimeRangePicker'
|
||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'
|
||
|
||
const usDebtData = [
|
||
{ year: '2019', debt: 22.7, gdp: 21.4, debtToGdp: 106.1, interestToGdp: 1.8 },
|
||
{ year: '2020', debt: 26.9, gdp: 20.9, debtToGdp: 128.7, interestToGdp: 1.6 },
|
||
{ year: '2021', debt: 28.4, gdp: 23.0, debtToGdp: 123.5, interestToGdp: 1.5 },
|
||
{ year: '2022', debt: 30.9, gdp: 25.4, debtToGdp: 121.6, interestToGdp: 1.6 },
|
||
{ year: '2023', debt: 33.1, gdp: 26.9, debtToGdp: 123.0, interestToGdp: 1.9 },
|
||
{ year: '2024', debt: 35.3, gdp: 28.5, debtToGdp: 123.9, interestToGdp: 2.1 },
|
||
{ year: '2025', debt: 37.5, gdp: 30.2, debtToGdp: 124.2, interestToGdp: 2.3 },
|
||
{ year: '2026', debt: 39.8, gdp: 31.9, debtToGdp: 124.8, interestToGdp: 2.5 }
|
||
]
|
||
|
||
const chinaDebtData = [
|
||
{ year: '2019', debt: 8.8, gdp: 14.3, debtToGdp: 61.5, interestToGdp: 1.9 },
|
||
{ year: '2020', debt: 10.3, gdp: 14.7, debtToGdp: 70.1, interestToGdp: 1.8 },
|
||
{ year: '2021', debt: 11.7, gdp: 16.1, debtToGdp: 72.7, interestToGdp: 1.7 },
|
||
{ year: '2022', debt: 13.1, gdp: 17.9, debtToGdp: 73.2, interestToGdp: 1.6 },
|
||
{ year: '2023', debt: 14.5, gdp: 19.4, debtToGdp: 74.7, interestToGdp: 1.6 },
|
||
{ year: '2024', debt: 15.9, gdp: 21.0, debtToGdp: 75.7, interestToGdp: 1.5 },
|
||
{ year: '2025', debt: 17.3, gdp: 22.8, debtToGdp: 75.9, interestToGdp: 1.5 },
|
||
{ year: '2026', debt: 18.8, gdp: 24.7, debtToGdp: 76.1, interestToGdp: 1.4 }
|
||
]
|
||
|
||
export default function Strategy() {
|
||
const [selectedStrategy, setSelectedStrategy] = useState('us-debt-gdp')
|
||
const [sh300ExchangeData, setSh300ExchangeData] = useState([])
|
||
const [sh300Loading, setSh300Loading] = useState(false)
|
||
const [timeRange, setTimeRange] = useState('1m')
|
||
const [startDate, setStartDate] = useState('')
|
||
const [endDate, setEndDate] = useState('')
|
||
|
||
const strategies = [
|
||
{
|
||
id: 'us-debt-gdp',
|
||
name: '美国政府债务/GDP'
|
||
},
|
||
{
|
||
id: 'china-debt-gdp',
|
||
name: '中国政府债务/GDP'
|
||
},
|
||
{
|
||
id: 'sh300-exchange-rate',
|
||
name: '沪深300与汇率对比'
|
||
}
|
||
]
|
||
|
||
useEffect(() => {
|
||
if (selectedStrategy === 'sh300-exchange-rate') {
|
||
fetchSh300ExchangeData()
|
||
}
|
||
}, [selectedStrategy, timeRange, startDate, endDate])
|
||
|
||
const handleTimeRangeChange = (range, start, end) => {
|
||
setTimeRange(range)
|
||
setStartDate(start)
|
||
setEndDate(end)
|
||
}
|
||
|
||
const fetchSh300ExchangeData = async () => {
|
||
setSh300Loading(true)
|
||
try {
|
||
let sh300Url = '/api/sh300-index'
|
||
let exchangeUrl = '/api/exchange-rate'
|
||
|
||
const params = []
|
||
if (timeRange === 'custom' && startDate && endDate) {
|
||
params.push(`startDate=${startDate}`)
|
||
params.push(`endDate=${endDate}`)
|
||
} else if (timeRange === '1m') {
|
||
params.push('limit=30')
|
||
} else if (timeRange === '3m') {
|
||
params.push('limit=90')
|
||
} else if (timeRange === '1y') {
|
||
params.push('limit=365')
|
||
}
|
||
|
||
if (params.length > 0) {
|
||
sh300Url += '?' + params.join('&')
|
||
exchangeUrl += '?' + params.join('&')
|
||
}
|
||
|
||
const [sh300Res, exchangeRes] = await Promise.all([
|
||
fetch(sh300Url),
|
||
fetch(exchangeUrl)
|
||
])
|
||
const sh300Json = await sh300Res.json()
|
||
const exchangeJson = await exchangeRes.json()
|
||
|
||
if (sh300Json.success && exchangeJson.success) {
|
||
const sh300Map = new Map(sh300Json.data.map(item => [item.date, item.close]))
|
||
const exchangeMap = new Map(exchangeJson.data.map(item => [item.date, item.rate]))
|
||
|
||
const allDates = [...new Set([...sh300Map.keys(), ...exchangeMap.keys()])].sort()
|
||
|
||
const mergedData = allDates.map(date => ({
|
||
date,
|
||
sh300: sh300Map.get(date) || null,
|
||
exchangeRate: exchangeMap.get(date) || null
|
||
})).filter(item => item.sh300 !== null && item.exchangeRate !== null)
|
||
|
||
setSh300ExchangeData(mergedData)
|
||
}
|
||
} catch (error) {
|
||
console.error('获取数据失败:', error)
|
||
} finally {
|
||
setSh300Loading(false)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div className="container">
|
||
<Head>
|
||
<title>策略 - iBoard</title>
|
||
<link rel="icon" href="/favicon.ico" />
|
||
</Head>
|
||
|
||
<Navbar />
|
||
|
||
<main>
|
||
<h1 className="title">
|
||
经济策略
|
||
</h1>
|
||
|
||
<p className="description">
|
||
按照经济理论组织的相关数据和图表的对比
|
||
</p>
|
||
|
||
<div className="strategy-layout">
|
||
<div className="strategy-sidebar">
|
||
<h3 className="sidebar-title">策略列表</h3>
|
||
<ul className="strategy-list">
|
||
{strategies.map((strategy) => (
|
||
<li
|
||
key={strategy.id}
|
||
className={`strategy-item ${selectedStrategy === strategy.id ? 'active' : ''}`}
|
||
onClick={() => setSelectedStrategy(strategy.id)}
|
||
>
|
||
{strategy.name}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
|
||
<div className="strategy-content">
|
||
{selectedStrategy === 'us-debt-gdp' && (
|
||
<div className="strategy-detail">
|
||
<h2 className="strategy-title">美国政府债务/GDP分析</h2>
|
||
<p className="strategy-description">
|
||
分析美国政府债务、GDP、债务/GDP比率以及债务利息/GDP比率的走势
|
||
</p>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">美国政府债务走势</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={usDebtData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="year" />
|
||
<YAxis domain={['dataMin - 2', 'dataMax + 2']} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line type="monotone" dataKey="debt" name="美国政府债务(万亿美元)" stroke="#8884d8" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">美国GDP走势</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={usDebtData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="year" />
|
||
<YAxis domain={['dataMin - 1', 'dataMax + 1']} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line type="monotone" dataKey="gdp" name="美国GDP(万亿美元)" stroke="#82ca9d" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">美国政府债务/GDP走势</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={usDebtData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="year" />
|
||
<YAxis domain={['dataMin - 5', 'dataMax + 5']} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line type="monotone" dataKey="debtToGdp" name="债务/GDP比率(%)" stroke="#ffc658" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">美国政府债务利息/GDP</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={usDebtData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="year" />
|
||
<YAxis domain={['dataMin - 0.2', 'dataMax + 0.2']} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line type="monotone" dataKey="interestToGdp" name="债务利息/GDP比率(%)" stroke="#ff7300" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="data-table-container">
|
||
<h3 className="table-title">详细数据</h3>
|
||
<table className="data-table">
|
||
<thead>
|
||
<tr>
|
||
<th>年份</th>
|
||
<th>政府债务(万亿美元)</th>
|
||
<th>GDP(万亿美元)</th>
|
||
<th>债务/GDP(%)</th>
|
||
<th>债务利息/GDP(%)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{usDebtData.map((row, index) => (
|
||
<tr key={index}>
|
||
<td>{row.year}</td>
|
||
<td>{row.debt.toFixed(1)}</td>
|
||
<td>{row.gdp.toFixed(1)}</td>
|
||
<td>{row.debtToGdp.toFixed(1)}</td>
|
||
<td>{row.interestToGdp.toFixed(1)}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{selectedStrategy === 'china-debt-gdp' && (
|
||
<div className="strategy-detail">
|
||
<h2 className="strategy-title">中国政府债务/GDP分析</h2>
|
||
<p className="strategy-description">
|
||
分析中国政府债务、GDP、债务/GDP比率以及债务利息/GDP比率的走势
|
||
</p>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">中国政府债务走势</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={chinaDebtData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="year" />
|
||
<YAxis domain={['dataMin - 1', 'dataMax + 1']} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line type="monotone" dataKey="debt" name="中国政府债务(万亿美元)" stroke="#e6194b" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">中国GDP走势</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={chinaDebtData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="year" />
|
||
<YAxis domain={['dataMin - 1', 'dataMax + 1']} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line type="monotone" dataKey="gdp" name="中国GDP(万亿美元)" stroke="#3cb44b" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">中国政府债务/GDP走势</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={chinaDebtData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="year" />
|
||
<YAxis domain={['dataMin - 5', 'dataMax + 5']} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line type="monotone" dataKey="debtToGdp" name="债务/GDP比率(%)" stroke="#4363d8" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">中国政府债务利息/GDP</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={chinaDebtData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="year" />
|
||
<YAxis domain={['dataMin - 0.2', 'dataMax + 0.2']} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line type="monotone" dataKey="interestToGdp" name="债务利息/GDP比率(%)" stroke="#f58231" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="data-table-container">
|
||
<h3 className="table-title">详细数据</h3>
|
||
<table className="data-table">
|
||
<thead>
|
||
<tr>
|
||
<th>年份</th>
|
||
<th>政府债务(万亿美元)</th>
|
||
<th>GDP(万亿美元)</th>
|
||
<th>债务/GDP(%)</th>
|
||
<th>债务利息/GDP(%)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{chinaDebtData.map((row, index) => (
|
||
<tr key={index}>
|
||
<td>{row.year}</td>
|
||
<td>{row.debt.toFixed(1)}</td>
|
||
<td>{row.gdp.toFixed(1)}</td>
|
||
<td>{row.debtToGdp.toFixed(1)}</td>
|
||
<td>{row.interestToGdp.toFixed(1)}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{selectedStrategy === 'sh300-exchange-rate' && (
|
||
<div className="strategy-detail">
|
||
<h2 className="strategy-title">沪深300与汇率对比分析</h2>
|
||
<p className="strategy-description">
|
||
对比沪深300指数收盘价与人民币兑美元汇率的走势关系
|
||
</p>
|
||
|
||
{sh300Loading ? (
|
||
<div className="loading">加载中...</div>
|
||
) : (
|
||
<>
|
||
<div className="chart-header">
|
||
<TimeRangePicker
|
||
value={timeRange}
|
||
onChange={handleTimeRangeChange}
|
||
/>
|
||
</div>
|
||
|
||
<div className="chart-section">
|
||
<h3 className="chart-title">沪深300与汇率对比(双Y轴)</h3>
|
||
<div className="chart-container">
|
||
<ResponsiveContainer width="100%" height={400}>
|
||
<LineChart data={sh300ExchangeData} margin={{ top: 20, right: 60, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" />
|
||
<XAxis dataKey="date" />
|
||
<YAxis yAxisId="left" domain={['dataMin - 100', 'dataMax + 100']} />
|
||
<YAxis yAxisId="right" orientation="right" domain={['dataMin - 0.05', 'dataMax + 0.05']} tickFormatter={(value) => value.toFixed(4)} />
|
||
<Tooltip />
|
||
<Legend />
|
||
<Line yAxisId="left" type="monotone" dataKey="sh300" name="沪深300收盘价" stroke="#8884d8" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
<Line yAxisId="right" type="monotone" dataKey="exchangeRate" name="汇率" stroke="#82ca9d" strokeWidth={2} activeDot={{ r: 8 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
</>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<Footer />
|
||
</div>
|
||
)
|
||
}
|