NoticeChart.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <template>
  2. <div>
  3. <div :style="{height:height,width:width}" class="text-container">
  4. <ul class="allNotice" @mouseleave="handleMouseLeave" @mouseover="handleMouseOver">
  5. <!-- 原始列表 -->
  6. <li v-for="(item,index) in noticeList" :key="'original-' + index" class="notice-item">
  7. <span>截止日期:{{ parseTime(item.deadline, '{yyyy}-{mm}-{dd}') }}
  8. <el-tag size="medium" effect="plain">{{ item.planName }}</el-tag>
  9. </span>
  10. <span>
  11. <el-tag effect="dark" size="mini" type="success" v-if="item.status == 1">已完成</el-tag>
  12. <el-tag effect="dark" size="mini" type="danger" v-if="item.status == 0">未完成</el-tag>
  13. </span>
  14. </li>
  15. <!-- 复制一份列表实现无缝滚动 -->
  16. <li v-for="(item,index) in noticeList" :key="'copy-' + index" class="notice-item" v-if="noticeList.length>10">
  17. <span>截止日期:{{ parseTime(item.deadline, '{yyyy}-{mm}-{dd}') }}
  18. <el-tag size="medium" effect="plain">{{ item.planName }}</el-tag>
  19. </span>
  20. <span>
  21. <el-tag effect="dark" size="mini" type="success" v-if="item.status == 1">已完成</el-tag>
  22. <el-tag effect="dark" size="mini" type="danger" v-if="item.status == 0">未完成</el-tag>
  23. </span>
  24. </li>
  25. </ul>
  26. </div>
  27. </div>
  28. </template>
  29. <script>
  30. import {listPlan} from "@/api/ps/patrol/plan";
  31. export default {
  32. name: "NoticeChart",
  33. props: {
  34. width: {
  35. type: String,
  36. default: '100%'
  37. },
  38. height: {
  39. type: String,
  40. default: '570px'
  41. }
  42. },
  43. data() {
  44. return {
  45. // 查询参数
  46. queryParams: {
  47. planMonth: new Date().getMonth() + 1, planYear: new Date().getFullYear()
  48. },
  49. // 公示公告列表
  50. noticeList: [],
  51. styleElement: null,
  52. }
  53. },
  54. created() {
  55. this.listNoticeNoPage();
  56. },
  57. beforeDestroy() {
  58. // 清理动态添加的 style 元素
  59. if (this.styleElement && this.styleElement.parentNode) {
  60. this.styleElement.parentNode.removeChild(this.styleElement);
  61. }
  62. },
  63. methods: {
  64. handleMouseOver() {
  65. let elem = document.querySelector('.allNotice');
  66. if (elem) {
  67. elem.style['animation-play-state'] = 'paused';
  68. }
  69. },
  70. handleMouseLeave() {
  71. let elem = document.querySelector('.allNotice');
  72. if (elem) {
  73. elem.style['animation-play-state'] = 'running';
  74. }
  75. },
  76. listNoticeNoPage() {
  77. listPlan(this.queryParams).then(response => {
  78. this.noticeList = response.rows || [];
  79. // 判断是否需要滚动
  80. if (this.noticeList.length > 10) {
  81. this.$nextTick(() => {
  82. // 清理之前的 style
  83. if (this.styleElement && this.styleElement.parentNode) {
  84. this.styleElement.parentNode.removeChild(this.styleElement);
  85. }
  86. let elem = document.querySelector('.allNotice');
  87. if (!elem) return;
  88. // 每个 li 的高度约为 50px(包括margin)
  89. const itemHeight = 50;
  90. const listHeight = this.noticeList.length * itemHeight;
  91. // 设置滚动时间(可根据列表长度调整)
  92. const scrollTime = this.noticeList.length * 2;
  93. // 创建无缝滚动的 keyframes
  94. // 从 0 滚动到 -listHeight,然后重新开始
  95. const keyframeName = 'seamlessScroll-' + Date.now();
  96. const myFirstkeyframes = `@keyframes ${keyframeName} {
  97. 0% {
  98. transform: translateY(0);
  99. }
  100. 100% {
  101. transform: translateY(-${listHeight}px);
  102. }
  103. }`;
  104. // 动态插入 keyframes
  105. this.styleElement = document.createElement("style");
  106. this.styleElement.setAttribute("type", "text/css");
  107. this.styleElement.textContent = myFirstkeyframes;
  108. document.head.appendChild(this.styleElement);
  109. // 应用动画
  110. elem.style['animation'] = `${keyframeName} ${scrollTime}s linear infinite`;
  111. });
  112. }
  113. });
  114. },
  115. }
  116. }
  117. </script>
  118. <style scoped>
  119. .text-container {
  120. line-height: 40px;
  121. overflow: hidden;
  122. background-color: #fff;
  123. padding: 10px;
  124. }
  125. .notice-item {
  126. border-radius: 3px;
  127. margin-bottom: 10px;
  128. font-size: 14px;
  129. display: flex;
  130. justify-content: space-between;
  131. align-items: center;
  132. padding-right: 10px;
  133. padding-left: 10px;
  134. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  135. height: 40px; /* 固定高度便于计算 */
  136. }
  137. .allNotice {
  138. list-style: none;
  139. padding: 0;
  140. margin: 0;
  141. }
  142. </style>