iboard/pages/strategy.js
2026-04-26 11:41:39 +08:00

404 lines
18 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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与汇率对比'
}
]
const handleTimeRangeChange = (range, start, end) => {
setTimeRange(range)
setStartDate(start)
setEndDate(end)
}
const fetchSh300ExchangeData = async () => {
console.log('fetchSh300ExchangeData called')
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('&')
}
console.log('Fetching from:', sh300Url, exchangeUrl)
const [sh300Res, exchangeRes] = await Promise.all([
fetch(sh300Url),
fetch(exchangeUrl)
])
console.log('Response status:', sh300Res.status, exchangeRes.status)
const sh300Json = await sh300Res.json()
const exchangeJson = await exchangeRes.json()
console.log('Response data:', sh300Json, exchangeJson)
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)
console.log('Merged data:', mergedData)
setSh300ExchangeData(mergedData)
}
} catch (error) {
console.error('获取数据失败:', error)
} finally {
setSh300Loading(false)
}
}
useEffect(() => {
if (selectedStrategy === 'sh300-exchange-rate') {
fetchSh300ExchangeData()
}
}, [selectedStrategy, timeRange, startDate, endDate])
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={['auto', 'auto']} allowDataOverflow={true} />
<YAxis yAxisId="right" orientation="right" domain={['auto', 'auto']} allowDataOverflow={true} 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>
)
}