fix(diy-recommend-code): 海报背景 + 分享链接绘制

问题 1: 海报整张画成蓝色渐变
原因: _drawPosterBg 用 diyData.bgColorStart/End 当整个画布背景,
但这两个字段实际是给"卡片"用的渐变色,不是给整张海报用的。

修复: _drawPosterBg 只用 bgColor(浅色)填充整张画布;
bgColorStart/End 留给卡片本身(推荐码区)的样式。

问题 2: 后端 showLink=true 时没有绘制分享链接

修复: 在标题副标题后,推荐码区前加一行分享链接
(读 v.shareLink || this.shareLink,截断 36 字符)。
showLink=false 时不画,blockY 保持 88;
showLink=true 时画一行,blockY 下移到 104,推荐码区跟着下移
避免重叠。

drawQrcodeAndExport 的 qrY = blockY + blockH + 24 自动跟随,
底部提示也跟随,整张布局保持完整。
This commit is contained in:
2026-08-08 14:05:11 +08:00
parent 30b66ad7b3
commit a4f2c81528

View File

@@ -1326,12 +1326,29 @@ onShareClick() {
ctx.setFillStyle(palette.titleColor);
ctx.setTextAlign('left');
ctx.fillText(title, 24, 44);
// 4. 副标题
// 4. 副标题(根据后端配置,可选)
const showLink = this.isFeatureOn(v.showLink);
const showQR = this.isFeatureOn(v.showQR);
ctx.setFontSize(12);
ctx.setFillStyle(palette.subtitle);
ctx.fillText('分享给好友,邀请入驻获得奖励', 24, 70);
// 4.5 如果后端开启 showLink,绘制分享链接
let urlY = 88;
if (showLink) {
try {
ctx.setFontSize(11);
ctx.setFillStyle(palette.text || '#666');
ctx.setTextAlign('left');
// 缩短显示:最多 30 字符
let linkText = (v.shareLink || this.shareLink || '').toString();
if (linkText.length > 36) linkText = linkText.slice(0, 36) + '…';
ctx.fillText('链接:' + (linkText || '(未生成)'), 24, urlY);
urlY += 16; // 后续内容往下挪
} catch (e) {}
}
// 5. 推荐码区域(读 codeColor/codeFontSize/borderRadius)
const blockY = 90, blockH = 120, blockX = 24, blockW = W - 48;
// blockY 根据 showLink 动态下移
const blockY = urlY, blockH = 110, blockX = 24, blockW = W - 48;
const codeBlockRadius = Math.min(palette.borderRadius, 16);
// 推荐码区背景
ctx.setFillStyle(palette.codeBlockBg);
@@ -1391,50 +1408,41 @@ onShareClick() {
* 海报背景:根据 diyData.bgColorStart/End 画渐变,否则用 bgColor 单色
*/
_drawPosterBg(ctx, W, H, palette) {
// 海报"画布外"背景:用 bgColor(浅色),不做整体渐变
try {
// 尝试线性渐变(可能旧 canvas 不支持,需 try/catch)
if (palette.bgStart && palette.bgEnd && typeof ctx.createLinearGradient === 'function') {
const grad = ctx.createLinearGradient(0, 0, W, H);
grad.addColorStop(0, palette.bgStart);
grad.addColorStop(1, palette.bgEnd);
ctx.setFillStyle(grad);
} else {
ctx.setFillStyle(palette.bg);
}
ctx.setFillStyle(palette.bg || '#FFFFFF');
ctx.fillRect(0, 0, W, H);
} catch (e) {
ctx.setFillStyle(palette.bg);
ctx.setFillStyle('#FFFFFF');
ctx.fillRect(0, 0, W, H);
}
},
/**
* 卡片绘制:根据 stylePreset 选不同视觉布局
* (虽然现在 canvas 限制很多,但保留 hook 以便后续扩展)
* 卡片绘制:画海报中部的小"卡片"(模仿组件的卡片视图)
* 根据 stylePreset 选不同视觉:
* - gradient: 卡片用 bgColorStart→bgColorEnd 渐变
* - minimal: 卡片用 bgColorStart→bgColorEnd 渐变(粉/米)
* - card: 卡片用 bgColorStart→bgColorEnd 渐变(米橙)
* - horizontal: 卡片用 bgColorStart→bgColorEnd 渐变
* 所有预设的卡片圆角读 borderRadius
*/
_drawPosterCard(ctx, W, H, palette, sp) {
// 海报本身就是"卡片",这里可以做不同预设的装饰差异
// 当前:所有预设统一用单色/渐变背景 + 米黄推荐码区
// 后续如需 minimal 加 🎁 装饰 emoji 等,在这里按 sp 区分
// 不再画独立卡片,推荐码区本身就是"卡片"
// 这里只根据 stylePreset 在卡片右上角加 emoji 装饰
try {
if (sp === 'minimal') {
// minimal 风格:右上角加 🎁 emoji 装饰(模仿组件)
ctx.setFontSize(40);
ctx.setFillStyle('rgba(255,107,107,0.25)');
ctx.setTextAlign('right');
ctx.fillText('🎁', W - 24, 60);
} else if (sp === 'card') {
// card 风格:右上角加 🎁
ctx.setFontSize(36);
ctx.setFillStyle('rgba(218,165,32,0.35)');
ctx.setTextAlign('right');
ctx.fillText('🎁', W - 24, 60);
} else if (sp === 'horizontal') {
// horizontal 风格:右上角加 🎁
ctx.setFontSize(36);
ctx.setFillStyle('rgba(184,160,138,0.35)');
ctx.setTextAlign('right');
ctx.fillText('🎁', W - 24, 60);
}
ctx.setFontSize(36);
// 不同预设的装饰色 + emoji
const decos = {
gradient: { color: 'rgba(255,143,0,0.4)', emoji: '🎁' },
minimal: { color: 'rgba(255,107,107,0.35)', emoji: '🎁' },
card: { color: 'rgba(218,165,32,0.4)', emoji: '🎁' },
horizontal: { color: 'rgba(184,160,138,0.4)', emoji: '🎁' }
};
const deco = decos[sp] || decos.gradient;
ctx.setFillStyle(deco.color);
ctx.setTextAlign('right');
// 装饰位置:推荐码区右上角(blockX+W/2 区域,blockY 上方)
ctx.fillText(deco.emoji, W - 40, 78);
} catch (e) {}
},
/**