cl-icon.uvue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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, parseRpx, parsePt, useCache, isDark } from "@/cool";
  27. import { icons } from "@/icons";
  28. defineOptions({
  29. name: "cl-icon"
  30. });
  31. // 定义组件属性
  32. const props = defineProps({
  33. // 透传样式
  34. pt: {
  35. type: Object,
  36. default: () => ({})
  37. },
  38. // 图标名称
  39. name: {
  40. type: String,
  41. default: ""
  42. },
  43. // 图标大小
  44. size: {
  45. type: [String, Number] as PropType<string | number>,
  46. default: 32
  47. },
  48. // 图标高度
  49. height: {
  50. type: [String, Number] as PropType<string | number>,
  51. default: null
  52. },
  53. // 图标宽度
  54. width: {
  55. type: [String, Number] as PropType<string | number>,
  56. default: null
  57. },
  58. // 图标颜色
  59. color: {
  60. type: String,
  61. default: ""
  62. }
  63. });
  64. // 缓存
  65. const { cache } = useCache(() => [props.color]);
  66. // 透传样式类型定义
  67. type PassThrough = {
  68. className?: string;
  69. };
  70. // 解析透传样式
  71. const pt = computed(() => parsePt<PassThrough>(props.pt));
  72. // 图标类型定义
  73. type Icon = {
  74. font: string; // 字体名称
  75. text: string; // 图标文本
  76. };
  77. // 图标信息
  78. const icon = computed<Icon>(() => {
  79. let font = "";
  80. let text = "";
  81. try {
  82. let code = "";
  83. // 遍历字体库查找对应图标
  84. forInObject(icons, (value, key) => {
  85. if (has(value, props.name)) {
  86. font = key;
  87. code = get(value, props.name) as string;
  88. }
  89. });
  90. // Android平台特殊处理
  91. // #ifdef APP-ANDROID
  92. // @ts-ignore
  93. text = new String(Character.toChars(parseInt(code, 16).toInt()));
  94. // #endif
  95. // 其他平台处理
  96. // #ifndef APP-ANDROID
  97. text = String.fromCharCode(parseInt(code, 16));
  98. // #endif
  99. } catch (e) {
  100. console.error(`图标 ${props.name} 不存在`, e);
  101. }
  102. return {
  103. font,
  104. text
  105. };
  106. });
  107. // 图标样式
  108. const iconStyle = computed(() => {
  109. const style = {};
  110. if (props.color != "") {
  111. style["color"] = props.color;
  112. }
  113. style["fontFamily"] = icon.value.font;
  114. style["fontSize"] = parseRpx(props.size!);
  115. style["height"] = parseRpx(props.height ?? props.size!);
  116. style["width"] = parseRpx(props.width ?? props.size!);
  117. style["lineHeight"] = parseRpx(props.size!);
  118. return style;
  119. });
  120. </script>