Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 65 additions & 44 deletions packages/core/src/components/Conversations/components/item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ const {
} = toRefs(props);

function renderIcon(icon: Component | null | undefined) {
if (!icon)
return null;
if (!icon) return null;
return h(icon);
}

Expand Down Expand Up @@ -118,40 +117,58 @@ function handleClick(key: string) {
emit('click', key);
}

const isTextOverflow = computed(() => {
return (label: string = '') => {
// 如果没有设置labelMaxWidth,直接返回false
if (!labelMaxWidth.value)
return false;
if (typeof window === 'undefined')
return false;
if (typeof document === 'undefined')
return false;
if (!document?.createElement || !document?.body?.appendChild) {
return false;
}
const labelRef = ref<HTMLElement | null>(null);

const isTextOverflow = ref(false);

let isMeasuring = false;

// 创建一个临时的span元素来测量文本宽度
const span = document.createElement('span');
if (!span || !('style' in span)) {
return false;
let observer: MutationObserver | null = null;

// 利用Range API计算是否超过宽度
function measure() {
if (isMeasuring) return;
if (!labelMaxWidth.value || !labelRef.value) {
isTextOverflow.value = false;
return;
}
isMeasuring = true;
try {
if (!labelRef.value.offsetParent) return;
const range = document.createRange();
range.selectNodeContents(labelRef.value);
isTextOverflow.value =
range.getBoundingClientRect().width > labelMaxWidth.value;
} catch {
isTextOverflow.value = false;
} finally {
isMeasuring = false;
}
}

watch([labelMaxWidth, () => item.value?.label], measure, { flush: 'post' });

watch(
labelRef,
(newVal, _) => {
if (observer) {
observer.disconnect();
observer = null;
}
span.style.visibility = 'hidden';
span.style.position = 'absolute';
span.style.whiteSpace = 'nowrap';
span.style.fontSize = '14px'; // 与CSS中定义的字体大小一致
span.textContent = label;

document.body.appendChild(span);
const textWidth = span.offsetWidth;
document.body.removeChild(span);

// 如果文本宽度大于最大宽度,则返回true表示溢出
return textWidth > labelMaxWidth.value;
};
});
if (newVal) {
observer = new MutationObserver(measure);
observer.observe(newVal, {
attributes: true,
attributeFilter: ['style', 'class']
});
measure();
}
},
{ flush: 'post', immediate: true }
);

// 计算标签样式

const labelStyle = computed(() => {
// 如果有labelMaxWidth,设置最大宽度并使用截断样式
if (labelMaxWidth.value) {
Expand Down Expand Up @@ -279,10 +296,13 @@ function closeDropdown() {
elDropdownRef.value.handleClose?.();
}
}

onMounted(() => {
console.log(elDropdownRef.value, '------');
});
onUnmounted(() => {
observer?.disconnect?.();
observer = null;
});
/* 内置菜单 结束 */
</script>

Expand Down Expand Up @@ -321,24 +341,20 @@ onMounted(() => {
<!-- 标签和时间戳 -->
<div class="conversation-label-container">
<ElTooltip
v-if="showTooltip && isTextOverflow(item.label)"
:disabled="!showTooltip || !isTextOverflow"
:content="item.label"
:placement="tooltipPlacement"
:offset="tooltipOffset"
effect="dark"
>
<span
ref="labelRef"
class="conversation-label"
:class="{ 'text-gradient': isTextOverflow(item.label) }"
:class="{ 'text-gradient': isTextOverflow }"
:style="labelStyle"
>{{ item.label }}</span>
>{{ item.label }}</span
>
</ElTooltip>
<span
v-else
class="conversation-label"
:class="{ 'text-gradient': isTextOverflow(item.label) }"
:style="labelStyle"
>{{ item.label }}</span>
</div>
</slot>
</div>
Expand Down Expand Up @@ -381,7 +397,6 @@ onMounted(() => {
>
<template #default>
<slot

name="more-filled"
v-bind="{
item,
Expand All @@ -397,7 +412,13 @@ onMounted(() => {
</slot>
</template>
<template #dropdown>
<slot name="menu" v-bind="{ handleOpen: openDropdown, handleClose: closeDropdown }">
<slot
name="menu"
v-bind="{
handleOpen: openDropdown,
handleClose: closeDropdown
}"
>
<el-dropdown-menu :style="mergedMenuStyle">
<el-dropdown-item
v-for="menuItem in menu"
Expand Down