cl-icon.uvue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <template>
  2. <text
  3. class="cl-icon"
  4. :class="[
  5. isDark ? 'text-white' : 'text-surface-700',
  6. {
  7. '!text-primary-500': color == 'primary',
  8. '!text-green-500': color == 'success',
  9. '!text-yellow-500': color == 'warn',
  10. '!text-red-500': color == 'error',
  11. '!text-surface-500': color == 'info',
  12. '!text-surface-700': color == 'dark',
  13. '!text-surface-50': color == 'light',
  14. '!text-surface-300': color == 'disabled'
  15. },
  16. pt.className
  17. ]"
  18. :style="iconStyle"
  19. :key="cache.key"
  20. >
  21. {{ icon.text }}
  22. </text>
  23. </template>
  24. <script setup lang="ts">
  25. import { computed, type PropType } from "vue";
  26. import { forInObject, get, has, parsePt, useCache, isDark } from "@/cool";
  27. import { icons } from "@/icons";
  28. import { useSize } from "../../hooks";
  29. defineOptions({
  30. name: "cl-icon"
  31. });
  32. // 定义组件属性
  33. const props = defineProps({
  34. // 透传样式
  35. pt: {
  36. type: Object,
  37. default: () => ({})
  38. },
  39. // 图标名称
  40. name: {
  41. type: String,
  42. default: ""
  43. },
  44. // 图标大小
  45. size: {
  46. type: [String, Number] as PropType<string | number>,
  47. default: 32
  48. },
  49. // 图标高度
  50. height: {
  51. type: [String, Number] as PropType<string | number>,
  52. default: null
  53. },
  54. // 图标宽度
  55. width: {
  56. type: [String, Number] as PropType<string | number>,
  57. default: null
  58. },
  59. // 图标颜色
  60. color: {
  61. type: String,
  62. default: ""
  63. }
  64. });
  65. // 缓存
  66. const { cache } = useCache(() => [props.color]);
  67. // 字号
  68. const { getRpx } = useSize();
  69. // 透传样式类型定义
  70. type PassThrough = {
  71. className?: string;
  72. };
  73. // 解析透传样式
  74. const pt = computed(() => parsePt<PassThrough>(props.pt));
  75. // 图标类型定义
  76. type Icon = {
  77. font: string; // 字体名称
  78. text: string; // 图标文本
  79. };
  80. // 图标信息
  81. const icon = computed<Icon>(() => {
  82. let font = "";
  83. let text = "";
  84. try {
  85. let code = "";
  86. // 遍历字体库查找对应图标
  87. forInObject(icons, (value, key) => {
  88. if (has(value, props.name)) {
  89. font = key;
  90. code = get(value, props.name) as string;
  91. }
  92. });
  93. // Android平台特殊处理
  94. // #ifdef APP-ANDROID
  95. // @ts-ignore
  96. text = new String(Character.toChars(parseInt(code, 16).toInt()));
  97. // #endif
  98. // 其他平台处理
  99. // #ifndef APP-ANDROID
  100. text = String.fromCharCode(parseInt(code, 16));
  101. // #endif
  102. } catch (e) {
  103. console.error(`图标 ${props.name} 不存在`, e);
  104. }
  105. return {
  106. font,
  107. text
  108. };
  109. });
  110. // 图标样式
  111. const iconStyle = computed(() => {
  112. const style = {};
  113. if (props.color != "") {
  114. style["color"] = props.color;
  115. }
  116. if (icon.value.font != "") {
  117. style["fontFamily"] = icon.value.font;
  118. }
  119. style["fontSize"] = getRpx(props.size!);
  120. style["height"] = getRpx(props.height ?? props.size!);
  121. style["width"] = getRpx(props.width ?? props.size!);
  122. style["lineHeight"] = getRpx(props.size!);
  123. return style;
  124. });
  125. </script>