Files
WAI_Project_UNIX/uni_modules/cool-ui/components/cl-icon/cl-icon.uvue
2025-10-22 17:49:07 +08:00

163 lines
3.0 KiB
Plaintext

<template>
<text class="cl-icon" :class="[ptClassName]" :style="iconStyle" :key="cache.key">
{{ icon.text }}
</text>
</template>
<script setup lang="ts">
import { computed, type PropType } from "vue";
import {
forInObject,
get,
has,
parsePt,
useCache,
isDark,
ctx,
hasTextColor,
isNull
} from "@/cool";
import { icons } from "@/icons";
import { useSize } from "../../hooks";
defineOptions({
name: "cl-icon"
});
// 定义组件属性
const props = defineProps({
// 透传样式
pt: {
type: Object,
default: () => ({})
},
// 图标名称
name: {
type: String,
default: ""
},
// 图标大小
size: {
type: [String, Number] as PropType<string | number>,
default: 32
},
// 图标高度
height: {
type: [String, Number] as PropType<string | number>,
default: null
},
// 图标宽度
width: {
type: [String, Number] as PropType<string | number>,
default: null
},
// 图标颜色
color: {
type: String,
default: ""
}
});
// 透传样式类型定义
type PassThrough = {
className?: string;
};
// 解析透传样式
const pt = computed(() => parsePt<PassThrough>(props.pt));
// 缓存
const { cache } = useCache(() => [props.color]);
// 字号
const { getRpx, ptClassName } = useSize(() => pt.value.className ?? "");
// 图标类型定义
type Icon = {
font: string; // 字体名称
text: string; // 图标文本
};
// 图标信息
const icon = computed<Icon>(() => {
let font = "";
let text = "";
try {
let code = "";
// 遍历字体库查找对应图标
forInObject(icons, (value, key) => {
if (has(value, props.name)) {
font = key;
code = get(value, props.name) as string;
}
});
text = String.fromCharCode(parseInt(code, 16));
} catch (e) {
console.error(`图标 ${props.name} 不存在`, e);
}
return {
font,
text
};
});
// 图标颜色
const color = computed(() => {
if (props.color != "" && !isNull(props.color)) {
switch (props.color) {
case "primary":
return ctx.color["primary-500"] as string;
case "success":
return "#22c55e";
case "warn":
return "#eab308";
case "error":
return "#ef4444";
case "info":
return ctx.color["surface-500"] as string;
case "dark":
return ctx.color["surface-700"] as string;
case "light":
return ctx.color["surface-50"] as string;
case "disabled":
return ctx.color["surface-300"] as string;
default:
return props.color;
}
}
return isDark.value ? "white" : (ctx.color["surface-700"] as string);
});
// 图标样式
const iconStyle = computed(() => {
const style = {};
// 判断是不是有颜色样式
if (!hasTextColor(ptClassName.value)) {
style["color"] = color.value;
}
// 设置字体
if (icon.value.font != "") {
style["fontFamily"] = icon.value.font;
}
// 设置字体大小
style["fontSize"] = getRpx(props.size!);
// 设置高度
style["height"] = getRpx(props.height ?? props.size!);
style["lineHeight"] = getRpx(props.size!);
// 设置宽度
style["width"] = getRpx(props.width ?? props.size!);
return style;
});
</script>