Tigshop开源商城 分销推广海报后端怎么合成?带二维码的那种(附代码)
📅 2026/8/1 8:25:21
👁️ 阅读次数
📝 编程学习
分销这套做着做着,又追加进来一条需求:分销员要能生成带自己专属二维码的商品海报,发朋友圈那种,别人扫码进来买就算他的业绩。这功能在 tigshop 里也是 Pro 的,官网"推广海报"标着 (Pro),开源版没有。
海报合成本身不复杂,就是"底图 + 商品图 + 二维码 + 文字"四层叠一起。PHP 用 GD 或者 Intervention Image 都行,我用 Intervention,代码干净点。按生成流程一步步走。
装库
tigshop 是 composer 项目,直接加依赖,别手动塞 vendor:
cdphpcomposerrequire intervention/imagecomposerrequire endroid/qr-code生成分销员专属二维码
二维码里带上分销员 id,扫码进小程序或 H5 时能识别是谁推广的,参数拼进落地页 URL:
<?phpnamespaceapp\service\front\salesman;useEndroid\QrCode\QrCode;useEndroid\QrCode\Writer\PngWriter;classPosterService{// 生成带分销员标识的二维码,返回本地临时路径privatefunctionmakeQrcode(int$salesmanId,int$productId):string{$url=sprintf('https://你的域名/mobile/#/pages/product/detail?id=%d&sid=%d',$productId,$salesmanId);$result=(newPngWriter())->write(QrCode::create($url)->setSize(180));$path=runtime_path().'poster/qr_'.$salesmanId.'_'.$productId.'.png';$result->saveToFile($path);return$path;}}四层叠图
底图放一张固定模板到public/static/poster_bg.png,商品主图从product表拿,二维码用上一步的,文字写价格和标题。注意商品字段名,售价列是product_price,图叫pic_url,别写成price:
useIntervention\Image\ImageManager;useIntervention\Image\Drivers\Gd\Driver;publicfunctiongenerate(int$salesmanId,int$productId):string{$manager=newImageManager(newDriver());// 1) 底图$poster=$manager->read(public_path().'static/poster_bg.png');// 2) 商品主图(缩放后贴到顶部)$product=\app\model\product\Product::field('product_name,pic_url,product_price')->find($productId);$cover=$manager->read($product->pic_url)->resize(600,600);$poster->place($cover,'top-left',40,40);// 3) 二维码贴右下角$qr=$manager->read($this->makeQrcode($salesmanId,$productId));$poster->place($qr,'bottom-right',40,40);// 4) 文字:标题 + 价格$poster->text($product->product_name,60,700,function($font){$font->file(public_path().'static/fonts/SourceHan.ttf');$font->size(32);$font->color('#333333');});$poster->text('¥'.$product->product_price,60,760,function($font){$font->file(public_path().'static/fonts/SourceHan.ttf');$font->size(40);$font->color('#e4393c');});// 存到 public,也可以直接推 OSS$save='poster/'.$salesmanId.'_'.$productId.'_'.time().'.png';$poster->save(public_path().$save);return'/'.$save;}字体一定要带一个中文 ttf 进去。GD 默认字体打中文是乱码,这个坑我踩过,排查了半天才发现是字体的事。
给 C 端一个接口
照 tigshop 的 controller 风格,挂在 user 分组下,当前登录用户换算出他对应的分销员 id:
<?phpnamespaceapp\api\controller\user;useapp\api\IndexBaseController;useapp\service\front\salesman\PosterService;usethink\App;usethink\Response;classPosterextendsIndexBaseController{protectedPosterService$service;publicfunction__construct(App$app,PosterService$service){parent::__construct($app);$this->service=$service;}publicfunctionproduct():Response{$this->checkLogin();$productId=$this->request->all('product_id/d',0);$salesman=\app\model\salesman\Salesman::where('user_id',request()->userId)->find();if(!$salesman)return$this->error('你还不是分销员');$url=$this->service->generate($salesman->salesman_id,$productId);return$this->success(['poster_url'=>$url]);}}路由:
Route::group('poster',function(){Route::get('product','user.poster/product');})->middleware([\app\api\middleware\CheckLogin::class]);前端展示 + 保存
Uniapp 拿到 URL 直接显示,长按保存:
<script setup lang="ts"> import request from '@/utils/request' const poster = ref('') async function gen(productId: number) { poster.value = (await request.get('/api/user/poster/product', { product_id: productId })).data.poster_url } </script> <template> <image v-if="poster" :src="poster" show-menu-by-longpress mode="widthFix" /> </template>合成量大了怎么办
同一个分销员同一个商品,海报别每次都现合成。加个 Redis key 判断,存在就直接返回旧图,省 CPU。合成量再大就扔队列异步跑,tigshop 本身支持 redis 队列,别卡在同步请求里让用户干等。
到这,分销员发圈的海报就齐活了,配上返佣记录,一套轻量分销就凑出来了。要做完整的推广素材体系还是得上 Pro,但这个需求下,上面这些跑起来没问题。
编程学习
技术分享
实战经验