You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1059 lines
24 KiB

  1. <template>
  2. <view class="deepMate-page">
  3. <!-- 顶部导航栏 - 固定定位 -->
  4. <view class="header" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
  5. <view class="header-left">
  6. <image
  7. src="https://d31zlh4on95l9h.cloudfront.net/images/f91e09b5987802185e7679055dafd272.svg"
  8. class="icon"
  9. ></image>
  10. </view>
  11. <view class="header-center">
  12. <text class="title">DeepMate</text>
  13. </view>
  14. <view class="header-right">
  15. <image
  16. src="https://d31zlh4on95l9h.cloudfront.net/images/d7c4e74201213a25dd9574e908233928.svg"
  17. class="icon"
  18. ></image>
  19. <image
  20. src="https://d31zlh4on95l9h.cloudfront.net/images/099903c4aabf5713488b5cb60815e3f7.svg"
  21. class="icon"
  22. ></image>
  23. <!-- 新增新会话按钮
  24. <button class="new-chat-button" @click="newChat">
  25. <text class="new-chat-text">新会话</text>
  26. </button> -->
  27. </view>
  28. </view>
  29. <!-- 主要内容区域 -->
  30. <view class="main-content">
  31. <!-- 顶部固定区域占位符 -->
  32. <view class="banner-placeholder"></view>
  33. <view
  34. class="banner-panel"
  35. :class="messages.length === 0 ? '' : 'panelShow'"
  36. :style="{ paddingTop: safeAreaInsets?.top + 'px' }"
  37. >
  38. <image
  39. src="https://d31zlh4on95l9h.cloudfront.net/images/42e18bd7fe97d4f4f37aa70439a0990b.svg"
  40. class="pray-banner"
  41. :class="messages.length === 0 ? '' : 'show'"
  42. :style="{ paddingTop: safeAreaInsets?.top + 'px' }"
  43. mode="aspectFill"
  44. ></image>
  45. <view class="contain">
  46. <!-- 机器人头像和欢迎语 -->
  47. <view class="robot-container">
  48. <image
  49. src="https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg"
  50. class="robot-avatar"
  51. ></image>
  52. <view class="welcome-message">
  53. <text class="greeting">Hi, 我是您的股市随身顾问~</text>
  54. <text class="description"
  55. >个股诊断市场情绪解读都可以找我</text
  56. >
  57. </view>
  58. </view>
  59. <!-- 功能标签栏 -->
  60. <view
  61. class="function-tabs"
  62. v-if="messages.length === 0"
  63. scroll-x="true"
  64. show-scrollbar="false"
  65. >
  66. <view class="tab-item">个股诊断</view>
  67. <view class="tab-item">市场情绪温度计</view>
  68. <view class="tab-item">买卖时机提示</view>
  69. <view class="tab-item">个股</view>
  70. </view>
  71. <!-- 特斯拉推荐卡片 -->
  72. <view class="recommend-card" v-if="messages.length === 0">
  73. <view class="arrow" v-if="messages.length === 0"></view>
  74. <view class="card-content">
  75. <image
  76. src="../../static/images/tesla-logo.png"
  77. class="logo"
  78. ></image>
  79. <view class="card-text">
  80. <text class="main-question">当前特斯拉该如何布局</text>
  81. <text class="stock-code">TSLA</text>
  82. </view>
  83. <image
  84. src="https://d31zlh4on95l9h.cloudfront.net/images/40d94054644f6e3f1c366751f07f0010.svg"
  85. class="arrow-icon"
  86. @click="goBlank"
  87. ></image>
  88. </view>
  89. </view>
  90. </view>
  91. </view>
  92. <!-- 可能感兴趣的话题 -->
  93. <view v-if="messages.length === 0" class="interest-section">
  94. <text class="section-title">- 您可能感兴趣 -</text>
  95. <view class="topics-list">
  96. <view class="topic-item" v-for="topic in hotTopics" :key="topic.id">
  97. <image :src="topic.icon" class="tag-icon"></image>
  98. <text class="topic-text" @click="sendMessageList(topic.text)">{{
  99. topic.text
  100. }}</text>
  101. </view>
  102. </view>
  103. </view>
  104. <!-- 聊天区域 -->
  105. <view class="chat-container" v-if="messages.length > 0">
  106. <!-- 给聊天容器添加滚动引用 -->
  107. <scroll-view
  108. class="chat-scroll-view"
  109. scroll-y="true"
  110. :scroll-top="scrollTop"
  111. :style="{ paddingTop: safeAreaInsets?.top + 'px' }"
  112. >
  113. <view class="message-list" id="messageList">
  114. <view
  115. v-for="(message, index) in messages"
  116. :key="index"
  117. :class="
  118. message.isUser ? 'message user-message' : 'message bot-message'
  119. "
  120. >
  121. <!-- 会话图标 -->
  122. <text
  123. :class="
  124. message.isUser
  125. ? 'fa-solid fa-user message-icon'
  126. : 'fa-solid fa-robot message-icon'
  127. "
  128. ></text>
  129. <!-- 会话内容 -->
  130. <view class="message-content">
  131. <!-- loading -->
  132. <view
  133. class="loading-dots"
  134. v-if="message.isThinking || !message.isUser"
  135. >
  136. <div class="thinking-process">
  137. <div class="thinking-header">
  138. <div class="thinking-icon"></div>
  139. <div class="thinking-title">深度思考 正在思考</div>
  140. <div class="thinking-count">25 个结果</div>
  141. <div class="thinking-toggle" @click="toggleThinking">
  142. <span v-if="showThinking"></span>
  143. <span v-else></span>
  144. </div>
  145. </div>
  146. <div v-show="showThinking" class="thinking-content">
  147. <div class="thinking-item">
  148. <div class="item-status">
  149. <span class="checkmark"></span>
  150. </div>
  151. <div class="item-text">问题分析完成</div>
  152. </div>
  153. <div class="thinking-item">
  154. <div class="item-status">
  155. <span class="checkmark"></span>
  156. </div>
  157. <div class="item-text">收集相关信息</div>
  158. </div>
  159. </div>
  160. </div>
  161. </view>
  162. <!-- 使用 rich-text 渲染 Markdown 内容 -->
  163. <rich-text v-if="!message.isUser" class="message-text" :nodes="renderMarkdown(message.content)"></rich-text>
  164. <text v-else class="message-text">{{ message.content }}</text>
  165. </view>
  166. </view>
  167. </view>
  168. </scroll-view>
  169. </view>
  170. </view>
  171. <!-- 输入框区域 -->
  172. <view class="input-area">
  173. <view class="input-wrapper">
  174. <input
  175. type="text"
  176. placeholder="请输入股票代码/名称,获取AI洞察"
  177. placeholder-style="color:#fff;opacity:1"
  178. class="input-field"
  179. v-model="inputMessage"
  180. @confirm="sendMessage"
  181. />
  182. <image class="send-button" @click="sendMessage" :disabled="isSending">
  183. <!-- <image
  184. src="https://d31zlh4on95l9h.cloudfront.net/images/95f1ea2262e9157db13c93c0dc1c5d96.svg"
  185. class="send-icon"
  186. ></image> -->
  187. </image>
  188. </view>
  189. <text class="disclaimer"
  190. >以上数据由AI生成不作为最终投资建议决策需独立</text
  191. >
  192. </view>
  193. <image
  194. class="back-to-top"
  195. src="https://d31zlh4on95l9h.cloudfront.net/images/ba357635d2bb480241952bb1cabacd73.svg"
  196. @click="scrollToTop"
  197. ></image>
  198. <footerBar class="static-footer" :type="type"></footerBar>
  199. </view>
  200. </template>
  201. <script setup>
  202. const { safeAreaInsets } = uni.getSystemInfoSync();
  203. import { ref, onMounted, nextTick, watch } from "vue";
  204. import footerBar from "../../components/footerBar-cn.vue";
  205. import marked from "marked"; // 引入 marked 库
  206. // 设置 marked 选项
  207. marked.setOptions({
  208. renderer: new marked.Renderer(),
  209. highlight: null, // 如果需要代码高亮,可以设置适当的函数
  210. langPrefix: 'language-',
  211. pedantic: false,
  212. gfm: true,
  213. breaks: false,
  214. sanitize: false,
  215. smartLists: true,
  216. smartypants: false,
  217. xhtml: false
  218. });
  219. // 创建一个用于渲染 Markdown 的函数
  220. const renderMarkdown = (content) => {
  221. if (!content) return '';
  222. return marked.parse(content);
  223. };
  224. const type = ref("member");
  225. const inputMessage = ref("");
  226. const showThinking = ref(true);
  227. const isSending = ref(false);
  228. const uuid = ref("");
  229. const messages = ref([]);
  230. const scrollTop = ref(0); // 用于控制scroll-view的滚动位置
  231. const dataInfo = ref("")
  232. const hotTopics = ref([
  233. {
  234. id: 1,
  235. text: "英伟达(NVDA)股票情绪温度?",
  236. icon: "https://d31zlh4on95l9h.cloudfront.net/images/7ed58be0f4b81aeb398d9ba2534a624b.svg",
  237. },
  238. {
  239. id: 2,
  240. text: "博通(AVGO)明天还能涨吗?",
  241. icon: "https://d31zlh4on95l9h.cloudfront.net/images/7ed58be0f4b81aeb398d9ba2534a624b.svg",
  242. },
  243. {
  244. id: 3,
  245. text: "为什么Fluence Energy(FLNC)会暴涨?",
  246. icon: "https://d31zlh4on95l9h.cloudfront.net/images/7ed58be0f4b81aeb398d9ba2534a624b.svg",
  247. },
  248. {
  249. id: 4,
  250. text: "为什么Fluence Energy(FLNC)会暴涨?",
  251. icon: "https://d31zlh4on95l9h.cloudfront.net/images/7ed58be0f4b81aeb398d9ba2534a624b.svg",
  252. },
  253. ]);
  254. // 初始化
  255. onMounted(() => {
  256. initUUID();
  257. // 如果有历史消息,滚动到底部
  258. if (messages.value.length > 0) {
  259. setTimeout(() => {
  260. scrollToBottom();
  261. }, 200);
  262. }
  263. });
  264. // 监听消息变化,当有新消息时自动滚动到最新消息
  265. watch(
  266. messages,
  267. (newMessages) => {
  268. // 延迟执行滚动,确保DOM更新完成
  269. setTimeout(() => {
  270. scrollToBottom();
  271. }, 100);
  272. },
  273. { deep: true }
  274. );
  275. // 初始化 UUID
  276. const initUUID = () => {
  277. let storedUUID = uni.getStorageSync("user_uuid");
  278. if (!storedUUID) {
  279. storedUUID = generateUUID();
  280. uni.setStorageSync("user_uuid", storedUUID);
  281. }
  282. uuid.value = storedUUID;
  283. };
  284. // 生成简单UUID
  285. const generateUUID = () => {
  286. return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
  287. var r = (Math.random() * 16) | 0,
  288. v = c == "x" ? r : (r & 0x3) | 0x8;
  289. return v.toString(16);
  290. });
  291. };
  292. // 新会话
  293. const newChat = () => {
  294. messages.value = [];
  295. uni.removeStorageSync("user_uuid");
  296. initUUID();
  297. };
  298. // 跳转到空白页
  299. const goBlank = () => {
  300. uni.navigateTo({
  301. url: "/pages/blank/blank",
  302. });
  303. };
  304. // 发送消息
  305. const sendMessage = async () => {
  306. if (inputMessage.value.trim() === "" || isSending.value) return;
  307. const res = await getDataInfo();
  308. console.log("数据格式为"+dataInfo.value);
  309. const userMessage = {
  310. content: inputMessage.value,
  311. isUser: true,
  312. isThinking: false,
  313. isTyping: false,
  314. };
  315. messages.value.push(userMessage);
  316. inputMessage.value = "";
  317. // 滚动到底部
  318. setTimeout(() => {
  319. scrollToBottom();
  320. }, 100);
  321. // 模拟机器人回复
  322. simulateBotResponse(userMessage.content);
  323. };
  324. // 发送消息
  325. const sendMessageList = (listMessage) => {
  326. console.log(listMessage);
  327. const userMessage = {
  328. content: listMessage,
  329. isUser: true,
  330. isThinking: false,
  331. isTyping: false,
  332. };
  333. messages.value.push(userMessage);
  334. inputMessage.value = "";
  335. // 滚动到底部
  336. setTimeout(() => {
  337. scrollToBottom();
  338. }, 100);
  339. // 模拟机器人回复
  340. simulateBotResponse(userMessage.content);
  341. };
  342. // 模拟机器人回复
  343. const simulateBotResponse = (userMessage) => {
  344. isSending.value = true;
  345. // 添加机器人加载消息
  346. const botMsg = {
  347. content: "",
  348. isUser: false,
  349. isTyping: true,
  350. isThinking: false,
  351. };
  352. messages.value.push(botMsg);
  353. // 滚动到底部
  354. setTimeout(() => {
  355. scrollToBottom();
  356. }, 100);
  357. // 模拟流式响应
  358. let responseText = `我已经收到您的消息: "${userMessage}"。
  359. ## 股票分析报告
  360. ### 股票名称: Tesla Inc. (TSLA)
  361. - **当前价格**: 448.980
  362. - **更新时间**: 23/10/2025
  363. - **今日无变盘点**
  364. ### 技术分析
  365. - **CFTL**: 当前牵牛绳为红色处于龙线区域最近出现牛刀小试度牛线目前处于青绿色区域
  366. - **空间预测**:
  367. - 预测低一值: 413.364
  368. - 预测高一值: 426.636
  369. - 预测低二值: 421.670
  370. - 预测高二值: 448.314
  371. - **能量分析**: AI智能均线多头排列当前卖盘小于买盘
  372. ### 资金与主力
  373. - **主力分析**:
  374. 1. 该股庄家中长期筹码成本价格为 356.036短期资金成本价格为 406.429该股筹码分散当日筹码成本价格为 439.322
  375. 2. 近日没有出现主力集中吸筹
  376. 3. 近期主力持仓比例大于散户持仓比例当日主力持仓增加当日散户持仓减少
  377. ### 综合评价
  378. - **个股走势评价**:
  379. - 该股整体趋势向好出现暴涨的可能性较大当前如果已经持有该股票可以继续持股观察如果尚未持有该股票可持续进行观察目前处于机会的初期处于反弹阶段可以分步建仓
  380. - **核心证据链**:
  381. - 资金共识当日多方资金流入
  382. - 趋势动能该股中长期处于上升趋势短期处于弱势状态
  383. - **牛股评级**:
  384. - **暴涨概率**: 60%
  385. - **风险评估**: 非常安全
  386. - **安全边际**: 432.671~458.057
  387. - **黄金价域**: 427.995~440.835`;
  388. let index = 0;
  389. const typeWriter = () => {
  390. if (index < responseText.length) {
  391. // 使用 Vue 的响应式更新机制
  392. messages.value[messages.value.length - 1].content =
  393. responseText.substring(0, index + 1);
  394. index++;
  395. // 滚动到底部,更频繁地触发滚动以适应文本增长
  396. setTimeout(() => {
  397. scrollToBottom();
  398. }, 20);
  399. setTimeout(typeWriter, 30);
  400. } else {
  401. messages.value[messages.value.length - 1].isTyping = false;
  402. isSending.value = false;
  403. // 最后确保滚动到底部
  404. setTimeout(() => {
  405. scrollToBottom();
  406. }, 100);
  407. }
  408. };
  409. setTimeout(typeWriter, 500);
  410. };
  411. // 滚动到底部
  412. const scrollToBottom = () => {
  413. // 使用scroll-view的scrollTop属性来控制滚动
  414. const query = uni.createSelectorQuery();
  415. query.select("#messageList").boundingClientRect();
  416. query.exec((res) => {
  417. if (res[0]) {
  418. // 设置scrollTop为消息列表的高度,实现滚动到底部
  419. scrollTop.value = res[0].height;
  420. }
  421. });
  422. };
  423. const scrollToTop = () => {
  424. // 滚动到顶部
  425. scrollTop.value = 0;
  426. };
  427. const toggleThinking = () => {
  428. showThinking.value = !showThinking.value;
  429. };
  430. // function getDataInfo() {
  431. // return uni.request({
  432. // url: 'http://localhost:8888/ka',
  433. // data: {},
  434. // header: {
  435. // Accept: 'application/json',
  436. // 'Content-Type': 'application/json',
  437. // 'X-Requested-With': 'XMLHttpRequest'
  438. // },
  439. // method: 'GET',
  440. // sslVerify: true,
  441. // success: (res) => {
  442. // console.log(res.data);
  443. // res.data.forEach(item => {
  444. // console.log("item是"+item);
  445. // dataInfo.value = item.name;
  446. // });
  447. // },
  448. // fail: (error) => {}
  449. // })
  450. // }
  451. </script>
  452. <style scoped>
  453. .deepMate-page {
  454. display: flex;
  455. flex-direction: column;
  456. height: 100vh;
  457. max-height: 100vh; /* 限制最大高度 */
  458. background-color: #ffffff;
  459. padding: 0; /* 移除padding,避免影响布局 */
  460. position: relative;
  461. overflow: hidden; /* 禁止页面整体滚动 */
  462. -webkit-overflow-scrolling: none; /* 禁用iOS弹性滚动 */
  463. }
  464. /* 顶部导航栏 - 固定定位 */
  465. .header {
  466. display: flex;
  467. justify-content: space-between;
  468. align-items: center;
  469. padding: 20rpx 30rpx;
  470. background-color: #ffffff;
  471. position: fixed;
  472. top: 0;
  473. left: 0;
  474. right: 0;
  475. z-index: 999;
  476. box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
  477. }
  478. /* 顶部固定区域占位符 */
  479. .header-placeholder {
  480. height: 120rpx; /* 与header高度一致 */
  481. }
  482. /* 顶部固定区域占位符 */
  483. .banner-placeholder {
  484. height: 80rpx; /* 与header高度一致,防止内容被固定头部遮挡 */
  485. }
  486. .header-left,
  487. .header-right {
  488. display: flex;
  489. align-items: center;
  490. }
  491. .header-left .icon,
  492. .header-right .icon {
  493. width: 40rpx;
  494. height: 40rpx;
  495. margin-right: 20rpx;
  496. }
  497. .header-center .title {
  498. font-size: 36rpx;
  499. font-weight: bold;
  500. color: #333333;
  501. }
  502. .new-chat-button {
  503. background-color: #ff6600;
  504. border: none;
  505. border-radius: 8rpx;
  506. padding: 10rpx 20rpx;
  507. }
  508. .new-chat-text {
  509. color: white;
  510. font-size: 24rpx;
  511. }
  512. .main-content {
  513. flex: 1;
  514. padding: 20rpx;
  515. overflow-y: hidden; /* 禁止主内容区域滚动 */
  516. margin-top: 20rpx;
  517. margin-bottom: 250rpx; /* 为底部输入区域留出空间 */
  518. max-height: calc(100vh - 200rpx); /* 确保内容区域不会超出视口 */
  519. -webkit-overflow-scrolling: none; /* 禁用iOS弹性滚动 */
  520. }
  521. .robot-container {
  522. display: flex;
  523. align-items: center;
  524. margin-bottom: 30rpx;
  525. }
  526. .robot-avatar {
  527. width: 130rpx;
  528. height: 130rpx;
  529. border-radius: 50%;
  530. margin-right: 10rpx;
  531. }
  532. .welcome-message {
  533. flex: 1;
  534. }
  535. .greeting {
  536. font-size: 32rpx;
  537. margin-left: 50rpx;
  538. top: 40rpx;
  539. font-weight: bold;
  540. color: #333333;
  541. line-height: 48rpx;
  542. }
  543. .description {
  544. display: block;
  545. font-size: 24rpx;
  546. color: #666666;
  547. line-height: 36rpx;
  548. margin-top: 10rpx;
  549. margin-left: 45rpx;
  550. }
  551. .function-tabs {
  552. display: flex;
  553. margin-bottom: 30rpx;
  554. }
  555. .tab-item {
  556. padding: 5rpx 20rpx;
  557. border-radius: 20rpx;
  558. font-size: 20rpx;
  559. font-weight: 700;
  560. color: #666666;
  561. background-color: #fffefe;
  562. margin-right: 20rpx;
  563. transition: all 0.3s;
  564. }
  565. .tab-item.active {
  566. color: #ff6600;
  567. background-color: #fff;
  568. border: 1rpx solid #ff6600;
  569. }
  570. .recommend-card {
  571. background: url("https://d31zlh4on95l9h.cloudfront.net/images/4da1d629a55c307c3605ca15bf15189a.svg");
  572. background-repeat: no-repeat;
  573. /* border-radius: 20rpx; */
  574. padding: 40rpx;
  575. margin-bottom: 30rpx;
  576. /* box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); */
  577. }
  578. .card-content {
  579. display: flex;
  580. align-items: center;
  581. justify-content: space-between;
  582. }
  583. .logo {
  584. width: 80rpx;
  585. height: 80rpx;
  586. background-color: #ff0000;
  587. border-radius: 10rpx;
  588. display: flex;
  589. align-items: center;
  590. justify-content: center;
  591. margin-right: 20rpx;
  592. }
  593. .card-text {
  594. flex: 1;
  595. margin-left: 20rpx;
  596. }
  597. .main-question {
  598. font-size: 32rpx;
  599. color: #333333;
  600. line-height: 48rpx;
  601. }
  602. .stock-code {
  603. display: block;
  604. font-size: 24rpx;
  605. color: #ff3b30;
  606. background-color: #ffffff;
  607. padding: 2rpx 15rpx;
  608. border-radius: 12rpx;
  609. margin-top: 8rpx;
  610. width: fit-content;
  611. border: 1rpx solid #ff3b30;
  612. }
  613. .arrow-icon {
  614. background: url("https://d31zlh4on95l9h.cloudfront.net/images/40d94054644f6e3f1c366751f07f0010.svg");
  615. background-repeat: no-repeat;
  616. left: 0.5rem;
  617. top: 1.8rem;
  618. background-size: 100% 100%;
  619. width: 60rpx;
  620. height: 60rpx;
  621. }
  622. .interest-section {
  623. margin-bottom: 30rpx;
  624. }
  625. .section-title {
  626. display: block;
  627. text-align: center;
  628. font-size: 26rpx;
  629. color: #666666;
  630. margin-bottom: 20rpx;
  631. }
  632. .topics-list {
  633. display: flex;
  634. flex-direction: column;
  635. gap: 15rpx;
  636. }
  637. .topic-item {
  638. display: flex;
  639. align-items: center;
  640. padding: 15rpx 20rpx;
  641. background-color: #f0f0f0;
  642. border-radius: 15rpx;
  643. width: fit-content;
  644. }
  645. .tag-icon {
  646. width: 24rpx;
  647. height: 24rpx;
  648. margin-right: 10rpx;
  649. }
  650. .topic-text {
  651. font-size: 28rpx;
  652. color: #333333;
  653. flex: 1;
  654. }
  655. /* 聊天区域样式 */
  656. .chat-container {
  657. margin-top: 30rpx;
  658. border-radius: 10rpx;
  659. height: fit-content;
  660. /* overflow-y: auto; */
  661. }
  662. .chat-scroll-view {
  663. height: calc(80vh - 250rpx); /* 根据需要调整高度 */
  664. margin-top: 120rpx;
  665. }
  666. .message-list {
  667. /* padding: 20rpx; */
  668. /* margin-top: 200rpx; */
  669. }
  670. .message {
  671. display: flex;
  672. align-items: flex-start;
  673. margin-bottom: 30rpx;
  674. }
  675. .user-message {
  676. flex-direction: row-reverse;
  677. }
  678. .message-icon {
  679. font-size: 24rpx;
  680. margin: 0 10rpx;
  681. padding: 10rpx;
  682. border-radius: 50%;
  683. background-color: #ddd;
  684. width: 40rpx;
  685. height: 40rpx;
  686. display: flex;
  687. align-items: center;
  688. justify-content: center;
  689. }
  690. .user-message .message-icon {
  691. background-color: #007aff;
  692. color: white;
  693. }
  694. .bot-message .message-icon {
  695. background-color: #34c759;
  696. color: white;
  697. }
  698. .message-content {
  699. max-width: 70%;
  700. position: relative;
  701. }
  702. .user-message .message-content {
  703. background-color: #007aff;
  704. border-radius: 10rpx;
  705. padding: 15rpx;
  706. }
  707. .bot-message .message-content {
  708. background-color: #f0f0f0;
  709. border-radius: 10rpx;
  710. padding: 15rpx;
  711. }
  712. .message-text {
  713. font-size: 28rpx;
  714. line-height: 40rpx;
  715. }
  716. .user-message .message-text {
  717. color: white;
  718. }
  719. .bot-message .message-text {
  720. color: #333;
  721. }
  722. .loading-dots {
  723. display: flex;
  724. align-items: center;
  725. padding-top: 10rpx;
  726. }
  727. .dot {
  728. width: 10rpx;
  729. height: 10rpx;
  730. background-color: #666;
  731. border-radius: 50%;
  732. margin: 0 4rpx;
  733. animation: loading 1.4s infinite ease-in-out both;
  734. }
  735. .user-message .dot {
  736. background-color: white;
  737. }
  738. .dot:nth-child(1) {
  739. animation-delay: -0.32s;
  740. }
  741. .dot:nth-child(2) {
  742. animation-delay: -0.16s;
  743. }
  744. @keyframes loading {
  745. 0%,
  746. 80%,
  747. 100% {
  748. transform: scale(0);
  749. }
  750. 40% {
  751. transform: scale(1);
  752. }
  753. }
  754. .input-area {
  755. position: fixed;
  756. bottom: 70rpx;
  757. left: 0;
  758. right: 0;
  759. padding: 0 40rpx 80rpx 40rpx;
  760. background-color: #ffffff;
  761. z-index: 999;
  762. -webkit-overflow-scrolling: none; /* 禁用iOS弹性滚动 */
  763. }
  764. .input-wrapper {
  765. position: relative;
  766. display: flex;
  767. align-items: center;
  768. padding: 15rpx 20rpx;
  769. background-color: rgb(220, 31, 29);
  770. border-radius: 100rpx;
  771. display: flex;
  772. align-items: center;
  773. justify-content: center;
  774. height: 50rpx;
  775. }
  776. .mic-icon {
  777. width: 36rpx;
  778. height: 36rpx;
  779. margin-right: 20rpx;
  780. }
  781. .input-field {
  782. flex: 1;
  783. font-size: 28rpx;
  784. color: #fff;
  785. display: flex;
  786. align-items: center;
  787. justify-content: center;
  788. margin-left: 60rpx;
  789. background: none;
  790. border: none;
  791. outline: none;
  792. }
  793. .input-field::placeholder {
  794. color: #ffffff !important;
  795. opacity: 1;
  796. }
  797. .send-button {
  798. background: url("https://d31zlh4on95l9h.cloudfront.net/images/95f1ea2262e9157db13c93c0dc1c5d96.svg");
  799. background-repeat: no-repeat;
  800. background-size: 100% 100%;
  801. height: 50rpx;
  802. width: 50rpx;
  803. padding: 0;
  804. border: 1rpx solid transparent;
  805. margin-left: 20rpx;
  806. }
  807. .send-icon {
  808. width: 36rpx;
  809. height: 36rpx;
  810. }
  811. .disclaimer {
  812. font-size: 15rpx;
  813. color: #4d4c4c;
  814. display: flex;
  815. align-items: center;
  816. justify-content: center;
  817. margin-top: 15rpx;
  818. }
  819. .banner-panel {
  820. position: relative;
  821. height: 480rpx; /* 拉长容器,灰色背景跟随变高 */
  822. overflow: hidden; /* 让圆角和内部层剪裁一致 */
  823. border-radius: 15rpx;
  824. }
  825. .panelShow {
  826. height: 12%;
  827. position: fixed;
  828. top: 70rpx;
  829. z-index: 999;
  830. width: 95%;
  831. }
  832. .pray-banner {
  833. position: absolute;
  834. /* background-size: 100% 100%; */
  835. inset: 0; /* 顶部、底部、左、右都贴合容器 */
  836. width: 100%;
  837. height: 88%;
  838. border-radius: 15rpx;
  839. z-index: 1; /* 在灰底之上、内容之下 */
  840. }
  841. .contain {
  842. margin: 0 20rpx;
  843. gap: 5rpx;
  844. }
  845. .banner-panel .robot-container,
  846. .banner-panel .function-tabs,
  847. .banner-panel .recommend-card {
  848. position: relative;
  849. z-index: 2;
  850. }
  851. .back-to-top {
  852. position: fixed;
  853. right: 30rpx;
  854. bottom: 35%;
  855. width: 100rpx;
  856. height: 100rpx;
  857. z-index: 1000;
  858. }
  859. .back-to-top:active {
  860. transform: scale(0.96);
  861. }
  862. .static-footer {
  863. position: fixed;
  864. bottom: 0;
  865. z-index: 999;
  866. }
  867. /* 顶部固定区域占位符 */
  868. .banner-placeholder {
  869. height: 120rpx; /* 与header高度一致,防止内容被固定头部遮挡 */
  870. }
  871. .thinking-process {
  872. margin: 10px 0;
  873. border: 1px solid #e5e5e5;
  874. border-radius: 8px;
  875. background-color: #f9f9f9;
  876. }
  877. .thinking-header {
  878. display: flex;
  879. align-items: center;
  880. padding: 10px 15px;
  881. cursor: pointer;
  882. background-color: #fff;
  883. border-bottom: 1px solid #e5e5e5;
  884. }
  885. .thinking-icon {
  886. font-size: 16px;
  887. margin-right: 8px;
  888. color: #d47c45;
  889. }
  890. .thinking-title {
  891. font-size: 14px;
  892. font-weight: 500;
  893. color: #d47c45;
  894. margin-right: 8px;
  895. }
  896. .thinking-count {
  897. font-size: 12px;
  898. color: #666;
  899. margin-right: 8px;
  900. }
  901. .thinking-toggle {
  902. font-size: 12px;
  903. color: #999;
  904. }
  905. .thinking-content {
  906. padding: 10px 15px;
  907. }
  908. .thinking-item {
  909. display: flex;
  910. align-items: center;
  911. margin-bottom: 8px;
  912. padding: 4px 0;
  913. }
  914. .item-status {
  915. width: 16px;
  916. height: 16px;
  917. border-radius: 50%;
  918. background-color: #f0f0f0;
  919. display: flex;
  920. justify-content: center;
  921. align-items: center;
  922. margin-right: 8px;
  923. }
  924. .checkmark {
  925. font-size: 10px;
  926. color: #ff0000;
  927. }
  928. .item-text {
  929. font-size: 12px;
  930. color: #333;
  931. }
  932. </style>