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.

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