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.

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