diff --git a/pages/api/sh300-index.js b/pages/api/sh300-index.js new file mode 100644 index 0000000..60bf102 --- /dev/null +++ b/pages/api/sh300-index.js @@ -0,0 +1,81 @@ +import { createPool } from 'mariadb'; + +async function handler(req, res) { + if (req.method !== 'GET') { + return res.status(405).json({ message: '只支持GET请求' }); + } + + const { startDate, endDate, limit } = req.query; + + let pool; + try { + pool = createPool({ + host: process.env.DB_HOST || '192.168.111.111', + port: parseInt(process.env.DB_PORT || '3306'), + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD || 'fullstack', + database: process.env.DB_NAME || 'iboard', + connectionLimit: 5 + }); + + let query = 'SELECT date, close FROM econ_SH300Index'; + const params = []; + const conditions = []; + + if (startDate) { + conditions.push('date >= ?'); + params.push(startDate); + } + + if (endDate) { + conditions.push('date <= ?'); + params.push(endDate); + } + + if (conditions.length > 0) { + query += ' WHERE ' + conditions.join(' AND '); + } + + query += ' ORDER BY date ASC'; + + if (limit) { + query += ' LIMIT ?'; + params.push(parseInt(limit)); + } + + const result = await pool.query(query, params); + + const data = result.map(row => { + let dateStr; + if (row.date instanceof Date) { + dateStr = row.date.toISOString().split('T')[0]; + } else if (typeof row.date === 'string') { + dateStr = row.date; + } else { + dateStr = String(row.date); + } + return { + date: dateStr, + close: parseFloat(row.close) + }; + }); + + return res.status(200).json({ + success: true, + data: data + }); + + } catch (error) { + console.error('获取沪深300数据失败:', error); + return res.status(500).json({ + success: false, + message: '获取沪深300数据失败: ' + error.message + }); + } finally { + if (pool) { + await pool.end(); + } + } +} + +export default handler; diff --git a/pages/strategy.js b/pages/strategy.js index de605e3..5143afc 100644 --- a/pages/strategy.js +++ b/pages/strategy.js @@ -1,7 +1,8 @@ -import { useState } from 'react' +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 = [ @@ -28,6 +29,11 @@ const chinaDebtData = [ 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 = [ { @@ -37,9 +43,76 @@ export default function Strategy() { { 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 (
@@ -272,6 +345,46 @@ export default function Strategy() {
)} + + {selectedStrategy === 'sh300-exchange-rate' && ( +
+

沪深300与汇率对比分析

+

+ 对比沪深300指数收盘价与人民币兑美元汇率的走势关系 +

+ + {sh300Loading ? ( +
加载中...
+ ) : ( + <> +
+ +
+ +
+

沪深300与汇率对比(双Y轴)

+
+ + + + + + value.toFixed(4)} /> + + + + + + +
+
+ + )} +
+ )}