147 lines
4.9 KiB
PHP
147 lines
4.9 KiB
PHP
<?php
|
||
|
||
namespace app\api\controller;
|
||
|
||
use app\common\model\ShortLink;
|
||
use app\common\service\FileService;
|
||
use app\common\service\ShortLinkPosterDataService;
|
||
use app\common\service\ShortLinkQrCodeService;
|
||
|
||
class ShortLinkController extends BaseApiController
|
||
{
|
||
public array $notNeedLogin = ['resolve', 'create'];
|
||
|
||
/**
|
||
* @notes 创建短链接
|
||
*/
|
||
public function create()
|
||
{
|
||
$pageType = $this->request->post('page_type', '');
|
||
$pageId = $this->request->post('page_id', '');
|
||
$path = $this->request->post('path', '');
|
||
$inviteCode = $this->request->post('invite_code', '');
|
||
$clientTitle = trim((string) $this->request->post('title', ''));
|
||
$clientDesc = trim((string) $this->request->post('description', ''));
|
||
|
||
if (empty($pageType)) {
|
||
return $this->fail('参数错误');
|
||
}
|
||
|
||
$params = [];
|
||
if (!empty($inviteCode)) {
|
||
$params['invite_code'] = $inviteCode;
|
||
}
|
||
$paramsJson = !empty($params) ? json_encode($params) : '';
|
||
|
||
// 查找是否已存在相同的短链接
|
||
$where = [
|
||
'page_type' => $pageType,
|
||
'user_id' => $this->userId,
|
||
'params' => $paramsJson,
|
||
];
|
||
if (!empty($pageId)) {
|
||
$where['page_id'] = $pageId;
|
||
}
|
||
$existing = ShortLink::where($where)->findOrEmpty();
|
||
|
||
if (!$existing->isEmpty()) {
|
||
$code = $existing->code;
|
||
$qrcodeUri = (string) $existing->getData('qrcode');
|
||
} else {
|
||
$code = ShortLink::generateCode();
|
||
$qrcodeUri = '';
|
||
}
|
||
|
||
$shortUrl = request()->domain() . '/s/' . $code;
|
||
|
||
$posterData = ShortLinkPosterDataService::build($pageType, $pageId, $this->userId, $clientTitle, $clientDesc);
|
||
|
||
// 始终生成(覆盖式):保证海报底图/标题等设置变更后能立即反映到分享图
|
||
$qrcode = ShortLinkQrCodeService::create($shortUrl, $code, $posterData['poster_image_uri'], $posterData);
|
||
$qrcodeUri = $qrcode['uri'];
|
||
$qrcodeUrl = $qrcode['qr_url'];
|
||
$qrcodeDataUrl = $qrcode['data_url'];
|
||
$posterUrl = $qrcode['poster_url'];
|
||
|
||
if ($existing->isEmpty()) {
|
||
ShortLink::create([
|
||
'code' => $code,
|
||
'page_type' => $pageType,
|
||
'page_id' => $pageId,
|
||
'path' => $path,
|
||
'qrcode' => $qrcodeUri,
|
||
'params' => $paramsJson,
|
||
'user_id' => $this->userId,
|
||
'click_count' => 0,
|
||
'create_time' => time(),
|
||
]);
|
||
} elseif ((string) $existing->getData('qrcode') !== $qrcodeUri) {
|
||
$existing->qrcode = $qrcodeUri;
|
||
$existing->save();
|
||
}
|
||
|
||
$poster = [
|
||
'poster_image' => $posterData['poster_image'],
|
||
'poster_title' => $posterData['poster_title'],
|
||
'title' => $posterData['title'],
|
||
'description' => $posterData['description'],
|
||
'sharer' => $posterData['sharer'],
|
||
'poster_url' => $posterUrl, // 后端合成的完整海报图(背景+文字+二维码),前端可直接展示
|
||
];
|
||
|
||
return $this->data([
|
||
'short_url' => $shortUrl,
|
||
'code' => $code,
|
||
'qrcode_url' => $qrcodeUrl,
|
||
'qrcode_data' => $qrcodeDataUrl,
|
||
'poster_url' => $posterUrl,
|
||
'poster' => $poster,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* @notes 解析短链接并上报指纹(前端主页调用)
|
||
*/
|
||
public function resolve()
|
||
{
|
||
$code = $this->request->post('code', '');
|
||
if (empty($code)) {
|
||
return $this->fail('参数错误');
|
||
}
|
||
|
||
$link = ShortLink::where('code', $code)->findOrEmpty();
|
||
if ($link->isEmpty()) {
|
||
return $this->fail('链接不存在或已失效');
|
||
}
|
||
|
||
// 更新点击次数
|
||
$link->inc('click_count')->update();
|
||
|
||
// 记录访问日志(指纹+referer)
|
||
$fingerprint = $this->request->post('fingerprint', '');
|
||
$referer = $this->request->post('referer', '');
|
||
if (!empty($fingerprint)) {
|
||
$ua = request()->header('user-agent', '');
|
||
\app\common\model\ShortLinkLog::create([
|
||
'short_link_id' => $link->id,
|
||
'code' => $link->code,
|
||
'ip' => request()->ip(),
|
||
'user_agent' => mb_substr($ua, 0, 512),
|
||
'referer' => mb_substr($referer, 0, 512),
|
||
'fingerprint' => mb_substr($fingerprint, 0, 64),
|
||
'platform' => \app\common\model\ShortLinkLog::parsePlatform($ua),
|
||
'create_time' => time(),
|
||
]);
|
||
}
|
||
|
||
$params = !empty($link->params) ? json_decode($link->params, true) : [];
|
||
|
||
return $this->data([
|
||
'page_type' => $link->page_type,
|
||
'page_id' => $link->page_id,
|
||
'path' => $link->path,
|
||
'params' => $params,
|
||
]);
|
||
}
|
||
}
|