feat: 添加抖音订单绑定功能并改进RPC日志。
This commit is contained in:
parent
bcbb18a939
commit
237d785a4f
@ -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 } })
|
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 } })
|
||||||
|
}
|
||||||
|
|||||||
@ -175,12 +175,18 @@
|
|||||||
</view>
|
</view>
|
||||||
<text class="menu-label">收货地址</text>
|
<text class="menu-label">收货地址</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="menu-item" @click="toHelp">
|
<view class="menu-item" @click="toHelp">
|
||||||
<view class="menu-icon-box">
|
<view class="menu-icon-box">
|
||||||
<image class="menu-icon-img" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEwIi8+PHBhdGggZD0iTTkuMDkgOWEzIDMgMCAwIDEgNS44MyAxYzAgMi0zIDMtMyAzIi8+PHBhdGggZD0iTTEyIDE3aC4wMSIvPjwvc3ZnPg==" mode="aspectFit"></image>
|
<image class="menu-icon-img" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEwIi8+PHBhdGggZD0iTTkuMDkgOWEzIDMgMCAwIDEgNS44MyAxYzAgMi0zIDMtMyAzIi8+PHBhdGggZD0iTTEyIDE3aC4wMSIvPjwvc3ZnPg==" mode="aspectFit"></image>
|
||||||
</view>
|
</view>
|
||||||
<text class="menu-label">帮助中心</text>
|
<text class="menu-label">帮助中心</text>
|
||||||
</view>
|
</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>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -468,7 +474,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
getUserInfo, getUserStats, getPointsBalance, getUserPoints, getUserCoupons, getItemCards,
|
getUserInfo, getUserStats, getPointsBalance, getUserPoints, getUserCoupons, getItemCards,
|
||||||
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile
|
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile, bindDouyinOrder
|
||||||
} from '../../api/appUser.js'
|
} from '../../api/appUser.js'
|
||||||
import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
|
import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
|
||||||
|
|
||||||
@ -481,6 +487,7 @@ export default {
|
|||||||
title: '', // 用户头衔
|
title: '', // 用户头衔
|
||||||
inviteCode: '',
|
inviteCode: '',
|
||||||
mobile: '', // 手机号
|
mobile: '', // 手机号
|
||||||
|
douyinUserId: '', // 抖音用户ID
|
||||||
pointsBalance: 0,
|
pointsBalance: 0,
|
||||||
|
|
||||||
stats: {
|
stats: {
|
||||||
@ -792,6 +799,7 @@ export default {
|
|||||||
this.inviteCode = profile.invite_code
|
this.inviteCode = profile.invite_code
|
||||||
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 || ''
|
||||||
|
|
||||||
// 更新缓存
|
// 更新缓存
|
||||||
const cachedUser = uni.getStorageSync('user_info') || {}
|
const cachedUser = uni.getStorageSync('user_info') || {}
|
||||||
@ -831,6 +839,7 @@ export default {
|
|||||||
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 || ''
|
||||||
|
this.douyinUserId = cachedUser.douyin_user_id || ''
|
||||||
} else if (cachedUserId) {
|
} else if (cachedUserId) {
|
||||||
this.userId = cachedUserId
|
this.userId = cachedUserId
|
||||||
}
|
}
|
||||||
@ -860,6 +869,7 @@ export default {
|
|||||||
this.inviteCode = res.invite_code
|
this.inviteCode = res.invite_code
|
||||||
this.pointsBalance = this.normalizePointsBalance(res.points_balance)
|
this.pointsBalance = this.normalizePointsBalance(res.points_balance)
|
||||||
this.mobile = res.mobile || res.phone || res.phone_number || ''
|
this.mobile = res.mobile || res.phone || res.phone_number || ''
|
||||||
|
this.douyinUserId = res.douyin_user_id || ''
|
||||||
uni.setStorageSync('user_info', res)
|
uni.setStorageSync('user_info', res)
|
||||||
uni.setStorageSync('user_id', res.id)
|
uni.setStorageSync('user_id', res.id)
|
||||||
|
|
||||||
@ -879,6 +889,7 @@ export default {
|
|||||||
this.avatar = ''
|
this.avatar = ''
|
||||||
this.title = ''
|
this.title = ''
|
||||||
this.pointsBalance = 0
|
this.pointsBalance = 0
|
||||||
|
this.douyinUserId = ''
|
||||||
this.stats = { coupon_count: 0, item_card_count: 0 }
|
this.stats = { coupon_count: 0, item_card_count: 0 }
|
||||||
},
|
},
|
||||||
handleJoin() {
|
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() {
|
handleInvite() {
|
||||||
const code = this.getInviteCode()
|
const code = this.getInviteCode()
|
||||||
const path = this.getInviteSharePath()
|
const path = this.getInviteSharePath()
|
||||||
|
|||||||
73
uni.scss
73
uni.scss
@ -10,38 +10,38 @@
|
|||||||
============================================ */
|
============================================ */
|
||||||
|
|
||||||
/* 主色调 - 更加活力与现代 */
|
/* 主色调 - 更加活力与现代 */
|
||||||
$brand-primary: #FF6B00; // 核心品牌橙 (更纯粹)
|
$brand-primary: #FF6B00; // 核心品牌橙 (更纯粹)
|
||||||
$brand-secondary: #FF9500; // 次级品牌色 (用于渐变/辅助)
|
$brand-secondary: #FF9500; // 次级品牌色 (用于渐变/辅助)
|
||||||
$brand-primary-light: #FF9500; // 亮橙
|
$brand-primary-light: #FF9500; // 亮橙
|
||||||
$brand-primary-dark: #E65100; // 深橙
|
$brand-primary-dark: #E65100; // 深橙
|
||||||
|
|
||||||
/* 辅助色 - 丰富视觉层次 */
|
/* 辅助色 - 丰富视觉层次 */
|
||||||
$accent-gold: #FFC107; // 质感金
|
$accent-gold: #FFC107; // 质感金
|
||||||
$accent-orange: #FF9500; // 活力橙
|
$accent-orange: #FF9500; // 活力橙
|
||||||
$accent-red: #FF3B30; // 促销红
|
$accent-red: #FF3B30; // 促销红
|
||||||
$accent-blue: #007AFF; // 科技蓝
|
$accent-blue: #007AFF; // 科技蓝
|
||||||
$accent-purple: #AF52DE; // 梦幻紫
|
$accent-purple: #AF52DE; // 梦幻紫
|
||||||
$accent-pink: #FF2D55; // 活力粉
|
$accent-pink: #FF2D55; // 活力粉
|
||||||
$accent-cyan: #5AC8FA; // 清新蓝
|
$accent-cyan: #5AC8FA; // 清新蓝
|
||||||
$color-success: #34C759; // 成功色
|
$color-success: #34C759; // 成功色
|
||||||
$color-warning: #FF9F0A; // 警告色
|
$color-warning: #FF9F0A; // 警告色
|
||||||
$color-error: #FF3B30; // 错误色
|
$color-error: #FF3B30; // 错误色
|
||||||
|
|
||||||
/* 中性色 - 提升阅读体验 */
|
/* 中性色 - 提升阅读体验 */
|
||||||
$text-main: #1D1D1F; // 主要文字 (接近纯黑但柔和)
|
$text-main: #1D1D1F; // 主要文字 (接近纯黑但柔和)
|
||||||
$text-sub: #86868B; // 次要文字
|
$text-sub: #86868B; // 次要文字
|
||||||
$text-secondary: $text-sub; // Alias for compatibility
|
$text-secondary: $text-sub; // Alias for compatibility
|
||||||
$text-tertiary: #C7C7CC; // 辅助/占位
|
$text-tertiary: #C7C7CC; // 辅助/占位
|
||||||
$text-placeholder: $text-tertiary; // Alias for compatibility
|
$text-placeholder: $text-tertiary; // Alias for compatibility
|
||||||
$text-disabled: #D1D1D6; // 禁用状态文字
|
$text-disabled: #D1D1D6; // 禁用状态文字
|
||||||
$text-inverse: #FFFFFF; // 反白文字
|
$text-inverse: #FFFFFF; // 反白文字
|
||||||
|
|
||||||
/* 背景色 - 营造氛围 */
|
/* 背景色 - 营造氛围 */
|
||||||
$bg-page: #F5F5F7; // 页面底色 (高级灰)
|
$bg-page: #F5F5F7; // 页面底色 (高级灰)
|
||||||
$bg-card: #FFFFFF; // 卡片背景
|
$bg-card: #FFFFFF; // 卡片背景
|
||||||
$bg-glass: rgba(255, 255, 255, 0.8); // 毛玻璃背景
|
$bg-glass: rgba(255, 255, 255, 0.8); // 毛玻璃背景
|
||||||
$bg-secondary: #F8F8F8; // 次级背景
|
$bg-secondary: #F8F8F8; // 次级背景
|
||||||
$bg-grey: #FAFAFA; // 浅灰背景
|
$bg-grey: #FAFAFA; // 浅灰背景
|
||||||
|
|
||||||
/* 渐变色 - 视觉冲击力 */
|
/* 渐变色 - 视觉冲击力 */
|
||||||
// 使用 CSS 变量在 style 中定义,此处保留 SCSS 变量供编译使用
|
// 使用 CSS 变量在 style 中定义,此处保留 SCSS 变量供编译使用
|
||||||
@ -53,11 +53,11 @@ $gradient-purple: linear-gradient(135deg, #BF5AF2 0%, #5E5CE6 100%);
|
|||||||
/* ============================================
|
/* ============================================
|
||||||
🌑 暗黑/特殊主题变量 (Dark Mode Support)
|
🌑 暗黑/特殊主题变量 (Dark Mode Support)
|
||||||
============================================ */
|
============================================ */
|
||||||
$bg-dark: #1A1A2E; // 深邃蓝黑
|
$bg-dark: #1A1A2E; // 深邃蓝黑
|
||||||
$bg-dark-card: rgba(30, 30, 50, 0.7); // 暗色玻璃卡片
|
$bg-dark-card: rgba(30, 30, 50, 0.7); // 暗色玻璃卡片
|
||||||
$text-dark-main: #FFFFFF; // 暗色模式主字
|
$text-dark-main: #FFFFFF; // 暗色模式主字
|
||||||
$text-dark-sub: rgba(255, 255, 255, 0.7); // 暗色模式副字
|
$text-dark-sub: rgba(255, 255, 255, 0.7); // 暗色模式副字
|
||||||
$border-dark: rgba(255, 255, 255, 0.1); // 暗色边框
|
$border-dark: rgba(255, 255, 255, 0.1); // 暗色边框
|
||||||
|
|
||||||
|
|
||||||
/* ============================================
|
/* ============================================
|
||||||
@ -192,7 +192,10 @@ $uni-font-size-paragraph: 15px;
|
|||||||
/* 1. 统一背景装饰 - 漂浮光球 */
|
/* 1. 统一背景装饰 - 漂浮光球 */
|
||||||
.bg-decoration {
|
.bg-decoration {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0; left: 0; width: 100%; height: 100%;
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -200,8 +203,10 @@ $uni-font-size-paragraph: 15px;
|
|||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -100rpx; right: -100rpx;
|
top: -100rpx;
|
||||||
width: 600rpx; height: 600rpx;
|
right: -100rpx;
|
||||||
|
width: 600rpx;
|
||||||
|
height: 600rpx;
|
||||||
background: radial-gradient(circle, rgba($brand-primary, 0.15) 0%, transparent 70%);
|
background: radial-gradient(circle, rgba($brand-primary, 0.15) 0%, transparent 70%);
|
||||||
filter: blur(60rpx);
|
filter: blur(60rpx);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@ -212,8 +217,10 @@ $uni-font-size-paragraph: 15px;
|
|||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 200rpx; left: -200rpx;
|
top: 200rpx;
|
||||||
width: 500rpx; height: 500rpx;
|
left: -200rpx;
|
||||||
|
width: 500rpx;
|
||||||
|
height: 500rpx;
|
||||||
background: radial-gradient(circle, rgba($brand-secondary, 0.1) 0%, transparent 70%);
|
background: radial-gradient(circle, rgba($brand-secondary, 0.1) 0%, transparent 70%);
|
||||||
filter: blur(50rpx);
|
filter: blur(50rpx);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@ -244,7 +251,7 @@ $uni-font-size-paragraph: 15px;
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
box-shadow: $shadow-warm;
|
box-shadow: $shadow-warm;
|
||||||
transition: all 0.2s $ease-out;
|
transition: all 0.2s $ease-out;
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
transform: scale(0.96);
|
transform: scale(0.96);
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
@ -262,7 +269,7 @@ $uni-font-size-paragraph: 15px;
|
|||||||
box-shadow: $shadow-sm;
|
box-shadow: $shadow-sm;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
transition: all 0.2s $ease-out;
|
transition: all 0.2s $ease-out;
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
transform: scale(0.96);
|
transform: scale(0.96);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|||||||
@ -361,9 +361,13 @@ class NakamaManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('[Nakama] RPC response:', id, response);
|
||||||
|
|
||||||
if (response.rpc && response.rpc.payload) {
|
if (response.rpc && response.rpc.payload) {
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
return response.rpc.payload;
|
return response.rpc.payload;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user