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.

2332 lines
58 KiB

5 months ago
5 days ago
5 days ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
1 week ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
2 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
  1. <script setup>
  2. // 导入
  3. import { ref, computed, onMounted, watch, nextTick, onUnmounted, h } from "vue";
  4. import { setHeight } from "../utils/setHeight";
  5. import { getUserCountAPI, showExchangeAPI } from "../api/AIxiaocaishen";
  6. import { ElMessage } from "element-plus";
  7. import AIchat from "./AIchat.vue";
  8. import AIfind from "./AIfind.vue";
  9. import Feedback from "./Feedback.vue";
  10. import Announcement from "./Announcement.vue";
  11. import { useAppBridge } from "../assets/js/useAppBridge.js";
  12. import { useDataStore } from "@/store/dataList.js";
  13. import { useChatStore } from "../store/chat";
  14. import { useEmotionAudioStore } from "../store/emotionAudio";
  15. import { useAudioStore } from "../store/audio";
  16. import _ from "lodash";
  17. import logo from "../assets/img/homePage/logo.png";
  18. import madeInHL from "../assets/img/homePage/madeInHL.png";
  19. import getCountAll from "../assets/img/homePage/get-count-all.png";
  20. import announcementBtn from "../assets/img/homePage/announcement.png";
  21. import thinkActive from "../assets/img/homePage/tail/think-active.png";
  22. import thinkNoActive from "../assets/img/homePage/tail/think-no-active.png";
  23. import languageBtn from "../assets/img/homePage/tail/language.png";
  24. import dbqbButton01 from "../assets/img/AiEmotion/dbqb-button01.png";
  25. import dbqbButton02 from "../assets/img/AiEmotion/dbqb-button02.png";
  26. import emotionButton01 from "../assets/img/AiEmotion/emotion-button01.png";
  27. import emotionButton02 from "../assets/img/AiEmotion/emotion-button02.png";
  28. import voice from "../assets/img/homePage/tail/voice.png";
  29. import voiceNoActive from "../assets/img/homePage/tail/voice-no-active.png";
  30. import sendBtn from "../assets/img/homePage/tail/send.png";
  31. import msgBtn from "../assets/img/homePage/tail/msg.png";
  32. import feedbackBtn from "../assets/img/Feedback/feedbackBtn.png";
  33. import AiEmotion from "./AiEmotion.vue";
  34. import HistoryRecord from "./components/HistoryRecord.vue";
  35. // import VConsole from "vconsole";
  36. // const vConsole = new VConsole();
  37. const isMobile = ref(null);
  38. // 获取 AiEmotion 组件的 ref
  39. const aiEmotionRef = ref(null);
  40. // 获取历史记录组件的 ref
  41. const historyRecordRef = ref(null);
  42. // import { useUserStore } from "../store/userPessionCode.js";
  43. const { getQueryVariable, setActiveTabIndex } = useDataStore();
  44. const dataStore = useDataStore();
  45. const chatStore = useChatStore();
  46. // 变量
  47. // 音频管理
  48. const emotionAudioStore = useEmotionAudioStore();
  49. const audioStore = useAudioStore();
  50. // 根据当前页面类型获取对应的音频store
  51. const getCurrentAudioStore = () => {
  52. return activeTab.value === "AiEmotion" ? emotionAudioStore : audioStore;
  53. };
  54. const isVoice = computed(() => {
  55. const currentStore = getCurrentAudioStore();
  56. return currentStore.isVoiceEnabled;
  57. });
  58. const toggleVoice = () => {
  59. const currentStore = getCurrentAudioStore();
  60. if (!currentStore.isVoiceEnabled) {
  61. // 如果语音功能关闭,先开启语音功能
  62. currentStore.toggleVoice();
  63. } else {
  64. // 如果语音功能开启,则切换播放/暂停状态
  65. if (currentStore.currentAudioUrl || currentStore.ttsUrl) {
  66. // 有音频时切换播放/暂停
  67. currentStore.togglePlayPause();
  68. } else {
  69. // 没有音频时关闭语音功能
  70. currentStore.toggleVoice();
  71. }
  72. }
  73. };
  74. // 将默认值改为从 sessionStorage 中获取,如果没有则使用默认值 'aifindCow'为第一个默认tab
  75. const activeTab = ref(sessionStorage.getItem("activeTabAI") || "AIchat");
  76. const activeIndex = ref(
  77. parseInt(sessionStorage.getItem("activeIndexAI") || "0")
  78. );
  79. const tabs = computed(() => [
  80. {
  81. name: "AIchat",
  82. label: "夺宝奇兵大模型",
  83. },
  84. // {
  85. // name: "AIfind",
  86. // label: "发现",
  87. // },
  88. {
  89. name: "AiEmotion",
  90. label: "AI情绪大模型",
  91. },
  92. ]);
  93. // 修改 setActiveTab 方法,添加一个可选参数 forceAIchat
  94. const setActiveTab = (tab, index, forceAIchat = false) => {
  95. isScrolling.value = false; //回复滚动到底部方法
  96. isAnnouncementVisible.value = false;
  97. // 重置输入框禁用状态,防止页面切换时状态残留
  98. console.log("tab", tab, "index", index);
  99. if (tab == "AIchat") {
  100. isInputDisabled.value = chatStore.chatInput;
  101. console.log("切换到AIchat页面,输入框状态为", isInputDisabled.value);
  102. } else if (tab == "AiEmotion") {
  103. isInputDisabled.value = chatStore.emotionInput;
  104. console.log("切换到AiEmotion页面,输入框状态为", isInputDisabled.value);
  105. } else {
  106. isInputDisabled.value = false;
  107. }
  108. if (forceAIchat && activeTab.value !== "AIchat") {
  109. activeTab.value = "AIchat";
  110. activeIndex.value = 0;
  111. sessionStorage.setItem("activeTabAI", "AIchat");
  112. sessionStorage.setItem("activeIndexAI", "0");
  113. } else {
  114. activeTab.value = tab;
  115. activeIndex.value = index;
  116. sessionStorage.setItem("activeTabAI", tab);
  117. sessionStorage.setItem("activeIndexAI", index.toString());
  118. }
  119. setActiveTabIndex(index);
  120. console.log(tab, index, "tab, index");
  121. setHeight(document.getElementById("testId")); // 给父组件发送窗口高度
  122. };
  123. // 修改 activeComponent 的计算逻辑
  124. const activeComponent = computed(() => {
  125. if (activeTab.value === "AIchat") {
  126. return AIchat;
  127. } else if (activeTab.value === "AIfind") {
  128. return AIfind;
  129. } else if (activeTab.value === "AiEmotion") {
  130. return AiEmotion; // 新增逻辑
  131. }
  132. });
  133. const activeTwoTab = computed(() => {
  134. if (isAnnouncementVisible.value) {
  135. return Announcement;
  136. } else {
  137. return Feedback;
  138. }
  139. });
  140. // 新增一个方法,调用时先判断是否处于 AIchat,若不在则跳转到 AIchat
  141. const ensureAIchat = () => {
  142. setActiveTab("AIchat", 0, true);
  143. };
  144. // 获取次数
  145. const UserCount = computed(() => chatStore.UserCount);
  146. const getCount = () => {
  147. console.log("点击了获取次数的按钮");
  148. };
  149. // 深度思考
  150. const isThinking = ref(true);
  151. const toggleThink = () => {
  152. isThinking.value = !isThinking.value;
  153. };
  154. // 发送消息
  155. const message = ref("");
  156. // 传输对象
  157. const messages = ref([]);
  158. // 信息加载状态
  159. const isLoading = computed(() => {
  160. chatStore.isLoading;
  161. });
  162. // 输入框禁用状态
  163. const isInputDisabled = ref(false);
  164. // 添加用户消息
  165. const updateMessage = (title) => {
  166. message.value = title;
  167. console.log("updateMessage 的值:", title);
  168. };
  169. watch(
  170. () => chatStore.announcementMsg,
  171. (newVal) => {
  172. console.log("监听到公告改变", chatStore.announcementMsg);
  173. if (chatStore.announcementMsg && !isInputDisabled.value) {
  174. message.value = chatStore.announcementMsg;
  175. chatStore.announcementMsg = null;
  176. }
  177. }
  178. );
  179. watch(
  180. () => dataStore.isFeedback,
  181. async (newVal) => {
  182. if (!dataStore.isFeedback) {
  183. // 重置公告页面显示状态
  184. isAnnouncementVisible.value = false;
  185. await nextTick();
  186. // 监听页面高度
  187. throttledHeightListener();
  188. }
  189. }
  190. );
  191. watch(
  192. () => chatStore.chatInput,
  193. async (newVal) => {
  194. if (activeTab.value == "AIchat") {
  195. isInputDisabled.value = chatStore.chatInput;
  196. }
  197. }
  198. );
  199. watch(
  200. () => chatStore.emotionInput,
  201. async (newVal) => {
  202. if (activeTab.value == "AiEmotion") {
  203. isInputDisabled.value = chatStore.emotionInput;
  204. }
  205. }
  206. );
  207. const sendMessage = async () => {
  208. if (
  209. localStorage.getItem("localToken") == null ||
  210. localStorage.getItem("localToken") == ""
  211. ) {
  212. ElMessage.error("请先登录");
  213. return;
  214. }
  215. // 检查输入内容是否为空
  216. if (!message.value || !message.value.trim()) {
  217. ElMessage.warning("输入内容不能为空");
  218. return;
  219. }
  220. isScrolling.value = false;
  221. // 注意:历史记录会在消息发送后自动更新,无需手动添加
  222. // 取消历史记录选中状态
  223. if (historyRecordRef) {
  224. historyRecordRef.value.selectedRecordId = null;
  225. }
  226. // 判断当前是否为 AiEmotion 组件
  227. if (activeTab.value === "AiEmotion") {
  228. // 禁用输入框
  229. isInputDisabled.value = true;
  230. chatStore.emotionInput = true;
  231. // 调用 AiEmotion 组件的 handleSendMessage 方法
  232. aiEmotionRef.value?.handleSendMessage(message.value, () => {
  233. // 打字机效果完成后的回调,重新启用输入框
  234. isInputDisabled.value = false;
  235. chatStore.emotionInput = false;
  236. });
  237. message.value = ""; // 清空输入框
  238. return;
  239. }
  240. // 调用 ensureAIchat 确保跳转到 AIchat 页面
  241. ensureAIchat();
  242. if (isInputDisabled.value) return;
  243. isInputDisabled.value = true;
  244. chatStore.chatInput = true;
  245. const messageContent = message.value;
  246. // 重置消息输入框
  247. message.value = "";
  248. setTimeout(() => {
  249. console.log("延时后添加消息", messageContent);
  250. // 发送消息时,设置 isLoading 为 true
  251. messages.value = [
  252. ...messages.value,
  253. {
  254. sender: "user",
  255. content: messageContent,
  256. audioArray: [],
  257. audioStatus: false,
  258. },
  259. ];
  260. console.log(messages.value, "messages.value");
  261. }, 200);
  262. };
  263. // 重新启用输入框的方法
  264. const enableInput = () => {
  265. console.log("解除禁用");
  266. isInputDisabled.value = false;
  267. };
  268. // 处理历史记录选择
  269. const handleHistorySelect = (stockData) => {
  270. console.log("接收到历史记录数据:", stockData);
  271. // 如果当前不在AiEmotion页面,切换到AiEmotion页面
  272. // if (activeTab.value !== 'AiEmotion') {
  273. // setActiveTab('AiEmotion', 1);
  274. // }
  275. // 等待组件渲染完成后调用addStock方法
  276. nextTick(() => {
  277. if (aiEmotionRef.value && aiEmotionRef.value.addStock) {
  278. aiEmotionRef.value.addStock(stockData);
  279. } else {
  280. console.error("AiEmotion组件或addStock方法不可用");
  281. }
  282. });
  283. };
  284. // 公告
  285. // 新增一个变量来控制是否显示公告页面
  286. const isAnnouncementVisible = ref(false);
  287. const showAnnouncement = async () => {
  288. console.log("打开公告");
  289. dataStore.isFeedback = true; // 显示用户反馈页面
  290. isScrolling.value = false; //回复滚动到底部方法
  291. isAnnouncementVisible.value = true; // 显示公告页面
  292. if (isMobile.value) {
  293. if (historyRecordRef) {
  294. historyRecordRef.value.isCollapsed = true;
  295. }
  296. }
  297. };
  298. // 跳转用户反馈
  299. const showFeedback = () => {
  300. console.log("打开用户反馈");
  301. dataStore.isFeedback = true; // 显示用户反馈页面
  302. isAnnouncementVisible.value = false; // 显示反馈页面
  303. if (isMobile.value) {
  304. if (historyRecordRef) {
  305. historyRecordRef.value.isCollapsed = true;
  306. }
  307. }
  308. };
  309. // 保证发送消息时,滚动屏在底部
  310. const tabContentAIchat = ref(null);
  311. const tabContentAiEmotion = ref(null);
  312. const isScrolling = ref(false); //判断用户是否在滚动
  313. // AiEmotion页面高度监听器相关变量
  314. const aiEmotionHeightObserver = ref(null);
  315. const isAiEmotionAutoScrollEnabled = ref(false);
  316. const isAiEmotionUserScrolling = ref(false); // 用户是否正在手动滚动
  317. const aiEmotionScrollTimer = ref(null); // 滚动检测定时器
  318. // 获取当前活动页面的滚动容器
  319. const getCurrentScrollContainer = () => {
  320. if (activeTab.value === "AIchat") {
  321. return tabContentAIchat.value;
  322. } else if (activeTab.value === "AiEmotion") {
  323. return tabContentAiEmotion.value;
  324. }
  325. return null;
  326. };
  327. const smoothScrollToBottom = async () => {
  328. // console.log("调用滚动到底部的方法");
  329. // await nextTick();
  330. const container = getCurrentScrollContainer();
  331. // console.log(container, 'container')
  332. // console.log(isScrolling.value, 'isScrolling.value')
  333. if (!container) return;
  334. await nextTick(); // 确保在DOM更新后执行
  335. if (!isScrolling.value) {
  336. container.scrollTop = container.scrollHeight - container.offsetHeight;
  337. // container.scrollTop = container.scrollHeight;
  338. // container.scrollTop = container.offsetHeight;
  339. // container.scrollTop = container.scrollHeight + container.offsetHeight;
  340. // console.log(container.scrollHeight, container.offsetHeight, container.scrollHeight - container.offsetHeight, container.scrollTop, "总长度", "可视长度", "位置")
  341. }
  342. };
  343. const throttledSmoothScrollToBottom = _.throttle(smoothScrollToBottom, 300, {
  344. trailing: false,
  345. });
  346. // AiEmotion页面自动滚动到底部的防抖函数
  347. const debouncedAiEmotionScrollToBottom = _.debounce(() => {
  348. if (
  349. activeTab.value === "AiEmotion" &&
  350. isAiEmotionAutoScrollEnabled.value &&
  351. !isAiEmotionUserScrolling.value
  352. ) {
  353. const container = tabContentAiEmotion.value;
  354. if (container) {
  355. container.scrollTop = container.scrollHeight - container.offsetHeight;
  356. }
  357. }
  358. }, 150);
  359. // 启动AiEmotion页面高度监听器
  360. const startAiEmotionHeightObserver = () => {
  361. // 先停止之前的监听器
  362. stopAiEmotionHeightObserver();
  363. isAiEmotionAutoScrollEnabled.value = true;
  364. // 创建ResizeObserver监听页面内容变化
  365. aiEmotionHeightObserver.value = new ResizeObserver((entries) => {
  366. if (isAiEmotionAutoScrollEnabled.value && activeTab.value === "AiEmotion") {
  367. debouncedAiEmotionScrollToBottom();
  368. }
  369. });
  370. // 监听document.body的尺寸变化
  371. if (document.body) {
  372. aiEmotionHeightObserver.value.observe(document.body);
  373. }
  374. // 创建MutationObserver监听DOM结构变化
  375. const mutationObserver = new MutationObserver((mutations) => {
  376. let shouldScroll = false;
  377. mutations.forEach((mutation) => {
  378. if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
  379. // 检查新增的节点是否包含实际内容
  380. const hasContent = Array.from(mutation.addedNodes).some((node) => {
  381. if (node.nodeType === Node.ELEMENT_NODE) {
  382. return node.offsetHeight > 0 || node.scrollHeight > 0;
  383. }
  384. return (
  385. node.nodeType === Node.TEXT_NODE &&
  386. node.textContent.trim().length > 0
  387. );
  388. });
  389. if (hasContent) {
  390. shouldScroll = true;
  391. }
  392. }
  393. });
  394. if (
  395. shouldScroll &&
  396. isAiEmotionAutoScrollEnabled.value &&
  397. activeTab.value === "AiEmotion"
  398. ) {
  399. debouncedAiEmotionScrollToBottom();
  400. }
  401. });
  402. // 监听AiEmotion页面的主要内容区域的DOM变化
  403. const aiEmotionContainer = tabContentAiEmotion.value;
  404. if (aiEmotionContainer) {
  405. mutationObserver.observe(aiEmotionContainer, {
  406. childList: true,
  407. subtree: true,
  408. attributes: false,
  409. characterData: true,
  410. });
  411. }
  412. // 保存mutationObserver引用以便清理
  413. aiEmotionHeightObserver.value.mutationObserver = mutationObserver;
  414. // 为AiEmotion页面的滚动容器添加滚动事件监听器
  415. if (aiEmotionContainer) {
  416. aiEmotionContainer.addEventListener("scroll", handleAiEmotionUserScroll, {
  417. passive: true,
  418. });
  419. // 保存滚动事件监听器引用以便清理
  420. aiEmotionHeightObserver.value.scrollListener = handleAiEmotionUserScroll;
  421. }
  422. console.log("AiEmotion页面高度监听器已启动");
  423. };
  424. // AiEmotion页面用户滚动检测
  425. const handleAiEmotionUserScroll = () => {
  426. // 标记用户正在滚动
  427. isAiEmotionUserScrolling.value = true;
  428. // 清除之前的定时器
  429. if (aiEmotionScrollTimer.value) {
  430. clearTimeout(aiEmotionScrollTimer.value);
  431. }
  432. // 设置定时器,2秒后恢复自动滚动
  433. // aiEmotionScrollTimer.value = setTimeout(() => {
  434. // isAiEmotionUserScrolling.value = false;
  435. // console.log("AiEmotion页面用户滚动检测:恢复自动滚动");
  436. // }, 2000);
  437. };
  438. // 处理AiEmotion页面的滚动请求
  439. const handleAiEmotionScrollToBottom = () => {
  440. if (activeTab.value === "AiEmotion") {
  441. const container = tabContentAiEmotion.value;
  442. if (container) {
  443. // 使用nextTick确保DOM已更新
  444. nextTick(() => {
  445. container.scrollTop = container.scrollHeight - container.offsetHeight;
  446. console.log("AiEmotion页面:执行容器滚动到底部");
  447. });
  448. }
  449. }
  450. };
  451. // 停止AiEmotion页面高度监听器
  452. const stopAiEmotionHeightObserver = () => {
  453. isAiEmotionAutoScrollEnabled.value = false;
  454. isAiEmotionUserScrolling.value = false;
  455. // 清理滚动检测定时器
  456. if (aiEmotionScrollTimer.value) {
  457. clearTimeout(aiEmotionScrollTimer.value);
  458. aiEmotionScrollTimer.value = null;
  459. }
  460. if (aiEmotionHeightObserver.value) {
  461. // 清理ResizeObserver
  462. aiEmotionHeightObserver.value.disconnect();
  463. // 清理MutationObserver
  464. if (aiEmotionHeightObserver.value.mutationObserver) {
  465. aiEmotionHeightObserver.value.mutationObserver.disconnect();
  466. aiEmotionHeightObserver.value.mutationObserver = null;
  467. }
  468. // 清理滚动事件监听器
  469. if (
  470. aiEmotionHeightObserver.value.scrollListener &&
  471. tabContentAiEmotion.value
  472. ) {
  473. tabContentAiEmotion.value.removeEventListener(
  474. "scroll",
  475. aiEmotionHeightObserver.value.scrollListener
  476. );
  477. aiEmotionHeightObserver.value.scrollListener = null;
  478. }
  479. aiEmotionHeightObserver.value = null;
  480. }
  481. console.log("AiEmotion页面高度监听器已停止");
  482. };
  483. watch(
  484. () => chatStore.messages.length,
  485. () => {
  486. // console.log('messages变化了')
  487. // 只有在AIchat页面时才执行自动滚动
  488. if (activeTab.value === "AIchat") {
  489. throttledSmoothScrollToBottom();
  490. }
  491. // setTimeout(throttledSmoothScrollToBottom, 100);
  492. },
  493. { deep: false, immediate: true }
  494. );
  495. watch(
  496. () => chatStore.dbqbClickRecord,
  497. async (newValue, oldValue) => {
  498. const container = getCurrentScrollContainer();
  499. if (!container) return;
  500. await nextTick(); // 确保在DOM更新后执行
  501. container.scrollTop = 0;
  502. }
  503. );
  504. watch(
  505. activeTab,
  506. async () => {
  507. console.log("activeTab变化了", activeTab.value);
  508. if (activeTab.value == "AIchat" || activeTab.value == "AiEmotion") {
  509. if (historyRecordRef.value && historyRecordRef.value.getHistoryList) {
  510. const result = historyRecordRef.value.getHistoryList({
  511. model: activeTab.value == "AIchat" ? 1 : 2,
  512. token: localStorage.getItem("localToken"),
  513. });
  514. }
  515. }
  516. if (activeTab.value === "AIchat") {
  517. isScrolling.value = false; //回复滚动到底部方法
  518. // 停止AiEmotion页面的高度监听器
  519. stopAiEmotionHeightObserver();
  520. setTimeout(() => {
  521. // throttledSmoothScrollToBottom();
  522. }, 100);
  523. } else if (activeTab.value === "AiEmotion") {
  524. // 启动AiEmotion页面的高度监听器
  525. await nextTick(); // 确保DOM更新后启动监听器
  526. startAiEmotionHeightObserver();
  527. } else {
  528. // 其他页面时停止AiEmotion页面的高度监听器
  529. stopAiEmotionHeightObserver();
  530. }
  531. // AiEmotion页面不执行自动滚动,避免刷新后滚动到底部
  532. // setTimeout(throttledSmoothScrollToBottom, 100);
  533. },
  534. { deep: true, immediate: true }
  535. );
  536. // 获取token的核心函数
  537. const fnGetToken = () => {
  538. // console.log('进入fnGetToken')
  539. window.JWready = (ress) => {
  540. // console.log('进入JWready')
  541. try {
  542. ress = JSON.parse(ress);
  543. // console.log(ress, 'ress')
  544. } catch (error) {
  545. console.log(error, "fnGetToken error");
  546. } //platform为5是app端
  547. // platform.value = ress.data.platform
  548. // 处理平台判断
  549. console.log(ress.data.platform, "ress.data.platform");
  550. if (!ress.data.platform) {
  551. // 非App环境通过URL参数获取
  552. localStorage.setItem(
  553. "localToken",
  554. decodeURIComponent(String(getQueryVariable("token")))
  555. );
  556. // localStorage.setItem('localToken', "+SsksARQgUHIbIG3rRnnbZi0+fEeMx8pywnIlrmTxo5EOPR/wjWDV7w7+ZUseiBtf9kFa/atmNx6QfSpv5w")
  557. } else {
  558. // App环境通过桥接获取
  559. useAppBridge().packageFun(
  560. "JWgetStorage",
  561. (response) => {
  562. const res = JSON.parse(response); // 解析返回的结果
  563. localStorage.setItem("localToken", res.data);
  564. // localStorage.setItem('localToken', "+SsksARQgUHIbIG3rRnnbZi0+fEeMx8pywnIlrmTxo5EOPR/wjWDV7w7+ZUseiBtf9kFa/atmNx6QfSpv5w")
  565. },
  566. 5,
  567. {
  568. key: "token",
  569. }
  570. );
  571. }
  572. };
  573. // console.log('出来了')
  574. // 触发App桥接
  575. useAppBridge().packageFun("JWwebReady", () => {}, 5, {});
  576. };
  577. // 在setTimeout中延迟执行
  578. setTimeout(() => {
  579. fnGetToken();
  580. }, 800);
  581. const heightListener = () => {
  582. const tabContainer = getCurrentScrollContainer();
  583. if (!tabContainer) return;
  584. let befortop = 0;
  585. const scrollHandler = () => {
  586. const aftertop = tabContainer.scrollTop;
  587. // 新增底部判断逻辑
  588. const isBottom =
  589. aftertop + tabContainer.offsetHeight + 70 >= tabContainer.scrollHeight;
  590. if (activeTab.value === "AIchat") {
  591. if (aftertop - befortop > 0) {
  592. // console.log("向下滚动");
  593. isScrolling.value = true;
  594. } else {
  595. // console.log("向上滚动");
  596. isScrolling.value = true;
  597. }
  598. // 添加底部状态检测
  599. if (isBottom) {
  600. // console.log("滚动到底部");
  601. isScrolling.value = false;
  602. }
  603. }
  604. befortop = aftertop;
  605. };
  606. // console.log(isScrolling.value, 'isScrolling.value')
  607. tabContainer.addEventListener("scroll", scrollHandler);
  608. };
  609. const throttledHeightListener = _.throttle(heightListener, 500, {
  610. trailing: false,
  611. });
  612. // const goToRecharge = () => {
  613. // console.log("点击充值");
  614. // // http://39.101.133.168:8919/payment/recharge/index?
  615. // // url=http%3A%2F%2Flocalhost%3A8080%2FLiveActivity%2Fpck
  616. // // &platform=1
  617. // // &token=+S4h5QEE1hTIb4CxphrnbZi0+fEeMx8pywnIlrmTmo4QO6IolWnVWu5r+J4rKXMwK41UPfKqyIp+RvWmtM8
  618. // const userAgent = navigator.userAgent.toLowerCase();
  619. // const mobileKeywords = ["mobile", "android", "iphone", "ipad", "ipod"];
  620. // const isMobile = mobileKeywords.some((keyword) =>
  621. // userAgent.includes(keyword)
  622. // );
  623. // console.log(isMobile ? "手机" : "电脑");
  624. // const url = encodeURI("http://39.101.133.168:8857/aixiaocaishen/homePage");
  625. // console.log(url, "url");
  626. // const platform = isMobile ? 2 : 1;
  627. // const token = encodeURIComponent(localStorage.getItem("localToken"));
  628. // console.log(token, "token");
  629. // const rechargeUrl =
  630. // "http://39.101.133.168:8919/payment/recharge/index?" +
  631. // "url=" +
  632. // url +
  633. // "&platform=" +
  634. // platform +
  635. // "&token=" +
  636. // token;
  637. // console.log(rechargeUrl, "rechargeUrl");
  638. // window.location.href = rechargeUrl;
  639. // // window.open(rechargeUrl)
  640. // };
  641. const adjustFooterPosition = (height) => {
  642. const html = document.querySelector("html");
  643. const body = document.querySelector("body");
  644. const isAndroid = /Android/i.test(navigator.userAgent);
  645. if (isAndroid) {
  646. console.log("是安卓设备");
  647. console.log("window.visualViewport", window.visualViewport.height);
  648. const homePage = document.querySelector(".homepage");
  649. homePage.style.height = `${height}px`;
  650. // homePage.style.height = `460px`;
  651. html.scrollTop = 0;
  652. } else {
  653. console.log("非安卓设备");
  654. console.log("调整底部位置", height);
  655. const homePage = document.querySelector(".homepage");
  656. homePage.style.height = `${height}px`;
  657. html.scrollTop = 0;
  658. }
  659. setTimeout(() => {
  660. // 隐藏滚动条
  661. html.style.overflow = "hidden";
  662. body.style.overflow = "hidden";
  663. }, 200);
  664. };
  665. // 是否正在输入法组合
  666. const inputing = ref(false);
  667. const onFocus = function () {
  668. const visualViewport = window.visualViewport;
  669. // 获取可视区域高度
  670. setTimeout(() => {
  671. console.log("输入框聚焦");
  672. console.log(visualViewport.height, "visualViewport.height");
  673. const keyboardHeight = window.innerHeight - visualViewport.height;
  674. console.log(window.innerHeight, "window.innerHeight");
  675. console.log(keyboardHeight, "keyboardHeight");
  676. adjustFooterPosition(visualViewport.height);
  677. }, 200);
  678. };
  679. const onBlur = function () {
  680. inputing.value = false;
  681. const visualViewport = window.visualViewport;
  682. setTimeout(() => {
  683. console.log("输入框失焦");
  684. const keyboardHeight = window.innerHeight - visualViewport.height;
  685. console.log(window.innerHeight, "window.innerHeight");
  686. console.log(visualViewport.height, "visualViewport.height");
  687. console.log(keyboardHeight, "keyboardHeight");
  688. adjustFooterPosition(visualViewport.height);
  689. }, 200);
  690. };
  691. // window.addEventListener("resize", () => {
  692. // // 检测是否为iOS设备
  693. // const isIOS = /iPhone|iPad|iPod|ios/i.test(navigator.userAgent);
  694. // console.log("是否为iOS设备:", isIOS);
  695. // if (!isIOS) {
  696. // console.log("窗口大小变化");
  697. // const homePage = document.querySelector(".homepage");
  698. // homePage.style.height = `${window.innerHeight}px`;
  699. // }
  700. // });
  701. let touchmoveHandlerRef = null;
  702. const touchmoveHandler = (e) => {
  703. if (!dataStore.isFeedback) {
  704. if (historyRecordRef) {
  705. if (!historyRecordRef.value.isCollapsed) {
  706. return;
  707. }
  708. }
  709. // 判断触摸目标是否在当前活动页面的可滚动区域内
  710. const currentContainer = getCurrentScrollContainer();
  711. const isScrollableArea =
  712. currentContainer && currentContainer.contains(e.target);
  713. // 如果不在可滚动区域,则阻止滚动
  714. if (!isScrollableArea) {
  715. e.preventDefault();
  716. }
  717. }
  718. };
  719. const judgeDevice = async () => {
  720. // 延时300ms
  721. await new Promise((resolve) => setTimeout(resolve, 200));
  722. const userAgent = navigator.userAgent;
  723. isMobile.value =
  724. /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
  725. userAgent
  726. );
  727. console.log("当前设备为:", isMobile.value ? "移动端" : "PC端");
  728. };
  729. const throttledJudgeDevice = _.throttle(judgeDevice, 300, {
  730. trailing: false,
  731. });
  732. const expandHistory = () => {
  733. // if (activeTab.value == "AIchat" || activeTab.value == "AiEmotion") {
  734. // historyRecordRef.value.getHistoryList({
  735. // token: localStorage.getItem("localToken"),
  736. // model: activeTab.value == "AIchat" ? 1 : 2,
  737. // });
  738. // }
  739. if (
  740. historyRecordRef.value &&
  741. historyRecordRef.value.isCollapsed !== undefined
  742. ) {
  743. console.log("存在");
  744. historyRecordRef.value.isCollapsed = !historyRecordRef.value.isCollapsed;
  745. if (activeTab.value == "AIchat") {
  746. chatStore.aiChatCall = true;
  747. } else if (activeTab.value == "AiEmotion") {
  748. chatStore.aiEmotionCall = true;
  749. }
  750. }
  751. };
  752. const backToHome = () => {
  753. if (isMobile.value) {
  754. console.log("用户是移动端");
  755. // 调用原生方法跳转到首页
  756. uni.postMessage({
  757. data: {
  758. val: {
  759. name: "JWopenView",
  760. extra: {
  761. data: {
  762. type: 3,
  763. },
  764. },
  765. },
  766. },
  767. });
  768. } else {
  769. console.log("用户是pc端");
  770. const env = import.meta.env.VITE_ENV;
  771. console.log("当前的环境为:", env);
  772. if (env == "development" || env == "test") {
  773. window.parent.location.href =
  774. "http://121.89.234.155:8807/hljw/homepage?menu=999999991";
  775. } else if (env == "product") {
  776. window.parent.location.href =
  777. "https://web.homilychart.com/product/hljw/homepage?menu=999999991";
  778. } else if (env == "production") {
  779. window.parent.location.href =
  780. "https://web.homilychart.com/hljw/homepage?menu=999999991";
  781. }
  782. // window.parent.location.href = window.parent.document.referrer
  783. }
  784. };
  785. // 8.18金币兑换Token start
  786. const userInfo = ref({
  787. username: "HomilyLink",
  788. jwcode: "90042088",
  789. img: " https://d31zlh4on95l9h.cloudfront.net/images/403ef762dd2f335df3b0c9e3fe488375.png",
  790. });
  791. const changeRule = ref({
  792. gold: 1,
  793. token: 1,
  794. });
  795. const changeLevelList = ref([
  796. { position: 10, calculatedPosition: 10 },
  797. { position: 20, calculatedPosition: 20 },
  798. { position: 50, calculatedPosition: 50 },
  799. { position: 100, calculatedPosition: 100 },
  800. { position: 200, calculatedPosition: 200 },
  801. { position: 500, calculatedPosition: 500 },
  802. { position: 1000, calculatedPosition: 1000 },
  803. ]);
  804. const activeLevel = ref(
  805. changeLevelList.value[0] || { position: 10, calculatedPosition: 10 }
  806. );
  807. const gold = ref(90);
  808. // 点击剩余次数会弹出的弹窗
  809. // 新增一个 ref 来控制弹窗的显示与隐藏
  810. const dialogVisible = ref(false);
  811. const rechargeDialogVisible = ref(false);
  812. const confirmDialogVisible = ref(false);
  813. const changeSuccessDialogVisible = ref(false);
  814. // 获取次数
  815. const showCount = async () => {
  816. try {
  817. const res = await showExchangeAPI();
  818. changeLevelList.value = res.data;
  819. activeLevel.value = changeLevelList.value[0];
  820. changeRule.value.token = res.data[0].ratio;
  821. // 显示弹窗
  822. dialogVisible.value = true;
  823. console.log("dialogVisible 的值:", dialogVisible.value); // 添加日志确认
  824. } catch (e) {
  825. console.error("获取兑换列表出错", e);
  826. }
  827. };
  828. const chooseLevel = (item) => {
  829. activeLevel.value = item;
  830. };
  831. const changeToken = () => {
  832. if (gold.value < activeLevel.value.position) {
  833. rechargeDialogVisible.value = true;
  834. return;
  835. } else {
  836. confirmDialogVisible.value = true;
  837. }
  838. };
  839. const goRecharge = () => {
  840. sessionStorage.setItem("rechargeFlag", "1");
  841. if (isMobile.value) {
  842. console.log("用户是移动端");
  843. // 调用原生方法跳转到首页
  844. uni.postMessage({
  845. data: {
  846. val: {
  847. name: "JWopenView",
  848. extra: {
  849. data: {
  850. type: 4,
  851. },
  852. },
  853. },
  854. },
  855. });
  856. } else {
  857. console.log("用户是pc端");
  858. const env = import.meta.env.VITE_ENV;
  859. console.log("当前的环境为:", env);
  860. if (env == "development" || env == "test") {
  861. window.parent.location.href =
  862. "http://192.168.1.24:8080/user/myGold?token=" +
  863. localStorage.getItem("localToken") +
  864. "&where=xiaocaishen&successUrl=http://192.168.1.5:3000/aixiaocaishen/homePage";
  865. } else if (env == "product") {
  866. // window.parent.location.href =
  867. // 'https://web.homilychart.com/product/hljw/homepage?menu=999999991'
  868. } else if (env == "production") {
  869. // window.parent.location.href = 'https://web.homilychart.com/hljw/homepage?menu=999999991'
  870. }
  871. // window.parent.location.href = window.parent.document.referrer
  872. }
  873. };
  874. const goChange = () => {
  875. confirmDialogVisible.value = false;
  876. dialogVisible.value = false;
  877. changeSuccessDialogVisible.value = true;
  878. setTimeout(() => {
  879. changeSuccessDialogVisible.value = false;
  880. }, 2000);
  881. };
  882. // 8.18金币兑换Token end
  883. onMounted(async () => {
  884. throttledJudgeDevice();
  885. // 禁用全局触摸滚动
  886. touchmoveHandlerRef = touchmoveHandler;
  887. document.addEventListener("touchmove", touchmoveHandlerRef, {
  888. passive: false,
  889. });
  890. setHeight(document.getElementById("testId")); // 给父组件发送窗口高度
  891. // 获取次数
  892. await chatStore.getUserCount();
  893. // 滚动到底部
  894. throttledSmoothScrollToBottom();
  895. // 监听页面高度
  896. throttledHeightListener();
  897. // 添加输入框焦点处理
  898. // handleInputFocus();
  899. // 初始化视口高度变量
  900. // updateAppHeight();
  901. // 添加原生事件监听器
  902. window.addEventListener("resize", throttledJudgeDevice);
  903. if (
  904. sessionStorage.getItem("rechargeFlag") == "1" &&
  905. getQueryVariable("successType") == "success"
  906. ) {
  907. dialogVisible.value = true;
  908. sessionStorage.setItem("rechargeFlag", "0");
  909. }
  910. });
  911. onUnmounted(() => {
  912. window.removeEventListener("resize", throttledJudgeDevice);
  913. if (touchmoveHandlerRef) {
  914. console.log("卸载touchmoveHandlerRef组件");
  915. document.removeEventListener("touchmove", touchmoveHandlerRef);
  916. }
  917. // 清理AiEmotion页面的高度监听器
  918. stopAiEmotionHeightObserver();
  919. });
  920. </script>
  921. <template>
  922. <div class="homepage" id="testId">
  923. <!-- 历史记录组件 -->
  924. <HistoryRecord
  925. ref="historyRecordRef"
  926. :current-type="activeTab"
  927. @selectRecord="handleHistorySelect"
  928. :isMobile="isMobile"
  929. @showAnnouncement="showAnnouncement"
  930. @showFeedback="showFeedback"
  931. />
  932. <div
  933. v-if="isMobile && !historyRecordRef?.isCollapsed"
  934. class="zhezhao"
  935. @click="expandHistory"
  936. ></div>
  937. <el-container
  938. v-if="!dataStore.isFeedback"
  939. class="main-container"
  940. :class="{
  941. collapsed: historyRecordRef?.isCollapsed && !isMobile,
  942. unCollapsed: !historyRecordRef?.isCollapsed && !isMobile,
  943. }"
  944. >
  945. <!-- AI小财神头部 logo 次数 公告 -->
  946. <el-header class="homepage-head">
  947. <!-- logo -->
  948. <div class="homepage-logo" v-if="isMobile">
  949. <img
  950. class="expand"
  951. @click="expandHistory"
  952. src="https://d31zlh4on95l9h.cloudfront.net/images/37fe3d79a8a700f6c674c9f0e7af066b.png"
  953. alt="icon"
  954. />
  955. <img :src="logo" alt="图片加载失败" class="logo1" />
  956. <!-- <img :src="madeInHL" alt="图片加载失败" class="logo2" /> -->
  957. </div>
  958. <div class="homepage-right-group" v-if="isMobile">
  959. <div class="count-badge" @click="showCount">
  960. <img
  961. src="https://d31zlh4on95l9h.cloudfront.net/images/74e20c65c9ef2526477c63ad68698a50.png"
  962. class="action-btn"
  963. />
  964. <div class="count-number">{{ UserCount }}</div>
  965. <div class="clickGetCount">点击获取Token</div>
  966. </div>
  967. <div class="backToHomeBtn" @click="backToHome()">
  968. <img
  969. src="https://d31zlh4on95l9h.cloudfront.net/images/d8b388e461423f79087ddbe016002217.png"
  970. alt="返回首页"
  971. class="backImg"
  972. />
  973. <div class="backContent">返回首页</div>
  974. </div>
  975. <!-- <img
  976. :src="announcementBtn"
  977. class="announcement-btn action-btn"
  978. @click="showAnnouncement"
  979. />
  980. <img
  981. :src="feedbackBtn"
  982. class="announcement-btn action-btn"
  983. @click="showFeedback"
  984. /> -->
  985. </div>
  986. </el-header>
  987. <!-- 主体部分小人 问题轮询图 对话内容 -->
  988. <el-main class="homepage-body">
  989. <div class="main-wrapper">
  990. <section class="tab-section">
  991. <div
  992. class="tab-container"
  993. :class="{
  994. pcTabContainer: !isMobile,
  995. }"
  996. >
  997. <div
  998. v-for="(tab, index) in tabs"
  999. :key="tab.name"
  1000. @click="setActiveTab(tab.name, index)"
  1001. :class="[
  1002. 'tab-item',
  1003. { active: activeIndex === index && !isAnnouncementVisible },
  1004. ]"
  1005. >
  1006. <span>{{ tab.label }}</span>
  1007. </div>
  1008. <div v-if="!isMobile" class="pc-count-badge">
  1009. <div class="pc-countBtn" @click="showCount">
  1010. <div class="pc-action-btn">
  1011. <div class="pc-count-number">{{ UserCount }}</div>
  1012. </div>
  1013. <div class="pc-clickGetCount">点击获取Token</div>
  1014. </div>
  1015. <div class="pc-backToHomeBtn" @click="backToHome()">
  1016. <img
  1017. src="https://d31zlh4on95l9h.cloudfront.net/images/d8b388e461423f79087ddbe016002217.png"
  1018. alt="返回首页"
  1019. class="pc-backImg"
  1020. />
  1021. <div class="pc-backContent">返回首页</div>
  1022. </div>
  1023. </div>
  1024. </div>
  1025. </section>
  1026. <!-- AIchat页面的独立滚动容器 -->
  1027. <div
  1028. v-show="activeTab === 'AIchat'"
  1029. class="tab-content"
  1030. :class="{
  1031. pcTabContent: !isMobile,
  1032. }"
  1033. ref="tabContentAIchat"
  1034. >
  1035. <component
  1036. v-if="activeTab === 'AIchat'"
  1037. :is="activeComponent"
  1038. :messages="messages"
  1039. @updateMessage="updateMessage"
  1040. @sendMessage="sendMessage"
  1041. @ensureAIchat="ensureAIchat"
  1042. @enableInput="enableInput"
  1043. />
  1044. </div>
  1045. <!-- AiEmotion页面的独立滚动容器 -->
  1046. <div
  1047. v-show="activeTab === 'AiEmotion'"
  1048. class="tab-content"
  1049. :class="{
  1050. pcTabContent: !isMobile,
  1051. }"
  1052. ref="tabContentAiEmotion"
  1053. >
  1054. <component
  1055. v-if="activeTab === 'AiEmotion'"
  1056. :is="activeComponent"
  1057. :messages="messages"
  1058. @updateMessage="updateMessage"
  1059. @sendMessage="sendMessage"
  1060. @ensureAIchat="ensureAIchat"
  1061. @enableInput="enableInput"
  1062. @scrollToBottom="handleAiEmotionScrollToBottom"
  1063. ref="aiEmotionRef"
  1064. />
  1065. </div>
  1066. </div>
  1067. </el-main>
  1068. <!-- 尾部 问题输入框 深度思考 多语言 语音播报 -->
  1069. <el-footer
  1070. class="homepage-footer"
  1071. :class="{
  1072. pcFooter: !isMobile,
  1073. }"
  1074. id="input"
  1075. >
  1076. <!-- 第一行按钮 -->
  1077. <div class="footer-first-line">
  1078. <div class="left-group">
  1079. <!-- <img v-if="isThinking" :src="thinkActive" @click="toggleThink" class="action-btn" />
  1080. <img v-else :src="thinkNoActive" @click="toggleThink" class="action-btn" />
  1081. <img :src="languageBtn" @click="changeLanguage" class="action-btn" /> -->
  1082. <!-- 夺宝奇兵大模型按钮 -->
  1083. <img
  1084. :src="activeTab === 'AIchat' ? dbqbButton01 : dbqbButton02"
  1085. @click="setActiveTab('AIchat', 0)"
  1086. class="action-btn model-btn"
  1087. alt="夺宝奇兵大模型"
  1088. />
  1089. <!-- AI情绪大模型按钮 -->
  1090. <img
  1091. :src="
  1092. activeTab === 'AiEmotion' ? emotionButton01 : emotionButton02
  1093. "
  1094. @click="setActiveTab('AiEmotion', 1)"
  1095. class="action-btn model-btn"
  1096. alt="AI情绪大模型"
  1097. />
  1098. <!-- <img v-if="
  1099. getCurrentAudioStore().isVoiceEnabled &&
  1100. getCurrentAudioStore().isPlaying
  1101. " :src="voice" @click="toggleVoice" class="action-btn" style="animation: pulse 1.5s infinite" />
  1102. <img v-else-if="
  1103. getCurrentAudioStore().isVoiceEnabled &&
  1104. !getCurrentAudioStore().isPlaying
  1105. " :src="voiceNoActive" @click="toggleVoice" class="action-btn" />
  1106. <img v-else :src="voiceNoActive" @click="toggleVoice" class="action-btn" /> -->
  1107. </div>
  1108. </div>
  1109. <!-- 第二行输入框 -->
  1110. <div class="footer-second-line">
  1111. <!-- <img :src="msgBtn" class="msg-icon" /> -->
  1112. <div class="input-container">
  1113. <el-input
  1114. type="textarea"
  1115. v-model="message"
  1116. @focus="onFocus"
  1117. @blur="onBlur"
  1118. :autosize="{ minRows: 1, maxRows: 4 }"
  1119. class="msg-input"
  1120. @keydown.enter.exact.prevent="
  1121. isLoading || isInputDisabled ? null : sendMessage()
  1122. "
  1123. :disabled="isInputDisabled"
  1124. resize="none"
  1125. :class="{ input: !message && !inputing }"
  1126. @compositionstart="inputing = true"
  1127. @compositionend="inputing = false"
  1128. >
  1129. </el-input>
  1130. <img
  1131. :src="
  1132. isInputDisabled
  1133. ? 'https://d31zlh4on95l9h.cloudfront.net/images/aa192bcbc1682c97e1bc6fb422f2afff.png'
  1134. : 'https://d31zlh4on95l9h.cloudfront.net/images/e6ec2ae238ced85b74e0912e988f243e.png'
  1135. "
  1136. @click="sendMessage"
  1137. class="action-btn send-btn-inner"
  1138. :style="{
  1139. opacity: isInputDisabled ? 0.5 : 1,
  1140. cursor: isInputDisabled ? 'not-allowed' : 'pointer',
  1141. }"
  1142. />
  1143. </div>
  1144. </div>
  1145. </el-footer>
  1146. </el-container>
  1147. <el-container
  1148. v-else
  1149. class="main-container"
  1150. :class="{
  1151. collapsed: historyRecordRef?.isCollapsed && !isMobile,
  1152. unCollapsed: !historyRecordRef?.isCollapsed && !isMobile,
  1153. }"
  1154. >
  1155. <el-header class="homepage-head">
  1156. <!-- logo -->
  1157. <!-- <div class="homepage-logo">
  1158. <img :src="logo" alt="图片加载失败" class="logo1" />
  1159. <img :src="madeInHL" alt="图片加载失败" class="logo2" />
  1160. </div> -->
  1161. <div class="homepage-right-group">
  1162. <div class="count-badge" @click="showCount">
  1163. <img
  1164. src="https://d31zlh4on95l9h.cloudfront.net/images/74e20c65c9ef2526477c63ad68698a50.png"
  1165. class="action-btn"
  1166. />
  1167. <div class="count-number">{{ UserCount }}</div>
  1168. <div class="clickGetCount">点击获取Token</div>
  1169. </div>
  1170. <div class="backToHomeBtn" @click="backToHome()">
  1171. <img
  1172. src="https://d31zlh4on95l9h.cloudfront.net/images/d8b388e461423f79087ddbe016002217.png"
  1173. alt="返回首页"
  1174. class="backImg"
  1175. />
  1176. <div class="backContent">返回首页</div>
  1177. </div>
  1178. <!-- <img
  1179. :src="announcementBtn"
  1180. class="announcement-btn action-btn"
  1181. @click="showAnnouncement"
  1182. />
  1183. <img
  1184. :src="feedbackBtn"
  1185. class="announcement-btn action-btn"
  1186. @click="showFeedback"
  1187. /> -->
  1188. </div>
  1189. </el-header>
  1190. <!-- 主体部分小人 问题轮询图 对话内容 -->
  1191. <el-main class="homepage-body">
  1192. <component :is="activeTwoTab" />
  1193. </el-main>
  1194. </el-container>
  1195. <!-- 弹窗 -->
  1196. <!-- 新增弹窗组件 -->
  1197. <el-dialog v-model="dialogVisible" :width="isMobile ? '80%' : '40%'">
  1198. <!-- 中间内容部分 -->
  1199. <div class="changeMsg">
  1200. <div class="changeInfo">
  1201. <div class="changeImg">
  1202. <img :src="userInfo.img" alt="头像" class="changeImgClass" />
  1203. </div>
  1204. <div class="changeContent">
  1205. <div class="changeUsername">{{ userInfo.username }}</div>
  1206. <div class="changeJwcode">精网号{{ userInfo.jwcode }}</div>
  1207. </div>
  1208. </div>
  1209. <div class="changeRule">
  1210. 兑换规则{{ changeRule.gold }}金币={{ changeRule.token }}Token
  1211. </div>
  1212. </div>
  1213. <div class="changeLevel">
  1214. <div class="changeLevelTitle">兑换Token</div>
  1215. <div class="changeLevelContent">
  1216. <div
  1217. class="changeLevelItems"
  1218. v-for="item in changeLevelList"
  1219. :key="item"
  1220. :class="{
  1221. changeLevelItemsActive: item.position == activeLevel.position,
  1222. }"
  1223. @click="chooseLevel(item)"
  1224. >
  1225. <div class="changeLevelItem">
  1226. <div class="changeLevelItemToken">
  1227. <img
  1228. src="https://d31zlh4on95l9h.cloudfront.net/images/403ef762dd2f335df3b0c9e3fe488375.png"
  1229. alt="token"
  1230. class="changeLevelItemTokenImg"
  1231. />
  1232. {{ item.calculatedPosition }}
  1233. </div>
  1234. <div class="changeLevelItemToken">{{ item.position }} 金币</div>
  1235. </div>
  1236. </div>
  1237. </div>
  1238. </div>
  1239. <div class="changeNow">
  1240. 应付金额
  1241. <div class="changePay">{{ activeLevel.position }}</div>
  1242. (金币余额{{ gold }})
  1243. </div>
  1244. <div class="changeBtn" @click="changeToken">立即兑换</div>
  1245. </el-dialog>
  1246. <el-dialog
  1247. v-model="rechargeDialogVisible"
  1248. :width="isMobile ? '60%' : '30%'"
  1249. :show-close="false"
  1250. >
  1251. <div class="rechargeDialogTitle">温馨提示</div>
  1252. <div class="rechargeDialogContent">
  1253. 尊敬的用户您好您当前的金币余额不足无法进行兑换可充值金币后进行兑换点击下方的前往充值可进行充值
  1254. </div>
  1255. <div class="rechargeDialogBtnGroup">
  1256. <div class="recharge" @click="goRecharge">前往充值</div>
  1257. <div
  1258. class="rechargeDialogCancel"
  1259. @click="rechargeDialogVisible = false"
  1260. >
  1261. 取消
  1262. </div>
  1263. </div>
  1264. </el-dialog>
  1265. <el-dialog
  1266. v-model="confirmDialogVisible"
  1267. :width="isMobile ? '60%' : '30%'"
  1268. :show-close="false"
  1269. >
  1270. <div class="confirmDialogTitle">兑换</div>
  1271. <div class="confirmDialogContent">
  1272. 尊敬的用户您好您确认要花费{{ activeLevel.position }}金币兑换{{
  1273. activeLevel.calculatedPosition
  1274. }}Token吗
  1275. </div>
  1276. <div class="confirmDialogBtnGroup">
  1277. <div class="confirmDialogConfirm" @click="goChange()">确认</div>
  1278. <div class="confirmDialogCancel" @click="confirmDialogVisible = false">
  1279. 取消
  1280. </div>
  1281. </div>
  1282. </el-dialog>
  1283. <el-dialog
  1284. v-model="changeSuccessDialogVisible"
  1285. :width="isMobile ? '60%' : '30%'"
  1286. :show-close="false"
  1287. class="changeSuccessDialog"
  1288. >
  1289. <div class="changeSuccessDialogTitle">兑换成功</div>
  1290. <div class="changeSuccessDialogContent">
  1291. 尊敬的用户恭喜您成功兑换{{ activeLevel.calculatedPosition }} Token
  1292. </div>
  1293. </el-dialog>
  1294. </div>
  1295. </template>
  1296. <style scoped>
  1297. /* 标签栏 */
  1298. .tab-container {
  1299. display: flex;
  1300. margin-bottom: 10px;
  1301. height: 100%;
  1302. position: relative;
  1303. justify-content: center;
  1304. align-items: center;
  1305. gap: 25vw;
  1306. /* 新增右对齐 */
  1307. }
  1308. .pcTabContainer {
  1309. }
  1310. .tab-item {
  1311. cursor: pointer;
  1312. padding: 8px 12px;
  1313. font-size: clamp(18px, 3vw, 20px);
  1314. /* color: #999; */
  1315. color: #fff;
  1316. transition: all 0.3s;
  1317. border-bottom: 2px solid transparent;
  1318. font-weight: bold;
  1319. }
  1320. .tab-item.active {
  1321. /* color: #000;
  1322. border-color: #000; */
  1323. background: linear-gradient(0deg, #ffffff, #fec13e);
  1324. -webkit-background-clip: text;
  1325. background-clip: text;
  1326. -webkit-text-fill-color: transparent;
  1327. color: transparent;
  1328. border-color: #fec13e;
  1329. }
  1330. .tab-item:not(.active):hover {
  1331. color: #999999;
  1332. }
  1333. .tab-content {
  1334. overflow-y: auto;
  1335. overflow-x: hidden;
  1336. scroll-behavior: smooth;
  1337. height: 100%;
  1338. /* 添加平滑滚动效果 */
  1339. }
  1340. .pcTabContent {
  1341. padding: 0 6%;
  1342. }
  1343. @media (max-width: 768px) {
  1344. .tab-container {
  1345. gap: 15px;
  1346. padding: 0 10px;
  1347. }
  1348. .tab-item {
  1349. font-size: clamp(14px, 3vw, 16px);
  1350. padding: 6px 10px;
  1351. }
  1352. }
  1353. </style>
  1354. <style scoped>
  1355. html {
  1356. height: 100dvh;
  1357. overflow: hidden !important;
  1358. position: fixed;
  1359. margin: 0;
  1360. padding: 0;
  1361. -webkit-overflow-scrolling: auto;
  1362. /* 禁用 iOS 弹性滚动 */
  1363. }
  1364. body {
  1365. height: 100dvh;
  1366. overflow: clip;
  1367. margin: 0;
  1368. padding: 0;
  1369. -webkit-overflow-scrolling: auto;
  1370. /* 禁用 iOS 弹性滚动 */
  1371. position: fixed;
  1372. }
  1373. #app {
  1374. overflow: hidden;
  1375. height: 100%;
  1376. margin: 0;
  1377. padding: 0;
  1378. }
  1379. .homepage {
  1380. /* height: var(--app-height, 100vh); */
  1381. height: var(--app-height, 100vh);
  1382. margin: 0 auto;
  1383. background-image: url("https://d31zlh4on95l9h.cloudfront.net/images/2dc3c13a74100b906e809d26b66db211.png");
  1384. background-size: 100% 100%;
  1385. background-repeat: no-repeat;
  1386. background-position: center;
  1387. display: flex;
  1388. flex-direction: row;
  1389. /* 改为水平布局 */
  1390. overflow: hidden;
  1391. position: fixed;
  1392. top: 0;
  1393. left: 0;
  1394. right: 0;
  1395. bottom: 0;
  1396. width: 100%;
  1397. /* -webkit-overflow-scrolling: touch; */
  1398. }
  1399. .main-container {
  1400. flex: 1;
  1401. transition: margin-left 0.3s ease;
  1402. display: flex;
  1403. flex-direction: column;
  1404. overflow: hidden;
  1405. }
  1406. .main-container.unCollapsed {
  1407. margin-left: 300px; /* 为历史记录组件留出空间 */
  1408. }
  1409. /* 当历史记录组件折叠时调整主容器边距 */
  1410. .main-container.collapsed {
  1411. margin-left: 3%;
  1412. }
  1413. .zhezhao {
  1414. width: 100%;
  1415. height: 100%;
  1416. background-color: rgba(0, 0, 0, 0.5);
  1417. z-index: 100;
  1418. position: fixed;
  1419. }
  1420. /* 移动端适配 */
  1421. @media (max-width: 768px) {
  1422. .homepage {
  1423. background-image: url("https://d31zlh4on95l9h.cloudfront.net/images/90d31d7052e729c63acb9e2cb94d1307.png");
  1424. }
  1425. .main-container {
  1426. /* margin-left: 280px; */
  1427. }
  1428. .main-container.unCollapsed {
  1429. margin-left: 280px;
  1430. }
  1431. .main-container.collapsed {
  1432. margin-left: 40px;
  1433. }
  1434. }
  1435. .homepage .el-container {
  1436. height: 100%;
  1437. flex-direction: column;
  1438. display: flex;
  1439. width: 100%;
  1440. overflow: hidden;
  1441. /* 防止容器滚动 */
  1442. }
  1443. .el-container .el-header {
  1444. flex-shrink: 0;
  1445. /* 防止头部压缩 */
  1446. height: auto;
  1447. min-height: 60px;
  1448. padding: 5px 0;
  1449. position: sticky;
  1450. top: 0;
  1451. z-index: 10;
  1452. /* background-color: rgba(255, 255, 255, 0.9); */
  1453. }
  1454. .el-container .el-main {
  1455. flex: 1;
  1456. /* 自动占据剩余空间 */
  1457. overflow: hidden;
  1458. /* 主容器不滚动 */
  1459. display: flex;
  1460. flex-direction: column;
  1461. min-height: 0;
  1462. /* 允许内容区域缩小 */
  1463. position: relative;
  1464. height: auto;
  1465. }
  1466. .el-container .el-footer {
  1467. flex-shrink: 0;
  1468. height: auto;
  1469. min-height: 70px;
  1470. position: sticky;
  1471. bottom: 0;
  1472. z-index: 20;
  1473. background-color: rgba(211, 24, 24, 0);
  1474. box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
  1475. -webkit-transform: translateZ(0);
  1476. transform: translateZ(0);
  1477. padding-bottom: env(safe-area-inset-bottom, 0);
  1478. /* 适配iPhone X及以上的底部安全区域 */
  1479. }
  1480. .homepage-head {
  1481. padding: 0px;
  1482. display: flex;
  1483. position: relative;
  1484. justify-content: space-between;
  1485. width: 100%;
  1486. }
  1487. .homepage-right-group {
  1488. display: flex;
  1489. gap: 8px;
  1490. align-items: center;
  1491. margin-left: auto;
  1492. margin-right: 20px;
  1493. }
  1494. .homepage-right-group .action-btn {
  1495. height: 40px;
  1496. }
  1497. .count-badge {
  1498. position: relative;
  1499. cursor: pointer;
  1500. }
  1501. .count-badge:hover {
  1502. transform: scale(1.05);
  1503. }
  1504. .count-number {
  1505. position: absolute;
  1506. top: 16px;
  1507. right: 0px;
  1508. width: 68%;
  1509. text-align: center;
  1510. color: #6a00ff;
  1511. font-size: 14px;
  1512. font-weight: bold;
  1513. }
  1514. .clickGetCount {
  1515. width: 100%;
  1516. text-align: center;
  1517. color: white;
  1518. font-size: 12px;
  1519. }
  1520. .backToHomeBtn {
  1521. display: flex;
  1522. flex-direction: column;
  1523. justify-content: center;
  1524. align-items: center;
  1525. cursor: pointer;
  1526. }
  1527. .backToHomeBtn:hover {
  1528. transform: scale(1.05);
  1529. }
  1530. .backImg {
  1531. width: 100%;
  1532. height: auto;
  1533. }
  1534. .backContent {
  1535. width: 100%;
  1536. text-align: center;
  1537. color: white;
  1538. font-size: 12px;
  1539. white-space: nowrap;
  1540. }
  1541. .pc-count-badge {
  1542. width: 200px;
  1543. height: 100%;
  1544. position: absolute;
  1545. right: 20px;
  1546. display: flex;
  1547. }
  1548. .pc-countBtn {
  1549. width: 65%;
  1550. height: 100%;
  1551. position: relative;
  1552. cursor: pointer;
  1553. }
  1554. .pc-countBtn:hover {
  1555. transform: scale(1.05);
  1556. }
  1557. .pc-action-btn {
  1558. width: 100%;
  1559. height: 70%;
  1560. background-image: url("https://d31zlh4on95l9h.cloudfront.net/images/74e20c65c9ef2526477c63ad68698a50.png");
  1561. background-repeat: no-repeat;
  1562. background-size: 100% 100%;
  1563. }
  1564. .pc-count-number {
  1565. position: absolute;
  1566. top: 15px;
  1567. right: 4px;
  1568. width: 68%;
  1569. text-align: center;
  1570. color: #6a00ff;
  1571. font-size: 15px;
  1572. font-weight: bold;
  1573. }
  1574. .pc-clickGetCount {
  1575. width: 100%;
  1576. text-align: center;
  1577. color: white;
  1578. font-size: 12px;
  1579. }
  1580. .pc-backToHomeBtn {
  1581. width: 35%;
  1582. height: 100%;
  1583. display: flex;
  1584. flex-direction: column;
  1585. align-items: center;
  1586. cursor: pointer;
  1587. }
  1588. .pc-backImg {
  1589. width: auto;
  1590. height: 70%;
  1591. }
  1592. .pc-backContent {
  1593. width: 100%;
  1594. text-align: center;
  1595. color: white;
  1596. font-size: 12px;
  1597. }
  1598. .pc-backToHomeBtn:hover {
  1599. transform: scale(1.05);
  1600. }
  1601. .homepage-right-group .announcement-btn {
  1602. cursor: pointer;
  1603. transition: transform 0.3s;
  1604. }
  1605. .homepage-right-group .announcement-btn:hover {
  1606. transform: scale(1.3);
  1607. }
  1608. .homepage-body {
  1609. padding: 0px;
  1610. display: flex;
  1611. flex-direction: column;
  1612. flex: 1;
  1613. min-height: 0;
  1614. /* 允许内容区域缩小 */
  1615. overflow: hidden;
  1616. }
  1617. .main-wrapper {
  1618. height: 100%;
  1619. display: flex;
  1620. flex-direction: column;
  1621. flex: 1;
  1622. min-height: 0;
  1623. /* 允许内容区域缩小 */
  1624. }
  1625. .tab-section {
  1626. flex-shrink: 0;
  1627. /* 禁止伸缩 */
  1628. }
  1629. .tab-content {
  1630. flex: 1;
  1631. overflow-y: auto;
  1632. min-height: 0;
  1633. /* 关键:允许内容收缩 */
  1634. }
  1635. .homepage-logo {
  1636. height: 100%;
  1637. width: fit-content;
  1638. display: flex;
  1639. /* flex-direction: column; */
  1640. align-items: center;
  1641. justify-content: center;
  1642. margin-left: 20px;
  1643. margin-right: auto;
  1644. position: relative;
  1645. gap: 10px;
  1646. }
  1647. .expand {
  1648. font-size: 2.5rem;
  1649. cursor: pointer;
  1650. color: white;
  1651. }
  1652. .logo1 {
  1653. width: 110px;
  1654. height: auto;
  1655. margin-bottom: 8px;
  1656. }
  1657. .logo2 {
  1658. width: 80px;
  1659. height: auto;
  1660. }
  1661. /* 尾部 */
  1662. .homepage-footer {
  1663. display: flex;
  1664. flex-direction: column;
  1665. gap: 5px;
  1666. flex-shrink: 0;
  1667. /* width: 100%; */
  1668. background-color: #fff;
  1669. }
  1670. .pcFooter {
  1671. margin: 0 6% 4%;
  1672. }
  1673. .footer-first-line {
  1674. display: flex;
  1675. justify-content: space-between;
  1676. align-items: center;
  1677. padding: 5px 15px;
  1678. flex-shrink: 0;
  1679. }
  1680. .left-group {
  1681. display: flex;
  1682. gap: 15px;
  1683. }
  1684. .action-btn {
  1685. cursor: pointer;
  1686. transition: transform 0.2s;
  1687. height: 28px;
  1688. }
  1689. .model-btn {
  1690. height: 32px;
  1691. transition: all 0.3s ease;
  1692. }
  1693. .model-btn:hover {
  1694. transform: scale(1.1);
  1695. }
  1696. .send-btn {
  1697. margin-left: 10px;
  1698. height: 33px !important;
  1699. width: auto;
  1700. /* margin-right: 5px; */
  1701. }
  1702. .input-container {
  1703. position: relative;
  1704. width: 100%;
  1705. }
  1706. .send-btn-inner {
  1707. position: absolute;
  1708. right: 10px;
  1709. top: 50%;
  1710. transform: translateY(-50%);
  1711. height: 28px !important;
  1712. width: auto;
  1713. z-index: 10;
  1714. transition: all 0.3s ease;
  1715. }
  1716. .send-btn-inner:hover {
  1717. transform: translateY(-50%) scale(1.1);
  1718. }
  1719. /* 音频播放动画 */
  1720. @keyframes pulse {
  1721. 0% {
  1722. transform: scale(1);
  1723. }
  1724. 50% {
  1725. transform: scale(1.1);
  1726. }
  1727. 100% {
  1728. transform: scale(1);
  1729. }
  1730. }
  1731. .footer-second-line {
  1732. position: relative;
  1733. display: flex;
  1734. align-items: center;
  1735. padding: 5px 15px 10px;
  1736. flex-shrink: 0;
  1737. }
  1738. .msg-icon {
  1739. position: absolute;
  1740. left: 25px;
  1741. top: 50%;
  1742. transform: translateY(-50%);
  1743. width: 24px;
  1744. z-index: 999;
  1745. }
  1746. .msg-input:deep(.el-textarea__inner) {
  1747. border: none !important;
  1748. box-shadow: none !important;
  1749. overflow-y: auto !important;
  1750. transition: all 0.2s ease-out;
  1751. resize: none !important;
  1752. line-height: 1.5 !important;
  1753. max-height: 100px !important;
  1754. padding-right: 45px !important;
  1755. }
  1756. .msg-input {
  1757. min-height: 34px;
  1758. width: 100%;
  1759. border-radius: 5px;
  1760. font-size: 16px;
  1761. transition: all 0.3s ease-out;
  1762. overflow-y: hidden;
  1763. box-shadow: 0 4px 12px rgba(89, 24, 241, 0.3);
  1764. background: #fff;
  1765. z-index: 5;
  1766. /* 添加iOS设备特殊处理 */
  1767. -webkit-appearance: none;
  1768. appearance: none;
  1769. }
  1770. .msg-input:focus {
  1771. outline: none;
  1772. }
  1773. .input::before {
  1774. content: "请输入股票名称或股票代码...";
  1775. position: absolute;
  1776. left: 11px;
  1777. top: 5px;
  1778. color: var(--el-text-color-secondary);
  1779. pointer-events: none;
  1780. white-space: nowrap;
  1781. overflow-x: hidden;
  1782. text-overflow: ellipsis;
  1783. width: 80%;
  1784. z-index: 6;
  1785. }
  1786. .changeMsg {
  1787. display: flex;
  1788. width: 100%;
  1789. margin-bottom: 30px;
  1790. flex-wrap: wrap;
  1791. gap: 20px;
  1792. }
  1793. .changeInfo {
  1794. display: flex;
  1795. background-color: #f8f8f8;
  1796. border-radius: 5px;
  1797. padding: 10px 20px;
  1798. /* width: 40%; */
  1799. white-space: nowrap;
  1800. }
  1801. .changeImg {
  1802. height: 100%;
  1803. display: flex;
  1804. justify-content: center;
  1805. align-items: center;
  1806. margin-right: 10px;
  1807. }
  1808. .changeImgClass {
  1809. }
  1810. .changeContent {
  1811. display: flex;
  1812. flex-direction: column;
  1813. justify-content: center;
  1814. font-weight: bold;
  1815. }
  1816. .changeRule {
  1817. display: flex;
  1818. background-color: #f8f8f8;
  1819. border-radius: 5px;
  1820. text-align: center;
  1821. align-items: center;
  1822. justify-content: center;
  1823. color: #4e86fe;
  1824. white-space: nowrap;
  1825. padding: 5px 20px;
  1826. min-width: 40%;
  1827. }
  1828. .changeLevel {
  1829. display: flex;
  1830. flex-direction: column;
  1831. }
  1832. .changeLevelTitle {
  1833. font-weight: bold;
  1834. margin-bottom: 10px;
  1835. }
  1836. .changeLevelContent {
  1837. display: flex;
  1838. flex-wrap: wrap;
  1839. gap: 15px;
  1840. margin-bottom: 10px;
  1841. }
  1842. .changeLevelItems {
  1843. display: flex;
  1844. background-color: #f8f8f8;
  1845. width: 20%;
  1846. min-width: 70px;
  1847. max-width: 150px;
  1848. justify-content: center;
  1849. align-items: center;
  1850. flex-direction: column;
  1851. border-radius: 10px;
  1852. padding: 5px;
  1853. cursor: pointer;
  1854. }
  1855. .changeLevelItems:hover {
  1856. background-color: #ecf2ff;
  1857. }
  1858. .changeLevelItemsActive {
  1859. border: 1px solid #4e86fe;
  1860. background-color: #ecf2ff;
  1861. }
  1862. .changeLevelItem {
  1863. display: flex;
  1864. flex-direction: column;
  1865. justify-content: center;
  1866. align-items: center;
  1867. }
  1868. .changeLevelItemToken {
  1869. display: flex;
  1870. justify-content: center;
  1871. align-items: center;
  1872. }
  1873. .changeLevelItemTokenImg {
  1874. width: 40px;
  1875. height: 40px;
  1876. }
  1877. .changeNow {
  1878. display: flex;
  1879. white-space: nowrap;
  1880. /* font-weight: bold; */
  1881. margin-bottom: 15px;
  1882. align-items: center;
  1883. }
  1884. .changePay {
  1885. color: #4e86fe;
  1886. margin: 0px 5px;
  1887. font-size: 1.1rem;
  1888. }
  1889. .changeBtn {
  1890. width: 40%;
  1891. max-width: 350px;
  1892. background-color: #4e86fe;
  1893. color: white;
  1894. display: flex;
  1895. justify-content: center;
  1896. align-content: center;
  1897. padding: 10px;
  1898. border-radius: 5px;
  1899. cursor: pointer;
  1900. }
  1901. .changeBtn:hover {
  1902. background-color: #3a73e6;
  1903. }
  1904. .rechargeDialogTitle {
  1905. font-size: 1.7rem;
  1906. /* font-weight: bold; */
  1907. color: #4e86fe;
  1908. display: flex;
  1909. justify-content: center;
  1910. align-items: center;
  1911. letter-spacing: 10px;
  1912. }
  1913. .rechargeDialogContent {
  1914. padding: 20px;
  1915. font-size: 1.2rem;
  1916. }
  1917. .rechargeDialogBtnGroup {
  1918. display: flex;
  1919. font-size: 1.2rem;
  1920. padding: 0px 20px;
  1921. justify-content: space-between;
  1922. }
  1923. .recharge {
  1924. color: white;
  1925. background-color: #4e86fe;
  1926. padding: 10px 20px;
  1927. border-radius: 13px;
  1928. cursor: pointer;
  1929. min-width: 20%;
  1930. text-align: center;
  1931. white-space: nowrap;
  1932. }
  1933. .recharge:hover {
  1934. background-color: #3a73e6;
  1935. }
  1936. .rechargeDialogCancel {
  1937. border: 1px solid rgb(202, 202, 202);
  1938. padding: 10px 20px;
  1939. border-radius: 13px;
  1940. cursor: pointer;
  1941. min-width: 20%;
  1942. text-align: center;
  1943. }
  1944. .rechargeDialogCancel:hover {
  1945. background-color: #ecf2ff;
  1946. }
  1947. .confirmDialogTitle {
  1948. font-size: 1.7rem;
  1949. /* font-weight: bold; */
  1950. color: #4e86fe;
  1951. display: flex;
  1952. justify-content: center;
  1953. align-items: center;
  1954. letter-spacing: 10px;
  1955. }
  1956. .confirmDialogContent {
  1957. padding: 20px;
  1958. font-size: 1.2rem;
  1959. }
  1960. .confirmDialogBtnGroup {
  1961. display: flex;
  1962. font-size: 1.2rem;
  1963. padding: 0px 20px;
  1964. justify-content: space-between;
  1965. }
  1966. .confirmDialogConfirm {
  1967. color: white;
  1968. background-color: #4e86fe;
  1969. padding: 10px 20px;
  1970. border-radius: 13px;
  1971. cursor: pointer;
  1972. min-width: 20%;
  1973. text-align: center;
  1974. }
  1975. .confirmDialogConfirm:hover {
  1976. background-color: #3a73e6;
  1977. }
  1978. .confirmDialogCancel {
  1979. border: 1px solid rgb(202, 202, 202);
  1980. padding: 10px 20px;
  1981. border-radius: 13px;
  1982. cursor: pointer;
  1983. min-width: 20%;
  1984. text-align: center;
  1985. }
  1986. .confirmDialogCancel:hover {
  1987. background-color: #ecf2ff;
  1988. }
  1989. .changeSuccessDialogTitle {
  1990. font-size: 1.7rem;
  1991. font-weight: bold;
  1992. color: #de93a3;
  1993. display: flex;
  1994. justify-content: center;
  1995. align-items: center;
  1996. letter-spacing: 10px;
  1997. }
  1998. .changeSuccessDialogContent {
  1999. padding: 20px;
  2000. font-size: 1.2rem;
  2001. font-weight: bold;
  2002. text-align: center;
  2003. }
  2004. @media (max-width: 768px) {
  2005. .action-btn {
  2006. height: 21px;
  2007. }
  2008. .footer-second-line {
  2009. padding: 5px 10px 10px;
  2010. }
  2011. .msg-input {
  2012. /* min-height: 44px; */
  2013. /* height: 44px; */
  2014. font-size: 16px;
  2015. }
  2016. /* .changeImg {
  2017. width: 30px;
  2018. height: 30px;
  2019. } */
  2020. .changeImgClass {
  2021. width: 30px;
  2022. height: 30px;
  2023. }
  2024. .changeContent {
  2025. font-size: 0.5rem;
  2026. }
  2027. .changeLevelItems {
  2028. font-size: 0.5rem;
  2029. }
  2030. .rechargeDialogTitle {
  2031. font-size: 1.3rem;
  2032. }
  2033. .rechargeDialogContent {
  2034. font-size: 1rem;
  2035. }
  2036. .rechargeDialogBtnGroup {
  2037. font-size: 1rem;
  2038. }
  2039. .recharge {
  2040. padding: 5px 10px;
  2041. }
  2042. .rechargeDialogCancel {
  2043. padding: 5px 10px;
  2044. }
  2045. .confirmDialogTitle {
  2046. font-size: 1.3rem;
  2047. }
  2048. .confirmDialogContent {
  2049. font-size: 1rem;
  2050. }
  2051. .confirmDialogBtnGroup {
  2052. font-size: 1rem;
  2053. }
  2054. .confirmDialogConfirm {
  2055. padding: 5px 10px;
  2056. }
  2057. .confirmDialogCancel {
  2058. padding: 5px 10px;
  2059. }
  2060. .changeSuccessDialogTitle {
  2061. font-size: 1.3rem;
  2062. }
  2063. .changeSuccessDialogContent {
  2064. font-size: 1rem;
  2065. }
  2066. }
  2067. </style>
  2068. <style>
  2069. .changeSuccessDialog {
  2070. background: linear-gradient(180deg, #a2dffe, #b59be1);
  2071. }
  2072. </style>