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.

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