51 Commits

Author SHA1 Message Date
zhaowenkang 2e08839371 行情tab栏 2 months ago
zhaowenkang adfad32d1b Merge branch 'milestone-20251031-简版功能开发' into zhaowenkang/feature-20251028181547-行情页面 2 months ago
hongxilin 6f3e2bdab8 Merge branch 'hongxilin/feature-20251023103318-行情数据及页面' into milestone-20251031-简版功能开发 2 months ago
hongxilin 8d9267d63b 对接tcp全部接口,行情数据页面的左右翻页 2 months ago
宋杰 a60d29b0f2 创建了自定义的我的自选页面;点击添加自选股跳转到行情页面; 2 months ago
宋杰 19e325e83b 点击首页我的自选的查看更多跳转到对应页面; 2 months ago
宋杰 08b584483c 创建我的自选页面; 2 months ago
宋杰 86eb9a5e3e 新建今日核心看点的机构动向解析缺省页并配置跳转逻辑; 2 months ago
宋杰 ca90666703 Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into milestone-20251031-简版功能开发 2 months ago
宋杰 68715b32e5 Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 2 months ago
宋杰 c5cf0d8a9d 早盘解析缺省页面; 2 months ago
zhaowenkang 4033ca4d43 Merge branch 'milestone-20251031-简版功能开发' into zhaowenkang/feature-20251028181547-行情页面 2 months ago
lihui 7a2e448a5c Merge branch 'refs/heads/lihuilin/feature-20251024095243-我的' into milestone-20251031-简版功能开发 2 months ago
lihui 64a4aec305 add:分享跳转功能 2 months ago
宋杰 68610b43ee Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 2 months ago
宋杰 6345303249 注释掉初始化tcp连接的代码; 2 months ago
宋杰 c0cef2252c Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into milestone-20251031-简版功能开发 2 months ago
宋杰 8067177fb8 Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 2 months ago
宋杰 d0c1a19d3e 今日市场概览中点击早盘解析跳转到该页面; 2 months ago
lihui fb31937f05 Merge branch 'refs/heads/milestone-20251031-简版功能开发' into lihuilin/feature-20251024095243-我的 2 months ago
lihui bdf69e855f Merge remote-tracking branch 'origin/lihuilin/feature-20251024095243-我的' into lihuilin/feature-20251024095243-我的 2 months ago
dongqian f2981e95f1 Merge branch 'dongqian/feature-20251022181325-deepmate简版' into milestone-20251031-简版功能开发 2 months ago
dongqian b171b88fac 修改选股策略手机模拟器滚动和颜色修改 2 months ago
宋杰 5d0bdb613f Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into milestone-20251031-简版功能开发 2 months ago
宋杰 9f70c70893 Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 2 months ago
宋杰 6b7684795d 点击深度探索的查看更多跳转到对应页面; 2 months ago
hongxilin f28d600e16 删除打印语句 2 months ago
ZhangYong 56685b5011 合并 2 months ago
ZhangYong 5f2dfe5eef 历史数据对接完成 2 months ago
hongxilin a2b882746e Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into hongxilin/feature-20251023103318-行情数据及页面 2 months ago
宋杰 7cca04c21e Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 2 months ago
宋杰 4ab2074459 修改配置; 2 months ago
hongxilin 08cf2e3ba0 Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into hongxilin/feature-20251023103318-行情数据及页面 2 months ago
dongqian 769382fe25 联调选股策略接口 2 months ago
宋杰 4f4e2ef130 Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into milestone-20251031-简版功能开发 2 months ago
宋杰 842b2b766f 首页deepMate输入内容跳转到该页面并发起请求; 2 months ago
maziyang 47956e1c5b Merge branch 'maziyang/feature-20251025172218-智能客服中台' into milestone-20251031-简版功能开发 2 months ago
hongxilin dd57ceefb0 Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into hongxilin/feature-20251023103318-行情数据及页面 2 months ago
maziyang 3d0d54ef94 接口对接 2 months ago
hongxilin 5d5bc36596 marketOverview引入tcp 2 months ago
zhaowenkang 017f0b1a58 Merge branch 'milestone-20251031-简版功能开发' into zhaowenkang/feature-20251028181547-行情页面 2 months ago
lihuilin 1ae496045d 合并 2 months ago
lihuilin 3bfff8bd1e 对接完成 2 months ago
ZhangYong e578879b50 对接 2 months ago
lihui a4cc07130c add:完成微信跳转(使用的lihui的Appid),信息复制到粘贴板,自定义分享组件 2 months ago
lihui 654ec484c2 Merge branch 'refs/heads/milestone-20251031-简版功能开发' into lihuilin/feature-20251024095243-我的 2 months ago
lihui 10a8a0b96a Merge remote-tracking branch 'origin/lihuilin/feature-20251024095243-我的' into lihuilin/feature-20251024095243-我的 2 months ago
dongqian 46cd063752 接上选股策略接口 2 months ago
lihui 8af11a2392 Merge branch 'refs/heads/milestone-20251031-简版功能开发' into lihuilin/feature-20251024095243-我的 2 months ago
dongqian 62ab22e3d4 Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into dongqian/feature-20251022181325-deepmate简版 2 months ago
dongqian 8c67bea900 调选股策略接口 2 months ago
  1. 8
      .hbuilderx/launch.json
  2. 41
      App.vue
  3. 18
      api/deepExploration/deepExploration.js
  4. 8
      api/setting/general.js
  5. 19
      api/setting/market.js
  6. 15
      api/setting/share.js
  7. 234
      api/tcpConnection.js
  8. 31
      components/DeepMate.vue
  9. 3
      components/IndexCard.vue
  10. 8
      components/MarketOverview.vue
  11. 190
      components/SharePopup.vue
  12. 10
      components/deepExploration_header.vue
  13. 9
      manifest.json
  14. 32
      pages.json
  15. 55
      pages/analysisInstitutionalTrends/analysisInstitutionalTrends.vue
  16. 147
      pages/customStockList/customStockList.vue
  17. 5
      pages/customerServicePlatform/csPlatformIndex.vue
  18. 9
      pages/customerServicePlatform/historyRecord.vue
  19. 5
      pages/customerServicePlatform/questionDetail.vue
  20. 506
      pages/deepExploration/MainForceActions.vue
  21. 152
      pages/deepExploration/deepExploration.vue
  22. 328
      pages/deepExploration/stockSelectDetail.vue
  23. 21
      pages/deepMate/deepMate.vue
  24. 64
      pages/home/home.vue
  25. 1
      pages/home/member.vue
  26. 124
      pages/marketSituation/countryMarket.vue
  27. 307
      pages/marketSituation/globalIndex.vue
  28. 322
      pages/marketSituation/marketCondition.vue
  29. 340
      pages/marketSituation/marketDetail.vue
  30. 290
      pages/marketSituation/marketOverview.vue
  31. 25
      pages/marketSituation/marketSituation.vue
  32. 39
      pages/morningMarketAnalysis/morningMarketAnalysis.vue
  33. 29
      pages/setting/account.vue
  34. 11
      pages/setting/bind.vue
  35. 26
      pages/setting/createPwd.vue
  36. 48
      pages/setting/font.vue
  37. 198
      pages/setting/market.vue
  38. 10
      pages/setting/password.vue
  39. 48
      pages/setting/server.vue
  40. 396
      pages/setting/share.vue
  41. 45
      pages/setting/theme.vue
  42. BIN
      static/my/share/KakaoTalk.png
  43. BIN
      static/my/share/Line.png
  44. BIN
      static/my/share/WeChat.png
  45. BIN
      static/my/share/WhatsApp.png
  46. BIN
      static/my/share/share.png
  47. BIN
      static/my/share/success.png
  48. 55
      stores/modules/marketSituation.js
  49. 26
      vue.config.js

8
.hbuilderx/launch.json

@ -2,11 +2,13 @@
"version" : "1.0",
"configurations" : [
{
"customPlaygroundType" : "local",
"customPlaygroundType" : "device",
"packageName" : "io.dcloud.HBuilder",
"playground" : "custom",
"type" : "uni-app:app-android"
// "playground" : "standard",
// "type" : "uni-app:app-ios"
}
]
}
// "playground" : "standard",
// "type" : "uni-app:app-ios"

41
App.vue

@ -1,16 +1,33 @@
<script>
export default {
onLaunch: function() {
console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
import { useDeviceStore } from './stores/modules/deviceInfo'
export default {
onLaunch: function() {
console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
console.log('App Launch')
//
// const deviceStore = useDeviceStore()
// try {
// const sys = uni.getSystemInfoSync()
// let deviceId = ''
// // #ifdef APP-PLUS
// try { deviceId = plus?.device?.uuid || '' } catch(e) {}
// // #endif
// if (!deviceId) deviceId = uni.getStorageSync('device_id')
// if (!deviceId) {
// deviceId = `web_${Date.now()}_${Math.random().toString(36).slice(2,10)}`
// uni.setStorageSync('device_id', deviceId)
// }
// deviceStore.setDeviceInfo({ deviceId, platform: sys.platform, model: sys.model })
// console.log('Device init:', deviceStore.deviceInfo)
// } catch(e) { console.warn('Init device info failed:', e) }
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style lang="scss">

18
api/deepExploration/deepExploration.js

@ -101,8 +101,22 @@ export const RecordListApi = (data) => {
data:data
})
}
// 选股策略
export const stocSelectApi = (data) => {
return http({
method: 'POST',
url: '/api/deep/getStrategy',
data:data
})
}
//根据名字选股策略
export const stocSelectByNameApi = (data) => {
return http({
method: 'POST',
url: '/api/deep/getStrategyByName',
data:data
})
}
//历史记录详情

8
api/setting/general.js

@ -9,3 +9,11 @@ export const getSetting = (data) => {
data: data,
})
}
export const updateSetting = (data) => {
return http({
method: 'POST',
url: '/api/my/updateSetting',
data: data,
})
}

19
api/setting/market.js

@ -0,0 +1,19 @@
import { http } from '../../utils/http'
export const getMarketSetting = (data) => {
return http({
method: 'POST',
url: '/api/my/getQuotationSetting',
data: data,
})
}
export const updateMarketSetting = (data) => {
return http({
method: 'POST',
url: '/api/my/updateQuotationSetting',
data: data,
})
}

15
api/setting/share.js

@ -0,0 +1,15 @@
import { http } from '../../utils/http'
/**
* 分享接口获取dccode
* @param data
* @returns {*}
*/
export const Share = (data) => {
return http({
method: 'POST',
url: '/api/my/share',
data: data,
})
}

234
api/tcpConnection.js

@ -6,7 +6,7 @@
*/
// 引用TCP插件
const TCPSocket = uni.requireNativePlugin('Aimer-TCPPlugin');
// const TCPSocket = uni.requireNativePlugin('Aimer-TCPPlugin');
// const TCPSocket = uni.requireNativePlugin("Aimer-TCPPlugin");
// TCP连接配置
@ -21,33 +21,33 @@ const TCP_CONFIG = {
* TCP连接管理类
*/
class TCPConnection {
constructor() {
this.channelConnections = new Map(); // 存储每个channel的连接状态
this.connectionCallbacks = [];
this.messageCallbacks = [];
}
constructor() {
this.channelConnections = new Map(); // 存储每个channel的连接状态
this.connectionCallbacks = [];
this.messageCallbacks = [];
}
/**
* TCP初始化连接
* @param {Object} config - 连接配置 {ip, port, channel, charsetname}
* @param {Function} callback - 连接状态回调函数
*/
connect(config = {}, callback = null) {
const channel = config.channel || TCP_CONFIG.channel;
// 如果该channel已经连接,先断开现有连接
if (this.channelConnections.get(channel)) {
console.log(`检测到channel ${channel}现有TCP连接,先断开...`);
this.disconnect(config);
// 等待断开完成后再连接
setTimeout(() => {
this._performConnect(config, callback);
}, 300);
} else {
// 直接连接
this._performConnect(config, callback);
}
/**
* TCP初始化连接
* @param {Object} config - 连接配置 {ip, port, channel, charsetname}
* @param {Function} callback - 连接状态回调函数
*/
connect(config = {}, callback = null) {
const channel = config.channel || TCP_CONFIG.channel;
// 如果该channel已经连接,先断开现有连接
if (this.channelConnections.get(channel)) {
console.log(`检测到channel ${channel}现有TCP连接,先断开...`);
this.disconnect(config);
// 等待断开完成后再连接
setTimeout(() => {
this._performConnect(config, callback);
}, 300);
} else {
// 直接连接
this._performConnect(config, callback);
}
}
/**
* 执行TCP连接
@ -66,33 +66,31 @@ class TCPConnection {
connectionConfig.charsetname = config.charsetname || TCP_CONFIG.charsetname;
}
console.log('开始建立TCP连接:', connectionConfig);
TCPSocket.connect(
connectionConfig,
result => {
/**
* status : 0 连接成功
* status : 1 断开连接
* receivedMsg : 服务器返回字符串(普通的字符串交互)
* receivedHexMsg : 服务器返回字节数组(单片机智能家居等硬件数据交互)
*/
if (result.status == '0') {
// TCP连接成功
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.channelConnections.set(connectionConfig.channel, false);
console.log(`TCP断开连接 - Channel ${connectionConfig.channel}`);
this._notifyConnectionCallbacks('disconnected', result, connectionConfig.channel);
}
console.log("开始建立TCP连接:", connectionConfig);
TCPSocket.connect(connectionConfig, (result) => {
/**
* status : 0 连接成功
* status : 1 断开连接
* receivedMsg : 服务器返回字符串(普通的字符串交互)
* receivedHexMsg : 服务器返回字节数组(单片机智能家居等硬件数据交互)
*/
if (result.status == "0") {
// TCP连接成功
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.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, null, connectionConfig.channel);
}
if (result.receivedMsg) {
// 服务器返回字符串
console.log("收到字符串消息:", result.receivedMsg);
this._notifyMessageCallbacks("string", result.receivedMsg, null, connectionConfig.channel);
}
// if (result.receivedHexMsg) {
// // 硬件服务器返回16进制数据
@ -115,18 +113,18 @@ class TCPConnection {
});
}
/**
* TCP发送消息(普通的字符串交互)
* @param {String|Object} message - 要发送的消息如果是对象会自动转换为JSON字符串
* @param {Object} config - 发送配置 {channel, charsetname}
*/
send(message, config = {}) {
const channel = config.channel || '1';
if (!this.channelConnections.get(channel)) {
console.warn(`TCP Channel ${channel}未连接,无法发送消息`);
return false;
}
/**
* TCP发送消息(普通的字符串交互)
* @param {String|Object} message - 要发送的消息如果是对象会自动转换为JSON字符串
* @param {Object} config - 发送配置 {channel, charsetname}
*/
send(message, config = {}) {
const channel = config.channel || "1";
if (!this.channelConnections.get(channel)) {
console.warn(`TCP Channel ${channel}未连接,无法发送消息`);
return false;
}
// 如果message是对象,转换为JSON字符串
let messageStr = message;
@ -149,20 +147,20 @@ class TCPConnection {
return true;
}
/**
* TCP断开连接
* @param {Object} config - 断开配置 {channel}
*/
disconnect(config = {}) {
const channel = config.channel || TCP_CONFIG.channel;
const disconnectConfig = {
channel: channel
};
/**
* TCP断开连接
* @param {Object} config - 断开配置 {channel}
*/
disconnect(config = {}) {
const channel = config.channel || TCP_CONFIG.channel;
const disconnectConfig = {
channel: channel,
};
TCPSocket.disconnect(disconnectConfig);
this.channelConnections.set(channel, false);
console.log(`TCP连接已断开 - Channel ${channel}`, disconnectConfig);
}
TCPSocket.disconnect(disconnectConfig);
this.channelConnections.set(channel, false);
console.log(`TCP连接已断开 - Channel ${channel}`, disconnectConfig);
}
/**
* 添加连接状态监听器
@ -206,50 +204,50 @@ class TCPConnection {
}
}
/**
* 获取连接状态
* @param {String} channel - 要检查的channel如果不指定则返回所有channel的连接状态
* @returns {Boolean|Object} 连接状态
*/
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;
/**
* 获取连接状态
* @param {String} channel - 要检查的channel如果不指定则返回所有channel的连接状态
* @returns {Boolean|Object} 连接状态
*/
getConnectionStatus(channel = null) {
if (channel) {
return this.channelConnections.get(channel) || false;
}
/**
* 通知连接状态回调
* @private
*/
_notifyConnectionCallbacks(status, result, channel) {
this.connectionCallbacks.forEach(callback => {
try {
callback(status, result, channel);
} catch (error) {
console.error('连接状态回调执行错误:', error);
}
});
// 返回所有channel的连接状态
const allConnections = {};
for (const [ch, status] of this.channelConnections) {
allConnections[ch] = status;
}
return allConnections;
}
/**
* 通知消息回调
* @private
*/
_notifyMessageCallbacks(type, message, parsedArray = null, channel = null) {
this.messageCallbacks.forEach(callback => {
try {
callback(type, message, parsedArray, channel);
} catch (error) {
console.error('消息回调执行错误:', error);
}
});
}
/**
* 通知连接状态回调
* @private
*/
_notifyConnectionCallbacks(status, result, channel) {
this.connectionCallbacks.forEach((callback) => {
try {
callback(status, result, channel);
} catch (error) {
console.error("连接状态回调执行错误:", error);
}
});
}
/**
* 通知消息回调
* @private
*/
_notifyMessageCallbacks(type, message, parsedArray = null, channel = null) {
this.messageCallbacks.forEach((callback) => {
try {
callback(type, message, parsedArray, channel);
} catch (error) {
console.error("消息回调执行错误:", error);
}
});
}
}
// 创建TCP连接实例

31
components/DeepMate.vue

@ -34,8 +34,14 @@
</view>
</view>
<view class="deepmate-action">
<input class="stock-input" type="text" placeholder="请输入股票代码/名称,获取AI洞察" />
<view class="send-button-container">
<input
class="stock-input"
type="text"
placeholder="请输入股票代码/名称,获取AI洞察"
v-model="inputValue"
@confirm="handleSend"
/>
<view class="send-button-container" @click="handleSend">
<image class="send-button" src="https://d31zlh4on95l9h.cloudfront.net/images/3da018821a5c82b06a1d6ddc81b960ac.png" mode="aspectFit"></image>
</view>
</view>
@ -49,7 +55,28 @@
name: 'DeepMate',
data() {
return {
inputValue: ''
}
},
methods: {
handleSend() {
//
if (!this.inputValue.trim()) {
uni.showToast({
title: '请输入股票代码或名称',
icon: 'none',
duration: 2000
})
return
}
// deepMate
uni.navigateTo({
url: `/pages/deepMate/deepMate?query=${encodeURIComponent(this.inputValue.trim())}`
})
//
this.inputValue = ''
}
}
}

3
components/IndexCard.vue

@ -64,7 +64,6 @@ const props = defineProps({
});
const getMarketFlag = (market) => {
console.log("market", market);
let imagePath;
if (market === "cn") {
@ -86,8 +85,6 @@ const getMarketFlag = (market) => {
} else {
imagePath = "/static/marketSituation-image/country-flag/global.png";
}
console.log("返回的图片路径:", imagePath);
return imagePath;
};

8
components/MarketOverview.vue

@ -47,7 +47,7 @@
<text class="analysis-dot blue"></text>
<text class="analysis-text">市场风险评级: 需警惕潜在风险</text>
</view>
<view class="analysis-item">
<view class="analysis-item" @click="goToMorningAnalysis">
<text class="analysis-dot green"></text>
<text class="analysis-text">早盘解析: 今日高开, 芯片稀土公共</text>
</view>
@ -142,6 +142,12 @@ export default {
}
},
methods: {
//
goToMorningAnalysis() {
uni.navigateTo({
url: '/pages/morningMarketAnalysis/morningMarketAnalysis'
})
},
showMarketSelector() {
//
this.showForexMarket = !this.showForexMarket;

190
components/SharePopup.vue

@ -0,0 +1,190 @@
<!--自定义分享弹窗 使用uni的更改-->
<template>
<view class="uni-popup-share">
<!-- <view class="uni-share-title">-->
<!-- <text class="uni-share-title-text">{{ shareTitleText }}</text>-->
<!-- </view>-->
<view class="uni-share-content">
<view class="uni-share-content-box">
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index"
@click.stop="select(item,index)">
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
<text class="uni-share-text">{{ item.text }}</text>
</view>
</view>
</view>
<view class="uni-share-button-box">
<button class="uni-share-button" @click="close">{{ cancelText }}</button>
</view>
</view>
</template>
<script>
import popup from '../uni_modules/uni-popup/components/uni-popup/popup.js'
// import popup from '../uni-popup/popup.js'
import {initVueI18n} from '@dcloudio/uni-i18n'
import messages from '../uni_modules/uni-popup/components/uni-popup/i18n/index.js'
const {t} = initVueI18n(messages)
export default {
name: 'SharePopup',
mixins: [popup],
emits: ['select'],
props: {
title: {
type: String,
default: ''
},
beforeClose: {
type: Boolean,
default: false
}
},
data() {
return {
bottomData: [{
text: 'WhatsApp',
icon: '/static/my/share/WhatsApp.png',
name: 'WhatsApp'
},
{
text: 'Line',
icon: '/static/my/share/Line.png',
name: 'Line'
},
{
text: 'KakaoTalk',
icon: '/static/my/share/KakaoTalk.png',
name: 'KakaoTalk'
},
{
text: 'WeChat',
icon: '/static/my/share/WeChat.png',
name: 'WeChat'
},
{
text: '复制链接',
icon: '/static/my/share/share.png',
name: '复制链接'
},
]
}
},
created() {
},
computed: {
cancelText() {
return t("uni-popup.cancel")
},
shareTitleText() {
return this.title || t("uni-popup.shareTitle")
}
},
methods: {
/**
* 选择内容
*/
select(item, index) {
this.$emit('select', {
item,
index
})
// this.close()
},
/**
* 关闭窗口
*/
close() {
if (this.beforeClose) return
this.popup.close()
}
}
}
</script>
<style lang="scss">
.uni-popup-share {
background-color: #fff;
border-top-left-radius: 11px;
border-top-right-radius: 11px;
}
.uni-share-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
height: 40px;
}
.uni-share-title-text {
font-size: 14px;
color: #666;
}
.uni-share-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
padding-top: 10px;
}
.uni-share-content-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
flex-wrap: wrap;
width: 360px;
}
.uni-share-content-item {
width: 72px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
padding: 10px 0;
align-items: center;
}
.uni-share-content-item:active {
background-color: #f5f5f5;
}
.uni-share-image {
width: 42px;
height: 42px;
}
.uni-share-text {
margin-top: 10px;
font-size: 14px;
color: #3B4144;
}
.uni-share-button-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
padding: 10px 15px;
}
.uni-share-button {
flex: 1;
border-radius: 50px;
color: #666;
font-size: 16px;
}
.uni-share-button::after {
border-radius: 50px;
}
</style>

10
components/deepExploration_header.vue

@ -156,13 +156,19 @@ async function itemClick(item) {
model: 5,
});
if (res.code == 200) {
const message = res.data;
const deepExplorationStore = useDeepExplorationStore();
deepExplorationStore.setDeepExplorationInfo(message);
console.log('点击了历史数据',deepExplorationStore.deepExplorationInfo);
onDrawerBackClick();
console.log(deepExplorationStore.deepExplorationInfo);
setTimeout(() => {
uni.navigateTo({
url: '/pages/deepExploration/MainForceActions'
});
}, 200);
}
}
const historyList = ref([]);

