- detail 顶部 favbtn 浮窗(需避让胶囊、丑)移除,改为底部 addbar 内与 CTA 并排的方形按钮 - fc-icon 新增 filled 属性:收藏态实心心形(Lucide 描边图标默认 fill=none,filled=true 时 fill=stroke 变实心) - 收藏按钮美化:圆角 24rpx 方形 + 发丝边框,未收藏描边(text-2)、已收藏实心(accent)+ accent-soft 底色 + accent-ring 边框 + 点按 scale 反馈 - detail.js 清理 favRight/favTop 胶囊避让逻辑(不再需要)
60 lines
2.0 KiB
JavaScript
60 lines
2.0 KiB
JavaScript
const iconSvg = require('../../utils/icon-svg');
|
||
|
||
// 设计 token 色值映射:调用方常传 var(--xxx),但 SVG data URI 内无法解析 CSS 变量,需转成具体色值
|
||
const CSS_VARS = {
|
||
'--accent': '#B6F24E',
|
||
'--accent-hover': '#C7F56E',
|
||
'--accent-active': '#9EDB3A',
|
||
'--text': '#ECF1EF',
|
||
'--text-2': '#9BA7A1',
|
||
'--text-3': '#6B7670',
|
||
'--danger': '#FF5C5C',
|
||
'--success': '#2BD9A6',
|
||
'--warn': '#F2B53D',
|
||
'--info': '#4FA8FF',
|
||
};
|
||
function resolveColor(c) {
|
||
if (!c) return '#ECF1EF';
|
||
const m = /^var\((--[\w-]+)\)$/.exec(String(c).trim());
|
||
if (m) return CSS_VARS[m[1]] || '#ECF1EF';
|
||
return c; // 已是具体色值(hex)
|
||
}
|
||
|
||
// 用 <image> 渲染 Lucide SVG 矢量图(微信小程序 <text> 自定义字体不可靠,改用此方案 100% 稳定)
|
||
Component({
|
||
properties: {
|
||
// Lucide 图标名,如 search / dumbbell / heart
|
||
name: { type: String, value: '' },
|
||
// 字号(rpx),同时作为图标宽高
|
||
size: { type: Number, value: 20 },
|
||
// 颜色:可传具体 hex,或 var(--xxx)(自动解析为对应 token 色值)
|
||
color: { type: String, value: '' },
|
||
// 是否实心填充(如收藏后实心心形)。默认描边
|
||
filled: { type: Boolean, value: false },
|
||
},
|
||
data: { src: '' },
|
||
observers: {
|
||
name() { this._build(); },
|
||
color() { this._build(); },
|
||
filled() { this._build(); },
|
||
},
|
||
lifetimes: {
|
||
attached() { this._build(); },
|
||
},
|
||
methods: {
|
||
_build() {
|
||
const { name, color, filled } = this.data;
|
||
const inner = iconSvg[name];
|
||
if (!inner) { this.setData({ src: '' }); return; }
|
||
const stroke = resolveColor(color);
|
||
const fill = filled ? stroke : 'none';
|
||
const body = inner.replace(/__C__/g, stroke);
|
||
const svg =
|
||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="' + fill + '" ' +
|
||
'stroke="' + stroke + '" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
|
||
body + '</svg>';
|
||
this.setData({ src: 'data:image/svg+xml,' + encodeURIComponent(svg) });
|
||
},
|
||
},
|
||
});
|