feat(shop): 添加商品分享邀请功能

- 切换API基础URL到生产环境地址
- 在商品详情页添加邀请参数解析和存储逻辑
- 实现分享链接携带邀请者ID和来源信息
- 新增商品分享来源类型标识
- 在短信登录成功后处理待绑定的邀请关系
- 添加邀请关系跟踪和统计功能
This commit is contained in:
2026-01-20 15:18:48 +08:00
parent 415e05cc4e
commit 0d6eb331c8
4 changed files with 39 additions and 3 deletions

View File

@@ -2,8 +2,8 @@
export const ENV_CONFIG = { export const ENV_CONFIG = {
// 开发环境 // 开发环境
development: { development: {
API_BASE_URL: 'http://127.0.0.1:9200/api', // API_BASE_URL: 'http://127.0.0.1:9200/api',
// API_BASE_URL: 'https://cms-api.websoft.top/api', API_BASE_URL: 'https://cms-api.websoft.top/api',
APP_NAME: '开发环境', APP_NAME: '开发环境',
DEBUG: 'true', DEBUG: 'true',
}, },

View File

@@ -3,6 +3,7 @@ import Taro from '@tarojs/taro'
import {Input, Button} from '@nutui/nutui-react-taro' import {Input, Button} from '@nutui/nutui-react-taro'
import {loginBySms, sendSmsCaptcha} from "@/api/passport/login"; import {loginBySms, sendSmsCaptcha} from "@/api/passport/login";
import {LoginParam} from "@/api/passport/login/model"; import {LoginParam} from "@/api/passport/login/model";
import {checkAndHandleInviteRelation, hasPendingInvite} from "@/utils/invite";
const SmsLogin = () => { const SmsLogin = () => {
const [loading, setLoading] = useState<boolean>(false) const [loading, setLoading] = useState<boolean>(false)
@@ -131,6 +132,15 @@ const SmsLogin = () => {
code: formData.code code: formData.code
}) })
// 登录成功后(可能是新注册用户),检查是否存在待处理的邀请关系并尝试绑定
if (hasPendingInvite()) {
try {
await checkAndHandleInviteRelation()
} catch (e) {
console.error('短信登录后处理邀请关系失败:', e)
}
}
Taro.showToast({ Taro.showToast({
title: '登录成功', title: '登录成功',
icon: 'success' icon: 'success'

View File

@@ -15,6 +15,7 @@ import SpecSelector from "@/components/SpecSelector";
import "./index.scss"; import "./index.scss";
import {useCart} from "@/hooks/useCart"; import {useCart} from "@/hooks/useCart";
import {useConfig} from "@/hooks/useConfig"; import {useConfig} from "@/hooks/useConfig";
import {parseInviteParams, saveInviteParams, trackInviteSource} from "@/utils/invite";
const GoodsDetail = () => { const GoodsDetail = () => {
const [statusBarHeight, setStatusBarHeight] = useState<number>(44); const [statusBarHeight, setStatusBarHeight] = useState<number>(44);
@@ -39,6 +40,24 @@ const GoodsDetail = () => {
const {cartCount, addToCart} = useCart() const {cartCount, addToCart} = useCart()
const {config} = useConfig() const {config} = useConfig()
// 如果从分享链接进入(携带 inviter/source/t且当前未登录则暂存邀请信息用于注册后绑定关系
useEffect(() => {
try {
const currentUserId = Taro.getStorageSync('UserId')
if (currentUserId) return
const inviteParams = parseInviteParams({query: router?.params})
if (inviteParams?.inviter) {
saveInviteParams(inviteParams)
trackInviteSource(inviteParams.source || 'share', parseInt(inviteParams.inviter))
}
} catch (e) {
// 邀请参数解析/存储失败不影响正常浏览商品
console.error('商品详情页处理邀请参数失败:', e)
}
// router 在 Taro 中可能不稳定;这里仅在 goodsId 变化时尝试处理一次即可
}, [goodsId])
// 处理加入购物车 // 处理加入购物车
const handleAddToCart = () => { const handleAddToCart = () => {
if (!goods) return; if (!goods) return;
@@ -186,9 +205,15 @@ const GoodsDetail = () => {
// 分享给好友 // 分享给好友
useShareAppMessage(() => { useShareAppMessage(() => {
const inviter = Taro.getStorageSync('UserId')
const sharePath =
inviter
? `/shop/goodsDetail/index?id=${goodsId}&inviter=${inviter}&source=goods_share&t=${Date.now()}`
: `/shop/goodsDetail/index?id=${goodsId}`
return { return {
title: goods?.name || '精选商品', title: goods?.name || '精选商品',
path: `/shop/goodsDetail/index?id=${goodsId}`, path: sharePath,
imageUrl: goods?.image ? `${goods.image}?x-oss-process=image/resize,w_500,h_400,m_fill` : undefined, // 分享图片调整为5:4比例 imageUrl: goods?.image ? `${goods.image}?x-oss-process=image/resize,w_500,h_400,m_fill` : undefined, // 分享图片调整为5:4比例
success: function (res: any) { success: function (res: any) {
console.log('分享成功', res); console.log('分享成功', res);

View File

@@ -235,6 +235,7 @@ export function getSourceDisplayName(source: string): string {
'qrcode': '小程序码', 'qrcode': '小程序码',
'link': '分享链接', 'link': '分享链接',
'share': '好友分享', 'share': '好友分享',
'goods_share': '商品分享',
'poster': '海报分享', 'poster': '海报分享',
'unknown': '未知来源' 'unknown': '未知来源'
} }