fix:修复了很多不规范用词,更改了手机绑定校验逻辑,调整最大限制购买次数为200次。
This commit is contained in:
parent
5dfb2c3ecb
commit
b959e634d2
@ -258,6 +258,18 @@ export function modifyUser(user_id, data) {
|
||||
return authRequest({ url: `/api/app/users/${user_id}`, method: 'PUT', data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户资料信息(新接口)
|
||||
* @returns {Promise} 用户资料信息 { id, nickname, avatar, mobile, balance, invite_code, inviter_id }
|
||||
*/
|
||||
export function getUserProfile() {
|
||||
return authRequest({ url: '/api/app/users/profile', method: 'GET' })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息(兼容旧接口)
|
||||
* @deprecated 建议使用 getUserProfile
|
||||
*/
|
||||
export function getUserInfo() {
|
||||
const user_info = uni.getStorageSync('user_info')
|
||||
if (user_info) return Promise.resolve(user_info)
|
||||
|
||||
@ -41,7 +41,13 @@
|
||||
<view class="action-row">
|
||||
<view class="stepper" @tap.stop>
|
||||
<text class="step-btn minus" @tap="updateCount(pkg.id, -1)">-</text>
|
||||
<text class="step-val">{{ counts[pkg.id] || 1 }}</text>
|
||||
<input
|
||||
class="step-input"
|
||||
type="number"
|
||||
:value="counts[pkg.id] || 1"
|
||||
@input="onInputCount(pkg.id, $event)"
|
||||
@blur="onBlurCount(pkg.id)"
|
||||
/>
|
||||
<text class="step-btn plus" @tap="updateCount(pkg.id, 1)">+</text>
|
||||
</view>
|
||||
<button class="btn-buy" :loading="purchasingId === pkg.id" @tap.stop="handlePurchase(pkg)">
|
||||
@ -75,11 +81,33 @@ const counts = ref({})
|
||||
function updateCount(pkgId, delta) {
|
||||
const current = counts.value[pkgId] || 1
|
||||
const newVal = current + delta
|
||||
if (newVal >= 1 && newVal <= 99) {
|
||||
if (newVal >= 1 && newVal <= 200) {
|
||||
counts.value[pkgId] = newVal
|
||||
}
|
||||
}
|
||||
|
||||
function onInputCount(pkgId, e) {
|
||||
const val = parseInt(e.detail.value) || 1
|
||||
// 允许输入过程中的临时值(如空字符串),但限制范围
|
||||
if (val >= 1 && val <= 200) {
|
||||
counts.value[pkgId] = val
|
||||
} else if (val < 1) {
|
||||
counts.value[pkgId] = 1
|
||||
} else if (val > 200) {
|
||||
counts.value[pkgId] = 200
|
||||
}
|
||||
}
|
||||
|
||||
function onBlurCount(pkgId) {
|
||||
// 失去焦点时确保值在有效范围内
|
||||
const current = counts.value[pkgId] || 1
|
||||
if (current < 1) {
|
||||
counts.value[pkgId] = 1
|
||||
} else if (current > 200) {
|
||||
counts.value[pkgId] = 200
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.visible, (val) => {
|
||||
if (val) {
|
||||
fetchPackages()
|
||||
@ -340,7 +368,7 @@ function handleClose() {
|
||||
background: #F3F4F6;
|
||||
border-radius: 12rpx;
|
||||
padding: 2rpx;
|
||||
|
||||
|
||||
.step-btn {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
@ -349,18 +377,29 @@ function handleClose() {
|
||||
font-size: 32rpx;
|
||||
color: #4B5563;
|
||||
font-weight: 300;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
||||
.minus {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.step-val {
|
||||
width: 40rpx;
|
||||
|
||||
.step-input {
|
||||
width: 60rpx;
|
||||
height: 44rpx;
|
||||
line-height: 44rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
color: #1F2937;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
&::placeholder {
|
||||
color: #9CA3AF;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -34,9 +34,9 @@
|
||||
<view class="popup-body">
|
||||
<!-- 次数卡选项(有数据时显示) -->
|
||||
<view v-if="gamePasses" class="game-pass-section">
|
||||
<view
|
||||
class="game-pass-option"
|
||||
:class="{ active: useGamePass, disabled: gamePassRemaining <= 0 }"
|
||||
<view
|
||||
class="game-pass-option"
|
||||
:class="{ active: useGamePass, disabled: gamePassRemaining <= 0 }"
|
||||
@tap="gamePassRemaining > 0 ? toggleGamePass() : null"
|
||||
>
|
||||
<view class="game-pass-radio">
|
||||
@ -44,11 +44,10 @@
|
||||
<view v-else-if="gamePassRemaining <= 0" class="radio-disabled" />
|
||||
</view>
|
||||
<view class="game-pass-info">
|
||||
<text class="game-pass-label" :class="{ 'text-disabled': gamePassRemaining <= 0 }">🎮 使用次数卡</text>
|
||||
<text class="game-pass-count" v-if="gamePassRemaining > 0">剩余 {{ gamePassRemaining }} 次</text>
|
||||
<text class="game-pass-label" :class="{ 'text-disabled': gamePassRemaining <= 0 }">剩余次数</text>
|
||||
<text class="game-pass-count" v-if="gamePassRemaining > 0">{{ gamePassRemaining }} 次</text>
|
||||
<text class="game-pass-count text-disabled" v-else>暂无可用次数卡</text>
|
||||
</view>
|
||||
<text v-if="gamePassRemaining > 0" class="game-pass-free">免费畅玩</text>
|
||||
</view>
|
||||
<view v-if="!useGamePass" class="divider-line">
|
||||
<text class="divider-text">或选择其他支付方式</text>
|
||||
@ -841,16 +840,16 @@ function handleConfirm() {
|
||||
&.active {
|
||||
background: linear-gradient(135deg, #10B981, #059669);
|
||||
border-color: #059669;
|
||||
|
||||
.game-pass-label, .game-pass-count, .game-pass-free {
|
||||
|
||||
.game-pass-label, .game-pass-count {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
|
||||
.game-pass-radio {
|
||||
background: #FFFFFF;
|
||||
border-color: #FFFFFF;
|
||||
}
|
||||
|
||||
|
||||
.radio-checked {
|
||||
color: #10B981;
|
||||
}
|
||||
@ -902,15 +901,6 @@ function handleConfirm() {
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.game-pass-free {
|
||||
font-size: $font-sm;
|
||||
font-weight: 600;
|
||||
color: #10B981;
|
||||
padding: 6rpx 16rpx;
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
border-radius: $radius-md;
|
||||
}
|
||||
|
||||
.divider-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -215,8 +215,8 @@ async function fetchProductMeta(productId) {
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
// 检查手机号绑定状态
|
||||
if (!checkPhoneBound()) return
|
||||
// 检查手机号绑定状态(快速检查本地缓存)
|
||||
if (!checkPhoneBoundSync()) return
|
||||
|
||||
// Check for external tab switch request
|
||||
try {
|
||||
|
||||
@ -180,8 +180,8 @@ export default {
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 检查手机号绑定状态
|
||||
if (!checkPhoneBound()) return
|
||||
// 检查手机号绑定状态(快速检查本地缓存)
|
||||
if (!checkPhoneBoundSync()) return
|
||||
|
||||
// 延迟 200ms 首次加载,让 Token/Session 有机会就绪
|
||||
// 同时避免页面动画卡顿
|
||||
|
||||
@ -468,9 +468,9 @@
|
||||
<script>
|
||||
import {
|
||||
getUserInfo, getUserStats, getPointsBalance, getUserPoints, getUserCoupons, getItemCards,
|
||||
getUserTasks, getTaskProgress, getInviteRecords, modifyUser
|
||||
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile
|
||||
} from '../../api/appUser.js'
|
||||
import { checkPhoneBound } from '../../utils/checkPhone.js'
|
||||
import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -537,8 +537,8 @@ export default {
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
// 检查手机号绑定状态
|
||||
if (!checkPhoneBound()) return
|
||||
// 检查手机号绑定状态(快速检查本地缓存)
|
||||
if (!checkPhoneBoundSync()) return
|
||||
|
||||
this.loadUserInfo()
|
||||
},
|
||||
@ -739,10 +739,49 @@ export default {
|
||||
return
|
||||
}
|
||||
try {
|
||||
// 优先使用新的 profile API
|
||||
const profile = await getUserProfile()
|
||||
|
||||
if (profile) {
|
||||
console.log('[Mine] 从 profile API 获取用户信息:', profile)
|
||||
this.userId = profile.id
|
||||
this.nickname = profile.nickname
|
||||
this.avatar = profile.avatar
|
||||
this.title = profile.title || ''
|
||||
this.inviteCode = profile.invite_code
|
||||
this.pointsBalance = this.normalizePointsBalance(profile.balance)
|
||||
this.mobile = profile.mobile || ''
|
||||
|
||||
// 更新缓存
|
||||
const cachedUser = uni.getStorageSync('user_info') || {}
|
||||
cachedUser.id = profile.id
|
||||
cachedUser.nickname = profile.nickname
|
||||
cachedUser.avatar = profile.avatar
|
||||
cachedUser.title = profile.title
|
||||
cachedUser.invite_code = profile.invite_code
|
||||
cachedUser.mobile = profile.mobile
|
||||
cachedUser.points_balance = this.pointsBalance
|
||||
uni.setStorageSync('user_info', cachedUser)
|
||||
uni.setStorageSync('user_id', profile.id)
|
||||
|
||||
// 如果有手机号,更新缓存
|
||||
if (profile.mobile) {
|
||||
uni.setStorageSync('phone_number', profile.mobile)
|
||||
}
|
||||
|
||||
// Load stats
|
||||
const s = await getUserStats(profile.id)
|
||||
if (s) this.stats = { ...this.stats, ...s }
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 降级到旧逻辑
|
||||
console.log('[Mine] profile API 无数据,使用降级逻辑')
|
||||
// 先尝试从缓存获取基础信息
|
||||
const cachedUser = uni.getStorageSync('user_info')
|
||||
const cachedUserId = uni.getStorageSync('user_id')
|
||||
|
||||
|
||||
if (cachedUser) {
|
||||
this.userId = cachedUser.id || cachedUserId
|
||||
this.nickname = cachedUser.nickname
|
||||
@ -754,7 +793,7 @@ export default {
|
||||
} else if (cachedUserId) {
|
||||
this.userId = cachedUserId
|
||||
}
|
||||
|
||||
|
||||
if (this.userId) {
|
||||
try {
|
||||
const balanceRes = await getPointsBalance(this.userId)
|
||||
@ -782,14 +821,14 @@ export default {
|
||||
this.mobile = res.mobile || res.phone || res.phone_number || ''
|
||||
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) {
|
||||
console.error(e)
|
||||
console.error('[Mine] loadUserInfo 错误:', e)
|
||||
// If 401, maybe clear token
|
||||
}
|
||||
},
|
||||
|
||||
@ -414,8 +414,8 @@ async function onRedeemTap(item) {
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
// 检查手机号绑定状态
|
||||
if (!checkPhoneBound()) return
|
||||
// 检查手机号绑定状态(快速检查本地缓存)
|
||||
if (!checkPhoneBoundSync()) return
|
||||
|
||||
const token = uni.getStorageSync('token')
|
||||
if (token) {
|
||||
|
||||
@ -1,31 +1,80 @@
|
||||
import { getUserProfile } from '../api/appUser'
|
||||
|
||||
/**
|
||||
* 检查手机号绑定状态
|
||||
* 如果未绑定手机号,则跳转到登录页面进行绑定
|
||||
* @returns {Promise<boolean>} 是否已绑定手机号
|
||||
*/
|
||||
export async function checkPhoneBound() {
|
||||
try {
|
||||
// 调用新的用户资料接口
|
||||
const profile = await getUserProfile()
|
||||
|
||||
console.log('[checkPhoneBound] 用户资料:', profile)
|
||||
|
||||
// 检查是否已绑定手机号
|
||||
const mobile = profile?.mobile
|
||||
|
||||
if (mobile) {
|
||||
console.log('[checkPhoneBound] 已检测到手机号,允许通过:', mobile)
|
||||
// 缓存手机号
|
||||
uni.setStorageSync('phone_number', mobile)
|
||||
return true
|
||||
}
|
||||
|
||||
// 未绑定手机号,显示提示并跳转
|
||||
console.warn('[checkPhoneBound] 未检测到手机号,提示用户绑定')
|
||||
uni.showModal({
|
||||
title: '需要绑定手机号',
|
||||
content: '为了账号安全,请先绑定手机号',
|
||||
showCancel: false,
|
||||
confirmText: '去绑定',
|
||||
success: () => {
|
||||
uni.navigateTo({ url: '/pages/login/index?mode=sms' })
|
||||
}
|
||||
})
|
||||
|
||||
return false
|
||||
} catch (err) {
|
||||
console.error('[checkPhoneBound] 获取用户信息失败:', err)
|
||||
|
||||
// 请求失败时,降级检查本地缓存
|
||||
const phoneNumber = uni.getStorageSync('phone_number') || ''
|
||||
console.log('[checkPhoneBound] 降级检查本地缓存:', phoneNumber ? phoneNumber : '未找到')
|
||||
|
||||
if (phoneNumber) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 本地也没有,提示重新登录
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '获取用户信息失败,请重新登录',
|
||||
showCancel: false,
|
||||
confirmText: '去登录',
|
||||
success: () => {
|
||||
uni.navigateTo({ url: '/pages/login/index' })
|
||||
}
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步检查手机号绑定状态(仅检查本地缓存)
|
||||
* @returns {boolean} 是否已绑定手机号
|
||||
*/
|
||||
export function checkPhoneBound() {
|
||||
// 直接检查 phone_number 缓存中是否有手机号
|
||||
export function checkPhoneBoundSync() {
|
||||
const phoneNumber = uni.getStorageSync('phone_number') || ''
|
||||
|
||||
console.log('[checkPhoneBound] 检查 phone_number 缓存:', phoneNumber ? phoneNumber : '未找到')
|
||||
console.log('[checkPhoneBoundSync] 检查 phone_number 缓存:', phoneNumber ? phoneNumber : '未找到')
|
||||
|
||||
// 如果已绑定手机号,直接返回
|
||||
if (phoneNumber) {
|
||||
console.log('[checkPhoneBound] 已检测到手机号,允许通过:', phoneNumber)
|
||||
console.log('[checkPhoneBoundSync] 已检测到手机号,允许通过:', phoneNumber)
|
||||
return true
|
||||
}
|
||||
|
||||
// 未绑定手机号,显示提示并跳转
|
||||
console.warn('[checkPhoneBound] 未检测到手机号,提示用户绑定')
|
||||
uni.showModal({
|
||||
title: '需要绑定手机号',
|
||||
content: '为了账号安全,请先绑定手机号',
|
||||
showCancel: false,
|
||||
confirmText: '去绑定',
|
||||
success: () => {
|
||||
uni.navigateTo({ url: '/pages/login/index?mode=sms' })
|
||||
}
|
||||
})
|
||||
|
||||
console.warn('[checkPhoneBoundSync] 未检测到手机号')
|
||||
return false
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user