Browse Source

我的自选tcp连接完成;tcp连接方法有修改;home页允许两个连接存在,并且是分别操作;

zhaowenkang/feature-20251028181547-行情页面
宋杰 4 weeks ago
parent
commit
bd49d785f6
  1. 60
      api/tcpConnection.js
  2. 621
      pages/home/home.vue

60
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);
}

621
pages/home/home.vue

@ -82,24 +82,37 @@
<text class="section-title">我的自选</text>
<text class="more-btn">添加自选股</text>
</view>
<!-- 我的自选TCP连接状态和控制 -->
<!-- <view class="my-stocks-tcp-control">
<view class="tcp-status" :class="{'connected': myStocksTcpConnected, 'disconnected': !myStocksTcpConnected}">
<text class="status-text">{{myStocksTcpConnected ? '自选已连接' : '自选未连接'}}</text>
</view>
<view class="tcp-buttons">
<button class="tcp-btn connect-btn" @click="connectMyStocksTcp" :disabled="myStocksTcpConnected">连接</button>
<button class="tcp-btn disconnect-btn" @click="disconnectMyStocksTcp" :disabled="!myStocksTcpConnected">断开</button>
</view>
</view> -->
</view>
<!-- 下部分股票列表 -->
<view class="stock-container">
<view class="stock-list">
<view class="stock-item" v-for="(item, index) in myStocks" :key="item.code">
<!-- 如果有TCP数据显示实时数据否则显示静态数据 -->
<view class="stock-item" v-for="(item, index) in (myStocksInfoList.length > 0 ? myStocksInfoList : myStocks)" :key="item.code || item.stock_code">
<view class="stock-info">
<view class="name-container">
<text class="stock-name">{{item.name}}</text>
<text class="stock-code-label">{{item.code}}</text>
<text class="stock-name">{{item.name || item.stock_name}}</text>
<text class="stock-code-label">{{item.code || item.stock_code}}</text>
</view>
<view class="price-container">
<text class="stock-price">{{item.price}}</text>
<text class="stock-change" :class="{'stock-up': item.change > 0, 'stock-down': item.change < 0}">{{item.change > 0 ? '+' : ''}}{{item.change}}%</text>
<text class="stock-price">{{item.price || item.current_price}}</text>
<text class="stock-change" :class="{'stock-up': (item.change_percent || item.change || item.change_amount || 0) > 0, 'stock-down': (item.change_percent || item.change || item.change_amount || 0) < 0}">
{{(item.change_percent || item.change || item.change_amount || 0) > 0 ? '+' : ''}}{{(parseFloat(item.change_percent || item.change || item.change_amount || 0)).toFixed(2)}}%
</text>
</view>
</view>
<view class="stock-chart">
<image :src="item.chartImg" mode="aspectFit" class="chart-image"></image>
<image :src="item.chartImg || '/static/c5.png'" mode="aspectFit" class="chart-image"></image>
</view>
</view>
</view>
@ -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 //
},
// 3MarketOverview
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(() => {
// TCPchannel 1
console.log('连接今日市场概览TCP(channel 1)...')
this.connectTcp()
// TCPchannel 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-8GBK
}
)
},
// TCP
disconnectMyStocksTcp() {
console.log('断开我的自选TCP连接...')
tcpConnection.disconnect(
{
ip: '192.168.1.9',
port: '8080',
channel: '2', // 使channel 2
charsetname: 'UTF-8' // UTF-8GBK
}
)
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('homeTCP:', 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 2TCP
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_chunkbatch_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;
}
</style>
Loading…
Cancel
Save