添加汇率数据
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import { createPool } from 'mariadb';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
function loadDatabaseConfig() {
|
||||
const envPath = path.join(process.cwd(), '.env');
|
||||
if (fs.existsSync(envPath)) {
|
||||
const envContent = fs.readFileSync(envPath, 'utf-8');
|
||||
const lines = envContent.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmedLine = line.trim();
|
||||
if (trimmedLine.startsWith('DATABASE_URL=')) {
|
||||
const url = trimmedLine.substring('DATABASE_URL='.length).replace(/^"|"$/g, '');
|
||||
|
||||
// 解析URL
|
||||
const parts = url.split('://')[1].split('@');
|
||||
const auth = parts[0].split(':');
|
||||
const hostAndDb = parts[1].split('/');
|
||||
const hostAndPort = hostAndDb[0].split(':');
|
||||
|
||||
return {
|
||||
user: auth[0],
|
||||
password: auth[1],
|
||||
host: hostAndPort[0],
|
||||
port: parseInt(hostAndPort[1]),
|
||||
database: hostAndDb[1]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
host: '192.168.111.111',
|
||||
port: 3306,
|
||||
user: 'root',
|
||||
password: 'fullstack',
|
||||
database: 'iboard'
|
||||
};
|
||||
}
|
||||
|
||||
let pool;
|
||||
|
||||
async function initPool() {
|
||||
if (!pool) {
|
||||
const config = loadDatabaseConfig();
|
||||
pool = createPool({
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
user: config.user,
|
||||
password: config.password,
|
||||
database: config.database,
|
||||
connectionLimit: 5
|
||||
});
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
try {
|
||||
await initPool();
|
||||
|
||||
// 获取查询参数
|
||||
const { startDate, endDate, limit = 30 } = req.query;
|
||||
|
||||
let query = 'SELECT date, centerPrice FROM econ_ExchangeRate WHERE currency = ? ORDER BY date DESC';
|
||||
const params = ['USD/CNY'];
|
||||
|
||||
if (startDate && endDate) {
|
||||
query = 'SELECT date, centerPrice FROM econ_ExchangeRate WHERE currency = ? AND date BETWEEN ? AND ? ORDER BY date DESC';
|
||||
params.push(startDate, endDate);
|
||||
}
|
||||
|
||||
const result = await pool.query(query, params);
|
||||
|
||||
// 限制返回数量
|
||||
const limitedResult = result.slice(0, parseInt(limit));
|
||||
|
||||
// 反转顺序,使日期从早到晚
|
||||
const sortedResult = limitedResult.reverse();
|
||||
|
||||
// 格式化数据
|
||||
const formattedData = sortedResult.map(row => ({
|
||||
date: row.date instanceof Date ? row.date.toISOString().split('T')[0] : row.date,
|
||||
rate: parseFloat(row.centerPrice)
|
||||
}));
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: formattedData,
|
||||
total: result.length
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取汇率数据失败:', error.message);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取汇率数据失败',
|
||||
error: error.message
|
||||
});
|
||||
} finally {
|
||||
if (pool) {
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
-2
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import Head from 'next/head'
|
||||
import Navbar from '../components/Navbar'
|
||||
import Footer from '../components/Footer'
|
||||
@@ -159,6 +159,34 @@ const sowInventoryData = [
|
||||
|
||||
export default function Data() {
|
||||
const [selectedIndicator, setSelectedIndicator] = useState('bond-china-treasury')
|
||||
const [exchangeRateData, setExchangeRateData] = useState([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedIndicator === 'central-bank-usd-cny-rate') {
|
||||
fetchExchangeRateData()
|
||||
}
|
||||
}, [selectedIndicator])
|
||||
|
||||
const fetchExchangeRateData = async () => {
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch('/api/exchange-rate?limit=60')
|
||||
const data = await response.json()
|
||||
if (data.success) {
|
||||
setExchangeRateData(data.data)
|
||||
} else {
|
||||
setError(data.message)
|
||||
}
|
||||
} catch (err) {
|
||||
setError('获取汇率数据失败')
|
||||
console.error('获取汇率数据失败:', err)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const indicators = [
|
||||
{
|
||||
@@ -180,7 +208,8 @@ export default function Data() {
|
||||
{ id: 'central-bank-china-gold-monthly', name: '中国黄金储备(月)' },
|
||||
{ id: 'central-bank-us-gold-monthly', name: '美国黄金储备(月)' },
|
||||
{ id: 'central-bank-china-gold-yearly', name: '中国黄金储备(年)' },
|
||||
{ id: 'central-bank-us-gold-yearly', name: '美国黄金储备(年)' }
|
||||
{ id: 'central-bank-us-gold-yearly', name: '美国黄金储备(年)' },
|
||||
{ id: 'central-bank-usd-cny-rate', name: '人民币兑美元汇率' }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -526,6 +555,54 @@ export default function Data() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedIndicator === 'central-bank-usd-cny-rate' && (
|
||||
<div className="indicator-detail">
|
||||
<h2 className="indicator-title">人民币兑美元汇率</h2>
|
||||
<p className="indicator-description">展示人民币兑美元汇率的变化趋势</p>
|
||||
|
||||
{loading ? (
|
||||
<div className="loading">加载中...</div>
|
||||
) : error ? (
|
||||
<div className="error">{error}</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="chart-container">
|
||||
<ResponsiveContainer width="100%" height={500}>
|
||||
<LineChart data={exchangeRateData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis domain={['dataMin - 0.1', 'dataMax + 0.1']} tickFormatter={(value) => value.toFixed(4)} />
|
||||
<Tooltip formatter={(value) => [value.toFixed(4), '汇率']} />
|
||||
<Legend />
|
||||
<Line type="monotone" dataKey="rate" name="汇率" stroke="#1e88e5" strokeWidth={2} activeDot={{ r: 8 }} />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
<div className="data-table-container">
|
||||
<h3 className="table-title">详细数据</h3>
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>日期</th>
|
||||
<th>汇率</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{exchangeRateData.map((row, index) => (
|
||||
<tr key={index}>
|
||||
<td>{row.date}</td>
|
||||
<td>{row.rate.toFixed(4)}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedIndicator === 'commodity-pork-price' && (
|
||||
<div className="indicator-detail">
|
||||
<h2 className="indicator-title">猪肉价格</h2>
|
||||
|
||||
Reference in New Issue
Block a user