TitleDescBlock.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <div class="TitleDescBlock">
  3. <div class="title-container">
  4. <h3 :class="{ 'title-box': titleBox, }">{{ title }}</h3>
  5. </div>
  6. <span v-if="date" class="time">{{ date }}</span>
  7. <SimpleRichHtml hydrate-never :class="'desc ' + (expand?'expand':'no-expand')" :contents="[desc]" />
  8. <slot name="addon" />
  9. <div class="footer">
  10. <div v-if="showExpand && desc.length > 200" :class="'expand'+(expand?' on':'')" @click="expand=!expand">
  11. {{expand?'折叠':'展开'}}
  12. <img src="@/assets/images/IconArrowRight.png" />
  13. </div>
  14. <div v-if="more" class="more" @click="moreLink ? undefined : emit('moreClick')">
  15. <NuxtLink :to="moreLink">
  16. 更多
  17. <img src="@/assets/images/IconArrowRight.png" alt="更多" />
  18. </NuxtLink>
  19. </div>
  20. </div>
  21. </div>
  22. </template>
  23. <script setup lang="ts">
  24. import { ref } from 'vue';
  25. import SimpleRichHtml from '../display/SimpleRichHtml.vue';
  26. const props = defineProps({
  27. title : {
  28. type: String,
  29. default: '',
  30. },
  31. titleBox: {
  32. type: Boolean,
  33. default: false,
  34. },
  35. desc: {
  36. type: String,
  37. default: '',
  38. },
  39. descLines: {
  40. type: Number,
  41. default: 3,
  42. },
  43. more: {
  44. type: Boolean,
  45. default: false,
  46. },
  47. moreLink: {
  48. type: String,
  49. default: '',
  50. },
  51. showExpand: {
  52. type: Boolean,
  53. default: false,
  54. },
  55. date: {
  56. type: String,
  57. default: '',
  58. },
  59. })
  60. const expand = ref(false)
  61. const emit = defineEmits([
  62. "moreClick"
  63. ]);
  64. </script>
  65. <style lang="scss">
  66. @use '@/assets/scss/colors.scss' as *;
  67. .TitleDescBlock {
  68. display: flex;
  69. flex-direction: column;
  70. justify-content: center;
  71. > .title-container {
  72. display: flex;
  73. flex-direction: row;
  74. justify-content: flex-start;
  75. }
  76. h3 {
  77. color: $text-content-color;
  78. font-size: 1.2rem;
  79. margin-top: 0;
  80. margin-bottom: 8px;
  81. }
  82. .desc,
  83. .time {
  84. color: $text-content-second-color;
  85. font-size: 0.85rem;
  86. }
  87. .time {
  88. margin-bottom: 16px;
  89. }
  90. > .desc {
  91. display: -webkit-box;
  92. -webkit-box-orient: vertical;
  93. margin: 0;
  94. overflow: hidden;
  95. text-overflow: ellipsis;
  96. &.expand {
  97. -webkit-line-clamp: 100;
  98. line-clamp: 100;
  99. }
  100. &.no-expand {
  101. -webkit-line-clamp: 5;
  102. line-clamp: 5;
  103. max-height: 300px;
  104. }
  105. }
  106. .footer {
  107. display: flex;
  108. flex-direction: row;
  109. align-items: center;
  110. justify-content: space-between;
  111. > div {
  112. display: flex;
  113. flex-direction: row;
  114. align-items: center;
  115. color: $text-content-second-color;
  116. font-size: 0.85rem;
  117. margin-top: 25px;
  118. cursor: pointer;
  119. &:hover {
  120. color: $primary-color;
  121. }
  122. }
  123. }
  124. .expand {
  125. img {
  126. width: 16px;
  127. height: 16px;
  128. transform: rotate(90deg);
  129. }
  130. &.on {
  131. img {
  132. transform: rotate(270deg);
  133. }
  134. }
  135. }
  136. .more {
  137. img {
  138. width: 16px;
  139. height: 16px;
  140. margin-left: 8px;
  141. }
  142. }
  143. }
  144. </style>