|
|
@@ -65,17 +65,18 @@ class PosterUtil
|
|
|
|
|
|
const FOOTER_BUY_HINT_SIZE = 26;
|
|
|
|
|
|
- const FOOTER_BUY_HINT_BAR_W = 430;
|
|
|
+ const FOOTER_BUY_HINT_BAR_H = 48;
|
|
|
|
|
|
- const FOOTER_BUY_HINT_BAR_H = 56;
|
|
|
+ const FOOTER_BUY_HINT_BAR_RADIUS = 12;
|
|
|
|
|
|
const FOOTER_BUY_HINT_BAR_COLOR = 'F2F2F2';
|
|
|
|
|
|
- const FOOTER_BUY_HINT_TEXT_PAD_X = 28;
|
|
|
+ /** 灰条左右内边距(条宽 = 文案宽度 + 两侧 padding) */
|
|
|
+ const FOOTER_BUY_HINT_TEXT_PAD_X = 20;
|
|
|
|
|
|
const FOOTER_TEXT_GAP = 12;
|
|
|
|
|
|
- const FOOTER_PRICE_SIZE = 56;
|
|
|
+ const FOOTER_PRICE_SIZE = 64;
|
|
|
|
|
|
/**
|
|
|
* 与 admin/home/me 一致:门店展示名、Logo 对象路径、itemRemark
|
|
|
@@ -327,12 +328,13 @@ class PosterUtil
|
|
|
/**
|
|
|
* 底部左侧(价格+灰条)与右侧太阳码垂直居中对齐
|
|
|
*
|
|
|
- * @return array{buyHintBarY:int,buyHintTextY:int,buyHintTextX:int,priceY:int,qrY:int}
|
|
|
+ * @return array{buyHintBarY:int,buyHintBarW:int,buyHintTextY:int,buyHintTextX:int,priceY:int,qrY:int}
|
|
|
*/
|
|
|
private static function calcFooterLayout()
|
|
|
{
|
|
|
$qrCenterFromBottom = self::QR_PAD_BOTTOM + (int)(self::QR_SIZE / 2);
|
|
|
$hintBarH = self::FOOTER_BUY_HINT_BAR_H;
|
|
|
+ $hintBarW = self::calcBuyHintBarWidth(self::FOOTER_BUY_HINT);
|
|
|
$priceH = (int)ceil(self::FOOTER_PRICE_SIZE * 1.3);
|
|
|
$gap = self::FOOTER_TEXT_GAP;
|
|
|
$blockH = $priceH + $gap + $hintBarH;
|
|
|
@@ -344,6 +346,7 @@ class PosterUtil
|
|
|
|
|
|
return [
|
|
|
'buyHintBarY' => $buyHintBarY,
|
|
|
+ 'buyHintBarW' => $hintBarW,
|
|
|
'buyHintTextY' => $buyHintTextY,
|
|
|
'buyHintTextX' => self::CANVAS_PAD_X + self::FOOTER_BUY_HINT_TEXT_PAD_X,
|
|
|
'priceY' => $priceY,
|
|
|
@@ -351,14 +354,28 @@ class PosterUtil
|
|
|
];
|
|
|
}
|
|
|
|
|
|
- /** OSS 生成灰色圆角底条(无需单独上传底图) */
|
|
|
- private static function buildBuyHintBarWatermarkPath()
|
|
|
+ /** 按文案长度估算灰条宽度,避免条过长导致 OSS 圆角裁切异常 */
|
|
|
+ private static function calcBuyHintBarWidth($text)
|
|
|
{
|
|
|
- $w = self::FOOTER_BUY_HINT_BAR_W;
|
|
|
+ $text = self::filterPosterUtf8Text($text);
|
|
|
+ if ($text === '') {
|
|
|
+ $text = self::FOOTER_BUY_HINT;
|
|
|
+ }
|
|
|
+ $charCount = mb_strlen($text, 'UTF-8');
|
|
|
+ $charW = (int)ceil(self::FOOTER_BUY_HINT_SIZE * 1.15);
|
|
|
+ $w = $charCount * $charW + self::FOOTER_BUY_HINT_TEXT_PAD_X * 2;
|
|
|
+
|
|
|
+ return max(220, min(self::SLOT_W - self::QR_SIZE - self::QR_PAD_RIGHT - 24, $w));
|
|
|
+ }
|
|
|
+
|
|
|
+ /** OSS 生成灰色小圆角底条 */
|
|
|
+ private static function buildBuyHintBarWatermarkPath($barW)
|
|
|
+ {
|
|
|
+ $w = max(200, (int)$barW);
|
|
|
$h = self::FOOTER_BUY_HINT_BAR_H;
|
|
|
- $r = (int)($h / 2);
|
|
|
+ $r = min(self::FOOTER_BUY_HINT_BAR_RADIUS, (int)floor($h / 2) - 2);
|
|
|
|
|
|
- return self::BLANK_CANVAS . '?x-oss-process=image/resize,m_pad,w_' . $w . ',h_' . $h
|
|
|
+ return self::BLANK_CANVAS . '?x-oss-process=image/resize,m_fill,w_' . $w . ',h_' . $h
|
|
|
. ',color_' . self::FOOTER_BUY_HINT_BAR_COLOR . '/rounded-corners,r_' . $r;
|
|
|
}
|
|
|
|
|
|
@@ -546,7 +563,7 @@ class PosterUtil
|
|
|
$url .= '/watermark,image_' . $logoB64 . ',g_se,x_210,y_48';
|
|
|
}
|
|
|
|
|
|
- $url .= '/watermark,image_' . stringUtil::ossBase64(self::buildBuyHintBarWatermarkPath())
|
|
|
+ $url .= '/watermark,image_' . stringUtil::ossBase64(self::buildBuyHintBarWatermarkPath($footer['buyHintBarW']))
|
|
|
. ',g_sw,x_' . self::CANVAS_PAD_X . ',y_' . $footer['buyHintBarY'];
|
|
|
$url .= '/watermark,text_' . stringUtil::ossBase64(self::FOOTER_BUY_HINT)
|
|
|
. ',g_sw,x_' . $footer['buyHintTextX'] . ',y_' . $footer['buyHintTextY']
|