cl-timeline-item.uvue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <template>
  2. <view class="cl-timeline-item" :class="[pt.className]">
  3. <view class="cl-timeline-item__left">
  4. <cl-icon
  5. v-if="icon != ''"
  6. :name="icon"
  7. :size="34"
  8. :pt="{
  9. className: `${pt.icon?.className}`
  10. }"
  11. ></cl-icon>
  12. <view v-else class="cl-timeline-item__dot"></view>
  13. <view class="cl-timeline-item__line" v-if="!hideLine"></view>
  14. </view>
  15. <view
  16. class="cl-timeline-item__right"
  17. :class="[
  18. {
  19. 'is-icon': icon != '',
  20. 'is-title': title != ''
  21. }
  22. ]"
  23. >
  24. <cl-text
  25. v-if="title != ''"
  26. :pt="{
  27. className: parseClass([
  28. `mb-1 !font-bold ${pt.title?.className}`,
  29. [isDark, 'text-white', 'text-surface-900']
  30. ])
  31. }"
  32. >{{ title }}</cl-text
  33. >
  34. <cl-text
  35. v-if="content != ''"
  36. :pt="{
  37. className: `mb-2 text-sm ${pt.content?.className}`
  38. }"
  39. >{{ content }}</cl-text
  40. >
  41. <slot></slot>
  42. <cl-text
  43. v-if="date != ''"
  44. :pt="{
  45. className: `text-xs ${pt.date?.className}`
  46. }"
  47. color="info"
  48. >{{ date }}</cl-text
  49. >
  50. </view>
  51. </view>
  52. </template>
  53. <script setup lang="ts">
  54. import { computed } from "vue";
  55. import { isDark, parseClass, parsePt } from "@/cool";
  56. import type { PassThroughProps } from "../../types";
  57. defineOptions({
  58. name: "cl-timeline-item"
  59. });
  60. const props = defineProps({
  61. pt: {
  62. type: Object,
  63. default: () => ({})
  64. },
  65. // 标题
  66. title: {
  67. type: String,
  68. default: ""
  69. },
  70. // 图标
  71. icon: {
  72. type: String,
  73. default: ""
  74. },
  75. // 内容
  76. content: {
  77. type: String,
  78. default: ""
  79. },
  80. // 日期
  81. date: {
  82. type: String,
  83. default: ""
  84. },
  85. // 是否隐藏线
  86. hideLine: {
  87. type: Boolean,
  88. default: false
  89. }
  90. });
  91. type PassThrough = {
  92. className?: string;
  93. icon?: PassThroughProps;
  94. title?: PassThroughProps;
  95. content?: PassThroughProps;
  96. date?: PassThroughProps;
  97. };
  98. const pt = computed(() => parsePt<PassThrough>(props.pt));
  99. </script>
  100. <style lang="scss" scoped>
  101. .cl-timeline-item {
  102. @apply flex flex-row w-full;
  103. overflow: visible;
  104. margin-bottom: 10rpx;
  105. &__left {
  106. @apply flex flex-col items-center overflow-visible;
  107. width: 50rpx;
  108. margin-right: 10rpx;
  109. }
  110. &__dot {
  111. @apply rounded-full bg-surface-300;
  112. height: 16rpx;
  113. width: 16rpx;
  114. }
  115. &__line {
  116. @apply bg-surface-300;
  117. width: 1rpx;
  118. flex: 1;
  119. margin-top: 10rpx;
  120. }
  121. &__right {
  122. @apply relative;
  123. top: -12rpx;
  124. flex: 1;
  125. margin-bottom: 40rpx;
  126. &.is-title {
  127. top: -12rpx;
  128. }
  129. &.is-icon {
  130. top: -4rpx;
  131. }
  132. }
  133. }
  134. </style>