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, ]); } }