合同小程序前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
5.2 KiB

1 week ago
  1. <template>
  2. <text class="l-icon" :class="[classes]" :style="[styles, lStyle]" v-if="!isImage && !isIconify && !isSVG" @click="$emit('click')">{{iconCode}}</text>
  3. <image class="l-icon" :class="[classes]" :style="[styles, lStyle]" v-else-if="(!isSVG && !isIconify) && isImage" :src="iconUrl" @click="$emit('click')"></image>
  4. <l-svg class="l-icon" :class="[classes]" :style="[styles, lStyle]" v-else :web="web" :color="color" :src="iconUrl" @error="imageError" @load="imageLoad" @click="$emit('click')"></l-svg>
  5. </template>
  6. <script lang="ts">
  7. // @ts-nocheck
  8. /**
  9. * LimeIcon 图标
  10. * @description ICON集
  11. * @tutorial https://ext.dcloud.net.cn/plugin?id=14057
  12. * @property {String} name 图标名称
  13. * @property {String} color 颜色
  14. * @property {String} size 尺寸
  15. * @property {String} prefix 字体图标前缀
  16. * @property {Boolean} inherit 是否继承颜色
  17. * @property {Boolean} web 原生 app(nvue,uvue) 是否使用web渲染
  18. * @event {Function} click 点击事件
  19. */
  20. // @ts-nocheck
  21. import { computed, defineComponent, ref, inject } from '@/uni_modules/lime-shared/vue';
  22. import icons from '../../static/icons.json';
  23. import { addUnit } from '@/uni_modules/lime-shared/addUnit';
  24. import { isObject } from '@/uni_modules/lime-shared/isObject';
  25. import IconProps from './props';
  26. // #ifdef VUE2 && MP
  27. import { getClassStr } from '@/uni_modules/lime-shared/getClassStr';
  28. // #endif
  29. // #ifdef APP-NVUE
  30. import iconSrc from '@/uni_modules/lime-icon/hybrid/html/t3.ttf';
  31. var domModule = weex.requireModule('dom');
  32. domModule.addRule('fontFace', {
  33. 'fontFamily': "uniicons",
  34. 'src': "url('" + iconSrc + "')"
  35. });
  36. // #endif
  37. const name = 'l-icon';
  38. export default defineComponent({
  39. name,
  40. externalClasses: ['l-class'],
  41. options: {
  42. addGlobalClass: true,
  43. virtualHost: true,
  44. },
  45. props: IconProps,
  46. emits: ['click'],
  47. setup(props, { emit }) {
  48. const $iconCollection = inject('$iconCollection', null)
  49. const { $limeIconsHost: $iconsHost } = uni as any
  50. const IconifyURL = 'https://api.iconify.design/'
  51. // const isAPP = uni.getSystemInfoSync().uniPlatform == 'app'
  52. const hasHost = computed(() => `${props.name}`.indexOf('/') !== -1);
  53. const isIconify = computed(() => !hasHost.value && `${props.name}`.includes(':'))
  54. const collectionIcon = computed(() => isObject($iconCollection) && $iconCollection.icons[props.name])
  55. const isImage = computed<boolean>(() : boolean => {
  56. return /\.(jpe?g|png|gif|bmp|webp|tiff?)$/i.test(props.name) || /^data:image\/(jpeg|png|gif|bmp|webp|tiff);base64,/.test(props.name)
  57. })
  58. const isSVG = computed<boolean>(() : boolean => {
  59. return /\.svg$/i.test(props.name) || props.name.startsWith('data:image/svg+xml') || props.name.startsWith('<svg')
  60. })
  61. const classes = computed(() => {
  62. const { prefix } = props
  63. const iconPrefix = prefix || name
  64. const iconName = `${iconPrefix}-${props.name}`
  65. const isFont = !isImage.value && !isIconify.value && !isSVG.value
  66. const isImages = isImage.value || isIconify.value || isSVG.value
  67. const cls = {
  68. [iconPrefix]: !isImages && prefix,
  69. [iconName]: !isImages,
  70. [`${name}--image`]: isImages,
  71. [`${name}--font`]: isFont,
  72. // [`is-inherit`]: isIconify.value && (props.color || props.inherit)
  73. }
  74. // #ifdef VUE2 && MP
  75. return getClassStr(cls)
  76. // #endif
  77. return cls
  78. })
  79. const iconCode = computed(() => {
  80. const isImages = isImage.value || isIconify.value || isSVG.value
  81. return (!isImages && icons[props.name]) || ''
  82. })
  83. const isError = ref(false)
  84. const cacheMap = new Map<string, string>()
  85. const iconUrl = computed(() => {
  86. const hasIconsHost = $iconsHost != null && $iconsHost != ''
  87. // const hasIconCollection = $iconCollectiont != null
  88. if (isImage.value) {
  89. return hasHost.value ? props.name : ($iconsHost ?? '') + props.name
  90. } else if (isIconify.value) {
  91. // 防止重绘
  92. if(cacheMap.has(props.name) && !isError.value) {
  93. return cacheMap.get(props.name)!
  94. }
  95. // 如果存在collectionIcon则使用
  96. // 如果设置的路径加载失败 就使用网络地址 就使用iconify api
  97. // !isError.value &&
  98. const _host = `${hasIconsHost ? $iconsHost : IconifyURL}`
  99. const _icon = collectionIcon.value || _host + `${props.name}.svg`.replace(/:/g, '/')
  100. cacheMap.set(props.name, _icon)
  101. return _icon
  102. } else if (isSVG.value) {
  103. return (/\.svg$/i.test(props.name) && hasIconsHost && !hasHost.value ? $iconsHost : '') + props.name.replace(/'/g, '"')
  104. } else {
  105. return null
  106. }
  107. })
  108. const styles = computed(() => {
  109. const style : Record<string, any> = {
  110. 'color': props.color,
  111. }
  112. if (typeof props.size == 'number' || props.size) {
  113. style['font-size'] = addUnit(props.size)
  114. }
  115. //#ifdef VUE2
  116. // VUE2小程序最后一个值莫名的出现undefined
  117. style['undefined'] = ''
  118. // #endif
  119. return style
  120. })
  121. const imageLoad = () => {
  122. isError.value = false
  123. }
  124. const imageError = () => {
  125. isError.value = true
  126. }
  127. return {
  128. iconCode,
  129. classes,
  130. styles,
  131. isImage,
  132. isSVG,
  133. isIconify,
  134. iconUrl,
  135. imageLoad,
  136. imageError
  137. }
  138. }
  139. })
  140. </script>
  141. <style lang="scss">
  142. @import './index.scss';
  143. </style>