<script setup lang="ts">
|
import { ref, computed, watchEffect, nextTick } from 'vue';
|
import type { CSSProperties } from 'vue';
|
import Tooltip from './Tooltip.vue';
|
|
interface Props {
|
maxWidth?: number | string; // 文本最大宽度
|
line?: number; // 最大行数
|
expand?: boolean; // 是否启用点击文本展开全部
|
tooltip?: boolean; // 是否启用文本提示框
|
// 以下均为 tooltip 组件属性
|
tooltipMaxWidth?: number; // 提示框内容最大宽度,单位px,默认不设置时,提示文本内容自动与展示文本宽度保持一致
|
tooltipFontSize?: number; // 提示文本字体大小,单位px,优先级高于 overlayStyle
|
tooltipColor?: string; // 提示文本字体颜色,优先级高于 overlayStyle
|
tooltipBackgroundColor?: string; // 提示框背景颜色,优先级高于 overlayStyle
|
tooltipOverlayStyle?: CSSProperties; // 提示框内容区域样式
|
}
|
const props = withDefaults(defineProps<Props>(), {
|
maxWidth: '100%',
|
line: undefined,
|
expand: false,
|
tooltip: true,
|
tooltipMaxWidth: undefined,
|
tooltipFontSize: 14,
|
tooltipColor: '#FFF',
|
tooltipBackgroundColor: 'rgba(0, 0, 0, .85)',
|
tooltipOverlayStyle: () => ({ padding: '8px 12px', textAlign: 'justify' }),
|
});
|
const textMaxWidth = computed(() => {
|
if (typeof props.maxWidth === 'number') {
|
return props.maxWidth + 'px';
|
}
|
return props.maxWidth;
|
});
|
const showTooltip = ref();
|
const ellipsis = ref();
|
const defaultTooltipMaxWidth = ref();
|
watchEffect(() => {
|
showTooltip.value = props.tooltip;
|
});
|
watchEffect(
|
() => {
|
if (props.tooltip) {
|
if (props.tooltipMaxWidth) {
|
defaultTooltipMaxWidth.value = props.tooltipMaxWidth;
|
} else {
|
defaultTooltipMaxWidth.value = ellipsis.value.offsetWidth + 24;
|
}
|
}
|
},
|
{ flush: 'post' },
|
);
|
const emit = defineEmits(['expandChange']);
|
function onExpand() {
|
if (ellipsis.value.style['-webkit-line-clamp']) {
|
if (props.tooltip) {
|
showTooltip.value = false;
|
nextTick(() => {
|
ellipsis.value.style['-webkit-line-clamp'] = '';
|
});
|
} else {
|
ellipsis.value.style['-webkit-line-clamp'] = '';
|
}
|
emit('expandChange', true);
|
} else {
|
if (props.tooltip) {
|
showTooltip.value = true;
|
}
|
ellipsis.value.style['-webkit-line-clamp'] = props.line;
|
emit('expandChange', false);
|
}
|
}
|
</script>
|
<template>
|
<Tooltip
|
v-if="showTooltip"
|
:max-width="defaultTooltipMaxWidth"
|
:fontSize="tooltipFontSize"
|
:color="tooltipColor"
|
:backgroundColor="tooltipBackgroundColor"
|
:overlayStyle="tooltipOverlayStyle"
|
>
|
<template #tooltip>
|
<slot name="tooltip">
|
<slot></slot>
|
</slot>
|
</template>
|
<div
|
ref="ellipsis"
|
class="m-ellipsis"
|
:class="[line ? 'ellipsis-line' : 'not-ellipsis-line', { 'cursor-pointer': expand }]"
|
:style="`-webkit-line-clamp: ${line}; max-width: ${textMaxWidth};`"
|
@click="expand ? onExpand() : () => false"
|
v-bind="$attrs"
|
>
|
<slot></slot>
|
</div>
|
</Tooltip>
|
<div
|
v-else
|
ref="ellipsis"
|
class="m-ellipsis"
|
:class="[line ? 'ellipsis-line' : 'not-ellipsis-line', { 'cursor-pointer': expand }]"
|
:style="`-webkit-line-clamp: ${line}; max-width: ${textMaxWidth};`"
|
@click="expand ? onExpand() : () => false"
|
v-bind="$attrs"
|
>
|
<slot></slot>
|
</div>
|
</template>
|
|
<style lang="less" scoped>
|
.m-ellipsis {
|
overflow: hidden;
|
cursor: text;
|
}
|
|
.ellipsis-line {
|
display: -webkit-inline-box;
|
-webkit-box-orient: vertical;
|
}
|
|
.not-ellipsis-line {
|
display: inline-block;
|
text-overflow: ellipsis;
|
vertical-align: bottom;
|
white-space: nowrap;
|
}
|
|
.cursor-pointer {
|
cursor: pointer;
|
}
|
</style>
|