// components/icon/icon.js
Component({
properties: {
// 图标名称
name: {
type: String,
value: 'share',
observer: 'updateIcon'
},
// 图标大小(rpx)
size: {
type: Number,
value: 48
},
// 图标颜色
color: {
type: String,
value: '#ffffff',
observer: 'updateIcon'
},
// 自定义类名
customClass: {
type: String,
value: ''
},
// 自定义样式
customStyle: {
type: String,
value: ''
}
},
data: {
svgData: '',
fontGlyph: ''
},
lifetimes: {
attached() {
this.updateIcon()
}
},
methods: {
// iconfont 映射:将业务 name(lucide 风格)映射到 iconfont 的 unicode(形如 "\ue6aa")
// 小程序不支持通过 :before { content } 渲染,因此必须直接输出 unicode 字符
getFontGlyph(name) {
const map = {
// 基础高频(来自 static/iconfont.css 的 content 值)
'wallet': '\ue6c8',
'gift': '\ue6c9',
'user': '\ue6b9',
'search': '\ue6aa',
'share': '\ue6ab',
'home': '\ue694',
'lock': '\ue699',
'camera': '\ue671',
'warning': '\ue6bd',
// 箭头/展开
'chevron-left': '\ue6c1',
'chevron-right': '\ue6c6',
'chevron-down': '\ue6c4',
'chevron-up': '\ue6c2',
'arrow-up-right': '\ue6c2',
// 交互/状态
'x': '\ue6c3',
'check': '\ue6c7',
'plus': '\ue664',
'trash-2': '\ue66a',
'pencil': '\ue685',
'zap': '\ue75c',
'info': '\ue69c',
// 语义近似映射(iconfont 不一定有同名)
'map-pin': '\ue6a8',
'message-circle': '\ue678',
'smartphone': '\ue6a0',
'refresh-cw': '\ue6a4',
'shield': '\ue6ad',
'star': '\ue689',
'heart': '\ue68e',
// 其他:若 iconfont 里不存在,则继续走 SVG 兜底
'book-open': '\ue993',
'bar-chart': '\ue672',
'clock': '\ue6b5',
}
return map[name] || ''
},
// SVG 图标数据映射(Lucide 风格,替换原 emoji)
getSvgPath(name) {
const s = '',
'arrow-up-right': s + '',
'chevron-left': s + '',
'search': s + '',
'heart': s + '',
'user': s + '',
'smartphone': s + '',
'map-pin': s + '',
'home': s + '',
'star': s + '',
'message-circle': s + '',
'package': s + '',
'book-open': s + '',
'lightbulb': s + '',
'handshake': s + '',
'rocket': s + '',
'trophy': s + '',
'refresh-cw': s + '',
'shield': s + '',
'wallet': s + '',
'wrench': s + '',
'camera': s + '',
'phone': s + '',
'clipboard': s + '',
'megaphone': s + '',
'image': s + '',
'gift': s + '',
'lock': s + '',
'lock-open': s + '',
'sparkles': s + '',
'save': s + '',
'globe': s + '',
'users': s + '',
'gamepad': s + '',
'check': s + '',
'trash-2': s + '',
'clock': s + '',
'plus': s + '',
'briefcase': s + '',
'target': s + '',
'rotate-ccw': s + '',
'corner-down-left': s + '',
'folder': s + '',
'bar-chart': s + '',
'link': s + ''
}
return svgMap[name] || ''
},
// 更新图标
updateIcon() {
const { name, color } = this.data
const fontGlyph = this.getFontGlyph(name)
let svgString = this.getSvgPath(name)
// 若 iconfont 存在映射,则优先用字体图标;否则走 SVG
if (fontGlyph) {
this.setData({ fontGlyph, svgData: '' })
return
}
if (svgString) {
// 替换颜色占位符
svgString = svgString.replace(/COLOR/g, color)
// 转换为 Base64 Data URL
const svgData = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`
this.setData({
svgData: svgData,
fontGlyph: ''
})
} else {
this.setData({
svgData: '',
fontGlyph: ''
})
}
}
}
})