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.

1217 lines
31 KiB

  1. <template>
  2. <div
  3. v-if="!isMobile"
  4. class="history-record-container"
  5. :class="{
  6. collapsed: !isCollapsed,
  7. }"
  8. >
  9. <!-- 收起状态的展开按钮和图标 -->
  10. <div v-if="isCollapsed" class="collapsed-container">
  11. <img
  12. class="collapsed-icon"
  13. src="https://d31zlh4on95l9h.cloudfront.net/images/74430a4ebbb67aefc713bf694147fb2a.png"
  14. alt="icon"
  15. />
  16. <img
  17. class="collapsed-toggle-btn"
  18. @click="openHistory"
  19. src="https://d31zlh4on95l9h.cloudfront.net/images/b2d784f8607ab65081f5289459581bfe.png"
  20. alt="icon"
  21. title="打开边栏"
  22. />
  23. </div>
  24. <div v-if="isCollapsed" class="collapsed-bottom-container">
  25. <div
  26. class="collapsed-bottom-btn"
  27. @click="handleAnnouncementClick"
  28. title="公告"
  29. >
  30. <img
  31. class="collapsed-bottom-announcement"
  32. src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
  33. alt="icon"
  34. />
  35. </div>
  36. <div
  37. class="collapsed-bottom-btn"
  38. @click="handleFeedbackClick"
  39. title="用户反馈"
  40. >
  41. <img
  42. class="collapsed-bottom-feedback"
  43. src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
  44. alt="icon"
  45. />
  46. </div>
  47. </div>
  48. <!-- 历史记录内容 -->
  49. <div class="history-content" v-if="!isCollapsed">
  50. <div class="head-container">
  51. <!-- 标题 -->
  52. <div class="history-actions">
  53. <img
  54. src="/src/assets/img/homePage/logo.png"
  55. alt="Logo"
  56. class="logo-img"
  57. />
  58. </div>
  59. <!-- 折叠/展开按钮 -->
  60. <img
  61. class="toggle-btn"
  62. @click="closeHistory"
  63. src="https://d31zlh4on95l9h.cloudfront.net/images/b2d784f8607ab65081f5289459581bfe.png"
  64. alt="icon"
  65. title="收起边栏"
  66. />
  67. </div>
  68. <!-- 历史记录列表 -->
  69. <div class="history-list">
  70. <!-- 空状态 -->
  71. <div v-if="historyRecords.length === 0" class="empty-state">
  72. <div class="empty-icon">
  73. <el-icon class="documentDelete"><DocumentDelete /></el-icon>
  74. </div>
  75. <p class="empty-text">暂无历史记录</p>
  76. </div>
  77. <div v-else v-for="history in categoryHistory" :key="history.name">
  78. <div class="categoryName">
  79. {{ history.name }}
  80. </div>
  81. <div
  82. v-for="record in history.list"
  83. :key="record.id"
  84. class="history-item"
  85. :class="{ active: selectedRecordId === record.id }"
  86. >
  87. <div class="record-content" @click="selectRecord(record)">
  88. <div class="record-img">
  89. <img
  90. :src="marketList[record.stockMarket]"
  91. :alt="record.stockMarket"
  92. />
  93. </div>
  94. <div class="record-msg">
  95. <div class="record-text">
  96. <span class="stock-name">{{ record.stockName }}</span>
  97. <span class="stock-code">({{ record.stockCode }})</span>
  98. <div v-if="history.name === '置顶'">
  99. <svg
  100. t="1755227529729"
  101. class="top-icon"
  102. viewBox="320 280 380 460"
  103. version="1.1"
  104. xmlns="http://www.w3.org/2000/svg"
  105. p-id="7392"
  106. >
  107. <path
  108. d="M351.085714 292.571429h321.828572v29.257142H351.085714v-29.257142z m175.542857 125.805714l146.285715 146.285714-20.48 20.48-125.805715-125.805714V731.428571h-29.257142v-272.091428L371.565714 585.142857l-20.48-20.48 146.285715-146.285714h29.257142z"
  109. fill="#FFFFFF"
  110. p-id="7393"
  111. ></path>
  112. </svg>
  113. </div>
  114. </div>
  115. <div class="record-time">
  116. {{ moment(record.createdTime).format("YYYY-MM-DD HH:mm:ss") }}
  117. </div>
  118. </div>
  119. </div>
  120. <div class="record-actions">
  121. <el-popover
  122. class="box-item"
  123. placement="right-start"
  124. trigger="click"
  125. >
  126. <template #reference>
  127. <el-icon class="more-btn"><MoreFilled /></el-icon>
  128. </template>
  129. <div class="popover-content">
  130. <div class="popover-item">
  131. <img
  132. class="popover-icon"
  133. src="https://d31zlh4on95l9h.cloudfront.net/images/9ad3617c94955bcb76e1b11db70bb80b.png"
  134. alt=""
  135. />
  136. 数据更新时间{{ moment(record.date).format("D/M/YYYY") }}
  137. </div>
  138. <div
  139. v-if="record.isTop"
  140. class="popover-item popover-btn"
  141. @click="changeTopStatus(record.isTop, record.id)"
  142. >
  143. <img
  144. class="popover-icon"
  145. src="https://d31zlh4on95l9h.cloudfront.net/images/a458305d8275734cc96bf6cad29864bf.png"
  146. alt=""
  147. />
  148. 取消置顶
  149. </div>
  150. <div
  151. v-else
  152. class="popover-item popover-btn"
  153. @click="changeTopStatus(record.isTop, record.id)"
  154. >
  155. <img
  156. class="popover-icon"
  157. src="https://d31zlh4on95l9h.cloudfront.net/images/a458305d8275734cc96bf6cad29864bf.png"
  158. alt=""
  159. />
  160. 置顶
  161. </div>
  162. <div
  163. class="popover-item popover-btn"
  164. @click="deleteRecord(record.id)"
  165. >
  166. <img
  167. class="popover-icon"
  168. src="https://d31zlh4on95l9h.cloudfront.net/images/027718d41523375a69e9cac927601cf8.png"
  169. alt=""
  170. />
  171. 删除
  172. </div>
  173. </div>
  174. </el-popover>
  175. <!-- <button
  176. @click="openDetail(record)"
  177. title="更多"
  178. ></button> -->
  179. </div>
  180. </div>
  181. </div>
  182. </div>
  183. <div class="bottom-container">
  184. <div class="bottom-btn" @click="handleAnnouncementClick" title="公告">
  185. <img
  186. class="bottom-announcement"
  187. src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
  188. alt="icon"
  189. />
  190. </div>
  191. <div class="bottom-btn" @click="handleFeedbackClick" title="用户反馈">
  192. <img
  193. class="bottom-feedback"
  194. src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
  195. alt="icon"
  196. />
  197. </div>
  198. </div>
  199. </div>
  200. </div>
  201. <div
  202. v-else
  203. class="mobile-history-record-container"
  204. :class="{
  205. mobileCollapsed: !isCollapsed,
  206. }"
  207. >
  208. <!-- 历史记录内容 -->
  209. <div class="history-content" v-if="!isCollapsed">
  210. <div class="mobile-head-container">
  211. <!-- 折叠/展开按钮 -->
  212. <img
  213. class="mobile-toggle-btn"
  214. @click="closeHistory"
  215. src="https://d31zlh4on95l9h.cloudfront.net/images/37fe3d79a8a700f6c674c9f0e7af066b.png"
  216. alt="icon"
  217. />
  218. <!-- 标题 -->
  219. <div class="mobile-history-actions">
  220. <img
  221. src="/src/assets/img/homePage/logo.png"
  222. alt="Logo"
  223. class="logo-img"
  224. />
  225. </div>
  226. </div>
  227. <!-- 历史记录列表 -->
  228. <div class="history-list">
  229. <!-- 空状态 -->
  230. <div v-if="historyRecords.length === 0" class="empty-state">
  231. <div class="empty-icon">
  232. <el-icon class="documentDelete"><DocumentDelete /></el-icon>
  233. </div>
  234. <p class="empty-text">暂无历史记录</p>
  235. </div>
  236. <div v-else v-for="history in categoryHistory" :key="history.name">
  237. <div class="categoryName">
  238. {{ history.name }}
  239. </div>
  240. <div
  241. v-for="record in history.list"
  242. :key="record.id"
  243. class="history-item"
  244. :class="{ active: selectedRecordId === record.id }"
  245. >
  246. <div class="record-content" @click="selectRecord(record)">
  247. <div class="record-img">
  248. <img
  249. :src="marketList[record.stockMarket]"
  250. :alt="record.stockMarket"
  251. />
  252. </div>
  253. <div class="record-msg">
  254. <div class="record-text">
  255. {{ record.stockCode }}
  256. <div v-if="history.name === '置顶'">
  257. <svg
  258. t="1755227529729"
  259. class="top-icon"
  260. viewBox="320 280 380 460"
  261. version="1.1"
  262. xmlns="http://www.w3.org/2000/svg"
  263. p-id="7392"
  264. >
  265. <path
  266. d="M351.085714 292.571429h321.828572v29.257142H351.085714v-29.257142z m175.542857 125.805714l146.285715 146.285714-20.48 20.48-125.805715-125.805714V731.428571h-29.257142v-272.091428L371.565714 585.142857l-20.48-20.48 146.285715-146.285714h29.257142z"
  267. fill="#FFFFFF"
  268. p-id="7393"
  269. ></path>
  270. </svg>
  271. </div>
  272. </div>
  273. <div class="record-time">
  274. {{ moment(record.createdTime).format("YYYY-MM-DD HH:mm:ss") }}
  275. </div>
  276. </div>
  277. </div>
  278. <div class="record-actions">
  279. <el-popover
  280. class="box-item"
  281. placement="right-start"
  282. trigger="click"
  283. >
  284. <template #reference>
  285. <el-icon class="more-btn"><MoreFilled /></el-icon>
  286. </template>
  287. <div class="popover-content">
  288. <div class="popover-item">
  289. <img
  290. class="popover-icon"
  291. src="https://d31zlh4on95l9h.cloudfront.net/images/9ad3617c94955bcb76e1b11db70bb80b.png"
  292. alt=""
  293. />
  294. 数据更新时间{{ moment(record.date).format("D/M/YYYY") }}
  295. </div>
  296. <div
  297. v-if="record.isTop"
  298. class="popover-item popover-btn"
  299. @click="changeTopStatus(record.isTop, record.id)"
  300. >
  301. <img
  302. class="popover-icon"
  303. src="https://d31zlh4on95l9h.cloudfront.net/images/a458305d8275734cc96bf6cad29864bf.png"
  304. alt=""
  305. />
  306. 取消置顶
  307. </div>
  308. <div
  309. v-else
  310. class="popover-item popover-btn"
  311. @click="changeTopStatus(record.isTop, record.id)"
  312. >
  313. <img
  314. class="popover-icon"
  315. src="https://d31zlh4on95l9h.cloudfront.net/images/a458305d8275734cc96bf6cad29864bf.png"
  316. alt=""
  317. />
  318. 置顶
  319. </div>
  320. <div
  321. class="popover-item popover-btn"
  322. @click="deleteRecord(record.id)"
  323. >
  324. <img
  325. class="popover-icon"
  326. src="https://d31zlh4on95l9h.cloudfront.net/images/027718d41523375a69e9cac927601cf8.png"
  327. alt=""
  328. />
  329. 删除
  330. </div>
  331. </div>
  332. </el-popover>
  333. <!-- <button
  334. @click="openDetail(record)"
  335. title="更多"
  336. ></button> -->
  337. </div>
  338. </div>
  339. </div>
  340. </div>
  341. <div class="mobile-bottom-container">
  342. <div
  343. class="mobile-bottom-btn"
  344. @click="handleAnnouncementClick"
  345. title="公告"
  346. >
  347. <img
  348. class="mobile-bottom-announcement"
  349. src="https://d31zlh4on95l9h.cloudfront.net/images/c51c7fbb68671729801fb10d65bd7789.png"
  350. alt="icon"
  351. />
  352. <div class="mobile-bottom-text">公告</div>
  353. </div>
  354. <div
  355. class="mobile-bottom-btn"
  356. @click="handleFeedbackClick"
  357. title="用户反馈"
  358. >
  359. <img
  360. class="mobile-bottom-feedback"
  361. src="https://d31zlh4on95l9h.cloudfront.net/images/41d6e25c19466718d462bcee2f050140.png"
  362. alt="icon"
  363. />
  364. <div class="mobile-bottom-text">用户反馈</div>
  365. </div>
  366. </div>
  367. </div>
  368. </div>
  369. <el-dialog v-model="deleteDialogVisible" title="永久删除记录" width="500">
  370. <span>删除后该记录将不可恢复确认删除吗</span>
  371. <template #footer>
  372. <div class="dialog-footer">
  373. <el-button @click="closeDeleteDialog()">取消</el-button>
  374. <el-button type="primary" @click="deleteRecordConfirm()">
  375. 删除
  376. </el-button>
  377. </div>
  378. </template>
  379. </el-dialog>
  380. </template>
  381. <script setup>
  382. import { ref, computed, onMounted, watch } from "vue";
  383. import {
  384. getHistoryListAPI,
  385. changeTopAPI,
  386. deleteRecordAPI,
  387. clickRecordAPI,
  388. } from "../../api/AIxiaocaishen";
  389. import moment from "moment";
  390. import { ElMessage } from "element-plus";
  391. import { useChatStore } from "../../store/chat";
  392. const chatStore = useChatStore();
  393. import { useRouter } from "vue-router";
  394. const router = useRouter();
  395. // Props
  396. const props = defineProps({
  397. currentType: {
  398. type: String,
  399. default: "AIchat", // 'AIchat' 或 'AiEmotion'
  400. },
  401. isMobile: {
  402. type: Boolean,
  403. default: false,
  404. },
  405. });
  406. // Emits
  407. const emit = defineEmits([
  408. "selectRecord",
  409. "recordAdded",
  410. "startNewChat",
  411. "showAnnouncement",
  412. "showFeedback",
  413. ]);
  414. // 响应式数据
  415. const marketList = ref({
  416. cn: "https://d31zlh4on95l9h.cloudfront.net/images/c685daa929d80a03c26841dfa783cc3c.png",
  417. usa: "https://d31zlh4on95l9h.cloudfront.net/images/bccbc3058f327f72aa158fa0852dce19.png",
  418. hk: "https://d31zlh4on95l9h.cloudfront.net/images/ab050afe6867e9f961561f665ed12d10.png",
  419. sg: "https://d31zlh4on95l9h.cloudfront.net/images/90c5ce1edef2235a100e3ee0ad3cac92.png",
  420. vi: "https://d31zlh4on95l9h.cloudfront.net/images/59404c85889abd57dfd15040099edc1a.png",
  421. th: "https://d31zlh4on95l9h.cloudfront.net/images/31f5433264cf1f84cf550995fa16d86e.png",
  422. can: "https://d31zlh4on95l9h.cloudfront.net/images/26382451bfa08e6a419a2190b799dae5.png",
  423. my: "https://d31zlh4on95l9h.cloudfront.net/images/7efa8487a1317ed17eacc77b58e0a26d.png",
  424. });
  425. const isCollapsed = ref(true);
  426. const selectedRecordId = ref(null);
  427. const delObj = ref({});
  428. const deleteDialogVisible = ref(false);
  429. const openDeleteDialog = () => {
  430. deleteDialogVisible.value = true;
  431. };
  432. const closeDeleteDialog = () => {
  433. delObj.value = {};
  434. deleteDialogVisible.value = false;
  435. };
  436. const historyRecords = ref([]);
  437. const categoryHistory = ref([]);
  438. let chatFirstFlag = true;
  439. let emotionTirstFlag = true;
  440. const getHistoryList = async (params) => {
  441. try {
  442. const result = await getHistoryListAPI(params);
  443. historyRecords.value = result.data;
  444. let remainingRecords = result.data; // 复制原数组
  445. console.log(
  446. "params",
  447. params,
  448. "result",
  449. result.data,
  450. "chatFirstFlag",
  451. chatFirstFlag,
  452. "emotionTirstFlag",
  453. emotionTirstFlag
  454. );
  455. if (chatFirstFlag && params.model == 1 && result.data.length != 0) {
  456. const userAgent = navigator.userAgent;
  457. if (
  458. !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
  459. userAgent
  460. )
  461. ) {
  462. chatStore.aiChatCall = true;
  463. }
  464. chatFirstFlag = false;
  465. }
  466. if (emotionTirstFlag && params.model == 2 && result.data.length != 0) {
  467. const userAgent = navigator.userAgent;
  468. if (
  469. !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
  470. userAgent
  471. )
  472. ) {
  473. chatStore.aiEmotionCall = true;
  474. }
  475. emotionTirstFlag = false;
  476. }
  477. if (props.currentType == "AIchat") {
  478. isCollapsed.value = !chatStore.aiChatCall;
  479. } else {
  480. isCollapsed.value = !chatStore.aiEmotionCall;
  481. }
  482. // 1. 筛选置顶记录
  483. let topList = remainingRecords.filter((record) => record.isTop === 1);
  484. remainingRecords = remainingRecords.filter((record) => record.isTop !== 1);
  485. // 2. 筛选今日记录
  486. let todayList = remainingRecords.filter((record) => {
  487. const today = moment().format("YYYY-MM-DD");
  488. const recordDate = moment(record.createdTime).format("YYYY-MM-DD");
  489. return recordDate === today;
  490. });
  491. remainingRecords = remainingRecords.filter((record) => {
  492. const today = moment().format("YYYY-MM-DD");
  493. const recordDate = moment(record.createdTime).format("YYYY-MM-DD");
  494. return recordDate !== today;
  495. });
  496. // 3. 筛选近3日记录(不包括今日)
  497. let recent3DaysList = remainingRecords.filter((record) => {
  498. const threeDaysAgo = moment().subtract(3, "days").startOf("day");
  499. const yesterday = moment().subtract(1, "days").endOf("day");
  500. const recordDate = moment(record.createdTime);
  501. return recordDate.isAfter(threeDaysAgo) && recordDate.isBefore(yesterday);
  502. });
  503. remainingRecords = remainingRecords.filter((record) => {
  504. const threeDaysAgo = moment().subtract(3, "days").startOf("day");
  505. const yesterday = moment().subtract(1, "days").endOf("day");
  506. const recordDate = moment(record.createdTime);
  507. return !(
  508. recordDate.isAfter(threeDaysAgo) && recordDate.isBefore(yesterday)
  509. );
  510. });
  511. // 4. 筛选近7日记录(不包括今日和近3日)
  512. let recent7DaysList = remainingRecords.filter((record) => {
  513. const sevenDaysAgo = moment().subtract(7, "days").startOf("day");
  514. const recordDate = moment(record.createdTime);
  515. return recordDate.isAfter(sevenDaysAgo);
  516. });
  517. remainingRecords = remainingRecords.filter((record) => {
  518. const sevenDaysAgo = moment().subtract(7, "days").startOf("day");
  519. const recordDate = moment(record.createdTime);
  520. return !recordDate.isAfter(sevenDaysAgo);
  521. });
  522. // 5. 筛选近30日记录(不包括前面已筛选的)
  523. let recent30DaysList = remainingRecords.filter((record) => {
  524. const thirtyDaysAgo = moment().subtract(30, "days").startOf("day");
  525. const recordDate = moment(record.createdTime);
  526. return recordDate.isAfter(thirtyDaysAgo);
  527. });
  528. remainingRecords = remainingRecords.filter((record) => {
  529. const thirtyDaysAgo = moment().subtract(30, "days").startOf("day");
  530. const recordDate = moment(record.createdTime);
  531. return !recordDate.isAfter(thirtyDaysAgo);
  532. });
  533. historyRecords.value = result.data;
  534. categoryHistory.value = [
  535. {
  536. name: "置顶",
  537. list: topList,
  538. },
  539. {
  540. name: "今日",
  541. list: todayList,
  542. },
  543. {
  544. name: "近3日",
  545. list: recent3DaysList,
  546. },
  547. {
  548. name: "近7日",
  549. list: recent7DaysList,
  550. },
  551. {
  552. name: "近30日",
  553. list: recent30DaysList,
  554. },
  555. ];
  556. console.log("historyRecords", historyRecords.value);
  557. console.log("categoryHistory", categoryHistory.value);
  558. } catch (e) {
  559. console.error("获取历史记录出错", e);
  560. // 确保在出错时historyRecords和categoryHistory仍然是数组
  561. historyRecords.value = [];
  562. categoryHistory.value = [];
  563. }
  564. };
  565. const changeTop = async (param) => {
  566. try {
  567. await changeTopAPI(param);
  568. } catch (e) {
  569. console.error("置顶或取消置顶失败", e);
  570. }
  571. };
  572. const changeTopStatus = async (isTop, id) => {
  573. try {
  574. if (isTop == 0 && categoryHistory.value[0].list.length >= 3) {
  575. console.log("超过置顶上线");
  576. ElMessage.warning("最多置顶三条内容,已达上限!");
  577. return;
  578. }
  579. await changeTop({
  580. model: props.currentType == "AIchat" ? 1 : 2,
  581. recordId: id,
  582. isTop: isTop == 1 ? 0 : 1,
  583. });
  584. await getHistoryList({
  585. model: props.currentType == "AIchat" ? 1 : 2,
  586. token: localStorage.getItem("localToken"),
  587. });
  588. } catch (error) {
  589. console.error("操作失败:", error);
  590. }
  591. };
  592. // 方法
  593. const toggleCollapse = () => {
  594. isCollapsed.value = !isCollapsed.value;
  595. // 保存折叠状态到本地存储
  596. localStorage.setItem("historyRecordCollapsed", isCollapsed.value);
  597. };
  598. const backToSelectModel = () => {
  599. router.push("/Selectmodel");
  600. };
  601. const openHistory = () => {
  602. // getHistoryList({
  603. // model: props.currentType == "AIchat" ? 1 : 2,
  604. // token: localStorage.getItem("localToken"),
  605. // });
  606. isCollapsed.value = false;
  607. if (props.currentType == "AIchat") {
  608. chatStore.aiChatCall = true;
  609. } else if (props.currentType == "AiEmotion") {
  610. chatStore.aiEmotionCall = true;
  611. }
  612. };
  613. const closeHistory = () => {
  614. isCollapsed.value = true;
  615. if (props.currentType == "AIchat") {
  616. chatStore.aiChatCall = false;
  617. } else if (props.currentType == "AiEmotion") {
  618. chatStore.aiEmotionCall = false;
  619. }
  620. };
  621. const openDetail = (record) => {
  622. console.log("record", record);
  623. };
  624. const historyData = ref({});
  625. const selectRecord = async (record) => {
  626. try {
  627. selectedRecordId.value = record.id;
  628. const result = await clickRecordAPI({
  629. model: props.currentType == "AIchat" ? 1 : 2,
  630. parentId: record.parentId,
  631. recordId: record.id,
  632. });
  633. if (result && result.data) {
  634. historyData.value = result.data;
  635. chatStore.dbqbClickRecord = historyData.value;
  636. // 构造股票数据对象,保持与现有结构一致
  637. const stockData = {
  638. queryText: record.stockCode || record.stockName || "", // 使用记录中的股票代码或名称作为查询文本
  639. stockInfo: {
  640. name: result.data.stockData?.stockName || record.stockName || "",
  641. code: record.stockCode || "",
  642. market: record.stockMarket || "cn",
  643. },
  644. apiData: result.data.stockData || {}, // 图表数据
  645. conclusionData: result.data.wokeFlowData?.One || {}, // 场景应用的结论和音频
  646. timestamp: new Date().toISOString(),
  647. };
  648. // 通过emit将数据传递给父组件
  649. emit("selectRecord", stockData);
  650. console.log("历史记录数据已发送给父组件:", stockData);
  651. } else {
  652. console.error("历史记录数据格式不正确:", result);
  653. }
  654. } catch (e) {
  655. console.error("获取历史记录数据失败", e);
  656. }
  657. };
  658. const deleteRecord = (id) => {
  659. delObj.value.id = id;
  660. openDeleteDialog();
  661. };
  662. const deleteRecordConfirm = async () => {
  663. try {
  664. const result = await deleteRecordAPI({
  665. model: props.currentType == "AIchat" ? 1 : 2,
  666. recordId: delObj.value.id,
  667. });
  668. console.log(result.msg);
  669. closeDeleteDialog();
  670. await getHistoryList({
  671. model: props.currentType == "AIchat" ? 1 : 2,
  672. token: localStorage.getItem("localToken"),
  673. });
  674. } catch (e) {
  675. console.error("删除失败", e);
  676. }
  677. };
  678. // 处理公告按钮点击
  679. const handleAnnouncementClick = () => {
  680. emit("showAnnouncement");
  681. };
  682. // 处理用户反馈按钮点击
  683. const handleFeedbackClick = () => {
  684. emit("showFeedback");
  685. };
  686. watch(
  687. () => chatStore.searchRecord,
  688. (newVal) => {
  689. if (chatStore.searchRecord) {
  690. getHistoryList({
  691. model: props.currentType == "AIchat" ? 1 : 2,
  692. token: localStorage.getItem("localToken"),
  693. });
  694. chatStore.searchRecord = false;
  695. }
  696. }
  697. );
  698. // 暴露方法和状态给父组件
  699. defineExpose({
  700. isCollapsed,
  701. toggleCollapse,
  702. getHistoryList,
  703. selectedRecordId,
  704. });
  705. // 生命周期
  706. onMounted(() => {
  707. getHistoryList({
  708. model: props.currentType == "AIchat" ? 1 : 2,
  709. token: localStorage.getItem("localToken"),
  710. });
  711. });
  712. </script>
  713. <style scoped>
  714. .history-record-container {
  715. min-width: 40px;
  716. width: 3%;
  717. position: fixed;
  718. left: 0;
  719. top: 0;
  720. bottom: 0;
  721. background: rgba(0, 0, 0, 0.5);
  722. border-right: 1px solid rgba(255, 255, 255, 0.1);
  723. backdrop-filter: blur(10px);
  724. z-index: 1000;
  725. transition: width 0.3s ease;
  726. display: flex;
  727. flex-direction: column;
  728. align-items: center;
  729. /* justify-content: center; */
  730. }
  731. .mobile-history-record-container {
  732. width: 0px;
  733. position: fixed;
  734. left: 0;
  735. top: 0;
  736. bottom: 0;
  737. background: rgba(0, 0, 0, 0.5);
  738. border-right: 1px solid rgba(255, 255, 255, 0.1);
  739. backdrop-filter: blur(10px);
  740. z-index: 1000;
  741. transition: width 0.3s ease;
  742. display: flex;
  743. flex-direction: column;
  744. align-items: center;
  745. }
  746. .collapsed {
  747. width: 300px;
  748. }
  749. .mobileCollapsed {
  750. /* max-width: 400px */
  751. width: 80vw;
  752. }
  753. .toggle-btn {
  754. width: 32px;
  755. height: 32px;
  756. transform: rotate(180deg);
  757. border-radius: 6px;
  758. color: white;
  759. cursor: pointer;
  760. display: flex;
  761. align-items: center;
  762. justify-content: center;
  763. transition: all 0.3s ease;
  764. z-index: 10;
  765. }
  766. .mobile-toggle-btn {
  767. width: 10%;
  768. height: auto;
  769. border-radius: 6px;
  770. color: white;
  771. cursor: pointer;
  772. display: flex;
  773. align-items: center;
  774. justify-content: center;
  775. transition: all 0.3s ease;
  776. z-index: 10;
  777. }
  778. .toggle-btn:hover {
  779. background: rgba(255, 255, 255, 0.2);
  780. border-color: rgba(255, 255, 255, 0.3);
  781. }
  782. .collapsed-container {
  783. width: 100%;
  784. margin-top: 60px;
  785. display: flex;
  786. flex-direction: column;
  787. align-items: center;
  788. gap: 20px;
  789. z-index: 1000;
  790. }
  791. .collapsed-icon {
  792. width: 80%;
  793. height: auto;
  794. object-fit: contain;
  795. }
  796. .collapsed-toggle-btn {
  797. width: 80%;
  798. height: auto;
  799. border-radius: 6px;
  800. display: flex;
  801. align-items: center;
  802. justify-content: center;
  803. cursor: pointer;
  804. transition: all 0.3s ease;
  805. color: white;
  806. }
  807. .collapsed-toggle-btn:hover {
  808. background: rgba(255, 255, 255, 0.2);
  809. border-color: rgba(255, 255, 255, 0.3);
  810. }
  811. .collapsed-bottom-container {
  812. width: 100%;
  813. height: 16%;
  814. margin-top: auto;
  815. background-color: rgba(106, 0, 255, 0.2);
  816. display: flex;
  817. flex-direction: column;
  818. align-items: center;
  819. justify-content: center;
  820. gap: 30px;
  821. z-index: 1000;
  822. }
  823. .collapsed-bottom-btn {
  824. width: 100%;
  825. /* height: 50%; */
  826. display: flex;
  827. justify-content: center;
  828. cursor: pointer;
  829. /* align-items: center; */
  830. }
  831. .collapsed-bottom-feedback {
  832. width: 60%;
  833. height: auto;
  834. }
  835. .collapsed-bottom-feedback:hover {
  836. transform: scale(1.1);
  837. }
  838. .collapsed-bottom-announcement {
  839. width: 60%;
  840. height: auto;
  841. }
  842. .collapsed-bottom-announcement:hover {
  843. transform: scale(1.1);
  844. }
  845. .history-content {
  846. flex: 1;
  847. display: flex;
  848. flex-direction: column;
  849. width: 100%;
  850. /* padding: 20px; */
  851. overflow: hidden;
  852. }
  853. .head-container {
  854. margin-top: 20%;
  855. margin-bottom: 10px;
  856. width: 100%;
  857. display: flex;
  858. align-items: center;
  859. justify-content: center;
  860. }
  861. .mobile-head-container {
  862. padding: 5px 0px 5px 20px;
  863. /* margin-left: 20px; */
  864. /* width: 100%; */
  865. display: flex;
  866. align-items: center;
  867. border-bottom: 2px solid #414141;
  868. /* justify-content: center; */
  869. }
  870. .history-header {
  871. display: flex;
  872. justify-content: space-between;
  873. align-items: center;
  874. margin-bottom: 20px;
  875. padding-bottom: 15px;
  876. border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  877. }
  878. .history-actions {
  879. display: flex;
  880. justify-content: center;
  881. align-items: center;
  882. }
  883. .mobile-history-actions {
  884. margin-left: auto;
  885. display: flex;
  886. justify-content: center;
  887. align-items: center;
  888. }
  889. .logo-img {
  890. height: auto;
  891. width: 70%;
  892. object-fit: contain;
  893. }
  894. .history-list {
  895. flex: 1;
  896. overflow-y: auto;
  897. scrollbar-width: thin;
  898. scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
  899. }
  900. .history-list::-webkit-scrollbar {
  901. width: 6px;
  902. }
  903. .history-list::-webkit-scrollbar-track {
  904. background: transparent;
  905. }
  906. .history-list::-webkit-scrollbar-thumb {
  907. background: rgba(255, 255, 255, 0.3);
  908. border-radius: 3px;
  909. }
  910. .history-list::-webkit-scrollbar-thumb:hover {
  911. background: rgba(255, 255, 255, 0.5);
  912. }
  913. .categoryName {
  914. color: white;
  915. padding: 12px;
  916. }
  917. .history-item {
  918. background: rgba(255, 255, 255, 0.05);
  919. border-radius: 8px;
  920. margin-bottom: 8px;
  921. padding: 12px;
  922. cursor: pointer;
  923. transition: all 0.2s ease;
  924. border: 1px solid transparent;
  925. display: flex;
  926. justify-content: center;
  927. align-items: center;
  928. }
  929. .history-item:hover {
  930. background: rgba(255, 255, 255, 0.1);
  931. }
  932. .history-item.active {
  933. background: rgba(255, 255, 255, 0.5);
  934. }
  935. .record-content {
  936. display: flex;
  937. width: 100%;
  938. }
  939. .record-img {
  940. display: flex;
  941. align-items: center;
  942. justify-content: center;
  943. width: 20%;
  944. }
  945. .record-msg {
  946. width: 80%;
  947. }
  948. .record-text {
  949. color: white;
  950. font-size: 13px;
  951. line-height: 1.4;
  952. margin-bottom: 6px;
  953. overflow: hidden;
  954. text-overflow: ellipsis;
  955. -webkit-line-clamp: 2;
  956. -webkit-box-orient: vertical;
  957. display: flex;
  958. }
  959. .top-icon {
  960. margin-left: 5px;
  961. color: white;
  962. height: auto;
  963. width: 15px;
  964. }
  965. .stock-name {
  966. font-weight: 500;
  967. margin-right: 4px;
  968. }
  969. .stock-code {
  970. color: rgba(255, 255, 255, 0.7);
  971. font-size: 12px;
  972. font-weight: 400;
  973. }
  974. .record-time {
  975. color: rgba(255, 255, 255, 0.6);
  976. font-size: 11px;
  977. }
  978. .record-actions {
  979. height: 100%;
  980. /* margin-left: 8px; */
  981. transition: opacity 0.2s ease;
  982. }
  983. .more-btn {
  984. background: rgba(231, 76, 60, 0);
  985. border: none;
  986. border-radius: 4px;
  987. color: white;
  988. padding: 4px;
  989. cursor: pointer;
  990. transition: all 0.2s ease;
  991. display: flex;
  992. align-items: center;
  993. justify-content: center;
  994. }
  995. .more-btn:hover {
  996. background: rgba(255, 255, 255, 0.3);
  997. transform: scale(1.1);
  998. }
  999. .popover-content {
  1000. display: flex;
  1001. flex-direction: column;
  1002. }
  1003. .popover-item {
  1004. display: flex;
  1005. align-items: center;
  1006. padding: 10px;
  1007. /* justify-content: center; */
  1008. }
  1009. .popover-btn {
  1010. cursor: pointer;
  1011. }
  1012. .popover-btn:hover {
  1013. background: rgba(0, 0, 0, 0.1);
  1014. }
  1015. .popover-icon {
  1016. margin-right: 5px;
  1017. }
  1018. .empty-state {
  1019. display: flex;
  1020. flex-direction: column;
  1021. align-items: center;
  1022. justify-content: center;
  1023. padding: 40px 20px;
  1024. text-align: center;
  1025. }
  1026. .empty-icon {
  1027. margin-bottom: 16px;
  1028. opacity: 0.5;
  1029. }
  1030. .documentDelete {
  1031. color: white;
  1032. font-size: 5rem;
  1033. }
  1034. .empty-text {
  1035. color: rgba(255, 255, 255, 0.6);
  1036. font-size: 14px;
  1037. margin: 0;
  1038. }
  1039. .bottom-container {
  1040. width: 100%;
  1041. height: 16%;
  1042. margin-top: auto;
  1043. background-color: rgba(106, 0, 255, 0.2);
  1044. display: flex;
  1045. justify-content: space-between;
  1046. align-items: center;
  1047. }
  1048. .mobile-bottom-container {
  1049. border-top: 2px solid #414141;
  1050. width: 100%;
  1051. height: 16%;
  1052. margin-top: auto;
  1053. background-color: rgba(106, 0, 255, 0.2);
  1054. display: flex;
  1055. flex-direction: column;
  1056. justify-content: space-between;
  1057. align-items: center;
  1058. }
  1059. .bottom-btn {
  1060. width: 50%;
  1061. display: flex;
  1062. justify-content: center;
  1063. align-items: center;
  1064. cursor: pointer;
  1065. }
  1066. .mobile-bottom-btn {
  1067. width: 100%;
  1068. height: 50%;
  1069. display: flex;
  1070. align-items: center;
  1071. }
  1072. .bottom-feedback {
  1073. width: 30%;
  1074. height: auto;
  1075. }
  1076. .mobile-bottom-feedback {
  1077. margin-left: 20px;
  1078. height: 60%;
  1079. width: auto;
  1080. }
  1081. .bottom-feedback:hover {
  1082. transform: scale(1.2);
  1083. }
  1084. .bottom-announcement {
  1085. width: 30%;
  1086. height: auto;
  1087. }
  1088. .mobile-bottom-announcement {
  1089. margin-left: 20px;
  1090. height: 60%;
  1091. width: auto;
  1092. }
  1093. .mobile-bottom-text {
  1094. color: white;
  1095. margin-left: 10px;
  1096. font-size: 1.1rem;
  1097. }
  1098. .bottom-announcement:hover {
  1099. transform: scale(1.2);
  1100. }
  1101. /* 移动端适配 */
  1102. @media (max-width: 768px) {
  1103. .history-content {
  1104. /* padding: 15px; */
  1105. }
  1106. }
  1107. </style>
  1108. <style>
  1109. .el-popover {
  1110. width: auto !important;
  1111. padding: 0 !important;
  1112. }
  1113. </style>