diff --git a/api/tcpConnection.js b/api/tcpConnection.js index ffe9d88..4c5c426 100644 --- a/api/tcpConnection.js +++ b/api/tcpConnection.js @@ -19,7 +19,7 @@ const TCP_CONFIG = { */ class TCPConnection { constructor() { - this.isConnected = false; + this.channelConnections = new Map(); // 存储每个channel的连接状态 this.connectionCallbacks = []; this.messageCallbacks = []; } @@ -30,9 +30,11 @@ class TCPConnection { * @param {Function} callback - 连接状态回调函数 */ connect(config = {}, callback = null) { - // 如果已经连接,先断开现有连接 - if (this.isConnected) { - console.log('检测到现有TCP连接,先断开...'); + const channel = config.channel || TCP_CONFIG.channel; + + // 如果该channel已经连接,先断开现有连接 + if (this.channelConnections.get(channel)) { + console.log(`检测到channel ${channel}现有TCP连接,先断开...`); this.disconnect(config); // 等待断开完成后再连接 setTimeout(() => { @@ -73,20 +75,20 @@ class TCPConnection { */ if (result.status == '0') { // TCP连接成功 - this.isConnected = true; - console.log('TCP连接成功'); - this._notifyConnectionCallbacks('connected', result); + this.channelConnections.set(connectionConfig.channel, true); + console.log(`TCP连接成功 - Channel ${connectionConfig.channel}`); + this._notifyConnectionCallbacks('connected', result, connectionConfig.channel); } else if (result.status == '1') { // TCP断开连接 - this.isConnected = false; - console.log('TCP断开连接'); - this._notifyConnectionCallbacks('disconnected', result); + this.channelConnections.set(connectionConfig.channel, false); + console.log(`TCP断开连接 - Channel ${connectionConfig.channel}`); + this._notifyConnectionCallbacks('disconnected', result, connectionConfig.channel); } if (result.receivedMsg) { // 服务器返回字符串 console.log('收到字符串消息:', result.receivedMsg); - this._notifyMessageCallbacks('string', result.receivedMsg); + this._notifyMessageCallbacks('string', result.receivedMsg, null, connectionConfig.channel); } // if (result.receivedHexMsg) { @@ -117,8 +119,10 @@ class TCPConnection { * @param {Object} config - 发送配置 {channel, charsetname} */ send(message, config = {}) { - if (!this.isConnected) { - console.warn('TCP未连接,无法发送消息'); + const channel = config.channel || '1'; + + if (!this.channelConnections.get(channel)) { + console.warn(`TCP Channel ${channel}未连接,无法发送消息`); return false; } @@ -148,13 +152,14 @@ class TCPConnection { * @param {Object} config - 断开配置 {channel} */ disconnect(config = {}) { + const channel = config.channel || TCP_CONFIG.channel; const disconnectConfig = { - channel: config.channel || TCP_CONFIG.channel + channel: channel }; TCPSocket.disconnect(disconnectConfig); - this.isConnected = false; - console.log('TCP连接已断开', disconnectConfig); + this.channelConnections.set(channel, false); + console.log(`TCP连接已断开 - Channel ${channel}`, disconnectConfig); } /** @@ -201,20 +206,29 @@ class TCPConnection { /** * 获取连接状态 - * @returns {Boolean} 连接状态 + * @param {String} channel - 要检查的channel,如果不指定则返回所有channel的连接状态 + * @returns {Boolean|Object} 连接状态 */ - getConnectionStatus() { - return this.isConnected; + getConnectionStatus(channel = null) { + if (channel) { + return this.channelConnections.get(channel) || false; + } + // 返回所有channel的连接状态 + const allConnections = {}; + for (const [ch, status] of this.channelConnections) { + allConnections[ch] = status; + } + return allConnections; } /** * 通知连接状态回调 * @private */ - _notifyConnectionCallbacks(status, result) { + _notifyConnectionCallbacks(status, result, channel) { this.connectionCallbacks.forEach(callback => { try { - callback(status, result); + callback(status, result, channel); } catch (error) { console.error('连接状态回调执行错误:', error); } @@ -225,10 +239,10 @@ class TCPConnection { * 通知消息回调 * @private */ - _notifyMessageCallbacks(type, message, parsedArray = null) { + _notifyMessageCallbacks(type, message, parsedArray = null, channel = null) { this.messageCallbacks.forEach(callback => { try { - callback(type, message, parsedArray); + callback(type, message, parsedArray, channel); } catch (error) { console.error('消息回调执行错误:', error); } diff --git a/pages/home/home.vue b/pages/home/home.vue index bd32e6b..92f54cf 100644 --- a/pages/home/home.vue +++ b/pages/home/home.vue @@ -82,24 +82,37 @@ 我的自选 添加自选股 + + - + + - {{item.name}} - {{item.code}} + {{item.name || item.stock_name}} + {{item.code || item.stock_code}} - {{item.price}} - {{item.change > 0 ? '+' : ''}}{{item.change}}% + {{item.price || item.current_price}} + + {{(item.change_percent || item.change || item.change_amount || 0) > 0 ? '+' : ''}}{{(parseFloat(item.change_percent || item.change || item.change_amount || 0)).toFixed(2)}}% + - + @@ -222,6 +235,9 @@ export default { tcpMessages: [], lastSentMessage: '', + // 我的自选TCP连接状态 + myStocksTcpConnected: false, + // TCP监听器引用,用于移除监听器 connectionListener: null, messageListener: null, @@ -235,6 +251,15 @@ export default { type: '' }, + // 我的自选TCP股票数据存储 + myStocksTcpData: { + count: 0, + data: {}, + stock_count: 0, + timestamp: '', + type: '' + }, + // TCP数据缓存机制,用于处理分片数据 tcpDataCache: { isCollecting: false, // 是否正在收集数据片段 @@ -247,6 +272,18 @@ export default { isWaitingSecondPart: false // 是否正在等待后半部分数据 }, + // 我的自选TCP数据缓存机制,用于处理分片数据 + myStocksTcpDataCache: { + isCollecting: false, // 是否正在收集数据片段 + expectedCount: 0, // 期望的数据总数 + collectedData: {}, // 已收集的数据对象(用于对象级拼接) + timestamp: '', // 数据时间戳 + type: '', // 数据类型 + // 字符串片段缓存 + firstPartData: '', // 前半部分数据字符串 + isWaitingSecondPart: false // 是否正在等待后半部分数据 + }, + // 当前显示的3个股票数据(用于MarketOverview组件) currentStockInfoList: [ { @@ -270,7 +307,10 @@ export default { change_value: 0, change_percent: 0 } - ] + ], + + // 我的自选处理后的股票信息列表 + myStocksInfoList: [] } }, @@ -297,22 +337,50 @@ export default { // 初始化TCP连接监听器 this.initTcpListeners() - // 页面渲染完成后自动连接TCP + // 页面渲染完成后自动连接两个TCP连接 this.$nextTick(() => { console.log('页面渲染完成,开始自动连接TCP服务器...') - this.connectTcp() + // 延迟一小段时间确保页面完全加载后再连接 + setTimeout(() => { + // 连接今日市场概览TCP(channel 1) + console.log('连接今日市场概览TCP(channel 1)...') + this.connectTcp() + + // 稍微延迟后连接我的自选TCP(channel 2) + setTimeout(() => { + console.log('连接我的自选TCP(channel 2)...') + this.connectMyStocksTcp() + }, 500) + }, 1000) }) }, // 页面销毁前的清理工作 onUnload() { - // 自动关闭TCP连接 + // 自动关闭主TCP连接 if (this.tcpConnected) { - console.log('页面销毁,自动关闭TCP连接') - tcpConnection.disconnect() + console.log('页面销毁,自动关闭主TCP连接') + tcpConnection.disconnect({ + ip: '192.168.1.9', + port: '8080', + channel: '1', + charsetname: 'UTF-8' + }) this.tcpConnected = false } + // 自动关闭我的自选TCP连接 + if (this.myStocksTcpConnected) { + console.log('页面销毁,自动关闭我的自选TCP连接') + tcpConnection.disconnect({ + ip: '192.168.1.9', + port: '8080', + channel: '2', + charsetname: 'UTF-8' + }) + this.myStocksTcpConnected = false + } + // 清理防抖定时器 if (this.debounceTimer) { clearTimeout(this.debounceTimer) @@ -338,43 +406,79 @@ export default { // 初始化TCP监听器 initTcpListeners() { // 创建连接状态监听器并保存引用 - this.connectionListener = (status, result) => { - this.tcpConnected = (status === 'connected') - console.log('TCP连接状态变化:', status, this.tcpConnected) + this.connectionListener = (status, result, channel) => { + console.log('TCP连接状态变化:', status, 'channel:', channel) - // 显示连接状态提示 - uni.showToast({ - title: status === 'connected' ? '连接服务器成功' : '服务器连接断开', - icon: status === 'connected' ? 'success' : 'none', - duration: 1000 - }) - - // 连接成功后自动发送股票数据请求命令 - if (status === 'connected') { - console.log('TCP连接成功,自动发送股票数据请求...') - // 延迟一小段时间确保连接稳定后再发送命令 - setTimeout(() => { - this.sendTcpMessage() - }, 500) + // 根据channel更新对应的连接状态 + if (channel === '1') { + // 主TCP连接 + this.tcpConnected = (status === 'connected') + console.log('主TCP连接状态:', this.tcpConnected) + + // 显示连接状态提示 + uni.showToast({ + title: status === 'connected' ? '主连接服务器成功' : '主服务器连接断开', + icon: status === 'connected' ? 'success' : 'none', + duration: 1000 + }) + + // 连接成功后自动发送股票数据请求命令 + if (status === 'connected') { + console.log('主TCP连接成功,自动发送股票数据请求...') + // 延迟一小段时间确保连接稳定后再发送命令 + setTimeout(() => { + this.sendTcpMessage() + }, 500) + } + } else if (channel === '2') { + // 我的自选TCP连接 + this.myStocksTcpConnected = (status === 'connected') + console.log('我的自选TCP连接状态:', this.myStocksTcpConnected) + + // 显示连接状态提示 + uni.showToast({ + title: status === 'connected' ? '我的自选连接成功' : '我的自选连接断开', + icon: status === 'connected' ? 'success' : 'none', + duration: 1000 + }) + + // 连接成功后自动发送我的自选股票数据请求 + if (status === 'connected') { + console.log('我的自选TCP连接成功,自动发送自选股票数据请求...') + // 延迟一小段时间确保连接稳定后再发送命令 + setTimeout(() => { + this.sendMyStocksTcpMessage() + }, 500) + } } } // 创建消息监听器并保存引用 - this.messageListener = (type, message, parsedArray) => { + this.messageListener = (type, message, parsedArray, channel) => { const messageObj = { type: type, content: message, parsedArray: parsedArray, + channel: channel, timestamp: new Date().toLocaleTimeString(), direction: 'received' } - console.log("0000") this.tcpMessages.push(messageObj) - // console.log('收到TCP消息:', messageObj) - console.log('home开始调用parseStockData',messageObj) + console.log('收到TCP消息:', messageObj) + console.log('消息来源channel:', channel) - // 解析股票数据 - this.parseStockData(message) + // 根据channel调用相应的数据处理方法 + if (channel === '1') { + // 主TCP连接 - 今日市场概览数据 + // console.log('处理今日市场概览数据') + this.parseStockData(message) + } else if (channel === '2') { + // 我的自选TCP连接 - 我的自选数据 + console.log('处理我的自选数据') + this.parseMyStocksData(message) + } else { + console.warn('未知的channel:', channel) + } } // 注册监听器 @@ -384,11 +488,11 @@ export default { // 连接TCP服务器 connectTcp() { - console.log('开始连接TCP服务器...') + // console.log('开始连接TCP服务器...') // 先断开现有连接(如果存在) if (this.tcpConnected) { - console.log('检测到现有连接,先断开...') + // console.log('检测到现有连接,先断开...') this.disconnectTcp() // 等待断开完成后再连接 setTimeout(() => { @@ -402,7 +506,7 @@ export default { // 执行TCP连接 performTcpConnect() { - console.log('执行TCP连接...') + // console.log('执行TCP连接...') tcpConnection.connect( { ip: '192.168.1.9', @@ -415,7 +519,7 @@ export default { // 断开TCP连接 disconnectTcp() { - console.log('断开TCP连接...') + // console.log('断开TCP连接...') tcpConnection.disconnect( { ip: '192.168.1.9', @@ -427,6 +531,321 @@ export default { this.tcpConnected = false }, + // 连接我的自选TCP服务器 + connectMyStocksTcp() { + console.log('开始连接我的自选TCP服务器...') + + // 先断开现有连接(如果存在) + if (this.myStocksTcpConnected) { + console.log('检测到我的自选现有连接,先断开...') + this.disconnectMyStocksTcp() + // 等待断开完成后再连接 + setTimeout(() => { + this.performMyStocksTcpConnect() + }, 500) + } else { + // 直接连接 + this.performMyStocksTcpConnect() + } + }, + + // 执行我的自选TCP连接 + performMyStocksTcpConnect() { + console.log('执行我的自选TCP连接...') + tcpConnection.connect( + { + ip: '192.168.1.9', + port: '8080', + channel: '2', // 我的自选使用channel 2 + charsetname: 'UTF-8' // 默认UTF-8,可选GBK + } + ) + }, + + // 断开我的自选TCP连接 + disconnectMyStocksTcp() { + console.log('断开我的自选TCP连接...') + tcpConnection.disconnect( + { + ip: '192.168.1.9', + port: '8080', + channel: '2', // 我的自选使用channel 2 + charsetname: 'UTF-8' // 默认UTF-8,可选GBK + } + ) + this.myStocksTcpConnected = false + }, + + // 解析我的自选TCP股票数据 + parseMyStocksData(message) { + try { + console.log('进入parseMyStocksData, message类型:', typeof message, '长度:', message.length) + + // 第一步:检查数据状态(完整、前半部分、后半部分) + const dataStatus = this.getMyStocksDataStatus(message) + + let completeMessage = '' + + switch (dataStatus) { + case 'complete': + // 完整数据,直接处理 + console.log('我的自选:检测到完整数据,直接处理') + completeMessage = message + break + + case 'first_part': + // 前半部分数据,缓存并等待后半部分 + console.log('我的自选:检测到前半部分数据,开始缓存') + this.cacheMyStocksFirstPartData(message) + return // 等待后半部分数据 + + case 'second_part': + // 后半部分数据,检查是否有缓存的前半部分 + if (this.myStocksTcpDataCache.isWaitingSecondPart) { + console.log('我的自选:检测到后半部分数据,开始拼接') + completeMessage = this.concatenateMyStocksDataParts(message) + } else { + console.log('我的自选:收到后半部分数据,但没有缓存的前半部分,跳过处理') + return + } + break + + case 'invalid': + default: + console.log('我的自选:数据格式无效,跳过处理') + return + } + + // 第二步:解析完整的JSON数据 + let parsedMessage + try { + console.log('我的自选:开始解析完整JSON数据,长度:', completeMessage.length) + parsedMessage = JSON.parse(completeMessage) + console.log('我的自选:JSON解析成功,解析后类型:', typeof parsedMessage, parsedMessage) + } catch (parseError) { + console.error('我的自选:JSON解析失败:', parseError.message) + // 清空字符串片段缓存 + this.clearMyStocksStringFragmentCache() + return + } + + // 第三步:检查是否是股票数据类型 + if (!((parsedMessage.type === 'batch_data_chunk' || parsedMessage.type === 'batch_realtime_data') && parsedMessage.data)) { + console.log('我的自选:不是batch_data_chunk或batch_realtime_data类型的消息,跳过处理') + return + } + + console.log('我的自选:开始处理股票数据') + + // 第四步:验证数据完整性(对象级别的完整性检查) + // 注意:batch_data_chunk类型的数据不需要验证完整性,直接处理 + if (parsedMessage.type === 'batch_data_chunk') { + console.log('我的自选:batch_data_chunk类型数据,跳过完整性验证,直接处理') + this.processCompleteMyStocksData(parsedMessage) + } else { + const isDataComplete = this.validateMyStocksDataIntegrity(parsedMessage) + + if (isDataComplete) { + // 数据完整,直接处理 + console.log('我的自选:对象级数据完整,直接处理') + this.processCompleteMyStocksData(parsedMessage) + } else { + // 数据不完整,需要拼接(对象级别的拼接) + console.log('我的自选:对象级数据不完整,开始拼接处理') + + // 将当前数据合并到缓存中 + this.mergeMyStocksDataToCache(parsedMessage) + + // 检查缓存中的数据是否已经完整 + if (this.isMyStocksCacheDataComplete()) { + console.log('我的自选:缓存数据已完整,开始处理') + const completeData = this.getCompleteMyStocksDataFromCache() + this.processCompleteMyStocksData(completeData) + } else { + console.log('我的自选:缓存数据仍不完整,等待更多数据片段') + } + } + } + } catch (error) { + console.error('我的自选:解析TCP股票数据失败:', error.message) + console.error('我的自选:错误详情:', error) + // 发生错误时清空所有缓存 + this.clearMyStocksStringFragmentCache() + if (this.myStocksTcpDataCache.isCollecting) { + console.log('我的自选:发生错误,清空对象级数据缓存') + this.myStocksTcpDataCache.isCollecting = false + this.myStocksTcpDataCache.expectedCount = 0 + this.myStocksTcpDataCache.collectedData = {} + this.myStocksTcpDataCache.timestamp = '' + this.myStocksTcpDataCache.type = '' + } + } + }, + + // 验证我的自选数据完整性 + validateMyStocksDataIntegrity(parsedMessage) { + if (!parsedMessage.count || !parsedMessage.data) { + return false + } + + const dataObjectCount = Object.keys(parsedMessage.data).length + const expectedCount = parsedMessage.count + + console.log(`我的自选数据完整性验证: 期望${expectedCount}个对象,实际${dataObjectCount}个对象`) + return dataObjectCount === expectedCount + }, + + // 检查我的自选数据状态(完整数据、前半部分数据、后半部分数据) + getMyStocksDataStatus(message) { + if (typeof message !== 'string') { + return 'invalid' + } + + const trimmedMessage = message.trim() + const startsWithBrace = trimmedMessage.startsWith('{') + const endsWithBrace = trimmedMessage.endsWith('}') + + if (startsWithBrace && endsWithBrace) { + // 以{开头,以}结尾 - 完整数据 + console.log('我的自选:检测到完整数据格式') + return 'complete' + } else if (startsWithBrace && !endsWithBrace) { + // 以{开头,不以}结尾 - 前半部分数据 + console.log('我的自选:检测到前半部分数据') + return 'first_part' + } else if (!startsWithBrace && endsWithBrace) { + // 不以{开头,以}结尾 - 后半部分数据 + console.log('我的自选:检测到后半部分数据') + return 'second_part' + } else { + // 其他情况 - 无效数据 + console.log('我的自选:检测到无效数据格式') + return 'invalid' + } + }, + + // 缓存我的自选前半部分数据 + cacheMyStocksFirstPartData(message) { + this.myStocksTcpDataCache.firstPartData = message.trim() + this.myStocksTcpDataCache.isWaitingSecondPart = true + console.log('我的自选:已缓存前半部分数据,长度:', this.myStocksTcpDataCache.firstPartData.length) + }, + + // 拼接我的自选前后两部分数据 + concatenateMyStocksDataParts(secondPartMessage) { + const completeMessage = this.myStocksTcpDataCache.firstPartData + secondPartMessage.trim() + console.log('我的自选:数据拼接完成,完整数据长度:', completeMessage.length) + + // 清空缓存 + this.clearMyStocksStringFragmentCache() + + return completeMessage + }, + + // 清空我的自选字符串片段缓存 + clearMyStocksStringFragmentCache() { + this.myStocksTcpDataCache.firstPartData = '' + this.myStocksTcpDataCache.isWaitingSecondPart = false + console.log('我的自选:字符串片段缓存已清空') + }, + + // 合并我的自选数据到缓存中 + mergeMyStocksDataToCache(parsedMessage) { + // 如果是第一次收集数据,初始化缓存 + if (!this.myStocksTcpDataCache.isCollecting) { + this.myStocksTcpDataCache.isCollecting = true + this.myStocksTcpDataCache.expectedCount = parsedMessage.count + this.myStocksTcpDataCache.collectedData = {} + this.myStocksTcpDataCache.timestamp = parsedMessage.timestamp + this.myStocksTcpDataCache.type = parsedMessage.type + console.log('我的自选:开始收集数据片段,期望总数:', parsedMessage.count) + } + + // 合并新数据到缓存中 + if (parsedMessage.data) { + Object.assign(this.myStocksTcpDataCache.collectedData, parsedMessage.data) + console.log('我的自选:数据片段已合并,当前已收集:', Object.keys(this.myStocksTcpDataCache.collectedData).length, '个对象') + } + }, + + // 检查我的自选缓存数据是否完整 + isMyStocksCacheDataComplete() { + const collectedCount = Object.keys(this.myStocksTcpDataCache.collectedData).length + const expectedCount = this.myStocksTcpDataCache.expectedCount + + console.log(`我的自选缓存数据检查: 已收集${collectedCount}个,期望${expectedCount}个`) + return collectedCount === expectedCount && collectedCount > 0 + }, + + // 获取我的自选完整的缓存数据并清空缓存 + getCompleteMyStocksDataFromCache() { + const completeData = { + count: this.myStocksTcpDataCache.expectedCount, + data: { ...this.myStocksTcpDataCache.collectedData }, + stock_count: this.myStocksTcpDataCache.expectedCount, + timestamp: this.myStocksTcpDataCache.timestamp, + type: this.myStocksTcpDataCache.type + } + + // 清空缓存 + this.myStocksTcpDataCache.isCollecting = false + this.myStocksTcpDataCache.expectedCount = 0 + this.myStocksTcpDataCache.collectedData = {} + this.myStocksTcpDataCache.timestamp = '' + this.myStocksTcpDataCache.type = '' + + console.log('我的自选:获取完整数据并清空缓存,数据对象数:', Object.keys(completeData.data).length) + return completeData + }, + + // 处理我的自选完整的股票数据 + processCompleteMyStocksData(completeData) { + console.log("我的自选:开始更新我的自选TCP股票数据存储") + + // 更新我的自选TCP股票数据存储 + this.myStocksTcpData = { + count: completeData.count || 0, + data: completeData.data || {}, + stock_count: completeData.stock_count || 0, + timestamp: completeData.timestamp || '', + type: completeData.type || '' + } + + // 获取所有股票的数据用于显示 + const stockCodes = Object.keys(completeData.data) + const newMyStocksInfoList = [] + + // 只处理前3条股票数据 + const maxStocks = Math.min(3, stockCodes.length) + for (let i = 0; i < maxStocks; i++) { + const stockCode = stockCodes[i] + + // 检查数据结构 + if (completeData.data[stockCode] && Array.isArray(completeData.data[stockCode]) && completeData.data[stockCode].length > 0) { + const stockData = completeData.data[stockCode][0] // 取第一条数据 + console.log('遍历的数据:', stockCode, stockData) + + if (stockData && stockData.current_price !== undefined) { + // 直接使用返回的数据,不重新计算 + newMyStocksInfoList.push({ + stock_code: stockCode, + stock_name: stockData.stock_name || '未知股票', + current_price: parseFloat(stockData.current_price).toFixed(2), + change: stockData.change || '0.00%', + change_value: stockData.change_value || 0, + change_percent: parseFloat(stockData.change) || 0 + }) + } + } + } + + // 更新我的自选股票信息列表 + if (newMyStocksInfoList.length > 0) { + this.myStocksInfoList = newMyStocksInfoList + console.log('我的自选:股票数据更新成功,共', newMyStocksInfoList.length, '个股票:', this.myStocksInfoList) + } + }, + // 发送TCP消息 sendTcpMessage() { // 构造要发送的消息对象 @@ -442,7 +861,7 @@ export default { // 发送消息 const success = tcpConnection.send(messageData) if (success) { - console.log('home发送TCP消息:', messageData) + // console.log('home发送TCP消息:', messageData) uni.showToast({ title: '服务器连接成功', icon: 'success', @@ -451,6 +870,30 @@ export default { } }, + // 发送我的自选TCP消息 + sendMyStocksTcpMessage() { + // 构造要发送的消息对象 - 我的自选股票数据请求 + const messageData = {"command": "batch_real_time", "stock_codes": ["SH.000001","SH.000002","SH.000003"]} + + // 发送消息到channel 2(我的自选TCP连接) + const success = tcpConnection.send(messageData, { channel: '2' }) + if (success) { + console.log('我的自选:发送TCP消息成功:', messageData) + uni.showToast({ + title: '我的自选数据请求已发送', + icon: 'success', + duration: 1500 + }) + } else { + console.error('我的自选:发送TCP消息失败') + uni.showToast({ + title: '我的自选连接失败', + icon: 'error', + duration: 1500 + }) + } + }, + // 清空消息记录 clearTcpMessages() { @@ -481,7 +924,7 @@ export default { const dataObjectCount = Object.keys(parsedMessage.data).length const expectedCount = parsedMessage.count - console.log(`数据完整性验证: 期望${expectedCount}个对象,实际${dataObjectCount}个对象`) + // console.log(`数据完整性验证: 期望${expectedCount}个对象,实际${dataObjectCount}个对象`) return dataObjectCount === expectedCount }, @@ -497,19 +940,19 @@ export default { if (startsWithBrace && endsWithBrace) { // 以{开头,以}结尾 - 完整数据 - console.log('检测到完整数据格式') + // console.log('检测到完整数据格式') return 'complete' } else if (startsWithBrace && !endsWithBrace) { // 以{开头,不以}结尾 - 前半部分数据 - console.log('检测到前半部分数据') + // console.log('检测到前半部分数据') return 'first_part' } else if (!startsWithBrace && endsWithBrace) { // 不以{开头,以}结尾 - 后半部分数据 - console.log('检测到后半部分数据') + // console.log('检测到后半部分数据') return 'second_part' } else { // 其他情况 - 无效数据 - console.log('检测到无效数据格式') + // console.log('检测到无效数据格式') return 'invalid' } @@ -519,13 +962,13 @@ export default { cacheFirstPartData(message) { this.tcpDataCache.firstPartData = message.trim() this.tcpDataCache.isWaitingSecondPart = true - console.log('已缓存前半部分数据,长度:', this.tcpDataCache.firstPartData.length) + // console.log('已缓存前半部分数据,长度:', this.tcpDataCache.firstPartData.length) }, // 拼接前后两部分数据 concatenateDataParts(secondPartMessage) { const completeMessage = this.tcpDataCache.firstPartData + secondPartMessage.trim() - console.log('数据拼接完成,完整数据长度:', completeMessage.length) + // console.log('数据拼接完成,完整数据长度:', completeMessage.length) // 清空缓存 this.clearStringFragmentCache() @@ -537,7 +980,7 @@ export default { clearStringFragmentCache() { this.tcpDataCache.firstPartData = '' this.tcpDataCache.isWaitingSecondPart = false - console.log('字符串片段缓存已清空') + // console.log('字符串片段缓存已清空') }, // 合并数据到缓存中 @@ -549,13 +992,13 @@ export default { this.tcpDataCache.collectedData = {} this.tcpDataCache.timestamp = parsedMessage.timestamp this.tcpDataCache.type = parsedMessage.type - console.log('开始收集数据片段,期望总数:', parsedMessage.count) + // console.log('开始收集数据片段,期望总数:', parsedMessage.count) } // 合并新数据到缓存中 if (parsedMessage.data) { Object.assign(this.tcpDataCache.collectedData, parsedMessage.data) - console.log('数据片段已合并,当前已收集:', Object.keys(this.tcpDataCache.collectedData).length, '个对象') + // console.log('数据片段已合并,当前已收集:', Object.keys(this.tcpDataCache.collectedData).length, '个对象') } }, @@ -564,7 +1007,7 @@ export default { const collectedCount = Object.keys(this.tcpDataCache.collectedData).length const expectedCount = this.tcpDataCache.expectedCount - console.log(`缓存数据检查: 已收集${collectedCount}个,期望${expectedCount}个`) + // console.log(`缓存数据检查: 已收集${collectedCount}个,期望${expectedCount}个`) return collectedCount === expectedCount && collectedCount > 0 }, @@ -585,14 +1028,14 @@ export default { this.tcpDataCache.timestamp = '' this.tcpDataCache.type = '' - console.log('获取完整数据并清空缓存,数据对象数:', Object.keys(completeData.data).length) + // console.log('获取完整数据并清空缓存,数据对象数:', Object.keys(completeData.data).length) return completeData }, // 解析TCP股票数据 parseStockData(message) { try { - console.log('进入parseStockData, message类型:', typeof message, '长度:', message.length) + // console.log('进入parseStockData, message类型:', typeof message, '长度:', message.length) // 第一步:检查数据状态(完整、前半部分、后半部分) const dataStatus = this.getDataStatus(message) @@ -602,41 +1045,41 @@ export default { switch (dataStatus) { case 'complete': // 完整数据,直接处理 - console.log('检测到完整数据,直接处理') + // console.log('检测到完整数据,直接处理') completeMessage = message break case 'first_part': // 前半部分数据,缓存并等待后半部分 - console.log('检测到前半部分数据,开始缓存') + // console.log('检测到前半部分数据,开始缓存') this.cacheFirstPartData(message) return // 等待后半部分数据 case 'second_part': // 后半部分数据,检查是否有缓存的前半部分 if (this.tcpDataCache.isWaitingSecondPart) { - console.log('检测到后半部分数据,开始拼接') + // console.log('检测到后半部分数据,开始拼接') completeMessage = this.concatenateDataParts(message) } else { - console.log('收到后半部分数据,但没有缓存的前半部分,跳过处理') + // console.log('收到后半部分数据,但没有缓存的前半部分,跳过处理') return } break case 'invalid': default: - console.log('数据格式无效,跳过处理') + // console.log('数据格式无效,跳过处理') return } // 第二步:解析完整的JSON数据 let parsedMessage try { - console.log('开始解析完整JSON数据,长度:', completeMessage.length) + // console.log('开始解析完整JSON数据,长度:', completeMessage.length) parsedMessage = JSON.parse(completeMessage) - console.log('JSON解析成功,解析后类型:', typeof parsedMessage, parsedMessage) + // console.log('JSON解析成功,解析后类型:', typeof parsedMessage, parsedMessage) } catch (parseError) { - console.error('JSON解析失败:', parseError.message) + // console.error('JSON解析失败:', parseError.message) // 清空字符串片段缓存 this.clearStringFragmentCache() return @@ -644,48 +1087,48 @@ export default { // 第三步:检查是否是股票数据类型 if (!((parsedMessage.type === 'batch_data_chunk' || parsedMessage.type === 'batch_realtime_data') && parsedMessage.data)) { - console.log('不是batch_data_chunk或batch_realtime_data类型的消息,跳过处理') + // console.log('不是batch_data_chunk或batch_realtime_data类型的消息,跳过处理') return } - console.log('开始处理股票数据') + // console.log('开始处理股票数据') // 第四步:验证数据完整性(对象级别的完整性检查) // 注意:batch_data_chunk类型的数据不需要验证完整性,直接处理 if (parsedMessage.type === 'batch_data_chunk') { - console.log('batch_data_chunk类型数据,跳过完整性验证,直接处理') + // console.log('batch_data_chunk类型数据,跳过完整性验证,直接处理') this.processCompleteStockData(parsedMessage) } else { const isDataComplete = this.validateDataIntegrity(parsedMessage) if (isDataComplete) { // 数据完整,直接处理 - console.log('对象级数据完整,直接处理') + // console.log('对象级数据完整,直接处理') this.processCompleteStockData(parsedMessage) } else { // 数据不完整,需要拼接(对象级别的拼接) - console.log('对象级数据不完整,开始拼接处理') + // console.log('对象级数据不完整,开始拼接处理') // 将当前数据合并到缓存中 this.mergeDataToCache(parsedMessage) // 检查缓存中的数据是否已经完整 if (this.isCacheDataComplete()) { - console.log('缓存数据已完整,开始处理') + // console.log('缓存数据已完整,开始处理') const completeData = this.getCompleteDataFromCache() this.processCompleteStockData(completeData) } else { - console.log('缓存数据仍不完整,等待更多数据片段') + // console.log('缓存数据仍不完整,等待更多数据片段') } } } } catch (error) { - console.error('解析TCP股票数据失败:', error.message) - console.error('错误详情:', error) + // console.error('解析TCP股票数据失败:', error.message) + // console.error('错误详情:', error) // 发生错误时清空所有缓存 this.clearStringFragmentCache() if (this.tcpDataCache.isCollecting) { - console.log('发生错误,清空对象级数据缓存') + // console.log('发生错误,清空对象级数据缓存') this.tcpDataCache.isCollecting = false this.tcpDataCache.expectedCount = 0 this.tcpDataCache.collectedData = {} @@ -697,7 +1140,7 @@ export default { // 处理完整的股票数据 processCompleteStockData(completeData) { - console.log("开始更新TCP股票数据存储") + // console.log("开始更新TCP股票数据存储") // 更新TCP股票数据存储 this.tcpStockData = { @@ -741,7 +1184,7 @@ export default { // 更新当前显示的股票信息列表 if (newStockInfoList.length > 0) { this.currentStockInfoList = newStockInfoList - console.log('股票数据更新成功,共', newStockInfoList.length, '个股票:', this.currentStockInfoList) + // console.log('股票数据更新成功,共', newStockInfoList.length, '个股票:', this.currentStockInfoList) } }, @@ -750,13 +1193,13 @@ export default { if (this.connectionListener) { tcpConnection.removeConnectionListener(this.connectionListener) this.connectionListener = null - console.log('已移除TCP连接状态监听器') + // console.log('已移除TCP连接状态监听器') } if (this.messageListener) { tcpConnection.removeMessageListener(this.messageListener) this.messageListener = null - console.log('已移除TCP消息监听器') + // console.log('已移除TCP消息监听器') } } } @@ -1405,4 +1848,32 @@ export default { color: #333; word-break: break-all; } + +/* 我的自选TCP控制样式 */ +.my-stocks-tcp-control { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 8px; + padding: 8px 12px; + background-color: #f8f9fa; + border-radius: 8px; + border: 1px solid #e9ecef; +} + +.tcp-buttons { + display: flex; + gap: 6px; +} + +.my-stocks-tcp-control .tcp-btn { + flex: none; + min-width: 50px; + height: 28px; + border-radius: 4px; + font-size: 11px; + border: none; + color: white; + font-weight: bold; +} \ No newline at end of file