220 lines
6.8 KiB
HTML
220 lines
6.8 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>K-LINE</title>
|
||
<style>
|
||
/* 样式美化 */
|
||
body {
|
||
font-family: Arial, sans-serif;
|
||
background-color: #1b1b1b;
|
||
color: #fff;
|
||
margin: 0;
|
||
padding: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
h2 {
|
||
margin: 20px 0;
|
||
color: #f0b90b;
|
||
}
|
||
|
||
select {
|
||
margin: 0 10px;
|
||
padding: 10px;
|
||
background-color: #2c2c2c;
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
#controls {
|
||
margin-bottom: 20px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
#kLineChart {
|
||
width: 100%;
|
||
height: 600px;
|
||
}
|
||
</style>
|
||
<!-- 引入 Lightweight Charts 库 -->
|
||
<script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script>
|
||
</head>
|
||
<body>
|
||
<h2>K-LINE</h2>
|
||
|
||
<!-- 控制区 -->
|
||
<div id="controls">
|
||
<!-- 交易对选择 -->
|
||
<label for="symbol">选择交易对:</label>
|
||
<select id="symbol" onchange="updateChart()">
|
||
<option value="BTCUSDT">BTC/USDT</option>
|
||
<option value="ETHUSDT">ETH/USDT</option>
|
||
</select>
|
||
|
||
<!-- 时间间隔选择 -->
|
||
<label for="timeInterval">选择时间间隔:</label>
|
||
<select id="timeInterval" onchange="updateChart()">
|
||
<option value="1m">1 分钟</option>
|
||
<option value="3m">3 分钟</option>
|
||
<option value="5m">5 分钟</option>
|
||
<option value="15m">15 分钟</option>
|
||
<option value="1h">1 小时</option>
|
||
<option value="3h">3 小时</option>
|
||
<option value="1d">1 天</option>
|
||
<option value="3d">3 天</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- K线图容器 -->
|
||
<div id="kLineChart"></div>
|
||
|
||
<script>
|
||
let chart, candlestickSeries, socket;
|
||
let lastKLineTime = 0; // 用于记录最后一个K线的时间
|
||
|
||
// 初始化 Lightweight Charts
|
||
function initChart() {
|
||
chart = LightweightCharts.createChart(document.getElementById('kLineChart'), {
|
||
width: document.getElementById('kLineChart').clientWidth,
|
||
height: 600,
|
||
layout: {
|
||
backgroundColor: '#131722',
|
||
textColor: '#d1d4dc',
|
||
},
|
||
grid: {
|
||
vertLines: {
|
||
color: '#2B2B43',
|
||
},
|
||
horzLines: {
|
||
color: '#363C4E',
|
||
},
|
||
},
|
||
crosshair: {
|
||
mode: LightweightCharts.CrosshairMode.Normal,
|
||
},
|
||
priceScale: {
|
||
borderColor: '#485c7b',
|
||
},
|
||
timeScale: {
|
||
borderColor: '#485c7b',
|
||
timeVisible: true,
|
||
secondsVisible: true,
|
||
localization: {
|
||
dateFormat: 'yyyy-MM-dd HH:mm:ss',
|
||
timeZone: 'Asia/Shanghai',
|
||
},
|
||
},
|
||
});
|
||
|
||
candlestickSeries = chart.addCandlestickSeries({
|
||
upColor: '#4CAF50',
|
||
downColor: '#F44336',
|
||
borderDownColor: '#F44336',
|
||
borderUpColor: '#4CAF50',
|
||
wickDownColor: '#F44336',
|
||
wickUpColor: '#4CAF50',
|
||
});
|
||
}
|
||
|
||
// 连接 WebSocket
|
||
function connectWebSocket() {
|
||
socket = new WebSocket("ws://localhost:8102/ws");
|
||
|
||
socket.onopen = function (event) {
|
||
console.log('WebSocket connection established.');
|
||
// Send initial data request to WebSocket
|
||
updateWebSocket();
|
||
};
|
||
|
||
socket.onmessage = function (event) {
|
||
const data = JSON.parse(event.data);
|
||
const kline = data.k;
|
||
if (kline.t > lastKLineTime) {
|
||
// 如果是新K线,先更新 lastKLineTime
|
||
lastKLineTime = kline.t;
|
||
}
|
||
const formattedData = {
|
||
time: lastKLineTime / 1000, // 时间戳(秒)
|
||
open: parseFloat(kline.o), // 开盘价
|
||
high: parseFloat(kline.h), // 最高价
|
||
low: parseFloat(kline.l), // 最低价
|
||
close: parseFloat(kline.c) // 收盘价
|
||
};
|
||
|
||
// 更新图表
|
||
candlestickSeries.update(formattedData);
|
||
};
|
||
|
||
socket.onclose = function (event) {
|
||
console.log('WebSocket is closed now.');
|
||
};
|
||
|
||
socket.onerror = function (error) {
|
||
console.error('WebSocket error observed:', error);
|
||
};
|
||
}
|
||
|
||
// 更新 WebSocket 连接
|
||
function updateWebSocket() {
|
||
const symbol = document.getElementById('symbol').value;
|
||
const interval = document.getElementById('timeInterval').value;
|
||
|
||
const payload = JSON.stringify({symbol: symbol, interval: interval});
|
||
socket.send(payload);
|
||
}
|
||
|
||
// 更新图表
|
||
function updateChart() {
|
||
const symbol = document.getElementById('symbol').value;
|
||
const interval = document.getElementById('timeInterval').value;
|
||
|
||
// 获取接口数据并更新图表
|
||
fetch(`http://localhost:8102/api/v1/admin/virtualCoin/uiKline?symbol=${symbol}&interval=${interval}`)
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
const formattedData = data.data.map(item => ({
|
||
time: item[0] / 1000, // 时间戳(秒)
|
||
open: parseFloat(item[1]), // 开盘价
|
||
high: parseFloat(item[2]), // 最高价
|
||
low: parseFloat(item[3]), // 最低价
|
||
close: parseFloat(item[4]) // 收盘价
|
||
}));
|
||
// 对数据进行排序(按时间升序)
|
||
formattedData.sort((a, b) => a.time - b.time);
|
||
|
||
// 设置初始的 lastKLineTime 为最后一条数据的时间戳(毫秒)
|
||
lastKLineTime = formattedData[formattedData.length - 1].time * 1000;
|
||
|
||
// 更新图表
|
||
candlestickSeries.setData(formattedData);
|
||
})
|
||
.catch(error => console.error('Error fetching data:', error));
|
||
|
||
// 更新 WebSocket 连接
|
||
if (socket && socket.readyState === WebSocket.OPEN) {
|
||
updateWebSocket();
|
||
}
|
||
}
|
||
|
||
// 初始化图表和 WebSocket 连接
|
||
initChart();
|
||
connectWebSocket();
|
||
|
||
// 监听窗口大小变化,调整图表尺寸
|
||
window.addEventListener('resize', () => {
|
||
chart.resize(document.getElementById('kLineChart').clientWidth, 600);
|
||
});
|
||
|
||
// 页面加载时更新图表
|
||
updateChart();
|
||
</script>
|
||
</body>
|
||
</html>
|