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.

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