From 7804a7fa8eff2d3086eb32bb7a2fadb9fdcb36ab Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 19 Aug 2025 11:19:25 +0800
Subject: [PATCH] feat(mall): 双击删除图片功能
---
src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java | 2
src/main/resources/static/febs/quant/okxCandle.html | 289 +++++++++++++++++
src/main/resources/static/febs/quant/okxWebsocketChannels.html | 381 ++++++++++++++++++++++
src/main/resources/static/febs/quant/okxWebsocketMonitor.html | 180 ++++++++++
src/main/resources/templates/febs/views/modules/banner/platformBannerDetail.html | 70 ++-
src/main/resources/templates/febs/views/modules/banner/platformBannerAdd.html | 69 ++-
6 files changed, 948 insertions(+), 43 deletions(-)
diff --git a/src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java b/src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java
index c31acb3..bab9b03 100644
--- a/src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java
+++ b/src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java
@@ -24,7 +24,7 @@
**/
@Slf4j
@Component
-@ConditionalOnProperty(prefix = "system", name = "job", havingValue = "true")
+@ConditionalOnProperty(prefix = "system", name = "job", havingValue = "false")
public class OrderOvertimeJob {
@Autowired
diff --git a/src/main/resources/static/febs/quant/okxCandle.html b/src/main/resources/static/febs/quant/okxCandle.html
new file mode 100644
index 0000000..6eea97b
--- /dev/null
+++ b/src/main/resources/static/febs/quant/okxCandle.html
@@ -0,0 +1,289 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>OKX 标记价格K线频道</title>
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-chart-financial"></script>
+ <style>
+ body {
+ font-family: Arial, sans-serif;
+ margin: 20px;
+ }
+ .channel {
+ margin-bottom: 20px;
+ padding: 15px;
+ border: 1px solid #ccc;
+ border-radius: 5px;
+ }
+ .channel h3 {
+ margin-top: 0;
+ }
+ .status {
+ font-weight: bold;
+ }
+ .connected {
+ color: green;
+ }
+ .disconnected {
+ color: red;
+ }
+ .messages {
+ height: 300px;
+ overflow-y: scroll;
+ border: 1px solid #eee;
+ padding: 10px;
+ margin-top: 10px;
+ background-color: #f9f9f9;
+ }
+ .chart-container {
+ width: 100%;
+ height: 300px;
+ margin-top: 20px;
+ }
+ .mode-toggle {
+ margin: 10px 0;
+ padding: 10px;
+ background-color: #f0f0f0;
+ border-radius: 5px;
+ }
+ .mode-toggle button {
+ margin: 0 5px;
+ padding: 5px 10px;
+ border: 1px solid #ccc;
+ background-color: #fff;
+ cursor: pointer;
+ }
+ .mode-toggle button.active {
+ background-color: #007bff;
+ color: white;
+ }
+ </style>
+</head>
+<body>
+ <h1>OKX 标记价格K线频道</h1>
+
+ <div class="mode-toggle">
+ <span>当前模式:</span>
+ <button id="demoModeBtn" class="active" onclick="switchMode('demo')">模拟盘 (wspap)</button>
+ <button id="liveModeBtn" onclick="switchMode('live')">实盘 (ws)</button>
+ </div>
+
+ <div class="channel" id="markPriceCandleChannel">
+ <h3>标记价格K线频道</h3>
+ <p>URL: <span id="markPriceCandleUrl">wss://wspap.okx.com:8443/ws/v5/business</span></p>
+ <p>状态: <span class="status disconnected" id="markPriceCandleStatus">未连接</span></p>
+ <button onclick="toggleConnection()">连接/断开</button>
+ <button onclick="clearMessages()">清除消息</button>
+ <div class="chart-container">
+ <canvas id="markPriceCandleChart"></canvas>
+ </div>
+ <div class="messages" id="markPriceCandleMessages"></div>
+ </div>
+
+ <script>
+ // 存储WebSocket连接对象
+ let connection = null;
+
+ // 存储各模式的URL
+ const urls = {
+ demo: 'wss://wspap.okx.com:8443/ws/v5/business',
+ live: 'wss://ws.okx.com:8443/ws/v5/business'
+ };
+
+ // 当前模式,默认为模拟盘
+ let currentMode = 'demo';
+
+ // 标记价格K线数据
+ const markPriceCandleData = [];
+ const markPriceCandleTimes = [];
+ let markPriceCandleChart = null;
+
+ // 初始化图表
+ function initChart() {
+ const ctx = document.getElementById('markPriceCandleChart').getContext('2d');
+ markPriceCandleChart = new Chart(ctx, {
+ type: 'line',
+ data: {
+ labels: [],
+ datasets: [{
+ label: 'ETH-USDT Mark Price',
+ data: [],
+ borderColor: 'rgb(75, 192, 192)',
+ tension: 0.1
+ }]
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: 'time',
+ time: {
+ unit: 'minute'
+ }
+ },
+ y: {
+ beginAtZero: false
+ }
+ }
+ }
+ });
+ }
+
+ // 更新图表
+ function updateChart() {
+ if (markPriceCandleChart) {
+ // 为折线图准备数据
+ const times = markPriceCandleData.map(item => item.x);
+ const prices = markPriceCandleData.map(item => item.c); // 使用收盘价
+
+ markPriceCandleChart.data.labels = times;
+ markPriceCandleChart.data.datasets[0].data = prices;
+ markPriceCandleChart.update();
+ }
+ }
+
+ // 连接/断开WebSocket连接
+ function toggleConnection() {
+ if (connection) {
+ // 如果已经连接,则断开连接
+ connection.close();
+ connection = null;
+ document.getElementById('markPriceCandleStatus').textContent = '未连接';
+ document.getElementById('markPriceCandleStatus').className = 'status disconnected';
+ } else {
+ // 如果未连接,则建立连接
+ connectToChannel();
+ }
+ }
+
+ // 清除消息
+ function clearMessages() {
+ const messagesDiv = document.getElementById('markPriceCandleMessages');
+ messagesDiv.innerHTML = '';
+
+ // 清除图表数据
+ markPriceCandleData.length = 0;
+ updateChart();
+ }
+
+ // 切换模式
+ function switchMode(mode) {
+ // 更新当前模式
+ currentMode = mode;
+
+ // 更新按钮状态
+ document.getElementById('demoModeBtn').classList.toggle('active', mode === 'demo');
+ document.getElementById('liveModeBtn').classList.toggle('active', mode === 'live');
+
+ // 更新URL显示
+ document.getElementById('markPriceCandleUrl').textContent = urls[mode];
+ }
+
+ // 连接到频道
+ function connectToChannel() {
+ const ws = new WebSocket(urls[currentMode]);
+
+ ws.onopen = function() {
+ console.log('标记价格K线频道连接成功');
+ document.getElementById('markPriceCandleStatus').textContent = '已连接';
+ document.getElementById('markPriceCandleStatus').className = 'status connected';
+
+ // 订阅标记价格K线数据 (BTC-USD-190628, 1分钟K线)
+ const subscribeMsg = {
+ op: 'subscribe',
+ args: [
+ {
+ channel: 'mark-price-candle1m',
+ instId: 'ETH-USDT'
+ }
+ ]
+ };
+ ws.send(JSON.stringify(subscribeMsg));
+
+ // 初始化图表
+ if (!markPriceCandleChart) {
+ initChart();
+ }
+ };
+
+ ws.onmessage = function(event) {
+ const message = event.data;
+ console.log('标记价格K线频道收到消息:', message);
+
+ // 在页面上显示消息
+ const messagesDiv = document.getElementById('markPriceCandleMessages');
+ const messageElement = document.createElement('div');
+
+ // 尝试解析JSON消息并格式化显示
+ try {
+ const jsonData = JSON.parse(message);
+
+ // 检查是否为标记价格K线数据
+ if (jsonData.arg && jsonData.arg.channel && jsonData.arg.channel.startsWith('mark-price-candle') &&
+ jsonData.arg.instId === 'ETH-USDT' && jsonData.data && jsonData.data.length > 0) {
+ // 处理标记价格K线数据
+ // 标记价格K线数据格式: [ts, o, h, l, c]
+ // ts: 开始时间, o: 开盘价, h: 最高价, l: 最低价, c: 收盘价
+ const candleData = jsonData.data[0];
+ const ts = parseInt(candleData[0]); // 时间戳
+ const o = parseFloat(candleData[1]); // 开盘价
+ const h = parseFloat(candleData[2]); // 最高价
+ const l = parseFloat(candleData[3]); // 最低价
+ const c = parseFloat(candleData[4]); // 收盘价
+
+ // 添加时间戳到时间数组
+ markPriceCandleTimes.push(ts);
+
+ // 添加K线数据到数组
+ markPriceCandleData.push({
+ x: ts,
+ o: o,
+ h: h,
+ l: l,
+ c: c
+ });
+
+ // 限制数据点数量,只保留最近的30个
+ if (markPriceCandleData.length > 30) {
+ markPriceCandleData.shift();
+ markPriceCandleTimes.shift();
+ }
+
+ // 更新图表
+ updateChart();
+
+ console.log('标记价格K线数据:', candleData);
+ }
+
+ messageElement.innerHTML = `<strong>[${new Date().toLocaleTimeString()}]</strong> ${JSON.stringify(jsonData, null, 2)}`;
+ } catch (e) {
+ // 如果不是JSON格式,则直接显示
+ messageElement.innerHTML = `<strong>[${new Date().toLocaleTimeString()}]</strong> ${message}`;
+ }
+
+ messagesDiv.appendChild(messageElement);
+ messagesDiv.scrollTop = messagesDiv.scrollHeight;
+ };
+
+ ws.onerror = function(error) {
+ console.error('标记价格K线频道连接错误:', error);
+ document.getElementById('markPriceCandleStatus').textContent = '连接错误';
+ document.getElementById('markPriceCandleStatus').className = 'status disconnected';
+ };
+
+ ws.onclose = function() {
+ console.log('标记价格K线频道连接已关闭');
+ document.getElementById('markPriceCandleStatus').textContent = '连接已关闭';
+ document.getElementById('markPriceCandleStatus').className = 'status disconnected';
+ connection = null;
+ };
+
+ connection = ws;
+ }
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/static/febs/quant/okxWebsocketChannels.html b/src/main/resources/static/febs/quant/okxWebsocketChannels.html
new file mode 100644
index 0000000..3a8a41d
--- /dev/null
+++ b/src/main/resources/static/febs/quant/okxWebsocketChannels.html
@@ -0,0 +1,381 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>OKX WebSocket 频道连接</title>
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>
+ <style>
+ body {
+ font-family: Arial, sans-serif;
+ margin: 20px;
+ }
+ .channel {
+ margin-bottom: 20px;
+ padding: 15px;
+ border: 1px solid #ccc;
+ border-radius: 5px;
+ }
+ .channel h3 {
+ margin-top: 0;
+ }
+ .status {
+ font-weight: bold;
+ }
+ .connected {
+ color: green;
+ }
+ .disconnected {
+ color: red;
+ }
+ .messages {
+ height: 200px;
+ overflow-y: scroll;
+ border: 1px solid #eee;
+ padding: 10px;
+ margin-top: 10px;
+ background-color: #f9f9f9;
+ }
+ .chart-container {
+ width: 100%;
+ height: 300px;
+ margin-top: 20px;
+ }
+ .mode-toggle {
+ margin: 10px 0;
+ padding: 10px;
+ background-color: #f0f0f0;
+ border-radius: 5px;
+ }
+ .mode-toggle button {
+ margin: 0 5px;
+ padding: 5px 10px;
+ border: 1px solid #ccc;
+ background-color: #fff;
+ cursor: pointer;
+ }
+ .mode-toggle button.active {
+ background-color: #007bff;
+ color: white;
+ }
+ </style>
+</head>
+<body>
+ <h1>OKX WebSocket 频道连接</h1>
+
+ <div class="mode-toggle">
+ <span>当前模式:</span>
+ <button id="demoModeBtn" class="active" onclick="switchMode('demo')">模拟盘 (wspap)</button>
+ <button id="liveModeBtn" onclick="switchMode('live')">实盘 (ws)</button>
+ </div>
+
+ <div class="channel" id="publicChannel">
+ <h3>公共频道</h3>
+ <p>URL: <input type="text" id="publicUrl" value="wss://wspap.okx.com:8443/ws/v5/public" style="width: 300px;"></p>
+ <p>状态: <span class="status disconnected" id="publicStatus">未连接</span></p>
+ <button onclick="toggleConnection('public')">连接/断开</button>
+ <button onclick="clearMessages('public')">清除消息</button>
+ <div class="chart-container">
+ <canvas id="ethUsdtChart"></canvas>
+ </div>
+ <div class="messages" id="publicMessages"></div>
+ </div>
+
+ <div class="channel" id="privateChannel">
+ <h3>私有频道</h3>
+ <p>URL: <input type="text" id="privateUrl" value="wss://wspap.okx.com:8443/ws/v5/private" style="width: 300px;"></p>
+ <p>状态: <span class="status disconnected" id="privateStatus">未连接</span></p>
+ <button onclick="toggleConnection('private')">连接/断开</button>
+ <div class="messages" id="privateMessages"></div>
+ </div>
+
+ <div class="channel" id="businessChannel">
+ <h3>业务频道</h3>
+ <p>URL: <input type="text" id="businessUrl" value="wss://wspap.okx.com:8443/ws/v5/business" style="width: 300px;"></p>
+ <p>状态: <span class="status disconnected" id="businessStatus">未连接</span></p>
+ <button onclick="toggleConnection('business')">连接/断开</button>
+ <div class="messages" id="businessMessages"></div>
+ </div>
+
+ <div class="channel" id="markPriceCandleChannel">
+ <h3>标记价格K线频道</h3>
+ <p>URL: <input type="text" id="markPriceCandleUrl" value="wss://wspap.okx.com:8443/ws/v5/business" style="width: 300px;"></p>
+ <p>状态: <span class="status disconnected" id="markPriceCandleStatus">未连接</span></p>
+ <button onclick="toggleConnection('markPriceCandle')">连接/断开</button>
+ <div class="messages" id="markPriceCandleMessages"></div>
+ </div>
+
+ <script>
+ // 存储WebSocket连接对象
+ const connections = {
+ public: null,
+ private: null,
+ business: null,
+ markPriceCandle: null
+ };
+
+ // 存储各频道的URL
+ const urls = {
+ demo: {
+ public: 'wss://wspap.okx.com:8443/ws/v5/public',
+ private: 'wss://wspap.okx.com:8443/ws/v5/private',
+ business: 'wss://wspap.okx.com:8443/ws/v5/business'
+ },
+ live: {
+ public: 'wss://ws.okx.com:8443/ws/v5/public',
+ private: 'wss://ws.okx.com:8443/ws/v5/private',
+ business: 'wss://ws.okx.com:8443/ws/v5/business'
+ }
+ };
+
+ // 为markPriceCandle频道添加URL配置
+ urls.demo.markPriceCandle = urls.demo.business;
+ urls.live.markPriceCandle = urls.live.business;
+
+ // 当前模式,默认为模拟盘
+ let currentMode = 'demo';
+
+ // ETH-USDT 价格数据
+ const ethUsdtPrices = [];
+ const ethUsdtTimes = [];
+ let ethUsdtChart = null;
+
+ // 初始化图表
+ function initChart() {
+ const ctx = document.getElementById('ethUsdtChart').getContext('2d');
+ ethUsdtChart = new Chart(ctx, {
+ type: 'line',
+ data: {
+ labels: ethUsdtTimes,
+ datasets: [{
+ label: 'ETH-USDT Price',
+ data: ethUsdtPrices,
+ borderColor: 'rgb(75, 192, 192)',
+ backgroundColor: 'rgba(75, 192, 192, 0.2)',
+ tension: 0.1,
+ fill: false
+ }]
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: 'time',
+ time: {
+ unit: 'minute'
+ }
+ },
+ y: {
+ beginAtZero: false
+ }
+ }
+ }
+ });
+ }
+
+ // 更新图表
+ function updateChart() {
+ if (ethUsdtChart) {
+ // 对于折线图,我们需要重新设置labels和data并调用update
+ ethUsdtChart.data.labels = ethUsdtTimes;
+ ethUsdtChart.data.datasets[0].data = ethUsdtPrices;
+ ethUsdtChart.update();
+ }
+ }
+
+ // 连接/断开WebSocket连接
+ function toggleConnection(channel) {
+ if (connections[channel]) {
+ // 如果已经连接,则断开连接
+ connections[channel].close();
+ connections[channel] = null;
+ document.getElementById(`${channel}Status`).textContent = '未连接';
+ document.getElementById(`${channel}Status`).className = 'status disconnected';
+ } else {
+ // 如果未连接,则建立连接
+ connectToChannel(channel);
+ }
+ }
+
+ // 清除指定频道的消息
+ function clearMessages(channel) {
+ const messagesDiv = document.getElementById(`${channel}Messages`);
+ messagesDiv.innerHTML = '';
+
+ // 清除图表数据
+ if (channel === 'public') {
+ ethUsdtPrices.length = 0;
+ ethUsdtTimes.length = 0;
+ updateChart();
+ }
+ }
+
+ // 切换模式
+ function switchMode(mode) {
+ // 更新当前模式
+ currentMode = mode;
+
+ // 更新按钮状态
+ document.getElementById('demoModeBtn').classList.toggle('active', mode === 'demo');
+ document.getElementById('liveModeBtn').classList.toggle('active', mode === 'live');
+
+ // 更新所有频道的URL输入框的值
+ document.querySelectorAll('.channel').forEach(channelDiv => {
+ const channelId = channelDiv.id.replace('Channel', '');
+ // 更新输入框的值而不是替换整个元素
+ const urlInput = document.getElementById(`${channelId}Url`);
+ if (urlInput && urls[mode] && urls[mode][channelId]) {
+ urlInput.value = urls[mode][channelId];
+ }
+ });
+ }
+
+ // 连接到指定频道
+ function connectToChannel(channel) {
+ // 获取用户输入的URL
+ let url;
+ switch(channel) {
+ case 'public':
+ url = document.getElementById('publicUrl').value;
+ break;
+ case 'private':
+ url = document.getElementById('privateUrl').value;
+ break;
+ case 'business':
+ url = document.getElementById('businessUrl').value;
+ break;
+ case 'markPriceCandle':
+ url = document.getElementById('markPriceCandleUrl').value;
+ break;
+ default:
+ url = urls[currentMode][channel];
+ }
+
+ const ws = new WebSocket(url);
+
+ ws.onopen = function() {
+ console.log(`${channel}频道连接成功`);
+ document.getElementById(`${channel}Status`).textContent = '已连接';
+ document.getElementById(`${channel}Status`).className = 'status connected';
+
+ // 发送订阅消息
+ if (channel === 'public') {
+ const subscribeMsg = {
+ op: 'subscribe',
+ args: [
+ {
+ channel: 'tickers',
+ instId: 'ETH-USDT'
+ }
+ ]
+ };
+ ws.send(JSON.stringify(subscribeMsg));
+
+ // 初始化图表
+ if (!ethUsdtChart) {
+ initChart();
+ }
+ } else if (channel === 'markPriceCandle') {
+ // 订阅标记价格K线数据 (BTC-USD-190628, 1分钟K线)
+ const subscribeMsg = {
+ op: 'subscribe',
+ args: [
+ {
+ channel: 'mark-price-candle1m',
+ instId: 'ETH-USDT'
+ }
+ ]
+ };
+ ws.send(JSON.stringify(subscribeMsg));
+ }
+ };
+
+ ws.onmessage = function(event) {
+ const message = event.data;
+ console.log(`${channel}频道收到消息:`, message);
+
+ // 在页面上显示消息
+ const messagesDiv = document.getElementById(`${channel}Messages`);
+ const messageElement = document.createElement('div');
+
+ // 尝试解析JSON消息并格式化显示
+ try {
+ const jsonData = JSON.parse(message);
+
+ // 检查是否为ETH-USDT的ticker数据
+ if (jsonData.arg && jsonData.arg.instId === 'ETH-USDT' && jsonData.data && jsonData.data.length > 0) {
+ const price = parseFloat(jsonData.data[0].last);
+ const time = new Date();
+
+ // 添加价格和时间到数组
+ ethUsdtPrices.push(price);
+ ethUsdtTimes.push(time);
+
+ // 限制数据点数量,只保留最近的1000个
+ // 为了保持图表连续性,我们采用滑动窗口的方式
+ if (ethUsdtPrices.length > 1000) {
+ // 移除最旧的数据点
+ ethUsdtPrices.shift();
+ ethUsdtTimes.shift();
+
+ // 为了保持图表连续性,我们需要保留最后一个数据点作为下一个数据段的起始点
+ // 这样可以避免图表出现断裂
+ // 当数据点超过1000个时,我们重新构建数据集,确保连续性
+ if (ethUsdtPrices.length > 1) {
+ // 保留最后一个数据点作为新数据段的起始点
+ const lastPrice = ethUsdtPrices[ethUsdtPrices.length - 1];
+ const lastTime = ethUsdtTimes[ethUsdtTimes.length - 1];
+
+ // 清空数组,但保留最后一个数据点
+ ethUsdtPrices.length = 0;
+ ethUsdtTimes.length = 0;
+
+ // 将最后一个数据点作为新数据段的起始点
+ ethUsdtPrices.push(lastPrice);
+ ethUsdtTimes.push(lastTime);
+ }
+ }
+
+ // 更新图表
+ updateChart();
+ }
+
+ // 检查是否为标记价格K线数据
+ if (jsonData.arg && jsonData.arg.channel && jsonData.arg.channel.startsWith('mark-price-candle') &&
+ jsonData.arg.instId === 'BTC-USD-190628' && jsonData.data && jsonData.data.length > 0) {
+ // 这里可以处理标记价格K线数据
+ // 标记价格K线数据格式: [ts, o, h, l, c]
+ // ts: 开始时间, o: 开盘价, h: 最高价, l: 最低价, c: 收盘价
+ console.log('标记价格K线数据:', jsonData.data[0]);
+ }
+
+ messageElement.innerHTML = `<strong>[${new Date().toLocaleTimeString()}]</strong> ${JSON.stringify(jsonData, null, 2)}`;
+ } catch (e) {
+ // 如果不是JSON格式,则直接显示
+ messageElement.innerHTML = `<strong>[${new Date().toLocaleTimeString()}]</strong> ${message}`;
+ }
+
+ messagesDiv.appendChild(messageElement);
+ messagesDiv.scrollTop = messagesDiv.scrollHeight;
+ };
+
+ ws.onerror = function(error) {
+ console.error(`${channel}频道连接错误:`, error);
+ document.getElementById(`${channel}Status`).textContent = '连接错误';
+ document.getElementById(`${channel}Status`).className = 'status disconnected';
+ };
+
+ ws.onclose = function() {
+ console.log(`${channel}频道连接已关闭`);
+ document.getElementById(`${channel}Status`).textContent = '连接已关闭';
+ document.getElementById(`${channel}Status`).className = 'status disconnected';
+ connections[channel] = null;
+ };
+
+ connections[channel] = ws;
+ }
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/static/febs/quant/okxWebsocketMonitor.html b/src/main/resources/static/febs/quant/okxWebsocketMonitor.html
new file mode 100644
index 0000000..0120c5f
--- /dev/null
+++ b/src/main/resources/static/febs/quant/okxWebsocketMonitor.html
@@ -0,0 +1,180 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>OKX WebSocket消息监控</title>
+ <style>
+ body {
+ font-family: Arial, sans-serif;
+ margin: 20px;
+ background-color: #f5f5f5;
+ }
+ .container {
+ max-width: 1200px;
+ margin: 0 auto;
+ background-color: white;
+ padding: 20px;
+ border-radius: 8px;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+ }
+ h1 {
+ color: #333;
+ text-align: center;
+ }
+ .controls {
+ margin: 20px 0;
+ text-align: center;
+ }
+ .controls input, .controls button {
+ margin: 5px;
+ padding: 8px 15px;
+ border-radius: 4px;
+ border: 1px solid #ddd;
+ }
+ .controls button {
+ background-color: #007bff;
+ color: white;
+ cursor: pointer;
+ }
+ .controls button:hover {
+ background-color: #0056b3;
+ }
+ #messageDisplay {
+ background-color: #f8f9fa;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ padding: 15px;
+ min-height: 300px;
+ max-height: 600px;
+ overflow-y: auto;
+ white-space: pre-wrap;
+ font-family: monospace;
+ }
+ .message {
+ margin-bottom: 10px;
+ padding: 10px;
+ border-radius: 4px;
+ background-color: #e9ecef;
+ }
+ .timestamp {
+ font-size: 0.8em;
+ color: #6c757d;
+ }
+ </style>
+</head>
+<body>
+ <div class="container">
+ <h1>OKX WebSocket消息监控</h1>
+
+ <div class="controls">
+ <label for="refreshInterval">刷新间隔(秒):</label>
+ <input type="number" id="refreshInterval" min="1" max="60" value="5">
+ <button onclick="startAutoRefresh()">开始自动刷新</button>
+ <button onclick="stopAutoRefresh()">停止自动刷新</button>
+ <button onclick="refreshMessage()">手动刷新</button>
+ <button onclick="clearMessages()">清除消息</button>
+ </div>
+
+ <div id="messageDisplay">
+ <p>等待接收消息...</p>
+ </div>
+ </div>
+
+ <script>
+ let refreshIntervalId;
+ let messageHistory = [];
+
+ // 获取最新消息
+ function refreshMessage() {
+ fetch('/quant/okx/latestMessage')
+ .then(response => response.json())
+ .then(data => {
+ if (data.code === 200 && data.data) {
+ displayMessage(data.data);
+ }
+ })
+ .catch(error => {
+ console.error('Error fetching message:', error);
+ displayMessage('Error: ' + error.message);
+ });
+ }
+
+ // 显示消息
+ function displayMessage(message) {
+ const display = document.getElementById('messageDisplay');
+ const timestamp = new Date().toLocaleString();
+
+ // 如果是新消息,添加到历史记录
+ if (!messageHistory.includes(message)) {
+ messageHistory.push({
+ timestamp: timestamp,
+ content: message
+ });
+
+ // 限制历史记录数量
+ if (messageHistory.length > 100) {
+ messageHistory.shift();
+ }
+ }
+
+ // 更新显示
+ display.innerHTML = '';
+ messageHistory.forEach(msg => {
+ const messageElement = document.createElement('div');
+ messageElement.className = 'message';
+ messageElement.innerHTML = `
+ <div class="timestamp">${msg.timestamp}</div>
+ <div>${formatJson(msg.content)}</div>
+ `;
+ display.appendChild(messageElement);
+ });
+
+ // 滚动到底部
+ display.scrollTop = display.scrollHeight;
+ }
+
+ // 格式化JSON
+ function formatJson(jsonString) {
+ try {
+ const obj = JSON.parse(jsonString);
+ return JSON.stringify(obj, null, 2);
+ } catch (e) {
+ return jsonString;
+ }
+ }
+
+ // 开始自动刷新
+ function startAutoRefresh() {
+ stopAutoRefresh(); // 先停止之前的定时器
+ const interval = document.getElementById('refreshInterval').value * 1000;
+ refreshIntervalId = setInterval(refreshMessage, interval);
+ refreshMessage(); // 立即获取一次消息
+ }
+
+ // 停止自动刷新
+ function stopAutoRefresh() {
+ if (refreshIntervalId) {
+ clearInterval(refreshIntervalId);
+ refreshIntervalId = null;
+ }
+ }
+
+ // 清除消息
+ function clearMessages() {
+ messageHistory = [];
+ document.getElementById('messageDisplay').innerHTML = '<p>消息已清除</p>';
+ }
+
+ // 页面加载完成后开始自动刷新
+ window.onload = function() {
+ startAutoRefresh();
+ };
+
+ // 页面关闭前停止定时器
+ window.onbeforeunload = function() {
+ stopAutoRefresh();
+ };
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/banner/platformBannerAdd.html b/src/main/resources/templates/febs/views/modules/banner/platformBannerAdd.html
index a78bb2a..074b274 100644
--- a/src/main/resources/templates/febs/views/modules/banner/platformBannerAdd.html
+++ b/src/main/resources/templates/febs/views/modules/banner/platformBannerAdd.html
@@ -47,6 +47,7 @@
<blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
<div class="layui-upload-list" id="bannerImgUpload"></div>
</blockquote>
+ <div class="layui-word-aux">双击图片删除</div>
</div>
</div>
</div>
@@ -60,27 +61,28 @@
</div>
</div>
- <div class="layui-row layui-col-space10 layui-form-item">
- <div class="layui-col-lg6">
- <label class="layui-form-label">背景图片:</label>
- <div class="layui-input-block">
- <div class="layui-upload">
- <button type="button" class="layui-btn layui-btn-normal layui-btn" id="bannerImgUploadButtonBack">上传</button>
- <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
- <div class="layui-upload-list" id="bannerImgUploadBack"></div>
- </blockquote>
- </div>
- </div>
- </div>
- </div>
- <div class="layui-row layui-col-space10 layui-form-item febs-hide">
- <div class="layui-col-lg6">
- <label class="layui-form-label">背景图片链接:</label>
- <div class="layui-input-block">
- <input type="text" id="imageBackUrl" name="imageBackUrl" autocomplete="off" class="layui-input" readonly>
- </div>
- </div>
- </div>
+<!-- <div class="layui-row layui-col-space10 layui-form-item">-->
+<!-- <div class="layui-col-lg6">-->
+<!-- <label class="layui-form-label">背景图片:</label>-->
+<!-- <div class="layui-input-block">-->
+<!-- <div class="layui-upload">-->
+<!-- <button type="button" class="layui-btn layui-btn-normal layui-btn" id="bannerImgUploadButtonBack">上传</button>-->
+<!-- <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">-->
+<!-- <div class="layui-upload-list" id="bannerImgUploadBack"></div>-->
+<!-- </blockquote>-->
+<!-- <div class="layui-word-aux">双击图片删除</div>-->
+<!-- </div>-->
+<!-- </div>-->
+<!-- </div>-->
+<!-- </div>-->
+<!-- <div class="layui-row layui-col-space10 layui-form-item febs-hide">-->
+<!-- <div class="layui-col-lg6">-->
+<!-- <label class="layui-form-label">背景图片链接:</label>-->
+<!-- <div class="layui-input-block">-->
+<!-- <input type="text" id="imageBackUrl" name="imageBackUrl" autocomplete="off" class="layui-input" readonly>-->
+<!-- </div>-->
+<!-- </div>-->
+<!-- </div>-->
<div class="layui-row layui-col-space10 layui-form-item">
<div class="layui-col-lg6">
@@ -191,6 +193,9 @@
}
,done: function(res){
$("#imageUrl").val(res.data.src);
+
+ imgUnBind(".single-image");
+ imgSingleBind("#imageUrl");
}
});
@@ -208,8 +213,30 @@
}
,done: function(res){
$("#imageBackUrl").val(res.data.src);
+
+ imgUnBind(".single-image");
+ imgSingleBind("#imageBackUrl");
}
});
+
+ function imgSingleBind(idName) {
+ $(".single-image").each(function(index, element) {
+ $(this).on("dblclick", function() {
+ var imgThumb = $(".single-image")[index];
+ $(imgThumb).remove();
+ $(idName).val("");
+
+ imgUnBind(".single-image");
+ imgSingleBind();
+ });
+ })
+ }
+ function imgUnBind(className) {
+ $(className).each(function() {
+ $(this).unbind('dblclick');
+ })
+ }
+
formSelects.render();
form.on('submit(banner-add-form-submit)', function (data) {
febs.post(ctx + 'admin/banner/platformBannerAdds', data.field, function () {
diff --git a/src/main/resources/templates/febs/views/modules/banner/platformBannerDetail.html b/src/main/resources/templates/febs/views/modules/banner/platformBannerDetail.html
index 10156a1..9ab453c 100644
--- a/src/main/resources/templates/febs/views/modules/banner/platformBannerDetail.html
+++ b/src/main/resources/templates/febs/views/modules/banner/platformBannerDetail.html
@@ -49,6 +49,7 @@
<blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
<div class="layui-upload-list" id="bannerImgUpload"></div>
</blockquote>
+ <div class="layui-word-aux">双击图片删除</div>
</div>
</div>
</div>
@@ -62,27 +63,28 @@
</div>
</div>
- <div class="layui-row layui-col-space10 layui-form-item">
- <div class="layui-col-lg6">
- <label class="layui-form-label">背景图片:</label>
- <div class="layui-input-block">
- <div class="layui-upload">
- <button type="button" class="layui-btn layui-btn-normal layui-btn" id="bannerImgUploadButtonBack">上传</button>
- <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
- <div class="layui-upload-list" id="bannerImgUploadBack"></div>
- </blockquote>
- </div>
- </div>
- </div>
- </div>
- <div class="layui-row layui-col-space10 layui-form-item febs-hide">
- <div class="layui-col-lg6">
- <label class="layui-form-label">背景图片链接:</label>
- <div class="layui-input-block">
- <input type="text" id="imageBackUrl" name="imageBackUrl" autocomplete="off" class="layui-input" readonly>
- </div>
- </div>
- </div>
+<!-- <div class="layui-row layui-col-space10 layui-form-item">-->
+<!-- <div class="layui-col-lg6">-->
+<!-- <label class="layui-form-label">背景图片:</label>-->
+<!-- <div class="layui-input-block">-->
+<!-- <div class="layui-upload">-->
+<!-- <button type="button" class="layui-btn layui-btn-normal layui-btn" id="bannerImgUploadButtonBack">上传</button>-->
+<!-- <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">-->
+<!-- <div class="layui-upload-list" id="bannerImgUploadBack"></div>-->
+<!-- </blockquote>-->
+<!-- <div class="layui-word-aux">双击图片删除</div>-->
+<!-- </div>-->
+<!-- </div>-->
+<!-- </div>-->
+<!-- </div>-->
+<!-- <div class="layui-row layui-col-space10 layui-form-item febs-hide">-->
+<!-- <div class="layui-col-lg6">-->
+<!-- <label class="layui-form-label">背景图片链接:</label>-->
+<!-- <div class="layui-input-block">-->
+<!-- <input type="text" id="imageBackUrl" name="imageBackUrl" autocomplete="off" class="layui-input" readonly>-->
+<!-- </div>-->
+<!-- </div>-->
+<!-- </div>-->
<div class="layui-row layui-col-space10 layui-form-item">
<div class="layui-col-lg6">
@@ -178,6 +180,9 @@
}
,done: function(res){
$("#imageUrl").val(res.data.src);
+
+ imgUnBind(".single-image");
+ imgSingleBind("#imageUrl");
}
});
@@ -195,8 +200,29 @@
}
,done: function(res){
$("#imageBackUrl").val(res.data.src);
+
+ imgUnBind(".single-image");
+ imgSingleBind("#imageBackUrl");
}
});
+
+ function imgSingleBind(idName) {
+ $(".single-image").each(function(index, element) {
+ $(this).on("dblclick", function() {
+ var imgThumb = $(".single-image")[index];
+ $(imgThumb).remove();
+ $(idName).val("");
+
+ imgUnBind(".single-image");
+ imgSingleBind(idName);
+ });
+ })
+ }
+ function imgUnBind(className) {
+ $(className).each(function() {
+ $(this).unbind('dblclick');
+ })
+ }
form.render();
//(下拉框)
@@ -233,9 +259,11 @@
$('#bannerImgUpload').append('<img src="' + banner.imageUrl + '" alt="" class="layui-upload-img single-image" style="width: 130px">');
$("#imageUrl").val(banner.imageUrl);
+ imgSingleBind("#imageUrl");
$('#bannerImgUploadBack').append('<img src="' + banner.imageBackUrl + '" alt="" class="layui-upload-img single-image" style="width: 130px">');
$("#imageBackUrl").val(banner.imageBackUrl);
+ imgSingleBind("#imageBackUrl");
}
form.on('submit(banner-info-form-submit)', function (data) {
--
Gitblit v1.9.1