Files
aida_front/src/component/Canvas/ExistsImageList/ToolButton.vue

176 lines
3.5 KiB
Vue
Raw Normal View History

<script setup>
import { computed } from "vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const props = defineProps({
tool: {
type: Object,
required: true,
},
activeTool: {
type: String,
default: "",
},
canUndo: {
type: Boolean,
default: true,
},
canRedo: {
type: Boolean,
default: true,
},
2025-09-24 11:53:25 +08:00
tipBody: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["click"]);
// 计算按钮是否激活
const isActive = computed(() => {
return (
props.tool.id === props.activeTool ||
props.tool.id === props.activeTool.toLowerCase() ||
props.tool?.activeList?.includes(props.activeTool)
);
});
// 计算按钮是否禁用
const isDisabled = computed(() => {
return (
(props.tool.id === "undo" && !props.canUndo) ||
(props.tool.id === "redo" && !props.canRedo)
);
});
// 处理按钮点击
const handleClick = () => {
if (isDisabled.value) return;
emit("click", props.tool);
};
2025-09-24 11:53:25 +08:00
const tipId = "tooltip-" + Math.random().toString(36).substring(2);
const el = ref(null);
// 鼠标移入获取位置信息
const handleMouseEnter = (e) => {
const tooltip = el.value;
const rect = tooltip.getBoundingClientRect();
const left = rect.left + rect.width;
const top = rect.top + rect.height / 2;
const tip = document.getElementById(tipId);
tip.style.position = 'fixed';
tip.style.left = `${left}px`;
tip.style.top = `${top}px`;
tip.style.display = 'block';
}
// 鼠标移出隐藏提示
const handleMouseLeave = () => {
const tip = document.getElementById(tipId);
tip.style.display = 'none';
}
onMounted(() => {
if(props.tipBody){
el.value.addEventListener('mouseenter', handleMouseEnter);
el.value.addEventListener('mouseleave', handleMouseLeave);
}
})
onUnmounted(() => {
2025-09-24 13:10:39 +08:00
if(props.tipBody && el.value){
2025-09-24 11:53:25 +08:00
el.value.removeEventListener('mouseenter', handleMouseEnter);
el.value.removeEventListener('mouseleave', handleMouseLeave);
2025-09-24 13:10:39 +08:00
}
2025-09-24 11:53:25 +08:00
})
</script>
<template>
<div
2025-09-24 11:53:25 +08:00
ref="el"
:class="[
'tool-btn',
tool.class,
{
active: isActive,
disabled: isDisabled,
},
]"
:style="tool.style"
@click="handleClick"
>
<SvgIcon :name="tool.icon.name" :size="tool.icon.size"></SvgIcon>
2025-09-24 11:53:25 +08:00
<teleport to="body" v-if="tipBody">
<div class="tool-tooltip" :id="tipId">{{ t(tool.title) }}</div>
</teleport>
<div class="tool-tooltip" v-else>{{ t(tool.title) }}</div>
</div>
</template>
<style scoped>
.tool-btn {
position: relative;
2025-07-24 20:15:39 +08:00
width: 3.5rem;
height: 3.5rem;
display: flex;
align-items: center;
justify-content: center;
background: none;
border: none;
border-radius: 4px;
cursor: pointer;
2025-07-24 20:15:39 +08:00
font-size: 1.6rem;
color: #333;
transition: all 0.2s ease;
2025-09-24 11:53:25 +08:00
flex-shrink: 0;
}
.tool-btn:hover {
background-color: #f0f0f0;
}
.tool-btn:hover .tool-tooltip {
display: block;
}
.tool-btn.active {
background-color: #e6f7ff;
color: #1890ff;
}
.tool-btn.disabled {
cursor: not-allowed;
color: #e0e0e0;
}
.tool-tooltip {
display: none;
position: absolute;
left: 100%;
top: 50%;
transform: translateY(-50%);
background-color: rgba(0, 0, 0, 0.7);
color: white;
2025-07-24 20:15:39 +08:00
padding: .4rem .8rem;
border-radius: .4rem;
margin-left: .8rem;
white-space: nowrap;
2025-07-24 20:15:39 +08:00
font-size: 1.2rem;
2025-09-24 11:53:25 +08:00
z-index: 9999;
2025-11-03 15:37:18 +08:00
pointer-events: none;
}
.tool-tooltip:before {
content: "";
position: absolute;
top: 50%;
right: 100%;
2025-07-24 20:15:39 +08:00
margin-top: -.5rem;
border-width: .5rem;
border-style: solid;
border-color: transparent rgba(0, 0, 0, 0.7) transparent transparent;
}
</style>