forked from gxwebsoft/mp-10550
feat(shop): 添加商品分享邀请功能
- 切换API基础URL到生产环境地址 - 在商品详情页添加邀请参数解析和存储逻辑 - 实现分享链接携带邀请者ID和来源信息 - 新增商品分享来源类型标识 - 在短信登录成功后处理待绑定的邀请关系 - 添加邀请关系跟踪和统计功能
This commit is contained in:
@@ -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',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -235,6 +235,7 @@ export function getSourceDisplayName(source: string): string {
|
|||||||
'qrcode': '小程序码',
|
'qrcode': '小程序码',
|
||||||
'link': '分享链接',
|
'link': '分享链接',
|
||||||
'share': '好友分享',
|
'share': '好友分享',
|
||||||
|
'goods_share': '商品分享',
|
||||||
'poster': '海报分享',
|
'poster': '海报分享',
|
||||||
'unknown': '未知来源'
|
'unknown': '未知来源'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user