TextEllipsis.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <script setup lang="ts">
  2. import { computed, ref } from 'vue';
  3. import type { TextProps } from '../basic/Text.vue';
  4. import Text from '../basic/Text.vue';
  5. import FlexCol from '../layout/FlexCol.vue';
  6. import BackgroundBox from './block/BackgroundBox.vue';
  7. export interface TextEllipsisProps extends TextProps {
  8. /**
  9. * 显示的行数
  10. * @default 1
  11. */
  12. lines?: number;
  13. /**
  14. * 是否可展开
  15. * @default true
  16. */
  17. expandable?: boolean;
  18. /**
  19. * 是否默认展开
  20. * @default false
  21. */
  22. startOpen?: boolean;
  23. /**
  24. * 展开按钮文字
  25. * @default '展开'
  26. */
  27. openText?: string;
  28. /**
  29. * 收起按钮文字
  30. * @default '收起'
  31. */
  32. closeText?: string;
  33. /**
  34. * 是否显示遮罩层,当定义了该属性时,折叠时将会显示一个遮罩层。
  35. * @default false
  36. */
  37. showMask?: boolean;
  38. /**
  39. * 遮罩层颜色
  40. * @default white
  41. */
  42. maskColor?: string;
  43. /**
  44. * 折叠时的高度
  45. * @default 140
  46. */
  47. collapsedHeight?: number;
  48. /**
  49. * 是否自定义内容,当定义了该属性时,可以通过slot自定义内容渲染,
  50. * 折叠时将会设置高度为collapsedHeight。
  51. * @default false
  52. */
  53. customContent?: boolean;
  54. }
  55. const emit = defineEmits(['expand', 'collapse']);
  56. const props = withDefaults(defineProps<TextEllipsisProps>(), {
  57. lines: 1,
  58. startOpen: false,
  59. expandable: true,
  60. customContent: false,
  61. showMask: false,
  62. maskColor: 'white',
  63. collapsedHeight: 140,
  64. openText: '展开',
  65. closeText: '收起',
  66. });
  67. const open = ref(props.startOpen);
  68. const currentLines = computed(() => {
  69. if (open.value)
  70. return undefined;
  71. return props.lines;
  72. });
  73. function handleClick() {
  74. open.value = !open.value;
  75. emit(open.value ? 'expand' : 'collapse');
  76. }
  77. defineOptions({
  78. options: {
  79. virtualHost: true,
  80. styleIsolation: "shared",
  81. },
  82. })
  83. </script>
  84. <template>
  85. <FlexCol position="relative">
  86. <FlexCol
  87. :height="customContent && !open ? collapsedHeight : undefined"
  88. overflow="hidden"
  89. >
  90. <slot>
  91. <Text
  92. :ellipsis="true"
  93. :lines="currentLines"
  94. v-bind="$attrs"
  95. :text="text"
  96. />
  97. </slot>
  98. <BackgroundBox
  99. v-if="!open && (showMask || customContent)"
  100. :height="collapsedHeight"
  101. color1="transparent"
  102. :color2="maskColor"
  103. :innerStyle="{
  104. position: 'absolute',
  105. bottom: '36rpx',
  106. left: 0,
  107. right: 0,
  108. }"
  109. />
  110. </FlexCol>
  111. <slot v-if="expandable" name="button" :onClick="handleClick">
  112. <Text
  113. innerClass="nana-text-ellipsis-expand"
  114. touchable
  115. :text="open ? closeText : openText"
  116. color="primary"
  117. @click="handleClick"
  118. />
  119. </slot>
  120. </FlexCol>
  121. </template>
  122. <style>
  123. .nana-text-ellipsis-expand {
  124. /* #ifndef APP-NVUE */
  125. display: inline-block;
  126. /* #endif */
  127. text-align: right;
  128. }
  129. </style>