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.

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