绑定邀请码
This commit is contained in:
parent
1cfa7e8322
commit
cdfe233ea8
@ -271,6 +271,10 @@ export function getUserInvites(user_id, page = 1, page_size = 20) {
|
|||||||
// 兼容性适配接口 (适配 pages/mine/index.vue)
|
// 兼容性适配接口 (适配 pages/mine/index.vue)
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
|
export function bindInviter(invite_code) {
|
||||||
|
return authRequest({ url: '/api/app/users/inviter/bind', method: 'POST', data: { invite_code } })
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 用户信息修改 API
|
// 用户信息修改 API
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
@ -157,6 +157,12 @@
|
|||||||
</view>
|
</view>
|
||||||
<text class="menu-label">任务中心</text>
|
<text class="menu-label">任务中心</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="menu-item" @click="showBindInviterPopup" v-if="!inviterId">
|
||||||
|
<view class="menu-icon-box">
|
||||||
|
<image class="menu-icon-img" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik0xMCAxMyxhNSw1IDAgMCwwIDcuNTQsLjU0bDMtM2E1LDUgMCAwLDAgLTcuMDctNy4wN2wtMS43MiwxLjcxIiAvPjxwYXRoIGQ9Ik0xNCAxMSxhNSw1IDAgMCwwIC03LjU0LC0uNTRsLTMsM2E1LDUgMCAwLDAgNy4wNyw3LjA3bDEuNzIsLTEuNzEiIC8+PC9zdmc+" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<text class="menu-label">填写邀请码</text>
|
||||||
|
</view>
|
||||||
<view class="menu-item" @click="toInvitesPage">
|
<view class="menu-item" @click="toInvitesPage">
|
||||||
<view class="menu-icon-box">
|
<view class="menu-icon-box">
|
||||||
<image class="menu-icon-img" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDdhNCA0IDAgMCAwLTQgNHYyIj48L3BhdGg+PGNpcmNsZSBjeD0iMTAiIGN5PSI3IiByPSI0Ij48L2NpcmNsZT48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy4yNyI+PC9wYXRoPjxwYXRoIGQ9Ik0xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiPjwvcGF0aD48L3N2Zz4=" mode="aspectFit"></image>
|
<image class="menu-icon-img" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDdhNCA0IDAgMCAwLTQgNHYyIj48L3BhdGg+PGNpcmNsZSBjeD0iMTAiIGN5PSI3IiByPSI0Ij48L2NpcmNsZT48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy4yNyI+PC9wYXRoPjxwYXRoIGQ9Ik0xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiPjwvcGF0aD48L3N2Zz4=" mode="aspectFit"></image>
|
||||||
@ -492,13 +498,31 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 绑定邀请码弹窗 -->
|
||||||
|
<view class="popup-mask" v-if="bindInviterVisible" @tap="closeBindInviterPopup">
|
||||||
|
<view class="popup-content bind-inviter-popup" @tap.stop>
|
||||||
|
<view class="popup-header">
|
||||||
|
<text class="popup-title">填写邀请码</text>
|
||||||
|
<text class="close-btn" @tap="closeBindInviterPopup">×</text>
|
||||||
|
</view>
|
||||||
|
<view class="bind-inviter-body">
|
||||||
|
<view class="bind-desc">请输入好友的邀请码,绑定后双方可获得奖励</view>
|
||||||
|
<view class="input-wrapper">
|
||||||
|
<input type="text" v-model="bindInviteCode" class="invite-code-input" placeholder="请输入邀请码" placeholder-class="input-placeholder" />
|
||||||
|
</view>
|
||||||
|
<button class="bind-btn" @tap="handleBindInviter">确认绑定</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
getUserInfo, getUserStats, getPointsBalance, getUserPoints, getUserCoupons, getItemCards,
|
getUserInfo, getUserStats, getPointsBalance, getUserPoints, getUserCoupons, getItemCards,
|
||||||
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile, bindDouyinID, getPublicConfig
|
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile, bindDouyinID, getPublicConfig,
|
||||||
|
bindInviter
|
||||||
} from '../../api/appUser.js'
|
} from '../../api/appUser.js'
|
||||||
import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
|
import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
|
||||||
// #ifdef MP-TOUTIAO
|
// #ifdef MP-TOUTIAO
|
||||||
@ -511,7 +535,7 @@ import customTabBar from '@/components/app-tab-bar.vue'
|
|||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
// #ifdef MP-TOUTIAO
|
// #ifdef MP-TOUTIAO
|
||||||
customTabBarToutiao
|
customTabBarToutiao,
|
||||||
// #endif
|
// #endif
|
||||||
// #ifndef MP-TOUTIAO
|
// #ifndef MP-TOUTIAO
|
||||||
customTabBar
|
customTabBar
|
||||||
@ -524,9 +548,16 @@ export default {
|
|||||||
avatar: '',
|
avatar: '',
|
||||||
title: '', // 用户头衔
|
title: '', // 用户头衔
|
||||||
inviteCode: '',
|
inviteCode: '',
|
||||||
|
inviterId: 0,
|
||||||
|
inviterNickname: '',
|
||||||
|
inviterAvatar: '',
|
||||||
|
|
||||||
|
// Bind Inviter Popup
|
||||||
|
bindInviterVisible: false,
|
||||||
|
bindInviteCode: '',
|
||||||
|
|
||||||
mobile: '', // 手机号
|
mobile: '', // 手机号
|
||||||
douyinUserId: '', // 抖音用户ID
|
douyinUserId: '', // 抖音用户ID
|
||||||
douyinUserId: '', // 抖音用户ID
|
|
||||||
customerServiceQrCode: '', // 客服二维码
|
customerServiceQrCode: '', // 客服二维码
|
||||||
customerServiceId: '0071112x', // 抖音IM客服账号
|
customerServiceId: '0071112x', // 抖音IM客服账号
|
||||||
pointsBalance: 0,
|
pointsBalance: 0,
|
||||||
@ -854,6 +885,9 @@ export default {
|
|||||||
this.avatar = profile.avatar
|
this.avatar = profile.avatar
|
||||||
this.title = profile.title || ''
|
this.title = profile.title || ''
|
||||||
this.inviteCode = profile.invite_code
|
this.inviteCode = profile.invite_code
|
||||||
|
this.inviterId = profile.inviter_id || 0
|
||||||
|
this.inviterNickname = profile.inviter_nickname || ''
|
||||||
|
this.inviterAvatar = profile.inviter_avatar || ''
|
||||||
this.pointsBalance = this.normalizePointsBalance(profile.balance)
|
this.pointsBalance = this.normalizePointsBalance(profile.balance)
|
||||||
this.mobile = profile.mobile || ''
|
this.mobile = profile.mobile || ''
|
||||||
this.douyinUserId = profile.douyin_user_id || ''
|
this.douyinUserId = profile.douyin_user_id || ''
|
||||||
@ -865,6 +899,9 @@ export default {
|
|||||||
cachedUser.avatar = profile.avatar
|
cachedUser.avatar = profile.avatar
|
||||||
cachedUser.title = profile.title
|
cachedUser.title = profile.title
|
||||||
cachedUser.invite_code = profile.invite_code
|
cachedUser.invite_code = profile.invite_code
|
||||||
|
cachedUser.inviter_id = profile.inviter_id
|
||||||
|
cachedUser.inviter_nickname = profile.inviter_nickname
|
||||||
|
cachedUser.inviter_avatar = profile.inviter_avatar
|
||||||
cachedUser.mobile = profile.mobile
|
cachedUser.mobile = profile.mobile
|
||||||
cachedUser.points_balance = this.pointsBalance
|
cachedUser.points_balance = this.pointsBalance
|
||||||
uni.setStorageSync('user_info', cachedUser)
|
uni.setStorageSync('user_info', cachedUser)
|
||||||
@ -882,9 +919,12 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 降级到旧逻辑
|
// 降级到旧逻辑 (通常不会走到这里,除非 API 挂了)
|
||||||
|
// ... (省略部分降级代码,或者保持原样)
|
||||||
|
// 简单起见,如果 profile 失败,降级逻辑里可能拿不到 inviterId,
|
||||||
|
// 但为了保持健壮性,这里保留原有的逻辑,只是不再去更新 inviterId(因为旧逻辑拿不到)
|
||||||
|
|
||||||
console.log('[Mine] profile API 无数据,使用降级逻辑')
|
console.log('[Mine] profile API 无数据,使用降级逻辑')
|
||||||
// 先尝试从缓存获取基础信息
|
|
||||||
const cachedUser = uni.getStorageSync('user_info')
|
const cachedUser = uni.getStorageSync('user_info')
|
||||||
const cachedUserId = uni.getStorageSync('user_id')
|
const cachedUserId = uni.getStorageSync('user_id')
|
||||||
|
|
||||||
@ -893,6 +933,11 @@ export default {
|
|||||||
this.nickname = cachedUser.nickname
|
this.nickname = cachedUser.nickname
|
||||||
this.avatar = cachedUser.avatar
|
this.avatar = cachedUser.avatar
|
||||||
this.inviteCode = cachedUser.invite_code
|
this.inviteCode = cachedUser.invite_code
|
||||||
|
// 缓存里可能有 inviter 信息
|
||||||
|
this.inviterId = cachedUser.inviter_id || 0
|
||||||
|
this.inviterNickname = cachedUser.inviter_nickname || ''
|
||||||
|
this.inviterAvatar = cachedUser.inviter_avatar || ''
|
||||||
|
|
||||||
this.title = cachedUser.title || ''
|
this.title = cachedUser.title || ''
|
||||||
this.pointsBalance = this.normalizePointsBalance(cachedUser.points_balance)
|
this.pointsBalance = this.normalizePointsBalance(cachedUser.points_balance)
|
||||||
this.mobile = cachedUser.mobile || cachedUser.phone || cachedUser.phone_number || ''
|
this.mobile = cachedUser.mobile || cachedUser.phone || cachedUser.phone_number || ''
|
||||||
@ -900,44 +945,51 @@ export default {
|
|||||||
} else if (cachedUserId) {
|
} else if (cachedUserId) {
|
||||||
this.userId = cachedUserId
|
this.userId = cachedUserId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ... 继续原有加载 stats 逻辑
|
||||||
if (this.userId) {
|
if (this.userId) {
|
||||||
try {
|
const s = await getUserStats(this.userId)
|
||||||
const balanceRes = await getPointsBalance(this.userId)
|
if (s) this.stats = { ...this.stats, ...s }
|
||||||
if (balanceRes !== undefined) {
|
|
||||||
this.pointsBalance = this.normalizePointsBalance(balanceRes)
|
|
||||||
if (cachedUser) {
|
|
||||||
cachedUser.points_balance = this.pointsBalance
|
|
||||||
uni.setStorageSync('user_info', cachedUser)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
const s = await getUserStats(this.userId)
|
|
||||||
if (s) this.stats = { ...this.stats, ...s }
|
|
||||||
} else {
|
|
||||||
// 如果没有 userId,尝试调用 getUserInfo (即使可能失败)
|
|
||||||
const res = await getUserInfo()
|
|
||||||
if (res) {
|
|
||||||
this.userId = res.id
|
|
||||||
this.nickname = res.nickname
|
|
||||||
this.avatar = res.avatar
|
|
||||||
this.title = res.title || res.level_name || ''
|
|
||||||
this.inviteCode = res.invite_code
|
|
||||||
this.pointsBalance = this.normalizePointsBalance(res.points_balance)
|
|
||||||
this.mobile = res.mobile || res.phone || res.phone_number || ''
|
|
||||||
this.douyinUserId = res.douyin_user_id || ''
|
|
||||||
uni.setStorageSync('user_info', res)
|
|
||||||
uni.setStorageSync('user_id', res.id)
|
|
||||||
|
|
||||||
// Load stats
|
|
||||||
const s = await getUserStats(res.id)
|
|
||||||
if(s) this.stats = { ...this.stats, ...s }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[Mine] loadUserInfo 错误:', e)
|
console.error('[Mine] loadUserInfo 错误:', e)
|
||||||
// If 401, maybe clear token
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showBindInviterPopup() {
|
||||||
|
if (!this.checkPhoneBound()) return
|
||||||
|
this.bindInviteCode = ''
|
||||||
|
this.bindInviterVisible = true
|
||||||
|
},
|
||||||
|
|
||||||
|
closeBindInviterPopup() {
|
||||||
|
this.bindInviterVisible = false
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleBindInviter() {
|
||||||
|
const code = this.bindInviteCode.trim()
|
||||||
|
if (!code) {
|
||||||
|
uni.showToast({ title: '请输入邀请码', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 不允许绑定自己
|
||||||
|
if (code === this.inviteCode) {
|
||||||
|
uni.showToast({ title: '不能绑定自己的邀请码', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
uni.showLoading({ title: '绑定中...' })
|
||||||
|
await bindInviter(code)
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '绑定成功', icon: 'success' })
|
||||||
|
this.bindInviterVisible = false
|
||||||
|
// 刷新用户信息,获取已绑定的邀请人信息
|
||||||
|
this.loadUserInfo()
|
||||||
|
} catch (err) {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: err.message || '绑定失败', icon: 'none' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resetUser() {
|
resetUser() {
|
||||||
@ -2271,6 +2323,58 @@ export default {
|
|||||||
.invite-time { font-size: 22rpx; color: $text-tertiary; margin-top: 4rpx; }
|
.invite-time { font-size: 22rpx; color: $text-tertiary; margin-top: 4rpx; }
|
||||||
.invite-status { font-size: 24rpx; color: #10B981; }
|
.invite-status { font-size: 24rpx; color: #10B981; }
|
||||||
|
|
||||||
|
/* 绑定邀请码弹窗 */
|
||||||
|
.bind-inviter-popup {
|
||||||
|
width: 600rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.bind-inviter-body {
|
||||||
|
padding: 40rpx 30rpx 50rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.bind-desc {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.input-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
background: #F5F7FA;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-bottom: 50rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid #EBEEF5;
|
||||||
|
}
|
||||||
|
.invite-code-input {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
height: 48rpx;
|
||||||
|
line-height: 48rpx;
|
||||||
|
}
|
||||||
|
.bind-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
background: linear-gradient(135deg, #FF6B00 0%, #FF9500 100%);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
}
|
||||||
|
.bind-btn:active {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||||
@keyframes zoomIn { from { transform: scale(0.9); opacity: 0; } to { transform: scale(1); opacity: 1; } }
|
@keyframes zoomIn { from { transform: scale(0.9); opacity: 0; } to { transform: scale(1); opacity: 1; } }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const BASE_URL = 'https://kdy.1024tool.vip'
|
const BASE_URL = 'http://127.0.0.1:9991'
|
||||||
|
|
||||||
let authModalShown = false
|
let authModalShown = false
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user