TextEllipsis.vue 3.1 KB

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