9
manifest.json

@ -17,7 +17,8 @@
"delay" : 0
},
"modules" : {
"OAuth" : {}
"OAuth" : {},
"Share" : {}
},
/* */
"distribute" : {
@ -53,6 +54,12 @@
"google" : {
"clientid" : "135"
}
},
"share" : {
"weixin" : {
"appid" : "wx6143d111fc5c9ba3",
"UniversalLinks" : ""
}
}
}
},

32
pages.json

@ -88,6 +88,13 @@
}
},
{
"path" : "pages/morningMarketAnalysis/morningMarketAnalysis",
"style" :
{
"navigationBarTitleText" : "早盘解析"
}
},
{
"path": "pages/marketSituation/marketSituation",
"style": {
"navigationStyle": "custom",
@ -246,14 +253,12 @@
"path": "pages/setting/phone",
"style": {
"navigationBarTitleText": "绑定账号"
//
}
},
{
"path": "pages/setting/email",
"style": {
"navigationBarTitleText": "绑定账号"
//
}
},
{
@ -333,6 +338,29 @@
"titleNView": false,
"bounce": false
}
},
{
"path" : "pages/analysisInstitutionalTrends/analysisInstitutionalTrends",
"style" :
{
"navigationBarTitleText" : "机构动向解析 "
}
},
{
"path" : "pages/customStockList/customStockList",
"style" :
{
"navigationBarTitleText" : "我的自选",
"app-plus": {
"titleNView": false
},
"h5": {
"titleNView": false
},
"mp-weixin": {
"navigationStyle": "custom"
}
}
}
],

55
pages/analysisInstitutionalTrends/analysisInstitutionalTrends.vue

