Files
ztab/app/src/components/IconCard/index.vue
yinsx d97ea9c791 1
2026-01-26 09:51:41 +08:00

108 lines
2.3 KiB
Vue

<template>
<a
:href="props.icon.url"
class="icon-card-wrapper"
:class="`size-${props.icon.size ?? '1x1'}`"
@click.prevent
target="_blank"
>
<div class="icon-card" :style="{ backgroundColor: props.icon.bgColor }">
<img v-if="props.icon.img" :src="props.icon.img" :alt="props.icon.name" />
<span v-else>{{ props.icon.name.charAt(0) }}</span>
</div>
<div class="label">{{ props.icon.name }}</div>
</a>
</template>
<script setup lang="ts">
type IconSize = '1x1' | '1x2' | '2x1' | '2x2' | '2x4';
interface Icon {
id: string;
name: string;
url: string;
size?: IconSize;
img?: string;
bgColor?: string;
}
const props = defineProps<{
icon: Icon;
}>();
</script>
<style lang="scss" scoped>
@import '@/styles/tokens.scss';
.icon-card-wrapper {
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: flex-start;
width: 100%;
height: 100%;
text-decoration: none;
border-radius: $border-radius-small;
padding: var(--icon-card-padding);
transition: transform $motion-duration-sm $motion-easing-standard;
user-select: none; // 拖拽时避免选中文本
box-sizing: border-box;
// 悬停效果由父级拖拽状态控制
&:hover {
.icon-card {
box-shadow: $shadow-lg;
}
}
}
.icon-card {
width: 100%;
flex: 1 1 auto;
min-height: 0;
border-radius: $border-radius-small;
display: flex;
align-items: center;
justify-content: center;
font-size: var(--icon-font-size);
font-weight: 500;
color: white;
box-shadow: $shadow-md;
transition: box-shadow $motion-duration-sm $motion-easing-standard;
margin-bottom: var(--icon-label-margin-top);
background-size: cover;
background-position: center;
pointer-events: none; // 指针事件交给外层容器处理
img {
width: 100%;
height: 100%;
border-radius: $border-radius-small;
object-fit: cover;
}
}
.icon-card-wrapper.size-1x1 {
align-items: center;
justify-content: center;
}
.icon-card-wrapper.size-1x1 .icon-card {
width: var(--icon-size);
height: var(--icon-size);
flex: 0 0 auto;
}
.label {
font-size: var(--icon-label-font-size);
color: $color-text-primary;
text-align: center;
width: 100%;
white-space: normal;
word-break: break-word;
line-height: 1.2;
pointer-events: none;
}
</style>