From 36e554ab44d43955059a95ab4faddaa22dc4024c Mon Sep 17 00:00:00 2001 From: wangyetao <2898314561@qq.com> Date: Sat, 25 Oct 2025 13:33:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=88=E5=B9=B6=E4=B9=8B?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 78 ++++++++++++++- package.json | 6 ++ pages/deepMate/deepMate.vue | 238 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 292 insertions(+), 30 deletions(-) create mode 100644 package.json diff --git a/package-lock.json b/package-lock.json index 188963d..a9eb9f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,5 +2,81 @@ "name": "deepChartVueApp", "lockfileVersion": 3, "requires": true, - "packages": {} + "packages": { + "": { + "dependencies": { + "markdown-it": "^14.1.0", + "marked": "^2.0.1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/marked": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/marked/-/marked-2.0.1.tgz", + "integrity": "sha512-5+/fKgMv2hARmMW7DOpykr2iLhl0NgjyELk5yn92iE7z8Se1IS9n3UsFm86hFXIkvMBmVxki8+ckcpjBeyo/hw==", + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">= 8.16.2" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + } + } } diff --git a/package.json b/package.json new file mode 100644 index 0000000..c0827ed --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "markdown-it": "^14.1.0", + "marked": "^2.0.1" + } +} diff --git a/pages/deepMate/deepMate.vue b/pages/deepMate/deepMate.vue index aea697c..77ff2d9 100644 --- a/pages/deepMate/deepMate.vue +++ b/pages/deepMate/deepMate.vue @@ -82,7 +82,7 @@ Hi, 我是您的股市随身顾问~ 个股诊断、市场情绪解读,都可以找我。 - + - {{ message.content }} + - - - +
+
+
+
深度思考 正在思考
+
25 个结果
+
+ + +
+
+
+
+
+ +
+
问题分析完成
+
+
+
+ +
+
收集相关信息
+
+
+
+ + + {{ message.content }}
-
+ @@ -158,12 +187,32 @@ const { safeAreaInsets } = uni.getSystemInfoSync(); import { ref, computed, onMounted, onUnmounted, watch, nextTick } from "vue"; import footerBar from '../../components/footerBar-cn' +import marked from "marked"; // 引入 marked 库 import { onPageScroll } from '@dcloudio/uni-app' - - +// 设置 marked 选项 +marked.setOptions({ + renderer: new marked.Renderer(), + highlight: null, // 如果需要代码高亮,可以设置适当的函数 + langPrefix: "language-", + pedantic: false, + gfm: true, + breaks: false, + sanitize: false, + smartLists: true, + smartypants: false, + xhtml: false, +}); +// 创建一个用于渲染 Markdown 的函数 +const renderMarkdown = (content) => { + if (!content) return ""; + return marked.parse(content); +}; const type = ref('member') const inputMessage = ref(""); +const showThinking = ref(true); const isSending = ref(false); +const chatScrollTop = ref(0); +const chatContainerHeight = ref(0); const uuid = ref(""); const messages = ref([]); const hotTopics = ref([ @@ -210,7 +259,7 @@ onMounted(() => { nextTick(startTabsMarquee); } if (messages.value.length > 0) { - nextTick(() => { scrollToBottom(); }); + nextTick(() => { measureChatContainer(); scrollToBottom(); }); } }); @@ -233,6 +282,15 @@ const generateUUID = () => { }); }; +// 计算聊天容器可视高度 +const measureChatContainer = () => { + const q = uni.createSelectorQuery(); + q.select('.chat-container').boundingClientRect(); + q.exec((res) => { + chatContainerHeight.value = res[0]?.height || 0; + }); +}; + // 新会话 const newChat = () => { messages.value = []; @@ -289,7 +347,42 @@ const simulateBotResponse = (userMessage) => { }); // 模拟流式响应 - let responseText = `我已经收到您的消息: "${userMessage}"。作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?`; + let responseText = `我已经收到您的消息: "${userMessage}"。 ## 股票分析报告 + +### 股票名称: Tesla Inc. (TSLA) + +- **当前价格**: 448.980 +- **更新时间**: 23/10/2025 +- **今日无变盘点** + +### 技术分析 +- **CFTL**: 当前牵牛绳为红色,处于龙线区域,最近出现“牛刀小试”,度牛线目前处于青绿色区域。 +- **空间预测**: + - 预测低一值: 413.364 + - 预测高一值: 426.636 + - 预测低二值: 421.670 + - 预测高二值: 448.314 +- **能量分析**: AI智能均线多头排列,当前卖盘小于买盘 + +### 资金与主力 +- **主力分析**: + 1. 该股庄家中长期筹码成本价格为 356.036,短期资金成本价格为 406.429。该股筹码分散,当日筹码成本价格为 439.322。 + 2. 近日没有出现主力集中吸筹。 + 3. 近期主力持仓比例大于散户持仓比例。当日主力持仓增加。当日散户持仓减少。 + +### 综合评价 +- **个股走势评价**: + - 该股整体趋势向好,出现暴涨的可能性较大,当前如果已经持有该股票,可以继续持股观察,如果尚未持有该股票,可持续进行观察,目前处于机会的初期,处于反弹阶段,可以分步建仓! + +- **核心证据链**: + - 资金共识:当日多方资金流入。 + - 趋势动能:该股中长期处于上升趋势,短期处于弱势状态。 + +- **牛股评级**: ★★★☆☆ +- **暴涨概率**: 60% +- **风险评估**: 非常安全 +- **安全边际**: 432.671~458.057 +- **黄金价域**: 427.995~440.835`; let index = 0; const botIndex = messages.value.length - 1; @@ -328,31 +421,40 @@ const simulateBotResponse = (userMessage) => { setTimeout(typeWriter, 500); }; -// 滚动到底部 +// 当消息出现或变化时,测量容器并滚到底部 +watch(messages, (arr) => { + if (arr.length > 0) { + nextTick(() => { + measureChatContainer(); + scrollToBottom(); + }); + } +}); + +// 滚动到底部(仅聊天区域滚动) const scrollToBottom = () => { - if (!shouldAutoScroll.value) return; // 暂停自动滚动 + if (!shouldAutoScroll.value) return; const query = uni.createSelectorQuery(); - query.select("#messageList").boundingClientRect(); - query.selectViewport().scrollOffset(); + query.select('#messageList').boundingClientRect(); query.exec((res) => { - if (res[0] && res[1]) { + if (res[0]) { latestContentHeight.value = res[0].height; - uni.pageScrollTo({ scrollTop: res[0].height, duration: 100 }); + chatScrollTop.value = res[0].height; // scroll-view 会自动夹紧到最大位置 } }); }; const scrollToTop = () => { - uni.pageScrollTo({ scrollTop: 0, duration: 200 }); + chatScrollTop.value = 0; }; // 自动滚动控制:用户向上滚动时暂停自动滚到底部 const shouldAutoScroll = ref(true); const latestContentHeight = ref(0); const lastScrollTop = ref(0); const windowHeight = uni.getSystemInfoSync().windowHeight; -const AUTO_SCROLL_REENABLE_THRESHOLD = 1; // px,接近底部时恢复自动滚动 +const AUTO_SCROLL_REENABLE_THRESHOLD = 400; // px,接近底部时恢复自动滚动 -onPageScroll((e) => { - const st = e.scrollTop; +const onChatScroll = (e) => { + const st = e.detail?.scrollTop || 0; const delta = st - lastScrollTop.value; lastScrollTop.value = st; @@ -361,11 +463,11 @@ onPageScroll((e) => { return; } - const distanceToBottom = latestContentHeight.value - st - windowHeight; + const distanceToBottom = latestContentHeight.value - st - chatContainerHeight.value; if (distanceToBottom <= AUTO_SCROLL_REENABLE_THRESHOLD) { shouldAutoScroll.value = true; } -}); +}; // 回到顶部图标拖拽状态 const backTopX = ref(0); @@ -445,10 +547,12 @@ const onBackTopClick = () => { .deepMate-page { display: flex; flex-direction: column; + position: fixed; /* 充满视口,彻底禁用页面滚动 */ + top: 0; left: 0; right: 0; bottom: 0; height: 100vh; + overflow: hidden; /* 锁定页面滚动 */ background-color: #ffffff; padding: 20rpx 0rpx; - } .header { @@ -457,7 +561,7 @@ const onBackTopClick = () => { align-items: center; padding: 20rpx 30rpx; background-color: #ffffff; - + box-shadow: 0 2rpx rgba(0, 0, 0, 0.1); } .header-left, @@ -494,9 +598,11 @@ const onBackTopClick = () => { .main-content { background-color: #fff; flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; /* 内部滚动交给聊天容器 */ padding: 20rpx; - /* overflow-y: auto; 取消独立滚动,使用页面滚动以便自动到达底部 */ - margin-top: 20rpx; + margin-top: 1rpx; margin-bottom: 120rpx; } @@ -680,8 +786,9 @@ const onBackTopClick = () => { .chat-container { margin-top: 30rpx; border-radius: 10rpx; - height: fit-content; - /* overflow-y: auto; */ + height: 65%; /* 缩短滚动区域,避免被输入框覆盖 */ + overflow-y: auto; + -webkit-overflow-scrolling: touch; } .message-list { @@ -843,7 +950,9 @@ const onBackTopClick = () => { color: #ffffff !important; opacity: 1; } - +/* .uni-scroll-view{ + height: 92%; +} */ .send-button { background: url("https://d31zlh4on95l9h.cloudfront.net/images/95f1ea2262e9157db13c93c0dc1c5d96.svg"); background-repeat: no-repeat; @@ -914,4 +1023,75 @@ const onBackTopClick = () => { position: fixed; bottom: 0; } +.thinking-process { + margin: 20rpx 0; + border: 2rpx solid #e5e5e5; + border-radius: 2rpx; + background-color: #f9f9f9; +} + +.thinking-header { + display: flex; + align-items: center; + padding: 20rpx 30rpx; + cursor: pointer; + background-color: #fff; + border-bottom: 2px solid #e5e5e5; +} + +.thinking-icon { + font-size: 32rpx; + margin-right: 16rpx; + color: #d47c45; +} + +.thinking-title { + font-size: 28rpx; + font-weight: 500; + color: #d47c45; + margin-right: 16rpx; +} + +.thinking-count { + font-size: 24rpx; + color: #666; + margin-right: 16rpx; +} + +.thinking-toggle { + font-size: 24rpx; + color: #999; +} + +.thinking-content { + padding: 20rpx 30rpx; +} + +.thinking-item { + display: flex; + align-items: center; + margin-bottom: 16rpx; + padding: 8rpx 0; +} + +.item-status { + width: 32rpx; + height: 32rpx; + border-radius: 50%; + background-color: #f0f0f0; + display: flex; + justify-content: center; + align-items: center; + margin-right: 16rpx; +} + +.checkmark { + font-size: 20rpx; + color: #ff0000; +} + +.item-text { + font-size: 24rpx; + color: #333; +} \ No newline at end of file