cl-icon.uvue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <template>
  2. <text class="cl-icon" :class="[ptClassName]" :style="iconStyle" :key="cache.key">
  3. {{ icon.text }}
  4. </text>
  5. </template>
  6. <script setup lang="ts">
  7. import { computed } from "vue";
  8. import { parsePt, useCache, isDark, ctx, hasTextColor, isNull } from "@/.cool";
  9. import { useSize } from "../../hooks";
  10. import { getIcon } from "./utils";
  11. defineOptions({
  12. name: "cl-icon"
  13. });
  14. // 定义组件属性
  15. const props = defineProps({
  16. // 透传样式
  17. pt: {
  18. type: Object,
  19. default: () => ({})
  20. },
  21. // 图标名称
  22. name: {
  23. type: String,
  24. default: ""
  25. },
  26. // 图标大小
  27. size: {
  28. type: Number,
  29. default: 16
  30. },
  31. // 图标高度
  32. height: {
  33. type: Number,
  34. default: null
  35. },
  36. // 图标宽度
  37. width: {
  38. type: Number,
  39. default: null
  40. },
  41. // 图标颜色
  42. color: {
  43. type: String,
  44. default: ""
  45. }
  46. });
  47. // 透传样式类型定义
  48. type PassThrough = {
  49. className?: string;
  50. };
  51. // 解析透传样式
  52. const pt = computed(() => parsePt<PassThrough>(props.pt));
  53. // 缓存
  54. const { cache } = useCache(() => [props.color]);
  55. // 字号
  56. const { toScale, ptClassName } = useSize(() => pt.value.className ?? "");
  57. // 图标信息
  58. const icon = computed(() => getIcon(props.name));
  59. // 图标颜色
  60. const color = computed(() => {
  61. if (props.color != "" && !isNull(props.color)) {
  62. switch (props.color) {
  63. case "primary":
  64. return ctx.color["primary-500"] as string;
  65. case "success":
  66. return "#22c55e";
  67. case "warn":
  68. return "#eab308";
  69. case "error":
  70. return "#ef4444";
  71. case "info":
  72. return ctx.color["surface-500"] as string;
  73. case "dark":
  74. return ctx.color["surface-700"] as string;
  75. case "light":
  76. return ctx.color["surface-50"] as string;
  77. case "disabled":
  78. return ctx.color["surface-300"] as string;
  79. default:
  80. return props.color;
  81. }
  82. }
  83. return isDark.value ? "white" : (ctx.color["surface-700"] as string);
  84. });
  85. // 图标样式
  86. const iconStyle = computed(() => {
  87. const style = {};
  88. // 判断是不是有颜色样式
  89. if (!hasTextColor(ptClassName.value)) {
  90. style["color"] = color.value;
  91. }
  92. // 设置字体
  93. if (icon.value.font != "") {
  94. style["fontFamily"] = icon.value.font;
  95. }
  96. // 设置字体大小
  97. style["fontSize"] = toScale(props.size) + "px";
  98. // #ifdef APP
  99. // 设置高度
  100. style["height"] = toScale(props.height ?? props.size) + "px";
  101. style["lineHeight"] = toScale(props.size) + "px";
  102. // 手动校准偏移量
  103. if (props.size <= 16) {
  104. style["position"] = "relative";
  105. style["top"] = "-0.5px";
  106. }
  107. // 设置宽度
  108. style["width"] = toScale(props.width ?? props.size) + "px";
  109. // #endif
  110. return style;
  111. });
  112. </script>