@ -0,0 +1,55 @@
<template>
<view class="container">
<view class="content">
<image
class="no-data-image"
src="https://d31zlh4on95l9h.cloudfront.net/images/f5a9bd32c81bc7cca47252b51357c12f.png"
mode="aspectFit"
></image>
<text class="no-data-text">暂无数据~</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
.container {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.no-data-image {
width: 200px;
height: 200px;
margin-bottom: 20px;
}
.no-data-text {
font-size: 16px;
color: #999999;
text-align: center;
}
</style>

147
pages/customStockList/customStockList.vue

@ -0,0 +1,147 @@
<!-- 自选股页面 -->
<template>
<view class="container">
<!-- 自定义导航栏 -->
<view class="custom-navbar">
<view class="navbar-content">
<view class="navbar-left">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
</view>
</view>
<view class="navbar-center">
<text class="navbar-title">我的自选</text>
</view>
<view class="navbar-right">
<image
class="navbar-btn"
src="https://d31zlh4on95l9h.cloudfront.net/images/ba5c8a2eda065274e868bcd9b2d7d914.png"
@click="onFirstButtonClick"
mode="aspectFit"
></image>
<image
class="navbar-btn"
src="https://d31zlh4on95l9h.cloudfront.net/images/a4ae8952aeae90dac6d2b4c221c65fa9.png"
@click="onSecondButtonClick"
mode="aspectFit"
></image>
</view>
</view>
</view>
<!-- 页面内容 -->
<view class="page-content">
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
//
goBack() {
uni.navigateBack()
},
//
onFirstButtonClick() {
console.log('第一个按钮被点击')
//
},
//
onSecondButtonClick() {
console.log('第二个按钮被点击')
//
}
}
}
</script>
<style>
.container {
width: 100%;
height: 100vh;
background-color: #f5f5f5;
}
/* 自定义导航栏 */
.custom-navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background-color: #ffffff;
border-bottom: 1px solid #e5e5e5;
}
.navbar-content {
display: flex;
align-items: center;
justify-content: space-between;
height: 44px;
padding: 0 15px;
/* 适配状态栏高度 */
padding-top: var(--status-bar-height, 20px);
min-height: calc(44px + var(--status-bar-height, 20px));
}
.navbar-left {
flex: 0 0 auto;
display: flex;
align-items: center;
}
.back-btn {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
font-size: 24px;
color: #333333;
font-weight: bold;
}
.navbar-center {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.navbar-title {
font-size: 18px;
font-weight: 500;
color: #333333;
}
.navbar-right {
flex: 0 0 auto;
display: flex;
align-items: center;
gap: 10px;
}
.navbar-btn {
width: 24px;
height: 24px;
}
/* 页面内容 */
.page-content {
padding-top: calc(44px + var(--status-bar-height, 20px) + 1px);
min-height: calc(100vh - 44px - var(--status-bar-height, 20px) - 1px);
}
</style>

5
pages/customerServicePlatform/csPlatformIndex.vue

@ -90,7 +90,6 @@
</template>
<script>
import { useUserStore } from "../../stores/modules/userInfo.js"
import {
getQuestionApi,
addFeedbackRecordApi,
@ -118,15 +117,12 @@
showQuestions: [],
feedbackText: '',
images: [],
token:''
}
},
mounted() {
//
this.iSMT = uni.getSystemInfoSync().statusBarHeight;
this.getQuestionList()
const memberStore = useUserStore()
this.token = memberStore.userInfo?.token
},
methods: {
onSuccess() {
@ -267,7 +263,6 @@
}
const [image1 = '', image2 = '', image3 = ''] = uploadedImages;
const res = await addFeedbackRecordApi({
token: this.token,
content: this.feedbackText,
image1,
image2,

9
pages/customerServicePlatform/historyRecord.vue

@ -57,7 +57,6 @@
</template>
<script>
import { useUserStore } from "../../stores/modules/userInfo.js"
import {
getFeedbackRecordsApi,
} from "../../api/customerServicePlatform/customerServicePlatform";
@ -67,14 +66,12 @@
iSMT: 0,
statusText: '反馈成功',
historyList: [],
token:''
};
},
mounted() {
this.iSMT = uni.getSystemInfoSync().statusBarHeight;
this.loadHistoryList()
const memberStore = useUserStore()
this.token = memberStore.userInfo?.token
},
methods: {
formatTime(str) {
@ -95,9 +92,7 @@
}
},
async loadHistoryList() {
const res = await getFeedbackRecordsApi({
token: this.token
})
const res = await getFeedbackRecordsApi()
console.log(res)
if (res.code == 200) {
this.historyList = res.data.map(item => {

5
pages/customerServicePlatform/questionDetail.vue

@ -62,7 +62,6 @@
</template>
<script>
import { useUserStore } from "../../stores/modules/userInfo.js"
import {
getAnswerApi
} from "../../api/customerServicePlatform/customerServicePlatform";
@ -74,14 +73,11 @@
questionTitle: '',
answerContent: '正在思考...',
showLoginRegister:false,
token:''
};
},
mounted() {
this.iSMT = uni.getSystemInfoSync().statusBarHeight || 0;
this.getAnswerContent()
const memberStore = useUserStore()
this.token = memberStore.userInfo?.token
},
onLoad(options) {
if (options.question) {
@ -106,7 +102,6 @@
const res = await getAnswerApi({
question: this.questionTitle,
conversationId: conversationId,
token:this.token
})
console.log(res)

506
pages/deepExploration/MainForceActions.vue

@ -23,24 +23,22 @@
<view class="graphAndTxt">
<view class="graph">
<view class="graph_header">
<view class="left">TESA</view>
<view class="left">{{stockCode}}</view>
<view class="center">
<image class="last" src="/static/deepExploration-images/last.png" mode="aspectFill"></image>
<text>Taewlkj.sejssssssssf</text>
<image class="next" src="/static/deepExploration-images/next.png" mode="aspectFill"></image>
<text>{{stockName}}</text>
</view>
<view class="right">2025/10/26</view>
<view class="right">{{stockTime}}</view>
</view>
<view class="graph_data">
<text>435.900</text>
<text>22.410</text>
<text>5.120%</text>
<text>{{stockPrice}}</text>
<text>{{stockChange}}</text>
<text>{{stockAdd}}</text>
</view>
<view class="graph_content">
<view class="charts-box">
<!-- uCharts 蜡烛图组件 -->
<qiun-data-charts type="candle" :opts="opts" :chartData="chartData" :disableScroll="true"
:ontouch="true" :onzoom="true" />
:ontouch="true" :onzoom="true" :key="chartKey" />
</view>
</view>
</view>
@ -65,7 +63,8 @@
<script setup>
import {
ref,
onMounted
onMounted,
watch
} from 'vue'
import deepExploration_header from '@/components/deepExploration_header.vue'
import footerBar from '@/components/footerBar.vue'
@ -87,6 +86,13 @@
import marked from 'marked'; // marked
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css'; //
import {
useDeepExplorationStore
} from '@/stores/modules/deepExploration'
const deepExplorationStore = useDeepExplorationStore()
const historyData = ref({})
//
const type = ref('deepExploration')
@ -113,10 +119,9 @@
//
const searchStock = () => {
htmlContent.value = ''
console.log('搜索参数:', stockName.value);
if (currentIndex.value ) {
handleModels()
getServerData()
console.log('搜索参数:', stockName.value, currentIndex.value);
if (currentIndex.value >= 0 && currentIndex.value <= 3) {
handleModels()
} else {
uni.showToast({
title: '请选择模块',
@ -127,20 +132,22 @@
}
//
const handleModel = async(index) => {
const handleModel = async (index) => {
htmlContent.value = ''
currentIndex.value = index
await handleModels()
// await getServerData()
}
const stockName = ref('')
const stockName = ref('Tesla Inc.')
const searchName = ref('')
const stockCode = ref('')
const stockCode = ref('TSLA')
const language = ref('')
const recordId = ref('')
const parentId = ref('')
const stockId = ref('')
const market = ref('')
const stockTime = ref('2025/10/24')
const loading = ref(true);
const error = ref('');
@ -175,52 +182,58 @@
// htmlContent.value = marked.parse(markdownContent.value);
loading.value = true;
if (searchName.value == '') {
console.log('没有搜索',searchName.value);
const rresult = await handleDefault()
// markdownContent.value = res.data.markdown
htmlContent.value = marked.parse(markdownContent.value);
}else{
console.log('搜索',searchName.value);
console.log('没有搜索', searchName.value);
handleDefault()
} else {
console.log('搜索', searchName.value);
const result = await getModel1First({
content: searchName.value,
language: "cn",
marketList: "hk,cn,usa,my,sg,vi,in,gb",
model: currentIndex.value+1
model: currentIndex.value + 1
})
console.log('result', result);
if (result.code == 200) {
stockCode.value = result.data.code
stockName.value = result.data.name
// stockName.value = result.data.name
recordId.value = result.data.recordId
parentId.value = result.data.parentId
stockId.value = result.data.stockId
language.value = result.data.language
market.value = result.data.market
market.value = result.data.market
const res = await getModel1Second({
language: language.value,
recordId: recordId.value,
parentId: parentId.value,
stockId: stockId.value,
token: 'pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q'
})
if (res.code == 200) {
const rawMarkdown = res.data.markdown;
const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // ###
markdownContent.value = adaptedMarkdown;
// markdownContent.value = res.data.markdown
htmlContent.value = marked.parse(markdownContent.value);
}
console.log('res', res);
await getServerData()
} else if (result.code == 400) {
markdownContent.value = result.message;
htmlContent.value = marked.parse(markdownContent.value);
} else {
return
}
const res = await getModel1Second({
language: language.value,
recordId: recordId.value,
parentId: parentId.value,
stockId: stockId.value,
token: 'pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q'
})
if (res.code == 200) {
const rawMarkdown = res.data.markdown;
const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // ###
markdownContent.value = adaptedMarkdown;
// markdownContent.value = res.data.markdown
htmlContent.value = marked.parse(markdownContent.value);
}
console.log('res', res);
}
} catch {
} catch (e) {
error.value = e.message || '加载失败,请重试';
} finally {
loading.value = false;
@ -228,28 +241,55 @@
}
const handleDefault = async () => {
const result = await getModeldefault({
const result = await getModeldefault({
token: "pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q",
model: currentIndex.value+1
model: currentIndex.value + 1
})
const rawMarkdown = result.data.markdown;
const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // ###
markdownContent.value = adaptedMarkdown;
htmlContent.value = marked.parse(markdownContent.value);
if (result.code == 200) {
const rawMarkdown = result.data.markdown;
const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // ###
markdownContent.value = adaptedMarkdown;
htmlContent.value = marked.parse(markdownContent.value);
} else {
}
}
const stockPrice = ref('435.900')
const stockAdd = ref('22.410')
const stockChange = ref('5.120%')
const chartKey = ref(0);
const getServerData = async () => {
const result = await getData({
market: market.value || '',
code: searchName.value || '',
language: "cn",
brainPrivilegeState: 1,
marketList: "usa.sg.my.hk.cn.can.vi.th.in.gb"
})
console.log('k线数据', result);
stockName.value = result.data.StockInformation.Name || 'Tesla Inc.'
stockCode.value = result.data.StockInformation.Code || 'TSLA'
stockTime.value = result.data.StockInformation.Time || '2025/10/29'
stockChange.value = result.data.StockInformation.Zhang || '5.120%'
stockAdd.value = result.data.StockInformation.ZhangFu || '22.410'
stockPrice.value = result.data.StockInformation.Price || '435.900'
if (result.data.chartData) {
chartData.value = {
...JSON.parse(JSON.stringify(result.data.chartData))
}
chartKey.value++;
console.log('chartData', chartData.value);
}
}
const getServerData = async() =>{
const result = await getData({
market: market.value || '',
code: searchName || '',
language: "cn",
brainPrivilegeState: 1,
marketList: "usa.sg.my.hk.cn.can.vi.th.in.gb"
})
console.log('k线数据',result);
}
// 1. K线
const opts = ref({
@ -316,51 +356,20 @@
})
// 2. K线
const chartData = ref({})
const chartData = ref({
categories: [],
series: [{
name: '',
data: []
}]
})
// K线methods
// const getServerData = () => {
//K线methods
// const getServerData1 = () => {
// //
// setTimeout(() => {
// const res = {
// "categories": [
// "2025/08/25",
// "2025/08/26",
// "2025/08/27",
// "2025/08/28",
// "2025/08/29",
// "2025/09/01",
// "2025/09/02",
// "2025/09/03",
// "2025/09/04",
// "2025/09/05",
// "2025/09/08",
// "2025/09/09",
// "2025/09/10",
// "2025/09/11",
// "2025/09/12",
// "2025/09/15",
// "2025/09/16",
// "2025/09/17",
// "2025/09/18",
// "2025/09/19",
// "2025/09/22",
// "2025/09/23",
// "2025/09/24",
// "2025/09/25",
// "2025/09/26",
// "2025/09/29",
// "2025/09/30",
// "2025/10/09",
// "2025/10/10",
// "2025/10/13",
// "2025/10/14",
// "2025/10/15",
// "2025/10/16",
// "2025/10/17",
// "2025/10/20",
// "2025/10/21",
// "2025/10/22",
// "2025/10/23",
// "2025/10/24",
// "2025/10/27"
@ -369,228 +378,6 @@
// "name": "",
// "data": [
// [
// 1470.01,
// 1496.0,
// 1466.0,
// 1499.33
// ],
// [
// 1490.32,
// 1474.23,
// 1480.01,
// 1481.61
// ],
// [
// 1481.88,
// 1484.93,
// 1448.0,
// 1448.0
// ],
// [
// 1447.97,
// 1456.1,
// 1438.77,
// 1446.1
// ],
// [
// 1453.0,
// 1482.58,
// 1452.0,
// 1480.0
// ],
// [
// 1482.2,
// 1488.0,
// 1465.7,
// 1476.1
// ],
// [
// 1478.66,
// 1509.0,
// 1478.0,
// 1491.3
// ],
// [
// 1491.0,
// 1503.5,
// 1466.0,
// 1480.55
// ],
// [
// 1472.0,
// 1479.3,
// 1460.47,
// 1480.66
// ],
// [
// 1471.0,
// 1486.97,
// 1464.0,
// 1483.0
// ],
// [
// 1483.0,
// 1506.44,
// 1477.5,
// 1501.23
// ],
// [
// 1505.0,
// 1509.95,
// 1493.42,
// 1505.0
// ],
// [
// 1506.66,
// 1529.95,
// 1496.0,
// 1522.01
// ],
// [
// 1522.01,
// 1526.02,
// 1508.5,
// 1523.5
// ],
// [
// 1526.0,
// 1538.02,
// 1510.53,
// 1516.0
// ],
// [
// 1515.87,
// 1517.48,
// 1501.5,
// 1515.1
// ],
// [
// 1515.1,
// 1520.99,
// 1496.21,
// 1499.98
// ],
// [
// 1499.99,
// 1510.28,
// 1490.01,
// 1493.0
// ],
// [
// 1492.0,
// 1497.8,
// 1463.5,
// 1467.96
// ],
// [
// 1467.99,
// 1475.5,
// 1457.01,
// 1467.97
// ],
// [
// 1465.09,
// 1467.97,
// 1450.01,
// 1453.35
// ],
// [
// 1450.5,
// 1457.5,
// 1440.0,
// 1447.42
// ],
// [
// 1434.07,
// 1456.78,
// 1434.07,
// 1442.0
// ],
// [
// 1442.83,
// 1445.21,
// 1436.0,
// 1439.0
// ],
// [
// 1441.18,
// 1447.11,
// 1428.01,
// 1435.0
// ],
// [
// 1439.38,
// 1469.99,
// 1435.0,
// 1460.86
// ],
// [
// 1460.0,
// 1460.76,
// 1440.0,
// 1443.99
// ],
// [
// 1436.0,
// 1439.38,
// 1420.0,
// 1436.78
// ],
// [
// 1437.6,
// 1439.94,
// 1427.5,
// 1430.0
// ],
// [
// 1415.7,
// 1422.85,
// 1415.12,
// 1419.2
// ],
// [
// 1429.99,
// 1464.0,
// 1429.99,
// 1451.02
// ],
// [
// 1450.98,
// 1463.0,
// 1445.08,
// 1462.0
// ],
// [
// 1461.92,
// 1484.95,
// 1458.88,
// 1484.91
// ],
// [
// 1483.1,
// 1488.0,
// 1454.03,
// 1455.0
// ],
// [
// 1455.0,
// 1469.5,
// 1454.88,
// 1457.93
// ],
// [
// 1459.0,
// 1469.94,
// 1455.5,
// 1462.26
// ],
// [
// 1462.08,
// 1465.73,
// 1456.0,
// 1458.7
// ],
// [
// 1455.0,
// 1468.8,
// 1447.2,
@ -616,10 +403,51 @@
// }, 500)
// }
let unwatch = null;
// onReady
onMounted(() => {
onMounted(async () => {
iSMT.value = uni.getSystemInfoSync().statusBarHeight
getServerData() //
await getServerData() //
await handleModels()
unwatch = watch(
() => deepExplorationStore.deepExplorationInfo, //
(newVal, oldVal) => {
console.log('deepExplorationInfo 变化了:', newVal)
historyData.value = {
...newVal
}
console.log(historyData.value.wokeFlowData);
console.log('222', historyData.value.stockData.StockInformation);
//
const rawMarkdown = historyData.value.wokeFlowData.One.markdown;
const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // ###
markdownContent.value = adaptedMarkdown;
// markdownContent.value = res.data.markdown
htmlContent.value = marked.parse(markdownContent.value);
//k线
chartData.value = {
...JSON.parse(JSON.stringify(historyData.value.stockData.chartData))
}
chartKey.value++;
console.log('chartData', chartData.value);
stockName.value = historyData.value.stockData.StockInformation.Name || 'Tesla Inc.'
stockCode.value = historyData.value.stockData.StockInformation.Code || 'TSLA'
stockTime.value = historyData.value.stockData.StockInformation.Time || '2025/10/29'
stockChange.value = historyData.value.stockData.StockInformation.Zhang || '5.120%'
stockAdd.value = historyData.value.stockData.StockInformation.ZhangFu || '22.410'
stockPrice.value = historyData.value.stockData.StockInformation.Price || '435.900'
}, {
deep: true,
immediate: true
} //
)
})
//
@ -629,8 +457,8 @@
console.log('模块:', currentIndex.value)
}
if (e.stockName) {
stockName.value = e.stockName
console.log('股票名称:', stockName.value)
searchName.value = e.stockName
console.log('股票名称:', searchName.value)
}
})
</script>
@ -738,7 +566,7 @@
}
.center {
margin-left: 105rpx;
margin-left: 155rpx;
display: flex;
align-items: center;
@ -758,21 +586,11 @@
line-height: 18px;
}
.last {
width: 15rpx;
height: 20rpx;
margin-right: 30rpx;
}
.next {
width: 15rpx;
height: 20rpx;
margin-left: 30rpx;
}
}
.right {
margin-left: 50rpx;
margin-left: 60rpx;
color: #6a6a6a;
font-family: "PingFang SC";
font-size: 13px;
@ -804,6 +622,8 @@
}
.graph_content {
min-height: 500rpx;
.charts-box {
width: 100%;
height: 100%;

152
pages/deepExploration/deepExploration.vue

@ -96,9 +96,9 @@
</view>
<view class="contentItem">
<view class="row" v-for="(item, index) in stockData" :key="index">
<view class="nameItem">{{ item.name }}</view>
<view class="nameItem">{{ item.tscode }}</view>
<view class="closeItem">{{ item.close }}</view>
<view class="priceItem">{{ item.select }}</view>
<view class="priceItem">{{ item.preClose }}</view>
</view>
</view>
</view>
@ -113,7 +113,7 @@
src="/static/deepExploration-images/plus.png"
mode="aspectFill"
></image>
<text>抄底卖顶</text>
<text>波段行情</text>
</view>
<view class="right">
<image
@ -130,10 +130,10 @@
<view class="contentTitle_price">选股价格</view>
</view>
<view class="contentItem">
<view class="row" v-for="(item, index) in stockData" :key="index">
<view class="nameItem">{{ item.name }}</view>
<view class="row" v-for="(item, index) in stockDataByName" :key="index">
<view class="nameItem">{{ item.tscode }}</view>
<view class="closeItem">{{ item.close }}</view>
<view class="priceItem">{{ item.select }}</view>
<view class="priceItem">{{ item.preClose }}</view>
</view>
</view>
</view>
@ -145,9 +145,13 @@
</template>
<script setup>
import { ref, onMounted } from "vue";
import footerBar from "@/components/footerBar.vue";
import deepExploration_header from "@/components/deepExploration_header.vue";
import {
ref,
onMounted
} from 'vue'
import footerBar from '@/components/footerBar.vue'
import deepExploration_header from '@/components/deepExploration_header.vue'
import { stocSelectApi, stocSelectByNameApi } from '@/api/deepExploration/deepExploration.js'
const type = ref("deepExploration");
const iSMT = ref(0);
@ -182,43 +186,109 @@ const searchStock = () => {
});
};
//
const viewAll = () => {
uni.navigateTo({
url: "/pages/deepExploration/stockSelectDetail",
});
};
//
const stockData = [
{
name: "(MKTW)MarketWise Inc",
close: "$14.190",
select: "$13.180",
},
{
name: "(MTCH)Match Group Inc",
close: "$32.120",
select: "$28.120",
},
{
name: "(MKTW)MarketWise Inc",
close: "$14.190",
select: "$13.180",
},
];
onMounted(() => {
//
iSMT.value = uni.getSystemInfoSync().statusBarHeight;
});
//
const viewAll = () => {
uni.navigateTo({
url: '/pages/deepExploration/stockSelectDetail'
})
}
//
const stockData = ref([]);
const stockDataByName = ref([]); //
//
const loadStockSelection = async () => {
try {
const res = await stocSelectApi({ language: 'cn', size: 3 })
// console.log(':', typeof res === 'object' ? JSON.stringify(res) : res)
const raw = res?.data
const listCandidates = [
raw?.list,
raw?.data?.list,
raw?.data?.rows,
raw?.rows,
Array.isArray(raw) ? raw : null
].filter(Array.isArray)
let list = listCandidates.length ? listCandidates[0] : []
//
if ((!Array.isArray(list) || !list.length) && raw && typeof raw === 'object' && !Array.isArray(raw)) {
const arrays = Object.values(raw).filter(Array.isArray)
if (arrays.length) {
list = arrays.flat()
}
}
if (Array.isArray(list) && list.length) {
const mapped = list.map(item => ({
tscode: item.tsCode ?? item.tscode ?? item.code ?? '',
close: item.close ?? item.lastClose ?? '',
preClose: item.preClose ?? item.preclose ?? item.prevClose ?? ''
}))
stockData.value = mapped.slice(0, 3)
console.log('选股策略列表长度:', stockData.value.length, '首项:', stockData.value[0])
} else {
console.warn('选股策略接口返回空列表或结构不匹配', raw)
}
} catch (e) {
console.error('选股策略接口调用失败', e)
uni.showToast({ title: '选股策略加载失败', icon: 'none' })
}
}
//
const loadStockSelectionByName = async () => {
try {
const res = await stocSelectByNameApi({ name: '安徽' })
const raw = res?.data
const dataObj = raw?.data || raw
let list = []
if (Array.isArray(dataObj)) {
list = dataObj
} else if (dataObj && typeof dataObj === 'object') {
const target = dataObj['安徽']
if (Array.isArray(target)) {
list = target
} else {
const firstArr = Object.values(dataObj).find(v => Array.isArray(v))
if (Array.isArray(firstArr)) list = firstArr
}
}
if (Array.isArray(list) && list.length) {
const mapped = list.map(item => ({
tscode: item.tsCode ?? item.tscode ?? item.code ?? '',
close: item.close ?? item.lastClose ?? '',
preClose: item.preClose ?? item.preclose ?? item.prevClose ?? ''
}))
stockDataByName.value = mapped.slice(0, 3)
console.log('安徽板块列表长度:', stockDataByName.value.length, '首项:', stockDataByName.value[0])
} else {
console.warn('按名称(安徽)接口返回空列表或结构不匹配', raw)
}
} catch (e) {
console.error('按名称(安徽)接口调用失败', e)
uni.showToast({ title: '安徽板块加载失败', icon: 'none' })
}
}
onMounted(() => {
//
iSMT.value = uni.getSystemInfoSync().statusBarHeight;
//
loadStockSelection()
loadStockSelectionByName() //
})
</script>
<style scoped lang="scss">
.main {
width: 100%;
height: 100vh;
min-height: 100vh; //
height: auto; //
overflow-y: auto; //
background-color: #fff;
padding-bottom: 120rpx; //
.search {
position: relative;
@ -451,6 +521,8 @@ onMounted(() => {
.static-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
}

328
pages/deepExploration/stockSelectDetail.vue

@ -3,12 +3,12 @@
<view class="table">
<view class="tableHeader">
<scroll-view class="tabs" scroll-x="true">
<view v-for="(item,index) in tabsData" :key="index" class="tabItem" @click="handleTab(item)">
<view v-for="(item,index) in tabsData" :key="index" :class="['tabItem', { 'tabItem-active': item === activeTab }]" @click="handleTab(item)">
{{item}}
</view>
</scroll-view>
</view>
<view class="tableContent">
</view>
<view class="tableContent">
<image class="showAll" src="/static/deepExploration-images/showAll.png" mode="aspectFill"></image>
<scroll-view scroll-x="true" show-scrollbar="false">
<view class="tableBox">
@ -23,7 +23,7 @@
</view>
</view>
<view class="box_content">
<view class="row" v-for="(item,index) in fakeData" :key="index" :class="{ 'increase-positive': item.increase.startsWith('+'),
<view class="row" v-for="(item,index) in strategyData" :key="index" :class="{ 'increase-positive': item.increase.startsWith('+'),
'increase-negative': item.increase.startsWith('-')}">
<view class="name_colum">
<text class="stockName">{{item.name}}</text>
@ -48,153 +48,182 @@
</template>
<script setup>
import {
ref
} from 'vue'
const tabsData = ref(['全部', '抄底卖顶', '波段行情', '价值投资', '资金及仓位管理', '价值投资', '价值投资', '价值投资', ])
const handleTab = (item) => {
uni.showToast({
title: `查看 ${item} 详情`,
icon: 'none',
duration: 2000
})
import { ref, onMounted } from 'vue'
import { stocSelectApi, stocSelectByNameApi } from '@/api/deepExploration/deepExploration.js'
import { useUserStore } from '@/stores/modules/userInfo.js'
import { useDeviceStore } from '@/stores/modules/deviceInfo.js'
import { LoginApi } from '@/api/start/login.js'
const tabsData = ref(['全部', '抄底卖顶', '波段行情', '价值投资', '资金及仓位管理', ])
const activeTab = ref('全部')
//
const handleTab = async (item) => {
activeTab.value = item
const nameMap = {
'抄底卖顶': '北京',
'波段行情': '安徽',
'价值投资': '重庆',
'资金及仓位管理': '黑龙江'
}
if (item === '全部') {
await loadStrategy()
uni.showToast({ title: `查看 ${item} 详情`, icon: 'none', duration: 1500 })
return
}
const apiName = nameMap[item]
if (apiName) {
await loadByName(apiName)
uni.showToast({ title: `${item}数据已更新`, icon: 'none', duration: 1500 })
} else {
uni.showToast({ title: `暂不支持:${item}`, icon: 'none' })
}
}
//
const ifASC = ref(true)
//
const tableContentHeaderData = ref(['最新', '涨幅', '跌幅', '昨收', '成交量', '成交额', '开盘价', '最高价', '最低价'])
const fakeData = [{
name: "TechCore",
stockCode: "600001",
latest: 1315.00,
increase: "+5.2%",
decrease: "+5.2%",
previousClose: 1250.00,
volume: 12000,
turnover: "15780K",
openingPrice: 1237.50,
highestPrice: 1320.00,
lowestPrice: 1230.00
},
{
name: "MediaLink",
stockCode: "600002",
latest: 1138.70,
increase: "-3.5%",
decrease: "-3.5%",
previousClose: 1180.00,
volume: 8500,
turnover: "967.9K",
openingPrice: 1191.80,
highestPrice: 1195.00,
lowestPrice: 1130.00
},
{
name: "FinServ",
stockCode: "600003",
latest: 1413.72,
increase: "+7.1%",
decrease: "+7.1%",
previousClose: 1320.00,
volume: 15000,
turnover: "2120.6K",
openingPrice: 1293.60,
highestPrice: 1420.00,
lowestPrice: 1290.00
},
{
name: "AutoDrive",
stockCode: "600004",
latest: 1080.40,
increase: "+2.8%",
decrease: "+2.8%",
previousClose: 1050.00,
volume: 9000,
turnover: "972.4K",
openingPrice: 1055.25,
highestPrice: 1085.00,
lowestPrice: 1050.00
},
{
name: "EduSmart",
stockCode: "600005",
latest: 968.24,
increase: "-1.2%",
decrease: "-1.2%",
previousClose: 980.00,
volume: 7000,
turnover: "677.8K",
openingPrice: 975.10,
highestPrice: 978.00,
lowestPrice: 965.00
},
{
name: "HealthPlusqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
stockCode: "600006",
latest: 1463.00,
increase: "+4.5%",
decrease: "+4.5%",
previousClose: 1400.00,
volume: 13000,
turnover: "1901.9K",
openingPrice: 1393.00,
highestPrice: 1470.00,
lowestPrice: 1385.00
},
{
name: "AgriTech",
stockCode: "600007",
latest: 1038.36,
increase: "+1.8%",
decrease: "+1.8%",
previousClose: 1020.00,
volume: 6500,
turnover: "674.9K",
openingPrice: 1028.16,
highestPrice: 1040.00,
lowestPrice: 1025.00
},
{
name: "LogiFlow",
stockCode: "600008",
latest: 1094.24,
increase: "-2.3%",
decrease: "-2.3%",
previousClose: 1120.00,
volume: 8000,
turnover: "875.4K",
openingPrice: 1122.24,
highestPrice: 1125.00,
lowestPrice: 1090.00
},
{
name: "EnergySol",
stockCode: "600009",
latest: 1435.05,
increase: "+6.3%",
decrease: "+6.3%",
previousClose: 1350.00,
volume: 14000,
turnover: "2009.1K",
openingPrice: 1339.75,
highestPrice: 1440.00,
lowestPrice: 1335.00
},
{
name: "RealEstate",
stockCode: "600010",
latest: 995.00,
increase: "-0.5%",
decrease: "-0.5%",
previousClose: 1000.00,
volume: 7500,
turnover: "746.3K",
openingPrice: 1003.00,
highestPrice: 1005.00,
lowestPrice: 990.00
const tableContentHeaderData = ref(['最新', '涨幅', '涨跌', '昨收', '成交量', '成交额', '开盘价', '最高价', '最低价'])
//
const strategyData = ref([])
// token
const ensureAuth = async () => {
const userStore = useUserStore()
if (userStore.userInfo?.token) return
try {
const deviceStore = useDeviceStore()
let deviceId = deviceStore.deviceInfo?.deviceId
if (!deviceId) {
const cached = uni.getStorageSync('deviceId')
deviceId = cached || `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`
uni.setStorageSync('deviceId', deviceId)
deviceStore.setDeviceInfo({ ...(deviceStore.deviceInfo || {}), deviceId })
}
const res = await LoginApi({
loginType: 'VISITOR',
account: deviceId,
useCode: false
})
if (res?.code === 200 && res?.data?.token) {
userStore.setUserInfo(res.data)
console.log('游客登录成功,token=', res.data.token)
} else {
console.warn('游客登录失败', res)
}
} catch (err) {
console.warn('游客登录异常', err)
}
}
const formatPctChg = (val) => {
if (val === null || val === undefined || val === '') return ''
const num = Number(val)
if (!isFinite(num)) return String(val)
const sign = num > 0 ? '+' : ''
return `${sign}${num.toFixed(2)}%`
}
// ( pctChg )
const sortByPctDesc = (arr) => arr.sort((a, b) => (Number(b.pctChg) || -Infinity) - (Number(a.pctChg) || -Infinity))
// ///
const loadByName = async (apiName) => {
try {
const userStore = useUserStore()
if (!userStore.userInfo?.token) {
await ensureAuth()
}
const token = useUserStore().userInfo?.token
const res = await stocSelectByNameApi({ name: apiName, token })
const raw = res?.data
const dataObj = raw?.data || raw
let list = []
if (dataObj && typeof dataObj === 'object' && !Array.isArray(dataObj)) {
const target = dataObj[apiName]
if (Array.isArray(target)) list = target
else {
const firstArr = Object.values(dataObj).find(v => Array.isArray(v))
if (Array.isArray(firstArr)) list = firstArr
}
}
if ((!Array.isArray(list) || !list.length) && Array.isArray(raw)) {
list = raw
}
//
if (Array.isArray(list)) list = sortByPctDesc(list)
if (Array.isArray(list) && list.length) {
strategyData.value = list.map(item => ({
name: item.tsCode ?? item.tscode ?? '',
stockCode: item.tsCode ?? item.tscode ?? '',
latest: item.close ?? '',
increase: formatPctChg(item.pctChg),
decrease: item.change ?? '',
previousClose: item.preClose ?? item.preclose ?? '',
volume: item.vol ?? '',
turnover: item.amount ?? '',
openingPrice: item.open ?? '',
highestPrice: item.high ?? '',
lowestPrice: item.low ?? ''
}))
console.log(`按名称(${apiName})加载成功,条数:`, strategyData.value.length, '首项:', strategyData.value[0])
} else {
console.warn('getStrategyByName 返回空列表或结构不匹配', raw)
}
} catch (e) {
console.error('getStrategyByName 接口调用失败', e)
uni.showToast({ title: '按名称加载失败', icon: 'none' })
}
];
}
const loadStrategy = async () => {
try {
const userStore = useUserStore()
if (!userStore.userInfo?.token) {
await ensureAuth()
}
const token = useUserStore().userInfo?.token
const res = await stocSelectApi({ language: 'cn', token })
const raw = res?.data
const listCandidates = [
raw?.list,
raw?.data?.list,
raw?.data?.rows,
raw?.rows,
Array.isArray(raw) ? raw : null
].filter(Array.isArray)
let list = listCandidates.length ? listCandidates[0] : []
if ((!Array.isArray(list) || !list.length) && raw && typeof raw === 'object' && !Array.isArray(raw)) {
const arrays = Object.values(raw).filter(Array.isArray)
if (arrays.length) list = arrays.flat()
}
//
if (Array.isArray(list)) list = sortByPctDesc(list)
if (Array.isArray(list) && list.length) {
strategyData.value = list.map(item => ({
name: item.tsCode ?? item.tscode ?? '',
stockCode: item.tsCode ?? item.tscode ?? '',
latest: item.close ?? '',
increase: formatPctChg(item.pctChg),
decrease: item.change ?? '',
previousClose: item.preClose ?? item.preclose ?? '',
volume: item.vol ?? '',
turnover: item.amount ?? '',
openingPrice: item.open ?? '',
highestPrice: item.high ?? '',
lowestPrice: item.low ?? ''
}))
console.log('stockSelectDetail 加载成功(已按涨幅降序),条数:', strategyData.value.length, '首项:', strategyData.value[0])
} else {
console.warn('stockSelectDetail 接口返回空列表或结构不匹配', raw)
}
} catch (e) {
console.error('stockSelectDetail 接口调用失败', e)
uni.showToast({ title: '选股策略详情加载失败', icon: 'none' })
}
}
onMounted(() => {
loadStrategy()
})
</script>
<style scoped lang="scss">
@ -229,12 +258,17 @@
background-color: rgb(243, 243, 243);
}
.tabItem-active {
background-color: #DB1F1D; //
color: #fff;
}
}
}
.tableContent {
width: 100%;
background-color: #fff;
position: relative;
.showAll {

21
pages/deepMate/deepMate.vue

@ -291,7 +291,7 @@ const { safeAreaInsets } = uni.getSystemInfoSync();
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from "vue";
import footerBar from "../../components/footerBar";
import marked from "marked"; // marked
import { onPageScroll } from "@dcloudio/uni-app";
import { onPageScroll, onLoad } from "@dcloudio/uni-app";
import {
postStock,
postIntent,
@ -358,6 +358,25 @@ const hotTopics = ref([
},
]);
//
onLoad((options) => {
console.log('deepMate页面接收到参数:', options);
// query
if (options.query) {
const decodedQuery = decodeURIComponent(options.query);
console.log('解码后的查询内容:', decodedQuery);
//
inputMessage.value = decodedQuery;
//
setTimeout(() => {
sendMessage();
}, 500);
}
});
//
onMounted(() => {
const sys = uni.getSystemInfoSync();

64
pages/home/home.vue

@ -47,7 +47,7 @@
<text class="section-title">深度探索</text>
</view>
<view class="header-right">
<text class="more-btn">查看更多</text>
<text class="more-btn" @click="goToDeepExploration">查看更多</text>
</view>
</view>
</view>
@ -81,7 +81,7 @@
<view class="section-header-container">
<view class="section-header">
<text class="section-title">我的自选</text>
<text class="more-btn">添加自选股</text>
<text class="more-btn" @click="goToMarketSituation">添加自选股</text>
</view>
<!-- 我的自选TCP连接状态和控制 -->
<!-- <view class="my-stocks-tcp-control">
@ -128,7 +128,7 @@
<view class="report-stock">{{report.stock}}</view>
<view class="report-status">{{report.status}}</view>
</view>
<view class="view-more">
<view class="view-more" @click="goToCustomStockList">
<text>查看更多 >></text>
</view>
</view>
@ -175,7 +175,7 @@
<view class="section-header highlights-title-container">
<text class="section-title">今日市场核心看点</text>
</view>
<view class="highlights-image-container">
<view class="highlights-image-container" @click="goToAnalysisInstitutionalTrends">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/8d5365af968402a18cedb120c09460b0.png" mode="aspectFit" class="highlights-image"></image>
</view>
@ -373,21 +373,21 @@ export default {
uni.$on('visitorLoginSuccess', this.handleVisitorLoginSuccess)
// TCP
this.$nextTick(() => {
console.log('页面渲染完成,开始自动连接TCP服务器...')
//
setTimeout(() => {
// TCPchannel 1
console.log('连接今日市场概览TCP(channel 1)...')
this.connectTcp()
// this.$nextTick(() => {
// console.log('TCP...')
// //
// setTimeout(() => {
// // TCPchannel 1
// console.log('TCPchannel 1...')
// this.connectTcp()
// TCPchannel 2
setTimeout(() => {
console.log('连接我的自选TCP(channel 2)...')
this.connectMyStocksTcp()
}, 500)
}, 1000)
})
// // TCPchannel 2
// setTimeout(() => {
// console.log('TCPchannel 2...')
// this.connectMyStocksTcp()
// }, 500)
// }, 1000)
// })
},
//
@ -430,6 +430,34 @@ export default {
},
methods: {
//
goToCustomStockList() {
uni.navigateTo({
url: '/pages/customStockList/customStockList'
})
},
//
goToMarketSituation() {
uni.navigateTo({
url: '/pages/marketSituation/marketSituation'
})
},
//
goToAnalysisInstitutionalTrends() {
uni.navigateTo({
url: '/pages/analysisInstitutionalTrends/analysisInstitutionalTrends'
})
},
//
goToDeepExploration() {
uni.navigateTo({
url: '/pages/deepExploration/deepExploration'
})
},
//
handleVisitorLoginSuccess(data) {
console.log('收到游客登录成功事件:', data)

1
pages/home/member.vue

@ -1,4 +1,5 @@
<template>
<LoginPrompt ref="loginPrompt"></LoginPrompt>
<view class="main">
<view class="top">
<view class="bell">

124
pages/marketSituation/countryMarket.vue

@ -10,14 +10,14 @@
</view>
<!-- 大盘指数 -->
<view class="section">
<view class="section" v-if="activeTabIndex === 0">
<view class="section_header">
<text class="section_title">大盘指数</text>
<text class="section_action" @click="viewMore('indices')">查看更多 ></text>
</view>
<view class="indices_grid">
<view v-for="(index, i) in countryInfo.mainIndices" :key="i" class="index_item">
<IndexCard :market="countryInfo.market" :indexName="index.name" :currentPrice="index.price" :changeAmount="index.change" :changePercent="index.changePercent" :isRising="index.isRising" />
<view v-for="(index, i) in countryInfo" :key="i" class="index_item">
<IndexCard :market="index.market" :stockName="index.name" :currentPrice="index.price" :changeAmount="index.change" :changePercent="index.changePercent" :isRising="index.isRising" />
</view>
</view>
@ -39,13 +39,13 @@
</view>
<!-- 板块 -->
<view class="section">
<view class="section" v-if="activeTabIndex === 1">
<view class="section_header">
<text class="section_title">板块</text>
<text class="section_action" @click="viewMore('sectors')">查看更多 ></text>
</view>
<view class="sectors_grid">
<view v-for="(sec, i) in sectors" :key="i" class="sector_item">
<view v-for="(sec, i) in countryInfo" :key="i" class="sector_item">
<view class="sector_header">
<text class="sector_name">{{ sec.name }}</text>
<text :class="['sector_change', sec.isRising ? 'rising' : 'falling']">
@ -58,7 +58,7 @@
</view>
<!-- 股票 -->
<view class="section">
<view class="section" v-if="activeTabIndex === 2">
<view class="section_header">
<text class="section_title">股票</text>
<text class="section_action" @click="viewMore('stocks')">查看更多 ></text>
@ -69,7 +69,7 @@
<text class="cell price">最新</text>
<text class="cell change">涨幅</text>
</view>
<view class="table_row" v-for="(stk, i) in stocks" :key="i">
<view class="table_row" v-for="(stk, i) in countryInfo" :key="i">
<view class="cell name">
<text class="stk_name">{{ stk.name }}</text>
<text class="stk_code">{{ stk.code }}</text>
@ -92,14 +92,30 @@
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { ref, computed, onMounted, watch } from "vue";
import IndexCard from "../../components/IndexCard.vue";
import { queryStockDataAPI } from "@/api/marketSituation/marketSituation";
onMounted(() => {
switchTab(0);
});
// Tab
// const marketTabs = ["", "", "", ""];
const activeTabIndex = ref(0);
const switchTab = (i) => {
activeTabIndex.value = i;
queryStockDataAPI({
parentId: props.countryId,
tradeId: activeTabIndex.value+1,
}).then((res) => {
if (res.code === 200) {
countryInfo.value = res.data.dataPage.records;
console.log(res.data)
console.log(res.data.dataPage.records)
console.log(countryInfo.value);
}
});
};
//
@ -125,80 +141,31 @@ const props = defineProps({
marketTabs: {
type: Array,
},
});
// /
const countryInfoMap = {
2: {
//
name: "新加坡",
flag: "🇸🇬",
isMarketOpen: true,
mainIndices: [
{ name: "海峡时报指数", price: "3,234.56", change: "+12.34", changePercent: "+0.38%", isRising: true },
{ name: "FTSE ST Mid Cap", price: "1,234.56", change: "-5.67", changePercent: "-0.46%", isRising: false },
],
hotStocks: [
{ name: "星展银行", code: "D05.SI", price: "35.20", change: "+0.15", isRising: true },
{ name: "华侨银行", code: "O39.SI", price: "13.45", change: "-0.05", isRising: false },
],
},
3: {
// 西
name: "马来西亚",
flag: "🇲🇾",
isMarketOpen: false,
mainIndices: [{ name: "富时大马KLCI指数", price: "1,567.89", change: "+8.90", changePercent: "+0.57%", isRising: true }],
hotStocks: [
{ name: "马来亚银行", code: "1155.KL", price: "9.85", change: "+0.10", isRising: true },
{ name: "大众银行", code: "1295.KL", price: "4.32", change: "-0.02", isRising: false },
],
},
4: {
// 西
name: "印度尼西亚",
flag: "🇮🇩",
isMarketOpen: true,
mainIndices: [{ name: "雅加达综合指数", price: "7,234.56", change: "+45.67", changePercent: "+0.63%", isRising: true }],
hotStocks: [],
},
5: {
//
name: "美国",
flag: "🇺🇸",
isMarketOpen: false,
mainIndices: [
{ name: "道琼斯", price: "45,757.90", change: "-125.22", changePercent: "-0.27%", isRising: false },
{ name: "纳斯达克", price: "22,333.96", change: "+125.22", changePercent: "+0.47%", isRising: true },
{ name: "标普500", price: "6,606.08", change: "+125.22", changePercent: "+0.27%", isRising: true },
],
hotStocks: [
{ name: "苹果", code: "AAPL", price: "195.89", change: "+2.34", isRising: true },
{ name: "微软", code: "MSFT", price: "378.85", change: "-1.23", isRising: false },
],
tabData: {
type: Object,
default: null
},
};
});
//
const countryInfo = computed(() => {
return (
countryInfoMap[props.countryId] || {
name: "未知地区",
flag: "🌍",
isMarketOpen: false,
mainIndices: [],
hotStocks: [],
const countryInfo = ref('')
//
const handleTabData = (tabData) => {
if (tabData && tabData.type === 'country' && tabData.data) {
if (tabData.data.dataPage && tabData.data.dataPage.records) {
countryInfo.value = tabData.data.dataPage.records;
console.log('countryMarket接收到数据:', countryInfo.value);
}
);
});
}
};
//
const sectors = computed(() => {
return countryInfoMap[props.countryId]?.sectors || [];
});
const stocks = computed(() => {
return countryInfoMap[props.countryId]?.stocks || [];
});
// tabData
watch(() => props.tabData, (newTabData) => {
if (newTabData) {
handleTabData(newTabData);
}
}, { immediate: true });
//
const viewMore = (type) => {
@ -257,11 +224,8 @@ const viewMore = (type) => {
}
.indices_grid {
padding: 20rpx;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20rpx;
background-color: #f6f6f6;
}
/* 情绪温度 */

307
pages/marketSituation/globalIndex.vue

@ -32,7 +32,7 @@
<!-- 内容区域 -->
<scroll-view class="content" :style="{ top: contentTopPosition + 'px' }" scroll-y="true">
<!-- 亚太-中华 -->
<view class="market-section" v-for="item in globalIndexArray" :key="item">
<view class="market-section" v-for="(item, parentIndex) in marketSituationStore.gloablCardData" :key="item">
<view class="market-header">
<text class="market-title">{{ item.ac }}</text>
<view class="market-more" @click="viewMore(item.ac)">
@ -41,7 +41,7 @@
</view>
</view>
<view class="cards-grid-three">
<view v-for="iitem in item.list" :key="iitem" class="card-item">
<view v-for="(iitem, index) in item.list" :key="iitem" class="card-item">
<IndexCard
:market="iitem.market"
:stockName="iitem.name"
@ -49,7 +49,7 @@
:changeAmount="iitem.changeAmount"
:changePercent="iitem.changePercent"
:isRising="iitem.isRising"
@click="viewIndexDetail(iitem)"
@click="viewIndexDetail(iitem, parentIndex, index)"
/>
</view>
</view>
@ -65,11 +65,12 @@
</template>
<script setup>
import { ref, onMounted, computed, nextTick, watch } from "vue";
import { ref, onMounted, onUnmounted, computed, nextTick, watch } from "vue";
import footerBar from "../../components/footerBar.vue";
import IndexCard from "../../components/IndexCard.vue";
import { getRegionalGroupAPI } from "../../api/marketSituation/marketSituation.js";
import { useMarketSituationStore } from "../../stores/modules/marketSituation.js";
const marketSituationStore = useMarketSituationStore();
//
const iSMT = ref(0); //
const contentHeight = ref(0);
@ -259,7 +260,7 @@ const viewMore = (market) => {
};
//
const viewIndexDetail = (item) => {
const viewIndexDetail = (item, parentIndex, index) => {
console.log("查看指数详情:", item.stockName);
// uni.showToast({
// title: ` ${item.stockName} `,
@ -268,7 +269,7 @@ const viewIndexDetail = (item) => {
// })
//
uni.navigateTo({
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}`,
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}&parentIndex=${parentIndex}&index=${index}&from=globalIndex`,
});
};
@ -276,14 +277,306 @@ const getRegionalGroup = async () => {
try {
const result = await getRegionalGroupAPI();
globalIndexArray.value = result.data;
marketSituationStore.gloablCardData = result.data;
} catch (e) {
console.log("获取区域指数失败", e);
}
};
// TCP
import tcpConnection, { TCPConnection, TCP_CONFIG } from "@/api/tcpConnection.js";
const tcpConnected = ref(false);
const connectionListener = ref(null);
const messageListener = ref(null);
// TCP
const initTcpListeners = () => {
//
connectionListener.value = (status, result) => {
tcpConnected.value = status === "connected";
console.log("TCP连接状态变化:", status, tcpConnected.value);
//
//
if (status === "connected") {
sendTcpMessage("batch_real_time");
}
};
//
messageListener.value = (type, message, parsedArray) => {
const messageObj = {
type: type,
content: message,
parsedArray: parsedArray,
timestamp: new Date().toLocaleTimeString(),
direction: "received",
};
//
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;
let messageDataArray = [];
if (command == "batch_real_time") {
for (let i = 0; i < globalIndexArray.value.length; ++i) {
for (let j = 0; j < globalIndexArray.value[i].list.length; ++j) {
messageDataArray.push(globalIndexArray.value[i].list[j].code);
}
}
}
console.log(messageDataArray);
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 "batch_real_time":
messageData = {
command: "batch_real_time",
stock_codes: messageDataArray,
};
break;
case "help":
messageData = {
command: "help",
};
break;
}
if (!messageData) {
return;
} else {
try {
//
const success = tcpConnection.send(messageData);
if (success) {
console.log("home发送TCP消息:", messageData);
}
} catch (error) {
console.error("发送TCP消息时出错:", error);
}
}
};
// TCP
const getTcpStatus = () => {
const status = tcpConnection.getConnectionStatus();
uni.showModal({
title: "TCP连接状态",
content: `当前状态: ${status ? "已连接" : "未连接"}`,
showCancel: false,
});
};
let isMorePacket = {
init_batch_real_time: false,
batch_real_time: false,
};
let receivedMessage;
// TCP
const parseStockData = (message) => {
try {
console.log("进入parseStockData, message类型:", typeof message);
let parsedMessage;
// isMorePackettrue
// message{JSON
//
if (message.includes("欢迎连接到股票数据服务器")) {
console.log("服务器命令列表,不予处理");
return;
}
if ((typeof message === "string" && message.includes("batch_data_start")) || isMorePacket.init_batch_real_time) {
if (typeof message === "string" && message.includes("batch_data_start")) {
console.log("开始接受分包数据");
receivedMessage = "";
} else {
console.log("接收分包数据过程中");
}
isMorePacket.init_batch_real_time = true;
receivedMessage += message;
// }JSON
if (receivedMessage.includes("batch_data_complete")) {
console.log("接受分包数据结束");
isMorePacket.init_batch_real_time = false;
console.log("展示数据", receivedMessage);
let startIndex = 0;
let startCount = 0;
let endIndex = receivedMessage.indexOf("batch_data_complete");
for (let i = 0; i < receivedMessage.length; ++i) {
if (receivedMessage[i] == "{") {
startCount++;
if (startCount == 2) {
startIndex = i;
break;
}
}
}
for (let i = receivedMessage.indexOf("batch_data_complete"); i >= 0; --i) {
if (receivedMessage[i] == "}" || startIndex == endIndex) {
endIndex = i;
break;
}
}
if (startIndex >= endIndex) {
throw new Error("JSON字符串格式错误");
}
console.log("message", startIndex, endIndex, receivedMessage[endIndex], receivedMessage[startIndex]);
parsedMessage = JSON.parse(receivedMessage.substring(startIndex, endIndex + 1));
console.log("JSON解析成功,解析后类型:", typeof parsedMessage, parsedMessage);
const stockDataArray = parsedMessage.data;
for (let i = 0; i < globalIndexArray.value.length; ++i) {
for (let j = 0; j < globalIndexArray.value[i].list.length; ++j) {
const stockCode = globalIndexArray.value[i].list[j].code;
marketSituationStore.gloablCardData[i].list[j].currentPrice = stockDataArray[stockCode][0].current_price.toFixed(2);
marketSituationStore.gloablCardData[i].list[j].changeAmount = (stockDataArray[stockCode][0].current_price - stockDataArray[stockCode][0].pre_close).toFixed(2);
marketSituationStore.gloablCardData[i].list[j].changePercent = ((100 * (stockDataArray[stockCode][0].current_price - stockDataArray[stockCode][0].pre_close)) / stockDataArray[stockCode][0].pre_close).toFixed(2) + "%";
marketSituationStore.gloablCardData[i].list[j].isRising = stockDataArray[stockCode][0].current_price - stockDataArray[stockCode][0].pre_close >= 0;
}
}
}
} else if ((typeof message === "string" && message.includes('{"count')) || isMorePacket.batch_real_time) {
if (typeof message === "string" && message.includes('{"count')) {
console.log("开始接受分包数据");
receivedMessage = "";
} else {
console.log("接收分包数据过程中");
}
isMorePacket.batch_real_time = true;
receivedMessage += message;
// }JSON
if (receivedMessage.includes("batch_realtime_data")) {
console.log("接受分包数据结束");
isMorePacket.batch_real_time = false;
console.log("展示数据", receivedMessage);
let startIndex = 0;
let endIndex = receivedMessage.length - 1;
for (let i = 0; i < receivedMessage.length; ++i) {
if (receivedMessage[i] == "{") {
startIndex = i;
break;
}
}
for (let i = receivedMessage.length - 1; i >= 0; --i) {
if (receivedMessage[i] == "}" || startIndex == endIndex) {
endIndex = i;
break;
}
}
if (startIndex >= endIndex) {
throw new Error("JSON字符串格式错误");
}
parsedMessage = JSON.parse(receivedMessage.substring(startIndex, endIndex + 1));
console.log("JSON解析成功,解析后类型:", typeof parsedMessage, parsedMessage);
const stockDataArray = parsedMessage.data;
for (let i = 0; i < globalIndexArray.value.length; ++i) {
for (let j = 0; j < globalIndexArray.value[i].list.length; ++j) {
const stockCode = globalIndexArray.value[i].list[j].code;
marketSituationStore.gloablCardData[i].list[j].currentPrice = stockDataArray[stockCode][0].current_price.toFixed(2);
marketSituationStore.gloablCardData[i].list[j].changeAmount = (stockDataArray[stockCode][0].current_price - stockDataArray[stockCode][0].pre_close).toFixed(2);
marketSituationStore.gloablCardData[i].list[j].changePercent = ((100 * (stockDataArray[stockCode][0].current_price - stockDataArray[stockCode][0].pre_close)) / stockDataArray[stockCode][0].pre_close).toFixed(2) + "%";
marketSituationStore.gloablCardData[i].list[j].isRising = stockDataArray[stockCode][0].current_price - stockDataArray[stockCode][0].pre_close >= 0;
}
}
}
} 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消息监听器");
}
};
const startTcp = () => {
try {
removeTcpListeners();
disconnectTcp();
initTcpListeners();
connectTcp();
} catch (error) {
console.error("建立连接并设置监听出错:", error);
}
};
onUnmounted(() => {
sendTcpMessage("stop_real_time");
removeTcpListeners();
disconnectTcp();
});
//
onMounted(async () => {
await getRegionalGroup();
initTcpListeners();
await nextTick();
//
startTcp();
//
const systemInfo = uni.getSystemInfoSync();
iSMT.value = systemInfo.statusBarHeight || 0;

322
pages/marketSituation/marketCondition.vue

@ -202,6 +202,19 @@
<button @click="sendTcpMessage('init_real_time')">初始化获取行情历史数据</button>
<button @click="sendTcpMessage('stop_real_time')">停止实时推送</button>
</view>
<view class="test" v-else-if="klineTab === 11">
<view class="button-sp-area">
<button class="mini-btn" type="default" size="mini" @click="ChangeMinutePeriod(1)">分时</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeMinutePeriod(5)">5D</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeKLinePeriod(0)">D</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeKLinePeriod(1)">W</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeKLinePeriod(4)">1M</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeKLinePeriod(5)">15M</button>
</view>
<view style='background-color:#ffffff;'>
<HQChartControl ref="HQChartCtrl" DefaultChart="{Type:'KLine'}" :DefaultSymbol="Symbol"> </HQChartControl>
</view>
</view>
<view v-else class="kline-chart-container">
<text>K线图开发中...</text>
</view>
@ -210,15 +223,15 @@
</view>
<view class="bottomTool">
<view class="index">
<view class="index" @click="goToIndexRepository">
<image class="icon" src="/static/marketSituation-image/marketCondition-image/index.png" mode="指标仓库图标"> </image>
指标仓库
</view>
<view class="function">
<view class="function" @click="goToFunction">
<image class="icon" src="/static/marketSituation-image/marketCondition-image/function.png" mode="功能图标"> </image>
功能
</view>
<view class="favorites">
<view class="favorites" @click="goToFavorites">
<image class="icon" src="/static/marketSituation-image/marketCondition-image/favorites.png" mode="加自选图标"></image>
加自选
</view>
@ -233,7 +246,149 @@ const instance = getCurrentInstance();
import { prevClosePrice, timeData as testTimeData, klineData as testKlineData } from "@/common/stockTimeInformation.js";
import { throttle } from "@/common/util.js";
import { HCharts } from "@/common/canvasMethod.js";
import tcpConnection, { TCPConnection, TCP_CONFIG } from "@/api/tcpConnection.js";
import tcpConnection, { TCPConnection, TCP_CONFIG } from "../../api/tcpConnection";
import { useMarketSituationStore } from "../../stores/modules/marketSituation.js";
const marketSituationStore = useMarketSituationStore();
import HQChartControl from '@/uni_modules/jones-hqchart2/js_sdk/HQChartControl.vue'
//
import HQData from "@/uni_modules/jones-hqchart2/js_sdk/umychart.NetworkFilterTest.vue.js"
import { dailyDataPackets } from '@/common/dailyData.js'
//
const Symbol = ref('GBPAUD.FXCM')
const ChartWidth = ref(350)
const ChartHeight = ref(500)
const HQChartCtrl = ref(null)
//
const CreateHQChart = () => {
const chartHeight = ChartHeight.value
const hqchartCtrl = HQChartCtrl.value
if (!hqchartCtrl) return
//option
//hqchartCtrl.KLine.Option.
hqchartCtrl.NetworkFilter = NetworkFilter
hqchartCtrl.SetSize(ChartWidth.value, chartHeight)
hqchartCtrl.OnSize()
hqchartCtrl.KLine.Option.IsAutoUpdate = false
hqchartCtrl.KLine.Option.KLine.Period = 4
nextTick(() => {
hqchartCtrl.CreateHQChart()
})
}
const transformDailyDataToHQChart = (dailyDataPackets) => {
const symbol = dailyDataPackets.stock_code || Symbol.value
const rows = Array.isArray(dailyDataPackets.data) ? dailyDataPackets.data : []
// HQChart线: [Date, Open, High, Low, Close, Volume]
const data = rows.map((r, idx) => ([
parseInt(r.trade_date, 10), // Date: YYYYMMDD
Number(idx > 0 ? rows[idx - 1].bid_close : r.bid_close), // YClose:
Number(r.bid_open), // Open
Number(r.bid_high), // High
Number(r.bid_low), // Low
Number(r.bid_close), // Close
Number(r.tick_qty || 0), // Volume
Number(r.amount || 0) // Amount0
]))
return { name: symbol, symbol, ver: 2.0, data }
}
const ClearHQChart = () => {
const hqchartCtrl = HQChartCtrl.value
if (hqchartCtrl) hqchartCtrl.ClearChart()
}
const ChangeMinutePeriod = (days) => {
const hqchartCtrl = HQChartCtrl.value
if (hqchartCtrl) hqchartCtrl.ChangeMinutePeriod(days)
}
const ChangeKLinePeriod = (period) => {
const hqchartCtrl = HQChartCtrl.value
if (hqchartCtrl) hqchartCtrl.ChangeKLinePeriod(period)
}
const NetworkFilter = (data, callback) => {
console.log(`[App:NetworkFilter] Name=${data.Name} Explain=${data.Explain}`)
// HQDataCDN
data.PreventDefault = true
const reqSymbol = (data?.Request?.Data?.symbol) || Symbol.value || 'GBPAUD.FXCM'
switch (data.Name) {
// K
case 'KLineChartContainer::RequestHistoryData': {
const packet = dailyDataPackets[reqSymbol]
if (packet) {
const mock = transformDailyDataToHQChart(packet)
callback({ data: mock })
} else {
//
callback({ data: { name: reqSymbol, symbol: reqSymbol, ver: 2.0, data: [] } })
}
break
}
// K
case 'KLineChartContainer::RequestRealtimeData': {
callback({ data: { name: reqSymbol, symbol: reqSymbol, ver: 2.0, data: [] } })
break
}
// /
case 'KLineChartContainer::ReqeustHistoryMinuteData':
case 'KLineChartContainer::RequestMinuteRealtimeData':
case 'MinuteChartContainer::RequestMinuteData':
case 'MinuteChartContainer::RequestHistoryMinuteData': {
callback({ data: { name: reqSymbol, symbol: reqSymbol, ver: 2.0, data: [] } })
break
}
default: {
//
callback({ data: { name: reqSymbol, symbol: reqSymbol, ver: 2.0, data: [] } })
break
}
}
}
//
const handleShow = () => {
uni.getSystemInfo({
success: (res) => {
const width = res.windowWidth
const height = res.windowHeight
ChartWidth.value = width
ChartHeight.value = height - 65
nextTick(() => {
CreateHQChart()
})
}
})
}
//
const handleHide = () => {
ClearHQChart()
}
//
const handleUnload = () => {
ClearHQChart()
}
//
onMounted(() => {
handleShow()
})
onUnmounted(() => {
handleUnload()
})
// TCP
const tcpConnected = ref(false);
@ -244,6 +399,7 @@ const messageListener = ref(null);
const currentStockFrom = ref();
//
const currentStockIndex = ref(-1);
const currentStockParentIndex = ref(-1);
//
const stockInformation = ref({
stockName: "----", //
@ -413,12 +569,7 @@ const startTcp = () => {
initTcpListeners();
connectTcp();
} catch (error) {
console.error("建立连接并设置监听:", error);
uni.showToast({
title: "建立连接并设置监听",
icon: "none",
duration: 1500,
});
console.error("建立连接并设置监听出错:", error);
}
};
@ -490,10 +641,13 @@ const selectKlineTab = (tabId) => {
});
break;
case 11:
uni.showToast({
title: "暂无年K数据",
icon: "none",
duration: 2000,
// K -
nextTick(() => {
CreateHQChart();
// K
setTimeout(() => {
ChangeKLinePeriod(3);
}, 100);
});
break;
default:
@ -516,25 +670,75 @@ const backToHomepage = () => {
};
const toLeftPage = () => {
if(currentStockFrom.value == "marketOverview"){
return;
}
if (currentStockIndex.value > 0) {
currentStockIndex.value--;
// updateStockInformation();
} else {
if (currentStockIndex.value == 0) {
uni.showToast({
title: "没有更多股票了",
icon: "none",
duration: 1000,
});
return;
} else {
currentStockIndex.value--;
let nextStockInformation;
if (currentStockFrom.value == "marketOverview") {
nextStockInformation = marketSituationStore.cardData[currentStockIndex.value];
} else if (currentStockFrom.value == "marketDetail") {
nextStockInformation = marketSituationStore.marketDetailCardData[currentStockIndex.value];
} else if (currentStockFrom.value == "globalIndex") {
nextStockInformation = marketSituationStore.gloablCardData[currentStockParentIndex.value].list[currentStockIndex.value];
} else {
uni.showToast({
title: "没有更多股票了",
icon: "none",
duration: 1000,
});
return;
}
updateStockInformation(nextStockInformation);
}
};
const toRightPage = () => {
if (currentStockIndex.value < stockList.length - 1) {
currentStockIndex.value++;
// updateStockInformation();
let nextStockInformation;
if (currentStockFrom.value == "marketOverview") {
if (currentStockIndex.value == marketSituationStore.cardData.length) {
uni.showToast({
title: "没有更多股票了",
icon: "none",
duration: 1000,
});
return;
} else {
currentStockIndex.value++;
nextStockInformation = marketSituationStore.cardData[currentStockIndex.value];
updateStockInformation(nextStockInformation);
}
} else if (currentStockFrom.value == "marketDetail") {
if (currentStockIndex.value == marketSituationStore.marketDetailCardData.length) {
uni.showToast({
title: "没有更多股票了",
icon: "none",
duration: 1000,
});
return;
} else {
currentStockIndex.value++;
nextStockInformation = marketSituationStore.marketDetailCardData[currentStockIndex.value];
updateStockInformation(nextStockInformation);
}
} else if (currentStockFrom.value == "globalIndex") {
if (currentStockIndex.value == marketSituationStore.gloablCardData[currentStockParentIndex.value].list.length) {
uni.showToast({
title: "没有更多股票了",
icon: "none",
duration: 1000,
});
return;
} else {
currentStockIndex.value++;
nextStockInformation = marketSituationStore.gloablCardData[currentStockParentIndex.value].list[currentStockIndex.value];
updateStockInformation(nextStockInformation);
}
} else {
uni.showToast({
title: "没有更多股票了",
@ -544,6 +748,38 @@ const toRightPage = () => {
}
};
const updateStockInformation = (stock) => {
klineTab.value = 1;
stockInformation.value.stockName = stock.stockName||stock.name;
stockInformation.value.stockCode = stock.stockCode||stock.code;
sendTcpMessage("stop_real_time");
sendTcpMessage("init_real_time");
};
const goToIndexRepository = () => {
uni.showToast({
title: "指标仓库",
icon: "none",
duration: 1000,
});
};
const goToFunction = () => {
uni.showToast({
title: "功能",
icon: "none",
duration: 1000,
});
};
const goToFavorites = () => {
uni.showToast({
title: "加自选",
icon: "none",
duration: 1000,
});
};
const openStockDetail = () => {
isStockDetail.value = true;
};
@ -1451,11 +1687,6 @@ const initTcpListeners = () => {
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) {
@ -1600,11 +1831,6 @@ const sendTcpMessage = (command) => {
break;
}
if (!messageData) {
uni.showToast({
title: "命令不存在",
icon: "none",
duration: 1000,
});
return;
} else {
try {
@ -1612,19 +1838,9 @@ const sendTcpMessage = (command) => {
const success = tcpConnection.send(messageData);
if (success) {
console.log("home发送TCP消息:", messageData);
uni.showToast({
title: "消息发送成功",
icon: "success",
duration: 1000,
});
}
} catch (error) {
console.error("发送TCP消息时出错:", error);
uni.showToast({
title: "消息发送失败",
icon: "none",
duration: 1000,
});
}
}
};
@ -2177,8 +2393,8 @@ onLoad((options) => {
// stockInformation
if (stockData) {
stockInformation.value.stockName = stockData.stockName;
stockInformation.value.stockCode = stockData.stockCode;
stockInformation.value.stockName = stockData.stockName||stockData.name;
stockInformation.value.stockCode = stockData.stockCode||stockData.code;
}
} catch (error) {
console.error("解析股票数据失败:", error);
@ -2193,16 +2409,24 @@ onLoad((options) => {
currentStockIndex.value = stockIndex;
}
// index
if (options.parentIndex) {
const stockParentIndex = parseInt(options.parentIndex);
console.log("股票在列表中的父索引:", stockParentIndex);
// index
currentStockParentIndex.value = stockParentIndex;
}
// stockFrom
if (options.stockFrom) {
currentStockFrom.value = options.stockFrom;
if (options.from) {
currentStockFrom.value = options.from;
}
});
//
onUnmounted(() => {
removeTcpListeners();
disconnect();
disconnectTcp();
if (timer) {
console.log("卸载定时器");
clearInterval(timer);

340
pages/marketSituation/marketDetail.vue

@ -36,19 +36,19 @@
<scroll-view class="content" :style="{ top: contentTopPosition + 'px' }" scroll-y="true">
<!-- 股票列表 -->
<view class="stock-list">
<view class="stock-row" v-for="(stock, index) in sortedStockList" :key="index" @click="viewIndexDetail(stock)">
<view class="stock-row" v-for="(item,index) in sortedStockList" :key="item" @click="viewIndexDetail(item,index)">
<view class="stock-cell name-column">
<view class="stock-name">{{ stock.stockName }}</view>
<view class="stock-code">{{ stock.stockCode }}</view>
<view class="stock-name">{{ item.stockName }}</view>
<view class="stock-code">{{ item.stockCode }}</view>
</view>
<view class="stock-cell price-column">
<text class="stock-price" :class="stock.isRising ? 'rising' : 'falling'">
{{ typeof stock.price === "number" ? stock.price.toFixed(2) : stock.price }}
<text class="stock-price" :class="item.isRising ? 'rising' : 'falling'">
{{ typeof item.currentPrice === "number" ? item.currentPrice.toFixed(2) : item.currentPrice }}
</text>
</view>
<view class="stock-cell change-column">
<text class="stock-change" :class="stock.isRising ? 'rising' : 'falling'">
{{ stock.change || stock.changePercent }}
<text class="stock-change" :class="item.isRising ? 'rising' : 'falling'">
{{ item.changePercent }}
</text>
</view>
</view>
@ -64,10 +64,12 @@
</template>
<script setup>
import { ref, computed, onMounted, watch } from "vue";
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import footerBar from "@/components/footerBar.vue";
import { getRegionalGroupListAPI } from "../../api/marketSituation/marketSituation.js";
import { useMarketSituationStore } from "../../stores/modules/marketSituation.js";
const marketSituationStore = useMarketSituationStore();
//
const iSMT = ref(0);
const contentHeight = ref(0);
@ -185,8 +187,8 @@ const contentTopPosition = computed(() => {
});
const sortedStockList = computed(() => {
console.log("计算sortedStockList,原始数据长度:", stockList.value.length);
let list = [...stockList.value];
console.log("计算sortedStockList,原始数据长度:", marketSituationStore.marketDetailCardData.length);
let list = [...marketSituationStore.marketDetailCardData];
if (sortType.value === "price") {
list.sort((a, b) => {
@ -194,8 +196,8 @@ const sortedStockList = computed(() => {
});
} else if (sortType.value === "change") {
list.sort((a, b) => {
const aChange = parseFloat(a.change.replace(/[+%-]/g, ""));
const bChange = parseFloat(b.change.replace(/[+%-]/g, ""));
const aChange = parseFloat(a.changePercent.replace(/[+%-]/g, ""));
const bChange = parseFloat(b.changePercent.replace(/[+%-]/g, ""));
return sortOrder.value === "asc" ? aChange - bChange : bChange - aChange;
});
}
@ -210,35 +212,23 @@ const getRegionalGroupList = async () => {
name: marketTitle.value,
});
regionalGroupArray.value = result.data;
marketSituationStore.marketDetailCardData = result.data;
} catch (e) {
console.error("获取区域分组列表失败:", e);
}
};
//
onLoad(async (options) => {
if (options && options.market) {
marketTitle.value = options.market;
await getRegionalGroupList();
}
});
//
const goBack = () => {
uni.navigateBack();
};
//
const viewIndexDetail = (item) => {
const viewIndexDetail = (item,index) => {
console.log("查看指数详情:", item.stockName);
// uni.showToast({
// title: ` ${item.stockName} `,
// icon: 'none',
// duration: 2000
// })
//
uni.navigateTo({
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}`,
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}&index=${index}&from=marketDetail`,
});
};
@ -260,6 +250,302 @@ const sortByChange = () => {
}
};
// TCP
import tcpConnection, { TCPConnection, TCP_CONFIG } from "@/api/tcpConnection.js";
const tcpConnected = ref(false);
const connectionListener = ref(null);
const messageListener = ref(null);
// TCP
const initTcpListeners = () => {
//
connectionListener.value = (status, result) => {
tcpConnected.value = status === "connected";
console.log("TCP连接状态变化:", status, tcpConnected.value);
//
if (status === "connected") {
sendTcpMessage("batch_real_time");
}
};
//
messageListener.value = (type, message, parsedArray) => {
const messageObj = {
type: type,
content: message,
parsedArray: parsedArray,
timestamp: new Date().toLocaleTimeString(),
direction: "received",
};
//
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;
let messageDataArray = [];
if (command == "batch_real_time") {
messageDataArray = regionalGroupArray.value.map((item) => item.code);
}
console.log(messageDataArray);
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 "batch_real_time":
messageData = {
command: "batch_real_time",
stock_codes: messageDataArray,
};
break;
case "help":
messageData = {
command: "help",
};
break;
}
if (!messageData) {
return;
} else {
try {
//
const success = tcpConnection.send(messageData);
if (success) {
console.log("home发送TCP消息:", messageData);
}
} catch (error) {
console.error("发送TCP消息时出错:", error);
}
}
};
// TCP
const getTcpStatus = () => {
const status = tcpConnection.getConnectionStatus();
uni.showModal({
title: "TCP连接状态",
content: `当前状态: ${status ? "已连接" : "未连接"}`,
showCancel: false,
});
};
let isMorePacket = {
init_batch_real_time: false,
batch_real_time: false,
};
let receivedMessage;
// TCP
const parseStockData = (message) => {
try {
console.log("进入parseStockData, message类型:", typeof message);
let parsedMessage;
// isMorePackettrue
// message{JSON
//
if (message.includes("欢迎连接到股票数据服务器")) {
console.log("服务器命令列表,不予处理");
return;
}
if ((typeof message === "string" && message.includes("batch_data_start")) || isMorePacket.init_batch_real_time) {
if (typeof message === "string" && message.includes("batch_data_start")) {
console.log("开始接受分包数据");
receivedMessage = "";
} else {
console.log("接收分包数据过程中");
}
isMorePacket.init_batch_real_time = true;
receivedMessage += message;
// }JSON
if (receivedMessage.includes("batch_data_complete")) {
console.log("接受分包数据结束");
isMorePacket.init_batch_real_time = false;
console.log("展示数据", receivedMessage);
let startIndex = 0;
let startCount = 0;
let endIndex = receivedMessage.indexOf("batch_data_complete");
for (let i = 0; i < receivedMessage.length; ++i) {
if (receivedMessage[i] == "{") {
startCount++;
if (startCount == 2) {
startIndex = i;
break;
}
}
}
for (let i = receivedMessage.indexOf("batch_data_complete"); i >= 0; --i) {
if (receivedMessage[i] == "}" || startIndex == endIndex) {
endIndex = i;
break;
}
}
if (startIndex >= endIndex) {
throw new Error("JSON字符串格式错误");
}
console.log("message", startIndex, endIndex, receivedMessage[endIndex], receivedMessage[startIndex]);
parsedMessage = JSON.parse(receivedMessage.substring(startIndex, endIndex + 1));
console.log("JSON解析成功,解析后类型:", typeof parsedMessage, parsedMessage);
const stockDataArray = parsedMessage.data;
marketSituationStore.marketDetailCardData = regionalGroupArray.value.map((item) => ({
market: item.market,
stockCode: item.code,
stockName: item.name,
id: item.id,
currentPrice: stockDataArray[item.code][0].current_price.toFixed(2),
changeAmount: (stockDataArray[item.code][0].current_price - stockDataArray[item.code][0].pre_close).toFixed(2),
changePercent: ((100 * (stockDataArray[item.code][0].current_price - stockDataArray[item.code][0].pre_close)) / stockDataArray[item.code][0].pre_close).toFixed(2) + "%",
isRising: stockDataArray[item.code][0].current_price - stockDataArray[item.code][0].pre_close >= 0,
}));
}
} else if ((typeof message === "string" && message.includes('{"count')) || isMorePacket.batch_real_time) {
if (typeof message === "string" && message.includes('{"count')) {
console.log("开始接受分包数据");
receivedMessage = "";
} else {
console.log("接收分包数据过程中");
}
isMorePacket.batch_real_time = true;
receivedMessage += message;
// }JSON
if (receivedMessage.includes("batch_realtime_data")) {
console.log("接受分包数据结束");
isMorePacket.batch_real_time = false;
console.log("展示数据", receivedMessage);
let startIndex = 0;
let endIndex = receivedMessage.length - 1;
for (let i = 0; i < receivedMessage.length; ++i) {
if (receivedMessage[i] == "{") {
startIndex = i;
break;
}
}
for (let i = receivedMessage.length - 1; i >= 0; --i) {
if (receivedMessage[i] == "}" || startIndex == endIndex) {
endIndex = i;
break;
}
}
if (startIndex >= endIndex) {
throw new Error("JSON字符串格式错误");
}
parsedMessage = JSON.parse(receivedMessage.substring(startIndex, endIndex + 1));
console.log("JSON解析成功,解析后类型:", typeof parsedMessage, parsedMessage);
const stockDataArray = parsedMessage.data;
marketSituationStore.marketDetailCardData = regionalGroupArray.value.map((item) => ({
market: item.market,
stockCode: item.code,
stockName: item.name,
id: item.id,
currentPrice: stockDataArray[item.code][0].current_price.toFixed(2),
changeAmount: (stockDataArray[item.code][0].current_price - stockDataArray[item.code][0].pre_close).toFixed(2),
changePercent: ((100 * (stockDataArray[item.code][0].current_price - stockDataArray[item.code][0].pre_close)) / stockDataArray[item.code][0].pre_close).toFixed(2) + "%",
isRising: stockDataArray[item.code][0].current_price - stockDataArray[item.code][0].pre_close >= 0,
}));
}
} 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消息监听器");
}
};
const startTcp = () => {
try {
removeTcpListeners();
disconnectTcp();
initTcpListeners();
connectTcp();
} catch (error) {
console.error("建立连接并设置监听出错:", error);
}
};
//
onLoad(async (options) => {
if (options && options.market) {
marketTitle.value = options.market;
await getRegionalGroupList();
initTcpListeners();
await nextTick();
//
startTcp();
}
});
onUnmounted(() => {
sendTcpMessage("stop_real_time");
removeTcpListeners();
disconnectTcp();
});
onMounted(() => {
//
iSMT.value = uni.getSystemInfoSync().statusBarHeight;

290
pages/marketSituation/marketOverview.vue

@ -46,7 +46,7 @@
</template>
<script setup>
import { ref, onMounted, watch, nextTick, computed } from "vue";
import { ref, onMounted, onUnmounted, watch, nextTick, computed } from "vue";
import util from "../../common/util.js";
import IndexCard from "../../components/IndexCard.vue";
import { useMarketSituationStore } from "../../stores/modules/marketSituation.js";
@ -168,8 +168,296 @@ const getGlobalIndex = async () => {
}
};
// TCP
import tcpConnection, { TCPConnection, TCP_CONFIG } from "@/api/tcpConnection.js";
const tcpConnected = ref(false);
const connectionListener = ref(null);
const messageListener = ref(null);
// TCP
const initTcpListeners = () => {
//
connectionListener.value = (status, result) => {
tcpConnected.value = status === "connected";
console.log("TCP连接状态变化:", status, tcpConnected.value);
//
if (status === "connected") {
sendTcpMessage("batch_real_time");
}
};
//
messageListener.value = (type, message, parsedArray) => {
const messageObj = {
type: type,
content: message,
parsedArray: parsedArray,
timestamp: new Date().toLocaleTimeString(),
direction: "received",
};
//
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;
let messageDataArray = [];
if (command == "batch_real_time") {
messageDataArray = globalIndexArray.value.map((item) => item.stockCode);
}
console.log(messageDataArray);
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 "batch_real_time":
messageData = {
command: "batch_real_time",
stock_codes: messageDataArray,
};
break;
case "help":
messageData = {
command: "help",
};
break;
}
if (!messageData) {
return;
} else {
try {
//
const success = tcpConnection.send(messageData);
if (success) {
console.log("home发送TCP消息:", messageData);
}
} catch (error) {
console.error("发送TCP消息时出错:", error);
}
}
};
// TCP
const getTcpStatus = () => {
const status = tcpConnection.getConnectionStatus();
uni.showModal({
title: "TCP连接状态",
content: `当前状态: ${status ? "已连接" : "未连接"}`,
showCancel: false,
});
};
let isMorePacket = {
init_batch_real_time: false,
batch_real_time: false,
};
let receivedMessage;
// TCP
const parseStockData = (message) => {
try {
console.log("进入parseStockData, message类型:", typeof message);
let parsedMessage;
// isMorePackettrue
// message{JSON
//
if (message.includes("欢迎连接到股票数据服务器")) {
console.log("服务器命令列表,不予处理");
return;
}
if ((typeof message === "string" && message.includes("batch_data_start")) || isMorePacket.init_batch_real_time) {
if (typeof message === "string" && message.includes("batch_data_start")) {
console.log("开始接受分包数据");
receivedMessage = "";
} else {
console.log("接收分包数据过程中");
}
isMorePacket.init_batch_real_time = true;
receivedMessage += message;
// }JSON
if (receivedMessage.includes("batch_data_complete")) {
console.log("接受分包数据结束");
isMorePacket.init_batch_real_time = false;
console.log("展示数据", receivedMessage);
let startIndex = 0;
let startCount = 0;
let endIndex = receivedMessage.indexOf("batch_data_complete");
for (let i = 0; i < receivedMessage.length; ++i) {
if (receivedMessage[i] == "{") {
startCount++;
if (startCount == 2) {
startIndex = i;
break;
}
}
}
for (let i = receivedMessage.indexOf("batch_data_complete"); i >= 0; --i) {
if (receivedMessage[i] == "}" || startIndex == endIndex) {
endIndex = i;
break;
}
}
if (startIndex >= endIndex) {
throw new Error("JSON字符串格式错误");
}
console.log("message", startIndex, endIndex, receivedMessage[endIndex], receivedMessage[startIndex]);
parsedMessage = JSON.parse(receivedMessage.substring(startIndex, endIndex + 1));
console.log("JSON解析成功,解析后类型:", typeof parsedMessage, parsedMessage);
const stockDataArray = parsedMessage.data;
marketSituationStore.cardData = globalIndexArray.value.map((item) => ({
market: item.market,
stockCode: item.stockCode,
stockName: item.stockName,
currentPrice: stockDataArray[item.stockCode][0].current_price.toFixed(2),
changeAmount: (stockDataArray[item.stockCode][0].current_price - stockDataArray[item.stockCode][0].pre_close).toFixed(2),
changePercent: ((100 * (stockDataArray[item.stockCode][0].current_price - stockDataArray[item.stockCode][0].pre_close)) / stockDataArray[item.stockCode][0].pre_close).toFixed(2) + "%",
isRising: stockDataArray[item.stockCode][0].current_price - stockDataArray[item.stockCode][0].pre_close >= 0,
}));
}
} else if ((typeof message === "string" && message.includes('{"count')) || isMorePacket.batch_real_time) {
if (typeof message === "string" && message.includes('{"count')) {
console.log("开始接受分包数据");
receivedMessage = "";
} else {
console.log("接收分包数据过程中");
}
isMorePacket.batch_real_time = true;
receivedMessage += message;
// }JSON
if (receivedMessage.includes("batch_realtime_data")) {
console.log("接受分包数据结束");
isMorePacket.batch_real_time = false;
console.log("展示数据", receivedMessage);
let startIndex = 0;
let endIndex = receivedMessage.length - 1;
for (let i = 0; i < receivedMessage.length; ++i) {
if (receivedMessage[i] == "{") {
startIndex = i;
break;
}
}
for (let i = receivedMessage.length - 1; i >= 0; --i) {
if (receivedMessage[i] == "}" || startIndex == endIndex) {
endIndex = i;
break;
}
}
if (startIndex >= endIndex) {
throw new Error("JSON字符串格式错误");
}
parsedMessage = JSON.parse(receivedMessage.substring(startIndex, endIndex + 1));
console.log("JSON解析成功,解析后类型:", typeof parsedMessage, parsedMessage);
const stockDataArray = parsedMessage.data;
marketSituationStore.cardData = globalIndexArray.value.map((item) => ({
market: item.market,
stockCode: item.stockCode,
stockName: item.stockName,
currentPrice: stockDataArray[item.stockCode][0].current_price.toFixed(2),
changeAmount: (stockDataArray[item.stockCode][0].current_price - stockDataArray[item.stockCode][0].pre_close).toFixed(2),
changePercent: ((100 * (stockDataArray[item.stockCode][0].current_price - stockDataArray[item.stockCode][0].pre_close)) / stockDataArray[item.stockCode][0].pre_close).toFixed(2) + "%",
isRising: stockDataArray[item.stockCode][0].current_price - stockDataArray[item.stockCode][0].pre_close >= 0,
}));
}
} 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消息监听器");
}
};
const startTcp = () => {
try {
removeTcpListeners();
disconnectTcp();
initTcpListeners();
connectTcp();
} catch (error) {
console.error("建立连接并设置监听出错:", error);
}
};
onUnmounted(() => {
sendTcpMessage("stop_real_time");
removeTcpListeners();
disconnectTcp();
});
onMounted(async () => {
await getGlobalIndex();
initTcpListeners();
await nextTick();
//
startTcp();
//
iSMT.value = uni.getSystemInfoSync().statusBarHeight;

25
pages/marketSituation/marketSituation.vue

@ -37,7 +37,7 @@
<!-- 可滚动内容区域 -->
<scroll-view class="content_scroll" scroll-y="true" :style="{ top: contentTopPosition + 'px' }">
<!-- 动态组件切换 -->
<component :is="currentComponent" :countryId="currentChannelId" :marketTabs="getChildMarketTabs(currentChannelId)" />
<component :is="currentComponent" :countryId="currentChannelId" :marketTabs="getChildMarketTabs(currentChannelId)" :tabData="currentTabData"/>
</scroll-view>
</view>
@ -61,6 +61,7 @@
</view>
</view>
</view>
<LoginPrompt ref="loginPrompt"></LoginPrompt>
</view>
</template>
@ -70,12 +71,13 @@ import footerBar from "../../components/footerBar.vue";
import forexMetals from "./forexMetals.vue";
import marketOverview from "./marketOverview.vue";
import countryMarket from "./countryMarket.vue";
import { getAllTabsAPI } from "../../api/marketSituation/marketSituation.js";
import { getAllTabsAPI, queryStockDataAPI } from "../../api/marketSituation/marketSituation.js";
const type = ref("marketSituation");
const iSMT = ref(0);
const searchValue = ref("");
const contentHeight = ref(0);
const headerHeight = ref(0); // header
const currentTabData = ref(null);
// Tab
const channelData = ref([{ id: 1, title: "概况" }]);
@ -191,11 +193,18 @@ const navClick = (index) => {
//
selectedCountry.value = currentItem.title;
uni.showToast({
title: `切换到: ${currentItem.title}`,
icon: "none",
});
// tab
queryStockDataAPI({
parentId: currentItem.id,
tradeId: 1,
}).then((res) => {
if (res.code == 200) {
currentTabData.value = {
type: 'country',
data: res.data
};
}
});
// tab
console.log("当前选中的 tab:", currentItem);
};
@ -586,4 +595,4 @@ watch(headerHeight, (newHeight) => {
.country_item.selected .country_text {
color: #fff;
}
</style>
</style>

39
pages/morningMarketAnalysis/morningMarketAnalysis.vue

@ -1,6 +1,13 @@
<template>
<view>
早盘解析页面
<view class="container">
<view class="content">
<image
class="no-data-image"
src="https://d31zlh4on95l9h.cloudfront.net/images/f5a9bd32c81bc7cca47252b51357c12f.png"
mode="aspectFit"
></image>
<text class="no-data-text">暂无数据~</text>
</view>
</view>
</template>
@ -18,5 +25,31 @@
</script>
<style>
.container {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
}
</style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.no-data-image {
width: 200px;
height: 200px;
margin-bottom: 20px;
}
.no-data-text {
font-size: 16px;
color: #999999;
text-align: center;
}
</style>

29
pages/setting/account.vue

@ -27,9 +27,7 @@
</view>
<view class="setting-item" @click="goToPassword">
<text class="item-label">
<template #default>
{{ userInfoRes.hasPwd === 0 ? '创建密码' : '修改密码' }}
</template>
</text>
<uni-icons type="arrowright" size="16"></uni-icons>
</view>
@ -67,19 +65,34 @@
ref,
onMounted
} from 'vue'
import {useUserStore} from "../../stores/modules/userInfo"
import {
getUserInfo
} from "@/api/member";
} from "@/api/member"
import {
useUserStore
} from "../../stores/modules/userInfo"
const userStore = useUserStore()
const iSMT = ref(0)
// const dccode = ref('')
const userInfoRes = ref({})
const showLogout = ref(false)
const userStore = useUserStore()
const handleConfirmLogout = () => {
const userInfoPromise = getUserInfo()
userInfoPromise.then(res => {
if (res.code === 200) {
userInfoRes.value.dccode = res.data.dccode;
userInfoRes.value.dcname = res.data.dcname;
userInfoRes.value.hasPwd = res.data.hasPassword;
console.log('用户信息', userInfoRes.value)
} else {
uni.showToast({
title: '用户信息请求失败',
icon: 'none',
})
}
})
const handleConfirmLogout = () => {
userStore.clearUserInfo()
showLogout.value = false
uni.showToast({

11
pages/setting/bind.vue

@ -8,7 +8,9 @@
<view class="top-list" @click="goToBindPhone">
<text class="label">手机号</text>
<view class="right">
<text style="font-size: 28rpx;">未绑定</text>
<text style="font-size: 28rpx;">
{{ userStore.userInfo?.phone || '未绑定' }}
</text>
<uni-icons type="arrowright" size="16" />
</view>
</view>
@ -16,7 +18,9 @@
<view class="top-list" @click="goToBindEmail">
<text class="label">邮箱</text>
<view class="right">
<text style="font-size: 28rpx;">analsak@163.com</text>
<text style="font-size: 28rpx;">
{{ userStore.userInfo?.email || '未绑定' }}
</text>
<uni-icons type="arrowright" size="16" />
</view>
</view>
@ -29,6 +33,8 @@
ref,
onMounted
} from 'vue'
import { useUserStore } from "../../stores/modules/userInfo"
const userStore = useUserStore()
const iSMT = ref(0)
const goToBindPhone = () =>{
uni.navigateTo({
@ -46,6 +52,7 @@
//
iSMT.value = uni.getSystemInfoSync().statusBarHeight;
console.log('看看高度', iSMT.value)
console.log('看看用户信息',userStore.userInfo)
})
</script>

26
pages/setting/createPwd.vue

@ -83,13 +83,24 @@
}
const goToPwdNext = async () => {
if (!userEmail.value) {
uni.showToast({
title: '请输入邮箱',
icon: 'none'
})
return
const goToPwdNext = async () => {
console.log('发请求之前的activeTab', activeTab.value)
if (activeTab.value === 'email') {
if (!userEmail.value) {
uni.showToast({
title: '请输入邮箱',
icon: 'none'
})
return
}
} else {
if (!userPhone.value) {
uni.showToast({
title: '请输入手机号',
icon: 'none'
})
return
}
}
if (!verifyCode.value) {
uni.showToast({
@ -99,6 +110,7 @@ const goToPwdNext = async () => {
return
}
try {
let param;
if (activeTab.value === 'email') {

48
pages/setting/font.vue

@ -5,17 +5,17 @@
<view class="top-list">
<text>标准</text>
<radio value="0" class="radio-btn" activeBackgroundColor="red" :checked="selectedIndex === 0"
@click="selectFont(0)" />
@click="selectFont('small')" />
</view>
<view class="top-list">
<text>中号</text>
<radio value="1" class="radio-btn" activeBackgroundColor="red" :checked="selectedIndex === 1"
@click="selectFont(1)" />
@click="selectFont('medium')" />
</view>
<view class="top-list">
<text>大号</text>
<radio value="2" class="radio-btn" activeBackgroundColor="red" :checked="selectedIndex === 2"
@click="selectFont(2)" />
@click="selectFont('large')" />
</view>
</view>
</view>
@ -27,32 +27,50 @@
onMounted
} from 'vue'
import {
getSetting
getSetting,
updateSetting
} from "@/api/setting/general"
const iSMT = ref(0)
const selectedIndex = ref(0)
const fontTypeMap = {
'small': 0,
'medium': 1,
'large': 2
}
const getFont = async () => {
try {
const res = await getSetting()
if (res.code === 200) {
const fontSize = res.data.fontSize
const sizeMap = {
small: 0,
medium: 1,
large: 2
}
console.log('看看字体', res.data.fontSize)
selectedIndex.value = sizeMap[fontSize] ?? 0;
selectedIndex.value = fontTypeMap[fontSize] ?? 0
}
} catch (err) {
console.error("获取字体设置失败:", err);
console.error("获取字体设置失败:", err)
}
}
const selectFont = (index) => {
selectedIndex.value = index
console.log('看看选中状态', selectedIndex.value)
const selectFont = async (fontType) => {
try {
selectedIndex.value = fontTypeMap[fontType]
console.log('字体类型:', fontType, ',looklook索引:', selectedIndex.value)
const updateRes = await updateSetting({
fontSize: fontType
})
if (updateRes.code === 200) {
uni.showToast({
title: '字体大小设置成功',
icon: 'none'
})
}
} catch (err) {
console.error("更新字体设置失败:", err)
uni.showToast({
title: '设置失败,请重试',
icon: 'none'
})
}
}
onMounted(() => {
//

198
pages/setting/market.vue

@ -8,83 +8,138 @@
<view style="height:57.5vh;background-color: white;">
<view class="title">A股竞价</view>
<view class="top-options">
<view class="option-btn" :class="{ 'active': aStockBid === 0 }" @click="aStockBid = 0">
<view
class="option-btn"
:class="{ 'active': aStockBid === 'auto' }"
@click="handleAStockBidChange('auto')"
>
<text>智能开启</text>
<view class="active-dot" v-if="aStockBid === 0"></view>
<view class="active-dot" v-if="aStockBid === 'auto'"></view>
</view>
<view class="option-btn" :class="{ 'active': aStockBid === 1 }" @click="aStockBid = 1">
<view
class="option-btn"
:class="{ 'active': aStockBid === 'open' }"
@click="handleAStockBidChange('open')"
>
<text>保持开启</text>
<view class="active-dot" v-if="aStockBid === 1"></view>
<view class="active-dot" v-if="aStockBid === 'open'"></view>
</view>
<view class="option-btn" :class="{ 'active': aStockBid === 2 }" @click="aStockBid = 2">
<view
class="option-btn"
:class="{ 'active': aStockBid === 'close' }"
@click="handleAStockBidChange('close')"
>
<text>保持关闭</text>
<view class="active-dot" v-if="aStockBid === 2"></view>
<view class="active-dot" v-if="aStockBid === 'close'"></view>
</view>
</view>
<view class="title">K线样式</view>
<view class="top-options">
<view class="option-btn" :class="{ 'active': kStyle === 0 }" @click="kStyle = 0">
<view
class="option-btn"
:class="{ 'active': kStyle === 'common' }"
@click="handleKStyleChange('common')"
>
<img src="/static/my/common.png" class="kline-icon" />
<text>普通</text>
<view class="active-dot" v-if="kStyle === 0"></view>
<view class="active-dot" v-if="kStyle === 'common'"></view>
</view>
<view class="option-btn" :class="{ 'active': kStyle === 1 }" @click="kStyle = 1">
<view
class="option-btn"
:class="{ 'active': kStyle === 'Outline' }"
@click="handleKStyleChange('Outline')"
>
<img src="/static/my/outline.png" class="kline-icon" />
<text>轮廓图</text>
<view class="active-dot" v-if="kStyle === 1"></view>
<view class="active-dot" v-if="kStyle === 'Outline'"></view>
</view>
<view class="option-btn" :class="{ 'active': kStyle === 2 }" @click="kStyle = 2">
<view
class="option-btn"
:class="{ 'active': kStyle === 'polylines' }"
@click="handleKStyleChange('polylines')"
>
<img src="/static/my/polylines.png" class="kline-icon" />
<text>折线图</text>
<view class="active-dot" v-if="kStyle === 2"></view>
<view class="active-dot" v-if="kStyle === 'polylines'"></view>
</view>
</view>
<view class="title">除权类型</view>
<view class="top-options">
<view class="option-btn" :class="{ 'active': exRights === 0 }" @click="exRights = 0">
<view
class="option-btn"
:class="{ 'active': exRights === 'exRights' }"
@click="handleExRightsChange('exRights')"
>
<text>除权</text>
<view class="active-dot" v-if="exRights === 0"></view>
<view class="active-dot" v-if="exRights === 'exRights'"></view>
</view>
<view class="option-btn" :class="{ 'active': exRights === 1 }" @click="exRights = 1">
<view
class="option-btn"
:class="{ 'active': exRights === 'normal' }"
@click="handleExRightsChange('normal')"
>
<text>普通</text>
<view class="active-dot" v-if="exRights === 1"></view>
<view class="active-dot" v-if="exRights === 'normal'"></view>
</view>
<view class="option-btn" :class="{ 'active': exRights === 2 }" @click="exRights = 2">
<view
class="option-btn"
:class="{ 'active': exRights === 'Weighted' }"
@click="handleExRightsChange('Weighted')"
>
<text>加权</text>
<view class="active-dot" v-if="exRights === 2"></view>
<view class="active-dot" v-if="exRights === 'Weighted'"></view>
</view>
</view>
<view class="title">涨跌颜色</view>
<view class="top-options">
<view class="option-btn" :class="{ 'active': rfColor === 0 }" @click="rfColor = 0">
<view
class="option-btn"
:class="{ 'active': rfColor === 'green' }"
@click="handleRfColorChange('green')"
>
<view class="color-icon">
<img src="/static/my/greenRise.png" class="kline-icon" />
</view>
<text>绿涨红跌</text>
<view class="active-dot" v-if="rfColor === 0"></view>
<view class="active-dot" v-if="rfColor === 'green'"></view>
</view>
<view class="option-btn" :class="{ 'active': rfColor === 1 }" @click="rfColor = 1">
<view
class="option-btn"
:class="{ 'active': rfColor === 'red' }"
@click="handleRfColorChange('red')"
>
<view class="color-icon">
<img src="/static/my/redRise.png" class="kline-icon" />
</view>
<text>红涨绿跌</text>
<view class="active-dot" v-if="rfColor === 1"></view>
<view class="active-dot" v-if="rfColor === 'red'"></view>
</view>
</view>
<view class="title">副图指标个数</view>
<view class="top-options">
<view class="option-btn" :class="{ 'active': indexCount === 0 }" @click="indexCount = 0">
<view
class="option-btn"
:class="{ 'active': indexCount === 1 }"
@click="handleIndexCountChange(1)"
>
<text>1</text>
</view>
<view class="option-btn" :class="{ 'active': indexCount === 1 }" @click="indexCount = 1">
<view
class="option-btn"
:class="{ 'active': indexCount === 2 }"
@click="handleIndexCountChange(2)"
>
<text>2</text>
</view>
<view class="option-btn" :class="{ 'active': indexCount === 2 }" @click="indexCount = 2">
<view
class="option-btn"
:class="{ 'active': indexCount === 3 }"
@click="handleIndexCountChange(3)"
>
<text>3</text>
</view>
</view>
@ -107,20 +162,91 @@
</template>
<script setup>
import {
ref,
onMounted
} from 'vue'
import { ref, onMounted } from 'vue'
import { getMarketSetting, updateMarketSetting } from "@/api/setting/market"
const iSMT = ref(0)
const aStockBid = ref(0) // Stock bidding
const kStyle = ref(0) // k线
const exRights = ref(0) // Ex-rights
const rfColor = ref(0) // rise-fall
const indexCount = ref(0) //
const aStockBid = ref('auto') // Aauto/open/close
const kStyle = ref('common') // K线common/Outline/polylines
const exRights = ref('exRights') // exRights/normal/Weighted
const rfColor = ref('green') // green/red
const indexCount = ref(1) // 1/2/3
const indicatorList = ref(['K线', '均线', '成交量', 'KDJ', 'MACD', 'RSI'])
const getMarketSettings = async () => {
try {
const res = await getMarketSetting()
if (res.code === 200) {
aStockBid.value = res.data.auctionDisplay ?? 'auto'
kStyle.value = res.data.klineStyle ?? 'common'
exRights.value = res.data.rightsIssueType ?? 'exRights'
rfColor.value = res.data.priceColorScheme ?? 'green'
indexCount.value = res.data.subChartCount ?? 1
}
} catch (err) {
console.error("获取市场设置失败:", err)
}
}
const updateSetting = async () => {
try {
const params = {
auctionDisplay: aStockBid.value,
klineStyle: kStyle.value,
rightsIssueType: exRights.value,
priceColorScheme: rfColor.value,
subChartCount: indexCount.value
}
const res = await updateMarketSetting(params)
if (res.code === 200) {
uni.showToast({ title: '设置已更新', icon: 'none' })
} else {
uni.showToast({ title: '更新失败', icon: 'none' })
}
} catch (err) {
console.error("更新设置失败:", err)
uni.showToast({ title: '更新失败', icon: 'none' })
}
}
const handleAStockBidChange = (newValue) => {
if (newValue !== aStockBid.value) {
aStockBid.value = newValue
updateSetting()
}
}
const handleKStyleChange = (newValue) => {
if (newValue !== kStyle.value) {
kStyle.value = newValue
updateSetting()
}
}
const handleExRightsChange = (newValue) => {
if (newValue !== exRights.value) {
exRights.value = newValue
updateSetting()
}
}
const handleRfColorChange = (newValue) => {
if (newValue !== rfColor.value) {
rfColor.value = newValue
updateSetting()
}
}
const handleIndexCountChange = (newValue) => {
if (newValue !== indexCount.value) {
indexCount.value = newValue
updateSetting()
}
}
onMounted(() => {
iSMT.value = uni.getSystemInfoSync().statusBarHeight;
getMarketSettings()
})
</script>
@ -206,7 +332,7 @@
.indicator-text {
font-size: 28rpx;
flex:1;
flex: 1;
}
.indicator-icons {

10
pages/setting/password.vue

@ -84,6 +84,7 @@
}
const goToPwdNext = async () => {
if (activeTab.value === 'email') {
if (!userEmail.value) {
uni.showToast({
title: '请输入邮箱',
@ -91,6 +92,15 @@ const goToPwdNext = async () => {
})
return
}
}else{
if (!userPhone.value) {
uni.showToast({
title: '请输入手机号',
icon: 'none'
})
return
}
}
if (!verifyCode.value) {
uni.showToast({
title: '请输入验证码',

48
pages/setting/server.vue

@ -5,17 +5,17 @@
<view class="top-list">
<text>自动选择</text>
<radio value="0" class="radio-btn" activeBackgroundColor="red"
:checked="selectedIndex === 0" @click="selectFont(0)" />
:checked="selectedIndex === 0" @click="selectFont('auto')" />
</view>
<view class="top-list">
<text>新加坡服务器</text>
<radio value="1" class="radio-btn" activeBackgroundColor="red"
:checked="selectedIndex === 1" @click="selectFont(1)" />
:checked="selectedIndex === 1" @click="selectFont('singapore')" />
</view>
<view class="top-list">
<text>香港服务器</text>
<radio value="2" class="radio-btn" activeBackgroundColor="red"
:checked="selectedIndex === 2" @click="selectFont(2)" />
:checked="selectedIndex === 2" @click="selectFont('hongkong')" />
</view>
</view>
</view>
@ -27,33 +27,51 @@
onMounted
} from 'vue'
import {
getSetting
getSetting,
updateSetting
} from "@/api/setting/general"
const iSMT = ref(0)
const selectedIndex = ref(0)
const servertypeMap = {
'auto': 0,
'singapore': 1,
'hongkong': 2
}
const getServer = async () => {
try {
const res = await getSetting()
if (res.code === 200) {
const fontSize = res.data.fontSize
const sizeMap = {
'auto': 0,
'singapore': 1,
'hongkong': 2
}
console.log('看看服务器', res.data.fontSize)
selectedIndex.value = sizeMap[fontSize] ?? 0;
const serverSelection = res.data.serverSelection
selectedIndex.value = servertypeMap[serverSelection] ?? 0;
}
} catch (err) {
console.error("获取服务器设置失败:", err);
}
}
const selectFont = (index) => {
selectedIndex.value = index
console.log('看看选中状态',selectedIndex.value)
const selectFont = async (servertype) => {
try {
selectedIndex.value = servertypeMap[servertype]
console.log('服务器类型:', servertype, ',looklook索引:', selectedIndex.value)
const updateRes = await updateSetting({
serverSelection: servertype
})
if (updateRes.code === 200) {
uni.showToast({
title: '服务器大小设置成功',
icon: 'none'
})
}
} catch (err) {
console.error("更新服务器设置失败:", err);
uni.showToast({
title: '设置失败,请重试',
icon: 'none'
})
}
}
onMounted(() => {

396
pages/setting/share.vue

@ -1,111 +1,299 @@
<template>
<view class="all">
<img class="img-share" src="/static/my/shareBackground.png" />
<img class="img-greenBack" src="/static/my/greenBackground.png" />
<img class="img-QRcode" src="/static/my/QRcode.png" />
<img class="img-award" src="/static/my/award.png" />
<img class="img-myFriends" src="/static/my/myFriends.png" />
<img class="img-friends" src="/static/my/shareFriends.png" />
<text class="jwcode">{{ jwcode }}</text>
<button class="invite">立即邀请</button>
</view>
<view class="all">
<!-- 背景图部分 -->
<image class="img-share" src="/static/my/shareBackground.png"/>
<image class="img-greenBack" src="/static/my/greenBackground.png"/>
<!-- todo 这里给我个码-->
<image class="img-QRcode" src="/static/my/QRcode.png"/>
<image class="img-award" src="/static/my/award.png"/>
<image class="img-myFriends" src="/static/my/myFriends.png"/>
<image class="img-friends" src="/static/my/shareFriends.png"/>
<!-- dccode -->
<text class="jwcode">{{ dccode }}</text>
<!-- 邀请按钮 -->
<button class="invite" @click="openShare">立即邀请</button>
<!-- 分享弹窗 -->
<uni-popup ref="shareRef" type="share" safeArea>
<SharePopup @select="onShareSelect" @close="closeShare" title=" "/>
</uni-popup>
<!-- 二次弹窗 -->
<uni-popup ref="secondPopup" type="share">
<view class="second-popup">
<view style=" display: flex;justify-content: center;align-items: center; font-size: 17px">
<image style="width: 16px; height: 16px; margin-right: 8rpx" src="/static/my/share/success.png"/>
<text>已复制</text>
</view>
<view class="popup-msg-box">
<text>{{ popupMsg }}</text>
</view>
<view style="justify-content: center; align-items: center;">
<!-- 二次弹窗中的按钮图标 -->
<button
style="border-radius: 40rpx; background-color: black; color: white; display: flex; align-items: center; justify-content: center; padding: 12rpx 24rpx;"
@click="closeSecondPopup">
<image style="width: 25px; height: 25px; margin-right: 8rpx;"
:src="platformIconMap[selectedPlatform]"/>
去粘贴给好友
</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script setup>
import {
ref
} from 'vue'
import {ref} from 'vue'
import SharePopup from '@/components/SharePopup.vue'
import {getUserInfo} from "@/api/member";
import {Share} from "@/api/setting/share";
/* =============== 数据与引用 =============== */
const shareRef = ref(null)
const secondPopup = ref(null)
const popupMsg = ref('')
// const jwcode = ref('90047681')
//
const selectedPlatform = ref('')
// dccode
const dccode = ref('')
// token
const token = ref('1ab8f83f391ca866191385d0e5048938')
//
const deviceId = ref(100)
//
const version = ref(100)
//
const client = ref('android')
//
const platformIconMap = ref({
'WeChat': '/static/my/share/WeChat.png',
'WhatsApp': '/static/my/share/WhatsApp.png',
'Line': '/static/my/share/Line.png',
'KakaoTalk': '/static/my/share/KakaoTalk.png',
'复制链接': '/static/my/share/share.png'
})
//
const userInfoRes = ref()
// dccode
const shareLink = ref('')
/* =============== 方法 =============== */
userInfoRes.value = getUserInfo()
userInfoRes.value.then(res => {
dccode.value = res.data.dccode
console.log('用户信息', res.data)
})
const ShareRes = ref()
ShareRes.value = Share()
ShareRes.value.then(res => {
if (res.code === 200){
shareLink.value = res.message
console.log('分享接口返回', res.data)
}else {
console.log('分享接口返回失败', res.data)
}
})
//
function openShare() {
Share()
shareRef.value.open()
}
//
function closeShare() {
shareRef.value.close()
}
//
//
function onShareSelect({item}) {
console.log('选择了:', item.name)
selectedPlatform.value = item.name //
// //
// const baseUrl = 'https:'
// // const shareLink = `${baseUrl}?token=${encodeURIComponent(token.value)}&deviceId=${encodeURIComponent(deviceId.value)}&version=${encodeURIComponent(version.value)}&client=${encodeURIComponent(client.value)}`
// const shareLink = `$ `
//
shareRef.value.close()
popupMsg.value = `【DeepChart】邀请你加入,点击链接帮我助力: ${shareLink.value}`
uni.setClipboardData({
data: popupMsg.value,
showToast: false
});
/* // 根据分享选项显示不同提示
if (item.name === '复制链接') {
popupMsg.value = '链接已复制,快去分享给好友吧~'
} else if (item.name === 'WeChat') {
popupMsg.value = '请在微信中分享~'
} else {
popupMsg.value = `你选择了 ${item.name}`
}*/
//
secondPopup.value.open()
}
//
function closeSecondPopup() {
if (selectedPlatform.value === 'WeChat') {
uni.share({
provider: "weixin",
scene: "WXSceneSession",
type: 1,
summary: popupMsg.value,
success: function (res) {
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
}
});
secondPopup.value.close()
}
//
else if (selectedPlatform.value === 'WhatsApp' || selectedPlatform.value === 'Line' || selectedPlatform.value === 'KakaoTalk') {
secondPopup.value.close()
uni.showToast({title: '开发中……', icon: 'none'})
} else if (selectedPlatform.value === '复制链接') {
uni.showToast({title: '已复制', icon: 'success'})
secondPopup.value.close()
}
}
const jwcode = ref('90047681')
</script>
<style>
.all {
position: relative;
width: 750rpx;
height: auto;
}
.img-share {
width: 750rpx;
height: 2118rpx;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
.img-QRcode{
width:320rpx;
height:320rpx;
position:absolute;
top:26vh;
left:215rpx;
z-index: 3;
}
.img-greenBack {
width: 670rpx;
height: 1740rpx;
position: absolute;
top: 16vh;
/* 为什么要用这个替代 margin-top */
left: 40rpx;
/* 还有 padding-left */
z-index: 2;
}
.img-friends {
width: 602rpx;
height: 840rpx;
position: absolute;
top: 68vh;
left: 74rpx;
z-index: 3;
}
.img-award {
width: 300rpx;
height: 120rpx;
position: absolute;
top: 61vh;
left: 75rpx;
z-index: 3;
}
.img-myFriends {
width: 300rpx;
height: 88rpx;
position: absolute;
top: 61vh;
right: 75rpx;
z-index: 3;
}
.jwcode {
width: 320rpx;
height: 38rpx;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 19vh;
left: 212rpx;
z-index: 999;
}
.invite {
width: 320rpx;
height: 80rpx;
border-radius: 40rpx;
background-color: black;
color:white;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50.7vh;
left: 212rpx;
z-index: 999;
}
</style>
<style scoped>
.all {
position: relative;
width: 750rpx;
height: auto;
}
/* 背景图片部分 */
.img-share {
width: 750rpx;
height: 2118rpx;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
.img-greenBack {
width: 670rpx;
height: 1740rpx;
position: absolute;
top: 16vh;
left: 40rpx;
z-index: 2;
}
.img-QRcode {
width: 320rpx;
height: 320rpx;
position: absolute;
top: 26vh;
left: 215rpx;
z-index: 3;
}
.img-award {
width: 300rpx;
height: 120rpx;
position: absolute;
top: 61vh;
left: 75rpx;
z-index: 3;
}
.img-myFriends {
width: 300rpx;
height: 88rpx;
position: absolute;
top: 61vh;
right: 75rpx;
z-index: 3;
}
.img-friends {
width: 602rpx;
height: 840rpx;
position: absolute;
top: 68vh;
left: 74rpx;
z-index: 3;
}
/* 邀请码与按钮 */
.jwcode {
width: 320rpx;
height: 38rpx;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 19vh;
left: 212rpx;
z-index: 999;
}
.invite {
width: 320rpx;
height: 80rpx;
border-radius: 40rpx;
background-color: black;
color: white;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50.7vh;
left: 212rpx;
z-index: 999;
}
/* 第二个弹窗样式 */
.second-popup {
background-color: #fff;
border-radius: 12px;
padding: 30rpx;
text-align: center;
}
.popup-msg-box {
background-color: #F3F3F3;
border-radius: 8px;
padding: 12px 16px;
margin: 10px;
align-items: center;
justify-content: center;
overflow: hidden; /* 隐藏溢出内容 */
text-overflow: ellipsis; /* 溢出部分显示... */
}
</style>

45
pages/setting/theme.vue

@ -5,12 +5,12 @@
<view class="left">
<image class="img-theme" src="/static/my/whiteTheme.png" mode="widthFix" />
<radio value="0" class="radio-btn" activeBackgroundColor="red" :checked="selectedIndex === 0"
@click="selectFont(0)" />
@click="updateTheme('light')" />
</view>
<view class="left">
<image class="img-theme" src="/static/my/blackTheme.png" mode="widthFix" />
<radio value="1" class="radio-btn" activeBackgroundColor="red" :checked="selectedIndex === 1"
@click="selectFont(1)" />
@click="updateTheme('dark')" />
</view>
</view>
</view>
@ -22,32 +22,51 @@
onMounted
} from 'vue'
import {
getSetting
getSetting,
updateSetting
} from "@/api/setting/general"
const iSMT = ref(0)
const selectedIndex = ref(0)
const themeTypeMap = {
'light': 0,
'dark': 1
}
const getTheme = async () => {
try {
const res = await getSetting()
if (res.code === 200) {
const theme = res.data.theme
const sizeMap = {
'light': 0,
'dark': 1
}
console.log('看看主题', res.data.theme)
selectedIndex.value = sizeMap[theme] ?? 0;
selectedIndex.value = themeTypeMap[theme] ?? 0
}
} catch (err) {
console.error("获取主题设置失败:", err);
}
}
const selectFont = (index) => {
selectedIndex.value = index
console.log('看看选中状态', selectedIndex.value)
const updateTheme = async (themeType) => {
try {
selectedIndex.value = themeTypeMap[themeType]
console.log('主题:', themeType, ',looklook索引:', selectedIndex.value)
const updateRes = await updateSetting({
theme: themeType
})
if (updateRes.code === 200) {
uni.showToast({
title: '主题设置成功',
icon: 'none'
})
}
} catch (err) {
console.error("更新主题设置失败:", err);
uni.showToast({
title: '设置失败,请重试',
icon: 'none'
})
}
}
onMounted(() => {
//
iSMT.value = uni.getSystemInfoSync().statusBarHeight;

BIN
static/my/share/KakaoTalk.png

After

Width: 42  |  Height: 42  |  Size: 2.5 KiB

BIN
static/my/share/Line.png

After

Width: 42  |  Height: 42  |  Size: 2.2 KiB

BIN
static/my/share/WeChat.png

After

Width: 42  |  Height: 42  |  Size: 2.4 KiB

BIN
static/my/share/WhatsApp.png

After

Width: 42  |  Height: 42  |  Size: 3.6 KiB

BIN
static/my/share/share.png

After

Width: 42  |  Height: 42  |  Size: 1.3 KiB

BIN
static/my/share/success.png

After

Width: 32  |  Height: 32  |  Size: 1.6 KiB

55
stores/modules/marketSituation.js

@ -6,57 +6,14 @@ import { ref } from "vue";
export const useMarketSituationStore = defineStore(
"marketSituation",
() => {
const cardData = ref([
{
market: "usa",
stockName: "道琼斯",
stockCode: "noCode",
currentPrice: "45757.90",
changeAmount: "-125.22",
changePercent: "-0.27%",
isRising: false,
},
{
market: "usa",
stockName: "纳斯达克",
stockCode: "noCode",
currentPrice: "22333.96",
changeAmount: "+125.22",
changePercent: "+0.47%",
isRising: true,
},
{
market: "usa",
stockName: "标普500",
stockCode: "noCode",
currentPrice: "6606.08",
changeAmount: "+125.22",
changePercent: "+0.27%",
isRising: true,
},
{
market: "cn",
stockName: "上证指数",
stockCode: "noCode",
currentPrice: "3333.96",
changeAmount: "+125.22",
changePercent: "+0.27%",
isRising: true,
},
{
market: "cn",
stockName: "科创50",
stockCode: "noCode",
currentPrice: "757.90",
changeAmount: "-25.22",
changePercent: "-0.27%",
isRising: false,
},
]);
const cardData = ref([]);
const gloablCardData = ref([]);
const marketDetailCardData = ref([]);
// 记得 return
return {
cardData
cardData,
gloablCardData,
marketDetailCardData,
};
},
// TODO: 持久化

26
vue.config.js

@ -1,24 +1,24 @@
module.exports = {
devServer: {
/* proxy: {
proxy: {
'/api': { // 你的目标服务器的请求路径前缀
target: 'https://hwjb.homilychart.com', // 目标服务器的地址
target: 'https://dbqb.nfdxy.net/testApi', // 目标服务器的地址
changeOrigin: true, // 是否跨域
secure: false, // 如果是https接口,需要配置这个参数
pathRewrite: {
'^/api': '' // 将 /api 替换为 /testApi,以便正确请求目标服务器的资源
}
}
} */
proxy: {
'/api': { // 你的目标服务器的请求路径前缀
target: 'http://192.168.40.8:9000', // 目标服务器的地址
changeOrigin: true, // 是否跨域
secure: false, // 如果是https接口,需要配置这个参数
pathRewrite: {
'^/api': '' // 将 /api 替换为 /testApi,以便正确请求目标服务器的资源
}
}
}
}
// proxy: {
// '/api': { // 你的目标服务器的请求路径前缀
// target: 'http://192.168.40.8:9000', // 目标服务器的地址
// changeOrigin: true, // 是否跨域
// secure: false, // 如果是https接口,需要配置这个参数
// pathRewrite: {
// '^/api': '' // 将 /api 替换为 /testApi,以便正确请求目标服务器的资源
// }
// }
// }
}
}
Loading…
Cancel
Save