177 lines
10 KiB
JavaScript
177 lines
10 KiB
JavaScript
// 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 = '<svg viewBox="0 0 24 24" fill="none" stroke="COLOR" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">'
|
||
const svgMap = {
|
||
'share': s + '<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>',
|
||
'arrow-up-right': s + '<line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>',
|
||
'chevron-left': s + '<polyline points="15 18 9 12 15 6"/></svg>',
|
||
'search': s + '<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>',
|
||
'heart': s + '<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>',
|
||
'user': s + '<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>',
|
||
'smartphone': s + '<rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg>',
|
||
'map-pin': s + '<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>',
|
||
'home': s + '<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>',
|
||
'star': s + '<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>',
|
||
'message-circle': s + '<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>',
|
||
'package': s + '<line x1="16.5" y1="9.4" x2="7.5" y2="4.21"/><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>',
|
||
'book-open': s + '<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>',
|
||
'lightbulb': s + '<path d="M9 18h6"/><path d="M10 22h4"/><path d="M15.09 14c.18-.98.65-1.74 1.41-2.5A4.65 4.65 0 0 0 18 8 6 6 0 0 0 6 8c0 1 .23 2.23 1.5 3.5A4.61 4.61 0 0 1 8.91 14"/></svg>',
|
||
'handshake': s + '<path d="m11 17 2 2a1 1 0 1 0 3-3"/><path d="m14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a1 1 0 0 0-1.4 1.4l.88.88"/><path d="M15 9 9.03 9"/><path d="m14 14-2.5-2.5"/><path d="m18 15-3-3"/><path d="m15 12-3-3"/><path d="m9 12 2 2"/></svg>',
|
||
'rocket': s + '<path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"/><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"/></svg>',
|
||
'trophy': s + '<path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20 7 22"/><path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20 17 22"/><path d="M18 2H6v7a6 6 0 0 0 12 0V2Z"/></svg>',
|
||
'refresh-cw': s + '<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>',
|
||
'shield': s + '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>',
|
||
'wallet': s + '<path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/><path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/><path d="M18 12a2 2 0 0 0 0 4h4v-4h-4z"/></svg>',
|
||
'wrench': s + '<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>',
|
||
'camera': s + '<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/></svg>',
|
||
'phone': s + '<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>',
|
||
'clipboard': s + '<rect x="8" y="2" width="8" height="4" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="6" width="8" height="12" rx="1"/></svg>',
|
||
'megaphone': s + '<path d="m3 11 18-5v12L3 14v-3z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/></svg>',
|
||
'image': s + '<rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>',
|
||
'gift': s + '<polyline points="20 12 20 22 4 22 4 12"/><rect x="2" y="7" width="20" height="5"/><line x1="12" y1="22" x2="12" y2="7"/><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></svg>',
|
||
'lock': s + '<rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>',
|
||
'sparkles': s + '<path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z"/></svg>',
|
||
'save': s + '<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>',
|
||
'globe': s + '<circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>',
|
||
'users': s + '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>',
|
||
'gamepad': s + '<line x1="6" y1="12" x2="10" y2="12"/><line x1="8" y1="10" x2="8" y2="14"/><line x1="15" y1="13" x2="15.01" y2="13"/><line x1="18" y1="11" x2="18.01" y2="11"/><rect x="2" y="6" width="20" height="12" rx="2"/></svg>',
|
||
'check': s + '<polyline points="20 6 9 17 4 12"/></svg>',
|
||
'trash-2': s + '<polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>',
|
||
'clock': s + '<circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>',
|
||
'plus': s + '<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>',
|
||
'briefcase': s + '<rect x="2" y="7" width="20" height="14" rx="2" ry="2"/><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/></svg>',
|
||
'target': s + '<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg>',
|
||
'rotate-ccw': s + '<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>',
|
||
'corner-down-left': s + '<polyline points="9 10 4 15 9 20"/><path d="M20 4v7a4 4 0 0 1-4 4H4"/></svg>',
|
||
'folder': s + '<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/><line x1="12" y1="11" x2="12" y2="17"/></svg>',
|
||
'bar-chart': s + '<line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/></svg>',
|
||
'link': s + '<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>'
|
||
}
|
||
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: ''
|
||
})
|
||
}
|
||
}
|
||
}
|
||
})
|