$maxLen) { return mb_substr($text, 0, $maxLen, 'UTF-8') . '…'; } return $text; } /** * 按商品图比例计算主图区高度与画布总高(能多矮就多矮,仅保留温和下限) * * @return array{imgH:int,totalH:int,scaledH:int,posterW:int} */ public static function calcPosterLayout($coverWidth, $coverHeight) { $coverWidth = (int)$coverWidth; $coverHeight = (int)$coverHeight; $scaledH = 0; if ($coverWidth > 0 && $coverHeight > 0) { $scaledH = (int)round($coverHeight * (self::SLOT_W / $coverWidth)); $imgH = max(self::IMG_H_MIN, min(self::IMG_H_MAX, $scaledH)); } else { $scaledH = self::IMG_H_MIN; $imgH = self::IMG_H_MIN; } $totalH = $imgH + self::FOOTER_H; $absoluteMin = self::FOOTER_H + 120; $totalH = max($absoluteMin, min(self::TOTAL_H_MAX, $totalH)); return [ 'imgH' => $imgH, 'totalH' => $totalH, 'scaledH' => $scaledH, 'posterW' => self::POSTER_W, ]; } /** * 商品图:常规按宽 SLOT_W 等比(无左右垫白);超高图用 m_fill 裁高至 IMG_H_MAX */ private static function buildCoverWatermarkPath($cover, $scaledH) { $scaledH = (int)$scaledH; if ($scaledH > self::IMG_H_MAX) { return $cover . '?x-oss-process=image/resize,m_fill,w_' . self::SLOT_W . ',h_' . self::IMG_H_MAX . ',limit_0'; } return $cover . '?x-oss-process=image/resize,m_lfit,w_' . self::SLOT_W . ',limit_0'; } /** * 太阳码水平中心 X(用于扫码文案 g_south 居中) */ private static function qrCenterX() { return self::POSTER_W - self::QR_PAD_RIGHT - (int)(self::QR_SIZE / 2); } /** * 扫码提示文案:位于太阳码正上方居中(g_south = 文字下边中点对齐) */ private static function scanHintYFromBottom() { return self::QR_PAD_BOTTOM + self::QR_SIZE + self::QR_HINT_GAP; } /** * 动态白底画布(blank.png → 750 × totalH) */ public static function buildCanvasBaseUrl($prefix, $totalH) { $absoluteMin = self::FOOTER_H + 120; $totalH = max($absoluteMin, min(self::TOTAL_H_MAX, (int)$totalH)); $process = '?x-oss-process=image/resize,m_pad,w_' . self::POSTER_W . ',h_' . $totalH . ',color_' . self::CANVAS_COLOR; return $prefix . self::BLANK_CANVAS . $process; } /** * 和炫鲜花等门店角标 */ public static function buildHyxhLogoWatermark($mainId) { if (!in_array((int)$mainId, [52, 1459, 13495], true)) { return ''; } $logo = 'poster/hyxh_ncd_logo.png?x-oss-process=image/resize,m_fill,h_72,w_72'; if ($mainId == 1459) { $logo = 'poster/hyxh_gcd_logo.png?x-oss-process=image/resize,m_fill,h_72,w_72'; } if ($mainId == 13495) { $logo = 'poster/hyxh_hzd_logo.png?x-oss-process=image/resize,m_fill,h_72,w_72'; } return stringUtil::ossBase64($logo); } /** * 花束海报 */ public static function buildMallGoodsPosterUrl($prefix, array $options) { return self::buildMallSharePosterUrl($prefix, $options); } /** * 花材海报(商城散客) */ public static function buildMallItemPosterUrl($prefix, array $options) { return self::buildMallSharePosterUrl($prefix, $options); } /** * 花农端花店采购海报(ghs 花材详情太阳码) */ public static function buildGhsHdItemPosterUrl($prefix, array $options) { return self::buildMallSharePosterUrl($prefix, $options); } /** * 散客/花束分享海报:动态画布 + 主图槽位 + 底部信息区 */ private static function buildMallSharePosterUrl($prefix, array $options) { $cover = $options['cover'] ?? ''; $miniCode = $options['miniCode'] ?? ''; $priceText = $options['priceText'] ?? ''; $name = $options['name'] ?? ''; $staffText = $options['staffText'] ?? ''; $mainId = (int)($options['mainId'] ?? 0); $flowerNum = (int)($options['flowerNum'] ?? 0); $subtitle = trim((string)($options['subtitle'] ?? '')); $scanHint = trim((string)($options['scanHint'] ?? self::SCAN_HINT)); if ($scanHint === '微信扫码采购') { $scanHint = self::SCAN_HINT; } $coverW = (int)($options['coverWidth'] ?? 0); $coverH = (int)($options['coverHeight'] ?? 0); if ($coverW <= 0 || $coverH <= 0) { list($coverW, $coverH) = imgUtil::getOssImageSize($cover, $prefix); } $layout = self::calcPosterLayout($coverW, $coverH); $imgH = $layout['imgH']; $totalH = $layout['totalH']; $displayName = self::truncateText($name, 14); if ($flowerNum > 0 && $displayName !== '') { $displayName .= ' · ' . $flowerNum . '支'; } elseif ($subtitle !== '' && $displayName !== '') { $displayName .= ' · ' . self::truncateText($subtitle, 8); } $coverWatermark = self::buildCoverWatermarkPath($cover, $layout['scaledH']); $qrWatermark = $miniCode . '?x-oss-process=image/resize,m_fill,h_' . self::QR_SIZE . ',w_' . self::QR_SIZE; $url = self::buildCanvasBaseUrl($prefix, $totalH); $url .= '/watermark,image_' . stringUtil::ossBase64($coverWatermark) . ',g_nw,x_' . self::CANVAS_PAD_X . ',y_8'; $url .= '/watermark,image_' . stringUtil::ossBase64($qrWatermark) . ',g_se,x_' . self::QR_PAD_RIGHT . ',y_' . self::QR_PAD_BOTTOM; $logoB64 = self::buildHyxhLogoWatermark($mainId); if ($logoB64 !== '') { $url .= '/watermark,image_' . $logoB64 . ',g_se,x_210,y_48'; } $url .= '/watermark,text_' . stringUtil::ossBase64($priceText) . ',g_sw,x_' . self::CANVAS_PAD_X . ',y_32,color_EE2C2C,type_' . self::FONT . ',size_56'; $url .= '/watermark,text_' . stringUtil::ossBase64($displayName) . ',g_sw,x_' . self::CANVAS_PAD_X . ',y_102,color_333333,type_' . self::FONT . ',size_36'; $url .= '/watermark,text_' . stringUtil::ossBase64($staffText) . ',g_sw,x_' . self::CANVAS_PAD_X . ',y_148,color_999999,type_' . self::FONT . ',size_26'; $url .= '/watermark,text_' . stringUtil::ossBase64($scanHint) . ',g_south,x_' . self::qrCenterX() . ',y_' . self::scanHintYFromBottom() . ',color_888888,type_' . self::FONT . ',size_24'; return $url; } }