|
|
@ -15,8 +15,8 @@ |
|
|
</view> |
|
|
</view> |
|
|
<view class="arrow-right"> </view> |
|
|
<view class="arrow-right"> </view> |
|
|
</view> |
|
|
</view> |
|
|
<image class="search" src="/static/marketSituation-image/search.png" mode="搜索" @click="startTcp()"> </image> |
|
|
|
|
|
<view class="more" @click="disconnect()">···</view> |
|
|
|
|
|
|
|
|
<image class="search" src="/static/marketSituation-image/search.png" mode="搜索" @click="search()"> </image> |
|
|
|
|
|
<view class="more" @click="getMore()">···</view> |
|
|
</view> |
|
|
</view> |
|
|
</view> |
|
|
</view> |
|
|
|
|
|
|
|
|
@ -196,8 +196,14 @@ |
|
|
</view> |
|
|
</view> |
|
|
<!-- K线图区域 --> |
|
|
<!-- K线图区域 --> |
|
|
<view class="test" v-else-if="klineTab === 3"> |
|
|
<view class="test" v-else-if="klineTab === 3"> |
|
|
<button @click="sendGetTimeData()">接收消息</button> |
|
|
|
|
|
|
|
|
<button @click="startTcp()">接收消息</button> |
|
|
<button @click="sendStopTimeData()">停止消息</button> |
|
|
<button @click="sendStopTimeData()">停止消息</button> |
|
|
|
|
|
<button @click="sendTcpMessage('real_time')">实时行情推送</button> |
|
|
|
|
|
<button @click="sendTcpMessage('init_real_time')">初始化获取行情历史数据</button> |
|
|
|
|
|
<button @click="sendTcpMessage('stop_real_time')">停止实时推送</button> |
|
|
|
|
|
<view class="tcpMsg" v-for="item in tcpMessages" :key="item"> |
|
|
|
|
|
{{ item }} |
|
|
|
|
|
</view> |
|
|
</view> |
|
|
</view> |
|
|
<view v-else class="kline-chart-container"> |
|
|
<view v-else class="kline-chart-container"> |
|
|
<text>K线图开发中...</text> |
|
|
<text>K线图开发中...</text> |
|
|
@ -230,15 +236,27 @@ const instance = getCurrentInstance(); |
|
|
import { prevClosePrice, timeData as testTimeData, klineData as testKlineData } from "@/common/stockTimeInformation.js"; |
|
|
import { prevClosePrice, timeData as testTimeData, klineData as testKlineData } from "@/common/stockTimeInformation.js"; |
|
|
import { throttle } from "@/common/util.js"; |
|
|
import { throttle } from "@/common/util.js"; |
|
|
import { HCharts } from "@/common/canvasMethod.js"; |
|
|
import { HCharts } from "@/common/canvasMethod.js"; |
|
|
// const TCPSocket = uni.requireNativePlugin("Aimer-TCPPlugin"); |
|
|
|
|
|
const tcpObject = { |
|
|
|
|
|
ip: "192.168.1.9", |
|
|
|
|
|
port: 8080, |
|
|
|
|
|
reconnectInterval: 3000, |
|
|
|
|
|
isConnected: false, |
|
|
|
|
|
}; |
|
|
|
|
|
const TIME_OUT = 1000 * 5; |
|
|
|
|
|
const resultR = ref([]); |
|
|
|
|
|
|
|
|
import tcpConnection, { TCPConnection, TCP_CONFIG } from "@/api/tcpConnection.js"; |
|
|
|
|
|
|
|
|
|
|
|
// TCP相关响应式变量 |
|
|
|
|
|
const tcpConnected = ref(false); |
|
|
|
|
|
const tcpMessages = ref([]); |
|
|
|
|
|
const tcpStockData = ref({ |
|
|
|
|
|
count: 0, |
|
|
|
|
|
data: {}, |
|
|
|
|
|
stock_count: 0, |
|
|
|
|
|
timestamp: "", |
|
|
|
|
|
type: "", |
|
|
|
|
|
}); |
|
|
|
|
|
const currentStockInfo = ref({ |
|
|
|
|
|
stock_name: "未知股票", |
|
|
|
|
|
current_price: "0.00", |
|
|
|
|
|
change: "0.00%", |
|
|
|
|
|
change_value: 0, |
|
|
|
|
|
change_percent: 0, |
|
|
|
|
|
}); |
|
|
|
|
|
const connectionListener = ref(null); |
|
|
|
|
|
const messageListener = ref(null); |
|
|
|
|
|
|
|
|
// 股票信息栏变量 |
|
|
// 股票信息栏变量 |
|
|
const stockInformation = ref({ |
|
|
const stockInformation = ref({ |
|
|
@ -401,29 +419,26 @@ const moreTabsData = ref([ |
|
|
|
|
|
|
|
|
// 股票当前选中的K线类型Tab |
|
|
// 股票当前选中的K线类型Tab |
|
|
// 1:分时 2:日K 3:周K 4:月K |
|
|
// 1:分时 2:日K 3:周K 4:月K |
|
|
const klineTab = ref(2); |
|
|
|
|
|
|
|
|
|
|
|
const sendGetTimeData = () => { |
|
|
|
|
|
console.log("执行发送消息的方法"); |
|
|
|
|
|
|
|
|
const klineTab = ref(1); |
|
|
|
|
|
const startTcp = () => { |
|
|
try { |
|
|
try { |
|
|
TCPSocket.send({ |
|
|
|
|
|
channel: "1", |
|
|
|
|
|
message: '{"command": "real_time", "stock_code": "SH.000001"}', |
|
|
|
|
|
|
|
|
removeTcpListeners(); |
|
|
|
|
|
disconnectTcp(); |
|
|
|
|
|
initTcpListeners(); |
|
|
|
|
|
connectTcp(); |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error("建立连接并设置监听:", error); |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: "建立连接并设置监听", |
|
|
|
|
|
icon: "none", |
|
|
|
|
|
duration: 1500, |
|
|
}); |
|
|
}); |
|
|
} catch (e) { |
|
|
|
|
|
console.log("error", e); |
|
|
|
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const sendStopTimeData = () => { |
|
|
const sendStopTimeData = () => { |
|
|
try { |
|
|
|
|
|
TCPSocket.send({ |
|
|
|
|
|
channel: "1", |
|
|
|
|
|
message: '{"command": "stop_real_time"}', |
|
|
|
|
|
}); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.log("error", e); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
disconnectTcp(); |
|
|
|
|
|
removeTcpListeners(); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// 确定股票数据的颜色方法 |
|
|
// 确定股票数据的颜色方法 |
|
|
@ -450,9 +465,11 @@ const confirmStockColor = (price, lastDayStockClosePrice) => { |
|
|
// 股票K线类型方法 |
|
|
// 股票K线类型方法 |
|
|
const selectKlineTab = (tabId) => { |
|
|
const selectKlineTab = (tabId) => { |
|
|
klineTab.value = tabId; |
|
|
klineTab.value = tabId; |
|
|
if (tabId === 1) { |
|
|
|
|
|
stockInformation.value.lastDayStockClosePrice = prevClosePrice; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (klineTab.value == 1) { |
|
|
|
|
|
sendTcpMessage("init_real_time"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
initCanvas(); |
|
|
initCanvas(); |
|
|
// startAddDataTimer(); |
|
|
// startAddDataTimer(); |
|
|
}; |
|
|
}; |
|
|
@ -929,6 +946,7 @@ const drawChart = () => { |
|
|
|
|
|
|
|
|
// 根据当前标签绘制对应图表 |
|
|
// 根据当前标签绘制对应图表 |
|
|
if (klineTab.value == 1) { |
|
|
if (klineTab.value == 1) { |
|
|
|
|
|
console.log("stockInfomaton.lastDayStockClosePrice", stockInformation.value.lastDayStockClosePrice); |
|
|
// 设置标签样式 |
|
|
// 设置标签样式 |
|
|
const label = [ |
|
|
const label = [ |
|
|
{ |
|
|
{ |
|
|
@ -1364,151 +1382,341 @@ watch(klineTab, () => { |
|
|
console.log("标签页变化"); |
|
|
console.log("标签页变化"); |
|
|
drawChart(); |
|
|
drawChart(); |
|
|
}); |
|
|
}); |
|
|
/* |
|
|
|
|
|
const connectTcp = (ip, port) => { |
|
|
|
|
|
console.log(`🚀 正在连接TCP服务器 ${ip}:${port}...`); |
|
|
|
|
|
TCPSocket.connect( |
|
|
|
|
|
{ |
|
|
|
|
|
channel: "1", |
|
|
|
|
|
ip: ip, |
|
|
|
|
|
port: port, |
|
|
|
|
|
}, |
|
|
|
|
|
(result) => { |
|
|
|
|
|
console.log(result); |
|
|
|
|
|
if (result.status == 0) { |
|
|
|
|
|
tcpObject.isConnected = true; |
|
|
|
|
|
console.log("tcp连接成功"); |
|
|
|
|
|
} else if (result.status == 1) { |
|
|
|
|
|
tcpObject.isConnected = false; |
|
|
|
|
|
console.log("tcp断开连接"); |
|
|
|
|
|
} |
|
|
|
|
|
if (result.receivedMsg) { |
|
|
|
|
|
console.log("收到服务器发送的数据", result.receivedMsg); |
|
|
|
|
|
if (result.receivedMsg.length == 0 || result.receivedMsg.includes("欢迎")) { |
|
|
|
|
|
resultR.value = []; |
|
|
|
|
|
} else { |
|
|
|
|
|
const msgPacket = JSON.parse(result.receivedMsg); |
|
|
|
|
|
resultR.value.push(msgPacket); |
|
|
|
|
|
// 股票代码 |
|
|
|
|
|
if (msgPacket.stock_code) { |
|
|
|
|
|
stockInformation.value.stockCode = msgPacket.stock_code; |
|
|
|
|
|
} |
|
|
|
|
|
// 股票名称 |
|
|
|
|
|
if (msgPacket.stock_name) { |
|
|
|
|
|
stockInformation.value.stockName = msgPacket.stock_name; |
|
|
|
|
|
} |
|
|
|
|
|
// 前一日收盘价 |
|
|
|
|
|
if (msgPacket.pre_close) { |
|
|
|
|
|
stockInformation.value.lastDayStockClosePrice = msgPacket.pre_close; |
|
|
|
|
|
} |
|
|
|
|
|
// 当前股价(收盘价) |
|
|
|
|
|
if (msgPacket.current_price) { |
|
|
|
|
|
stockInformation.value.currentPrice = msgPacket.current_price; |
|
|
|
|
|
} |
|
|
|
|
|
// 涨跌额度 |
|
|
|
|
|
if (msgPacket.current_price && msgPacket.pre_close) { |
|
|
|
|
|
stockInformation.value.currentValue = msgPacket.current_price - msgPacket.pre_close; |
|
|
|
|
|
stockInformation.value.currentRatio = ((msgPacket.current_price - msgPacket.pre_close) / msgPacket.pre_close) * 100; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 最高价 |
|
|
|
|
|
if (msgPacket.high_price) { |
|
|
|
|
|
stockInformation.value.highPrice = msgPacket.high_price; |
|
|
|
|
|
} |
|
|
|
|
|
// 最低价 |
|
|
|
|
|
if (msgPacket.close_price) { |
|
|
|
|
|
stockInformation.value.lowPrice = msgPacket.close_price; |
|
|
|
|
|
} |
|
|
|
|
|
// 开盘价 |
|
|
|
|
|
if (msgPacket.open_price) { |
|
|
|
|
|
stockInformation.value.openPrice = msgPacket.open_price; |
|
|
|
|
|
} |
|
|
|
|
|
// 开盘价 |
|
|
|
|
|
if (msgPacket.low_price) { |
|
|
|
|
|
stockInformation.value.lowPrice = msgPacket.low_price; |
|
|
|
|
|
} |
|
|
|
|
|
// 收盘价(当前股价) |
|
|
|
|
|
if (msgPacket.current_price) { |
|
|
|
|
|
stockInformation.value.closePrice = msgPacket.current_price; |
|
|
|
|
|
} |
|
|
|
|
|
// 成交量 |
|
|
|
|
|
if (msgPacket.volume) { |
|
|
|
|
|
stockInformation.value.volume = msgPacket.volume; |
|
|
|
|
|
} |
|
|
|
|
|
// 成交量比 |
|
|
|
|
|
if (msgPacket.volume_ratio) { |
|
|
|
|
|
stockInformation.value.volumeRatio = msgPacket.volume_ratio; |
|
|
|
|
|
} |
|
|
|
|
|
// 成交额 |
|
|
|
|
|
if (msgPacket.amount) { |
|
|
|
|
|
stockInformation.value.amount = msgPacket.amount; |
|
|
|
|
|
} |
|
|
|
|
|
// 市盈 |
|
|
|
|
|
if (msgPacket.market_earn) { |
|
|
|
|
|
stockInformation.value.marketEarn = msgPacket.market_earn; |
|
|
|
|
|
} |
|
|
|
|
|
// 换手率 |
|
|
|
|
|
if (msgPacket.turnover_ratio) { |
|
|
|
|
|
stockInformation.value.turnoverRatio = msgPacket.turnover_ratio; |
|
|
|
|
|
} |
|
|
|
|
|
// 市值 |
|
|
|
|
|
if (msgPacket.total_market_value) { |
|
|
|
|
|
stockInformation.value.marketValue = msgPacket.total_market_value; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
// if (result.receivedHexMsg) { |
|
|
|
|
|
// //服务器返回16进制数据 |
|
|
|
|
|
// console.log("📥 收到16进制数据:", result.receivedHexMsg); |
|
|
|
|
|
// let msg = result.receivedHexMsg; |
|
|
|
|
|
// let sum = msg.length / 2; |
|
|
|
|
|
// let arr = []; |
|
|
|
|
|
// for (let k = 0; k < sum; k++) { |
|
|
|
|
|
// let i = msg.substring(k * 2, k * 2 + 2); |
|
|
|
|
|
// arr.push(i); |
|
|
|
|
|
// } |
|
|
|
|
|
// console.log("转换成16进制数组:", arr); |
|
|
|
|
|
// if (tcpObject.responseCallback) { |
|
|
|
|
|
// tcpObject.responseCallback({ |
|
|
|
|
|
// data: arr, |
|
|
|
|
|
// }); |
|
|
|
|
|
// } |
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
// 设置连接超时 |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
if (!tcpObject.isConnected) { |
|
|
|
|
|
throw new Error("连接超时"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
}, TIME_OUT); |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
}; |
|
|
|
|
|
// 断开连接 |
|
|
|
|
|
const disconnect = () => { |
|
|
|
|
|
try { |
|
|
|
|
|
TCPSocket.disconnect({ |
|
|
|
|
|
channel: "1", |
|
|
|
|
|
}); |
|
|
|
|
|
tcpObject.isConnected = false; |
|
|
|
|
|
console.log("✅ 连接已关闭"); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.log("⚠️ 断开连接时发生错误:", e.message); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const startTcp = async () => { |
|
|
|
|
|
console.log("🚀 TCP客户端启动"); |
|
|
|
|
|
console.log(`目标服务器: ${tcpObject.ip}:${tcpObject.port}`); |
|
|
|
|
|
try { |
|
|
|
|
|
// 连接服务器 |
|
|
|
|
|
await connectTcp(tcpObject.ip, tcpObject.port); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.log("error", e); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化TCP监听器 |
|
|
|
|
|
const initTcpListeners = () => { |
|
|
|
|
|
// 创建连接状态监听器并保存引用 |
|
|
|
|
|
connectionListener.value = (status, result) => { |
|
|
|
|
|
tcpConnected.value = status === "connected"; |
|
|
|
|
|
console.log("TCP连接状态变化:", status, tcpConnected.value); |
|
|
|
|
|
|
|
|
|
|
|
// 显示连接状态提示 |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: status === "connected" ? "TCP连接成功" : "TCP连接断开", |
|
|
|
|
|
icon: status === "connected" ? "success" : "none", |
|
|
|
|
|
duration: 2000, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (status === "connected") { |
|
|
|
|
|
if (klineTab.value == 1) { |
|
|
|
|
|
sendTcpMessage("init_real_time"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 创建消息监听器并保存引用 |
|
|
|
|
|
messageListener.value = (type, message, parsedArray) => { |
|
|
|
|
|
const messageObj = { |
|
|
|
|
|
type: type, |
|
|
|
|
|
content: message, |
|
|
|
|
|
parsedArray: parsedArray, |
|
|
|
|
|
timestamp: new Date().toLocaleTimeString(), |
|
|
|
|
|
direction: "received", |
|
|
|
|
|
}; |
|
|
|
|
|
console.log("0000"); |
|
|
|
|
|
tcpMessages.value.push(messageObj); |
|
|
|
|
|
// console.log('收到TCP消息:', messageObj) |
|
|
|
|
|
console.log("home开始调用parseStockData", messageObj); |
|
|
|
|
|
|
|
|
|
|
|
// 解析股票数据 |
|
|
|
|
|
parseStockData(message); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 注册监听器 |
|
|
|
|
|
tcpConnection.onConnectionChange(connectionListener.value); |
|
|
|
|
|
tcpConnection.onMessage(messageListener.value); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 连接TCP服务器 |
|
|
|
|
|
const connectTcp = () => { |
|
|
|
|
|
console.log("开始连接TCP服务器..."); |
|
|
|
|
|
tcpConnection.connect(); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 断开TCP连接 |
|
|
|
|
|
const disconnectTcp = () => { |
|
|
|
|
|
console.log("断开TCP连接..."); |
|
|
|
|
|
tcpConnection.disconnect(); |
|
|
|
|
|
tcpConnected.value = false; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 发送TCP消息 |
|
|
|
|
|
const sendTcpMessage = (command) => { |
|
|
|
|
|
let messageData; |
|
|
|
|
|
switch (command) { |
|
|
|
|
|
// 实时行情推送 |
|
|
|
|
|
case "real_time": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "real_time", |
|
|
|
|
|
stock_code: "SH.000001", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
// 初始化获取行情历史数据 |
|
|
|
|
|
case "init_real_time": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "init_real_time", |
|
|
|
|
|
stock_code: "SH.000001", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "stop_real_time": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "stop_real_time", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
// 股票列表 |
|
|
|
|
|
case "stock_list": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "stock_list", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "daily_data": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "daily_data", |
|
|
|
|
|
stock_code: "GBPAUD.FXCM", |
|
|
|
|
|
start_date: "20251001", |
|
|
|
|
|
end_date: "20251023", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "weekly_data": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "weekly_data", |
|
|
|
|
|
stock_code: "000001.SZ", |
|
|
|
|
|
start_date: "20251001", |
|
|
|
|
|
end_date: "20251023", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "daily_one_minutes_data": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "daily_one_minutes_data", |
|
|
|
|
|
stock_code: "000001.SZ", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "daily_five_minutes_data": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "daily_five_minutes_data", |
|
|
|
|
|
stock_code: "000001.SZ", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "daily_fifteen_minutes_data": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "daily_fifteen_minutes_data", |
|
|
|
|
|
stock_code: "000001.SZ", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "daily_thirty_minutes_data": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "daily_thirty_minutes_data", |
|
|
|
|
|
stock_code: "000001.SZ", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "daily_sixty_minutes_data": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "daily_sixty_minutes_data", |
|
|
|
|
|
stock_code: "000001.SZ", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "batch_real_time": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "batch_real_time", |
|
|
|
|
|
stock_codes: ["SH.000001", "SH.000002", "SH.000003", "SH.000004", "SH.000005"], |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
case "help": |
|
|
|
|
|
messageData = { |
|
|
|
|
|
command: "help", |
|
|
|
|
|
}; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
if (!messageData) { |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: "命令不存在", |
|
|
|
|
|
icon: "none", |
|
|
|
|
|
duration: 1500, |
|
|
|
|
|
}); |
|
|
|
|
|
return; |
|
|
|
|
|
} else { |
|
|
|
|
|
try { |
|
|
|
|
|
// 发送消息 |
|
|
|
|
|
const success = tcpConnection.send(messageData); |
|
|
|
|
|
if (success) { |
|
|
|
|
|
console.log("home发送TCP消息:", messageData); |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: "消息发送成功", |
|
|
|
|
|
icon: "success", |
|
|
|
|
|
duration: 1500, |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error("发送TCP消息时出错:", error); |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: "消息发送失败", |
|
|
|
|
|
icon: "none", |
|
|
|
|
|
duration: 1500, |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 清空消息记录 |
|
|
|
|
|
const clearTcpMessages = () => { |
|
|
|
|
|
tcpMessages.value = []; |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: "消息记录已清空", |
|
|
|
|
|
icon: "success", |
|
|
|
|
|
duration: 1500, |
|
|
|
|
|
}); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 获取TCP连接状态 |
|
|
|
|
|
const getTcpStatus = () => { |
|
|
|
|
|
const status = tcpConnection.getConnectionStatus(); |
|
|
|
|
|
uni.showModal({ |
|
|
|
|
|
title: "TCP连接状态", |
|
|
|
|
|
content: `当前状态: ${status ? "已连接" : "未连接"}\n消息数量: ${tcpMessages.value.length}`, |
|
|
|
|
|
showCancel: false, |
|
|
|
|
|
}); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let isMorePacket = false; |
|
|
|
|
|
let receivedMessage; |
|
|
|
|
|
// 解析TCP股票数据 |
|
|
|
|
|
const parseStockData = (message) => { |
|
|
|
|
|
try { |
|
|
|
|
|
console.log("进入parseStockData, message类型:", typeof message); |
|
|
|
|
|
|
|
|
|
|
|
let parsedMessage; |
|
|
|
|
|
// 如果isMorePacket是true,说明正在接受分包数据,无条件接收 |
|
|
|
|
|
// 如果message是字符串且以{开头,说明是JSON字符串,需要解析 |
|
|
|
|
|
// 如果不属于以上两种情况,说明是普通字符串,不预解析 |
|
|
|
|
|
if (message.includes("欢迎连接到股票数据服务器")) { |
|
|
|
|
|
console.log("服务器命令列表,不予处理"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if ((typeof message === "string" && message.includes("init_real_data_start")) || isMorePacket) { |
|
|
|
|
|
if (typeof message === "string" && message.includes("init_real_data_start")) { |
|
|
|
|
|
console.log("开始接受分包数据"); |
|
|
|
|
|
receivedMessage = ""; |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("接收分包数据过程中"); |
|
|
|
|
|
} |
|
|
|
|
|
isMorePacket = true; |
|
|
|
|
|
receivedMessage += message; |
|
|
|
|
|
// 如果当前消息包含},说明收到JSON字符串结尾,结束接收,开始解析 |
|
|
|
|
|
if (receivedMessage.includes("init_real_data_complete")) { |
|
|
|
|
|
console.log("接受分包数据结束"); |
|
|
|
|
|
isMorePacket = false; |
|
|
|
|
|
|
|
|
|
|
|
console.log("展示数据", receivedMessage); |
|
|
|
|
|
// 获取JSON字符串的开头和结尾的坐标 |
|
|
|
|
|
let jsonStartIndex = 0; |
|
|
|
|
|
let jsonEndIndex = receivedMessage.indexOf("init_real_data_complete"); |
|
|
|
|
|
let jsonStartCount = 0; |
|
|
|
|
|
let jsonEndCount = 0; |
|
|
|
|
|
for (let i = 0; i < receivedMessage.length - 1; ++i) { |
|
|
|
|
|
if (receivedMessage[i] == "{") { |
|
|
|
|
|
jsonStartCount++; |
|
|
|
|
|
if (jsonStartCount == 2) { |
|
|
|
|
|
jsonStartIndex = i; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (let i = receivedMessage.indexOf("init_real_data_complete"); i >= 0; --i) { |
|
|
|
|
|
if (receivedMessage[i] == "}" || i == jsonStartIndex) { |
|
|
|
|
|
jsonEndCount++; |
|
|
|
|
|
if (jsonEndCount == 1) { |
|
|
|
|
|
jsonEndIndex = i; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
// 检查JSON字符串是否有效 |
|
|
|
|
|
if (jsonStartIndex >= jsonEndIndex) { |
|
|
|
|
|
throw new Error("JSON字符串格式错误"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log("检测到JSON字符串,开始解析"); |
|
|
|
|
|
parsedMessage = JSON.parse(receivedMessage.substring(jsonStartIndex, jsonEndIndex + 1)); |
|
|
|
|
|
console.log("JSON解析成功,解析后类型:", typeof parsedMessage, parsedMessage); |
|
|
|
|
|
if (parsedMessage.type === "daily_data") { |
|
|
|
|
|
timeData.value = parsedMessage.data; |
|
|
|
|
|
stockInformation.value.lastDayStockClosePrice = parsedMessage.pre_close; |
|
|
|
|
|
console.log("lastDayStockClosePrice", stockInformation.value.lastDayStockClosePrice); |
|
|
|
|
|
drawChart(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
// 通过了JSON解析判断,说明返回的数据是需要的正确数据,进行股票实时数据检查 |
|
|
|
|
|
console.log("开始处理解析后的数据"); |
|
|
|
|
|
|
|
|
|
|
|
// 检查是否是股票数据(支持batch_data_chunk和batch_realtime_data两种类型) |
|
|
|
|
|
if ((parsedMessage.type === "batch_data_chunk" || parsedMessage.type === "batch_realtime_data") && parsedMessage.data) { |
|
|
|
|
|
console.log("开始更新TCP股票数据存储"); |
|
|
|
|
|
// 更新TCP股票数据存储 |
|
|
|
|
|
tcpStockData.value = { |
|
|
|
|
|
count: parsedMessage.count || 0, |
|
|
|
|
|
data: parsedMessage.data || {}, |
|
|
|
|
|
stock_count: parsedMessage.stock_count || 0, |
|
|
|
|
|
timestamp: parsedMessage.timestamp || "", |
|
|
|
|
|
type: parsedMessage.type || "", |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 获取第一个股票的数据用于显示 |
|
|
|
|
|
const stockCodes = Object.keys(parsedMessage.data); |
|
|
|
|
|
if (stockCodes.length > 0) { |
|
|
|
|
|
const firstStockCode = stockCodes[0]; |
|
|
|
|
|
|
|
|
|
|
|
// 检查数据结构 |
|
|
|
|
|
if (parsedMessage.data[firstStockCode] && Array.isArray(parsedMessage.data[firstStockCode]) && parsedMessage.data[firstStockCode].length > 0) { |
|
|
|
|
|
const stockData = parsedMessage.data[firstStockCode][0]; // 取第一条数据 |
|
|
|
|
|
|
|
|
|
|
|
if (stockData && stockData.current_price !== undefined && stockData.pre_close !== undefined) { |
|
|
|
|
|
// 计算涨跌幅 |
|
|
|
|
|
const changeValue = stockData.current_price - stockData.pre_close; |
|
|
|
|
|
const changePercent = ((changeValue / stockData.pre_close) * 100).toFixed(2); |
|
|
|
|
|
const changeSign = changeValue >= 0 ? "+" : ""; |
|
|
|
|
|
|
|
|
|
|
|
// 更新当前显示的股票信息 |
|
|
|
|
|
currentStockInfo.value = { |
|
|
|
|
|
stock_name: stockData.stock_name || "未知股票", |
|
|
|
|
|
current_price: stockData.current_price ? stockData.current_price.toFixed(2) : "0.00", |
|
|
|
|
|
change: `${changeSign}${changePercent}%`, |
|
|
|
|
|
change_value: changeValue, |
|
|
|
|
|
change_percent: parseFloat(changePercent), |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
console.log("股票数据更新成功:", currentStockInfo.value); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("不是batch_data_chunk或batch_realtime_data类型的消息,跳过处理"); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// 没有通过JSON解析判断,说明不是需要的数据 |
|
|
|
|
|
console.log("不是需要的数据,不做处理"); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error("解析TCP股票数据失败:", error.message); |
|
|
|
|
|
console.error("错误详情:", error); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 移除TCP监听器 |
|
|
|
|
|
const removeTcpListeners = () => { |
|
|
|
|
|
if (connectionListener.value) { |
|
|
|
|
|
tcpConnection.removeConnectionListener(connectionListener.value); |
|
|
|
|
|
connectionListener.value = null; |
|
|
|
|
|
console.log("已移除TCP连接状态监听器"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (messageListener.value) { |
|
|
|
|
|
tcpConnection.removeMessageListener(messageListener.value); |
|
|
|
|
|
messageListener.value = null; |
|
|
|
|
|
console.log("已移除TCP消息监听器"); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// 定时器标识(用于清除定时器) |
|
|
// 定时器标识(用于清除定时器) |
|
|
let timer = null; |
|
|
let timer = null; |
|
|
let index = 0; |
|
|
let index = 0; |
|
|
@ -1544,8 +1752,8 @@ onLoad((options) => { |
|
|
|
|
|
|
|
|
// 更新stockInformation |
|
|
// 更新stockInformation |
|
|
if (stockData) { |
|
|
if (stockData) { |
|
|
stockInformation.value.stockName=stockData.stockName; |
|
|
|
|
|
stockInformation.value.stockCode=stockData.stockCode; |
|
|
|
|
|
|
|
|
stockInformation.value.stockName = stockData.stockName; |
|
|
|
|
|
stockInformation.value.stockCode = stockData.stockCode; |
|
|
} |
|
|
} |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("解析股票数据失败:", error); |
|
|
console.error("解析股票数据失败:", error); |
|
|
@ -1562,7 +1770,7 @@ onLoad((options) => { |
|
|
if (stockData) { |
|
|
if (stockData) { |
|
|
stockInformation.value = { |
|
|
stockInformation.value = { |
|
|
...stockInformation.value, |
|
|
...stockInformation.value, |
|
|
...stockData |
|
|
|
|
|
|
|
|
...stockData, |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
@ -1589,39 +1797,43 @@ onUnmounted(() => { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
onMounted(async () => { |
|
|
onMounted(async () => { |
|
|
// 获取系统信息,处理高清屏 |
|
|
|
|
|
const systemInfo = uni.getSystemInfoSync(); |
|
|
|
|
|
pixelRatio.value = systemInfo.pixelRatio; |
|
|
|
|
|
// 设置Canvas实际像素(考虑pixelRatio以获得高清效果) |
|
|
|
|
|
// 1rpx = 设备屏幕宽度 / 750 |
|
|
|
|
|
const rpxToPx = systemInfo.windowWidth / 750; |
|
|
|
|
|
const offsetHeight = (150 + 200 + 80 + 150 + 30) * rpxToPx; // 350rpx转换为px |
|
|
|
|
|
const calculatedHeight = systemInfo.windowHeight - offsetHeight; |
|
|
|
|
|
canvasWidth.value = systemInfo.windowWidth; |
|
|
|
|
|
canvasHeight.value = Math.max(calculatedHeight, canvasHeight.value); |
|
|
|
|
|
// startTcp(); |
|
|
|
|
|
// timeData.value = testTimeData; |
|
|
|
|
|
timeData.value = testTimeData.slice(0, 100); |
|
|
|
|
|
klineData.value = testKlineData; |
|
|
|
|
|
// klineData.value = testKlineData.slice(-touchState.baseVisibleCount); |
|
|
|
|
|
// 前一日收盘价 |
|
|
|
|
|
let prevClosePrice = timeData.value[timeData.value.length - 2].price || stockInformation.value.closePrice; |
|
|
|
|
|
stockInformation.value.lastDayStockClosePrice = prevClosePrice; |
|
|
|
|
|
// 当前股价 |
|
|
|
|
|
stockInformation.value.currentPrice = timeData.value[timeData.value.length - 1].price; |
|
|
|
|
|
// 涨跌额度 |
|
|
|
|
|
stockInformation.value.currentValue = stockInformation.value.currentPrice - stockInformation.value.lastDayStockClosePrice; |
|
|
|
|
|
// 涨跌幅度 |
|
|
|
|
|
stockInformation.value.currentRatio = ((stockInformation.value.currentPrice - stockInformation.value.lastDayStockClosePrice) / stockInformation.value.lastDayStockClosePrice) * 100; |
|
|
|
|
|
// 成交量 |
|
|
|
|
|
stockInformation.value.volume = timeData.value[timeData.value.length - 1].volume; |
|
|
|
|
|
text[0][1].value = utils.formatPrice(stockInformation.value.currentPrice); |
|
|
|
|
|
text[1][0].value = utils.formatStockNumber(stockInformation.value.volume); |
|
|
|
|
|
|
|
|
|
|
|
await nextTick(); |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
console.log("步骤1: 初始化系统信息"); |
|
|
|
|
|
const systemInfo = uni.getSystemInfoSync(); |
|
|
|
|
|
pixelRatio.value = systemInfo.pixelRatio; |
|
|
|
|
|
// 设置Canvas实际像素(考虑pixelRatio以获得高清效果) |
|
|
|
|
|
// 1rpx = 设备屏幕宽度 / 750 |
|
|
|
|
|
const rpxToPx = systemInfo.windowWidth / 750; |
|
|
|
|
|
const offsetHeight = (150 + 200 + 80 + 150 + 30) * rpxToPx; // 350rpx转换为px |
|
|
|
|
|
const calculatedHeight = systemInfo.windowHeight - offsetHeight; |
|
|
|
|
|
canvasWidth.value = systemInfo.windowWidth; |
|
|
|
|
|
canvasHeight.value = Math.max(calculatedHeight, canvasHeight.value); |
|
|
|
|
|
|
|
|
|
|
|
initTcpListeners(); |
|
|
|
|
|
await nextTick(); |
|
|
|
|
|
// 开始连接 |
|
|
|
|
|
startTcp(); |
|
|
|
|
|
|
|
|
|
|
|
if (timeData.value && timeData.value.length > 0) { |
|
|
|
|
|
// 当前股价 |
|
|
|
|
|
stockInformation.value.currentPrice = timeData.value[timeData.value.length - 1].price; |
|
|
|
|
|
// 涨跌额度 |
|
|
|
|
|
stockInformation.value.currentValue = stockInformation.value.currentPrice - stockInformation.value.lastDayStockClosePrice; |
|
|
|
|
|
// 涨跌幅度 |
|
|
|
|
|
stockInformation.value.currentRatio = ((stockInformation.value.currentPrice - stockInformation.value.lastDayStockClosePrice) / stockInformation.value.lastDayStockClosePrice) * 100; |
|
|
|
|
|
// 成交量 |
|
|
|
|
|
stockInformation.value.volume = timeData.value[timeData.value.length - 1].volume; |
|
|
|
|
|
text[0][1].value = utils.formatPrice(stockInformation.value.currentPrice); |
|
|
|
|
|
text[1][0].value = utils.formatStockNumber(stockInformation.value.volume); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn("没有时间数据,跳过股票信息计算"); |
|
|
|
|
|
} |
|
|
|
|
|
await nextTick(); |
|
|
initCanvas(); |
|
|
initCanvas(); |
|
|
}, 200); |
|
|
|
|
|
|
|
|
console.log("所有初始化步骤完成"); |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error("初始化过程中出现错误:", error); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
</script> |
|
|
</script> |
|
|
|
|
|
|
|
|
|