feat: 添加抖音订单绑定功能并改进RPC日志。

This commit is contained in:
邹方成 2026-01-05 01:09:47 +08:00
parent bcbb18a939
commit 237d785a4f
4 changed files with 114 additions and 41 deletions

View File

@ -372,3 +372,10 @@ export function purchaseGamePass(package_id, count = 1) {
return authRequest({ url: '/api/app/game-passes/purchase', method: 'POST', data: { package_id, count } })
}
/**
* 绑定抖音订单获取抖音用户ID
* @param {string} shop_order_id - 抖音订单号
*/
export function bindDouyinOrder(order_id) {
return authRequest({ url: '/api/app/users/douyin/bind-order', method: 'POST', data: { order_id } })
}

View File

@ -181,6 +181,12 @@
</view>
<text class="menu-label">帮助中心</text>
</view>
<view class="menu-item" @click="toBindDouyinOrder">
<view class="menu-icon-box">
<image class="menu-icon-img" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik05IDExVjlhMyAzIDAgMCAxIDMtM2g0YTMgMyAwIDAgMSAzIDN2Mm0tMTAtM2gtNGEzIDMgMCAwIDAtMyAzdi04YTIgMiAwIDAgMSAyLTJoMTRhMiAyIDAgMCAxIDIgMnY4YTIgMiAwIDAgMS0yIDJoLTRhMyAzIDAgMCAxLTMtM3oiLz48Y2lyY2xlIGN4PSIxMiIgY3k9IjEzIiByPSIzIi8+PC9zdmc+" mode="aspectFit"></image>
</view>
<text class="menu-label">{{ douyinUserId ? '已绑定' : '绑定订单' }}</text>
</view>
</view>
</view>
@ -468,7 +474,7 @@
<script>
import {
getUserInfo, getUserStats, getPointsBalance, getUserPoints, getUserCoupons, getItemCards,
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile, bindDouyinOrder
} from '../../api/appUser.js'
import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
@ -481,6 +487,7 @@ export default {
title: '', //
inviteCode: '',
mobile: '', //
douyinUserId: '', // ID
pointsBalance: 0,
stats: {
@ -792,6 +799,7 @@ export default {
this.inviteCode = profile.invite_code
this.pointsBalance = this.normalizePointsBalance(profile.balance)
this.mobile = profile.mobile || ''
this.douyinUserId = profile.douyin_user_id || ''
//
const cachedUser = uni.getStorageSync('user_info') || {}
@ -831,6 +839,7 @@ export default {
this.title = cachedUser.title || ''
this.pointsBalance = this.normalizePointsBalance(cachedUser.points_balance)
this.mobile = cachedUser.mobile || cachedUser.phone || cachedUser.phone_number || ''
this.douyinUserId = cachedUser.douyin_user_id || ''
} else if (cachedUserId) {
this.userId = cachedUserId
}
@ -860,6 +869,7 @@ export default {
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)
@ -879,6 +889,7 @@ export default {
this.avatar = ''
this.title = ''
this.pointsBalance = 0
this.douyinUserId = ''
this.stats = { coupon_count: 0, item_card_count: 0 }
},
handleJoin() {
@ -933,6 +944,50 @@ export default {
}
})
},
toBindDouyinOrder() {
if (!this.checkPhoneBound()) return
//
if (this.douyinUserId) {
uni.showToast({
title: '您已绑定抖音账号,暂不支持换绑',
icon: 'none'
})
return
}
uni.showModal({
title: '绑定抖音订单',
editable: true,
placeholderText: '请输入抖音订单号',
success: async (res) => {
if (res.confirm) {
const orderId = res.content?.trim()
if (!orderId) {
uni.showToast({ title: '订单号不能为空', icon: 'none' })
return
}
try {
uni.showLoading({ title: '绑定中...' })
const data = await bindDouyinOrder(orderId)
this.douyinUserId = data.douyin_user_id
//
const userInfo = uni.getStorageSync('user_info') || {}
userInfo.douyin_user_id = data.douyin_user_id
uni.setStorageSync('user_info', userInfo)
uni.hideLoading()
uni.showToast({ title: '绑定成功', icon: 'success' })
} catch (err) {
uni.hideLoading()
uni.showToast({ title: err.message || '绑定失败', icon: 'none' })
}
}
}
})
},
handleInvite() {
const code = this.getInviteCode()
const path = this.getInviteSharePath()

View File

@ -192,7 +192,10 @@ $uni-font-size-paragraph: 15px;
/* 1. 统一背景装饰 - 漂浮光球 */
.bg-decoration {
position: fixed;
top: 0; left: 0; width: 100%; height: 100%;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 0;
overflow: hidden;
@ -200,8 +203,10 @@ $uni-font-size-paragraph: 15px;
&::before {
content: '';
position: absolute;
top: -100rpx; right: -100rpx;
width: 600rpx; height: 600rpx;
top: -100rpx;
right: -100rpx;
width: 600rpx;
height: 600rpx;
background: radial-gradient(circle, rgba($brand-primary, 0.15) 0%, transparent 70%);
filter: blur(60rpx);
border-radius: 50%;
@ -212,8 +217,10 @@ $uni-font-size-paragraph: 15px;
&::after {
content: '';
position: absolute;
top: 200rpx; left: -200rpx;
width: 500rpx; height: 500rpx;
top: 200rpx;
left: -200rpx;
width: 500rpx;
height: 500rpx;
background: radial-gradient(circle, rgba($brand-secondary, 0.1) 0%, transparent 70%);
filter: blur(50rpx);
border-radius: 50%;

View File

@ -361,9 +361,13 @@ class NakamaManager {
}
});
console.log('[Nakama] RPC response:', id, response);
if (response.rpc && response.rpc.payload) {
try {
return JSON.parse(response.rpc.payload);
const parsed = JSON.parse(response.rpc.payload);
console.log('[Nakama] RPC parsed result:', id, parsed);
return parsed;
} catch (e) {
return response.rpc.payload;
}