feat:新增前端的假退出,真清除缓存功能,fix:修复后端大模型为对齐字段导致的前端积分显示不一致的问题。
This commit is contained in:
parent
01eb9a425a
commit
c53e179ce2
@ -9,7 +9,7 @@
|
|||||||
<view class="title">{{ detail.title || detail.name || '-' }}</view>
|
<view class="title">{{ detail.title || detail.name || '-' }}</view>
|
||||||
<view class="price-row">
|
<view class="price-row">
|
||||||
<view class="points-wrap">
|
<view class="points-wrap">
|
||||||
<text class="points-val">{{ (detail.points_required ? (detail.points_required).toFixed(0) : '0') || (detail.price ? (detail.price / 100).toFixed(1) : '0.0') }}</text>
|
<text class="points-val">{{ formatPoints( detail.price) }}</text>
|
||||||
<text class="points-unit">积分</text>
|
<text class="points-unit">积分</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -51,6 +51,20 @@ function formatPrice(p) {
|
|||||||
return (Number(p) / 100).toFixed(2)
|
return (Number(p) / 100).toFixed(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 格式化积分显示 - 不四舍五入,保留两位小数
|
||||||
|
function formatPoints(value) {
|
||||||
|
if (value === undefined || value === null) return '0.00'
|
||||||
|
const num = Number(value)
|
||||||
|
if (isNaN(num)) return '0.00'
|
||||||
|
|
||||||
|
// 价格字段单位是分,如 1250 = 12.50积分
|
||||||
|
// 除以100得到显示值
|
||||||
|
const finalValue = num / 100
|
||||||
|
|
||||||
|
// 使用 Math.floor 避免四舍五入,保留两位小数
|
||||||
|
return String(Math.floor(finalValue * 100) / 100).replace(/(\.\d)$/, '$10')
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchDetail(id) {
|
async function fetchDetail(id) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
isOutOfStock.value = false
|
isOutOfStock.value = false
|
||||||
@ -103,7 +117,7 @@ async function onRedeem() {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = uni.getStorageSync('token')
|
const token = uni.getStorageSync('token')
|
||||||
if (!token) {
|
if (!token) {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
@ -114,8 +128,8 @@ async function onRedeem() {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const points = (detail.value.points_required ? (detail.value.points_required).toFixed(0) : '0') || (detail.value.price ? (detail.value.price / 100).toFixed(1) : '0.0')
|
const points = formatPoints(p.price)
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '确认兑换',
|
title: '确认兑换',
|
||||||
content: `是否消耗 ${points} 积分兑换 ${p.title || p.name}?`,
|
content: `是否消耗 ${points} 积分兑换 ${p.title || p.name}?`,
|
||||||
@ -125,7 +139,7 @@ async function onRedeem() {
|
|||||||
try {
|
try {
|
||||||
const userId = uni.getStorageSync('user_id')
|
const userId = uni.getStorageSync('user_id')
|
||||||
if (!userId) throw new Error('用户ID不存在')
|
if (!userId) throw new Error('用户ID不存在')
|
||||||
|
|
||||||
await redeemProductByPoints(userId, p.id, 1)
|
await redeemProductByPoints(userId, p.id, 1)
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
|
|||||||
183
pages-user/settings/index.vue
Normal file
183
pages-user/settings/index.vue
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
<template>
|
||||||
|
<view class="settings-container">
|
||||||
|
<!-- 自定义 tabBar -->
|
||||||
|
<!-- #ifdef MP-TOUTIAO -->
|
||||||
|
<customTabBarToutiao />
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef MP-TOUTIAO -->
|
||||||
|
<customTabBar />
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<view class="navbar">
|
||||||
|
<view class="navbar-content">
|
||||||
|
<text class="navbar-title">设置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 设置内容区域 -->
|
||||||
|
<view class="settings-content">
|
||||||
|
<!-- 退出登录按钮 -->
|
||||||
|
<view class="logout-section">
|
||||||
|
<view class="logout-btn" @click="handleLogout">
|
||||||
|
<view class="logout-icon">
|
||||||
|
<image class="logout-icon-img" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNGRjQwNDAiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik05IDIxSDVhMiAyIDAgMCAxLTItMnYtNWEyIDIgMCAwIDEgMi0yaDRtMCAwdjZtMC0wdjZtMC02aDZhMiAyIDAgMCAxIDIgMnY4YTIgMiAwIDAgMS0yIDJINyIgLz48cGF0aCBkPSJNOCAxM2w1LTU1IDU1LTUiIC8+PC9zdmc+" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<text class="logout-text">退出当前账号</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// #ifdef MP-TOUTIAO
|
||||||
|
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP-TOUTIAO
|
||||||
|
import customTabBar from '@/components/app-tab-bar.vue'
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
// #ifdef MP-TOUTTAO
|
||||||
|
customTabBarToutiao
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP-TOUTIAO
|
||||||
|
customTabBar
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleLogout() {
|
||||||
|
uni.showModal({
|
||||||
|
title: '退出登录',
|
||||||
|
content: '确定要退出当前账号吗?退出后将清空本地缓存。',
|
||||||
|
confirmText: '确定退出',
|
||||||
|
confirmColor: '#FF6B00',
|
||||||
|
cancelText: '取消',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
this.logout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
try {
|
||||||
|
// 清空所有本地存储
|
||||||
|
uni.clearStorageSync()
|
||||||
|
|
||||||
|
// 显示提示
|
||||||
|
uni.showToast({
|
||||||
|
title: '已退出登录',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
|
||||||
|
// 延迟跳转到登录页
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/login/index'
|
||||||
|
})
|
||||||
|
}, 1500)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('退出登录失败:', e)
|
||||||
|
uni.showToast({
|
||||||
|
title: '退出失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.settings-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: $bg-page;
|
||||||
|
padding-bottom: calc(env(safe-area-inset-bottom) + 120rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 导航栏 */
|
||||||
|
.navbar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 100;
|
||||||
|
background: linear-gradient(135deg, rgba(255,255,255,0.98), rgba(255,255,255,0.95));
|
||||||
|
backdrop-filter: blur(20rpx);
|
||||||
|
border-bottom: 1px solid rgba(0,0,0,0.05);
|
||||||
|
padding-top: env(safe-area-inset-top);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-content {
|
||||||
|
height: 88rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
color: $text-main;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 设置内容区 */
|
||||||
|
.settings-content {
|
||||||
|
padding-top: calc(env(safe-area-inset-top) + 88rpx + $spacing-lg);
|
||||||
|
padding-left: $spacing-lg;
|
||||||
|
padding-right: $spacing-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 退出登录区域 */
|
||||||
|
.logout-section {
|
||||||
|
background: $bg-card;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: $shadow-card;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 32rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: $uni-bg-color-hover;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-icon {
|
||||||
|
width: 48rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-icon-img {
|
||||||
|
width: 48rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-text {
|
||||||
|
font-size: $font-lg;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FF4040;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -154,6 +154,13 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "购买协议"
|
"navigationBarTitleText": "购买协议"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "settings/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "设置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -204,6 +204,12 @@
|
|||||||
<text class="menu-label">扫雷</text>
|
<text class="menu-label">扫雷</text>
|
||||||
</view>
|
</view>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
|
<view class="menu-item" @click="toSettings">
|
||||||
|
<view class="menu-icon-box">
|
||||||
|
<image class="menu-icon-img" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjMiLz48cGF0aCBkPSJNMTIgMTV2M20wLTZ2MyIvPjxwYXRoIGQ9Ik0xOS40IDE1YTEsMSAwIDAsMC0uMTc4LjM4OWwtMTAuNSA3LjJhMSwxIDAsMCwwLTEuMTg5LS4xODlsLTQuNS04LjVhMSwxIDAsMCwwIC4xNzgtMS4xODlsOC41LTQuNWExLDEgMCAwLDEgLjM4OS4xNzhsNC41IDguNTE5YTEsMSAwIDAsMC0uMTc4LjM4OXoiLz48L3N2Zz4=" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<text class="menu-label">设置</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -1025,6 +1031,9 @@ export default {
|
|||||||
if (!this.checkPhoneBound()) return
|
if (!this.checkPhoneBound()) return
|
||||||
uni.navigateTo({ url: '/pages-game/game/minesweeper/index' })
|
uni.navigateTo({ url: '/pages-game/game/minesweeper/index' })
|
||||||
},
|
},
|
||||||
|
toSettings() {
|
||||||
|
uni.navigateTo({ url: '/pages-user/settings/index' })
|
||||||
|
},
|
||||||
// 抖音IM客服回调
|
// 抖音IM客服回调
|
||||||
onImCallback(e) {
|
onImCallback(e) {
|
||||||
console.log('[Douyin IM] 跳转IM客服成功', e.detail)
|
console.log('[Douyin IM] 跳转IM客服成功', e.detail)
|
||||||
|
|||||||
@ -262,13 +262,28 @@ function cleanUrl(u) {
|
|||||||
|
|
||||||
function normalizeItems(list, kind) {
|
function normalizeItems(list, kind) {
|
||||||
if (!Array.isArray(list)) return []
|
if (!Array.isArray(list)) return []
|
||||||
|
|
||||||
|
// 格式化积分显示 - 不四舍五入,保留两位小数
|
||||||
|
const formatPoints = (value) => {
|
||||||
|
if (value === undefined || value === null) return '0.00'
|
||||||
|
const num = Number(value)
|
||||||
|
if (isNaN(num)) return '0.00'
|
||||||
|
|
||||||
|
// 价格字段单位是分,如 1250 = 12.50积分
|
||||||
|
// 除以100得到显示值
|
||||||
|
const finalValue = num / 100
|
||||||
|
|
||||||
|
// 使用 Math.floor 避免四舍五入,保留两位小数
|
||||||
|
return String(Math.floor(finalValue * 100) / 100).replace(/(\.\d)$/, '$10')
|
||||||
|
}
|
||||||
|
|
||||||
return list.map((i, idx) => ({
|
return list.map((i, idx) => ({
|
||||||
id: i.id,
|
id: i.id,
|
||||||
kind: i.kind || kind,
|
kind: i.kind || kind,
|
||||||
image: cleanUrl(i.main_image || i.image || ''),
|
image: cleanUrl(i.main_image || i.image || ''),
|
||||||
title: i.name || i.title || '',
|
title: i.name || i.title || '',
|
||||||
price: i.price || i.discount_value || 0,
|
price: i.price || i.discount_value || 0,
|
||||||
points: i.points_required ? (i.points_required).toFixed(0) : (i.price ? (i.price / 100).toFixed(1) : (i.discount_value ? (i.discount_value / 100).toFixed(1) : '0')),
|
points: formatPoints(i.price || i.discount_value),
|
||||||
stock: i.in_stock ? 99 : 0, // Simplified stock check if returned as bool
|
stock: i.in_stock ? 99 : 0, // Simplified stock check if returned as bool
|
||||||
discount_value: i.discount_value || 0,
|
discount_value: i.discount_value || 0,
|
||||||
min_spend: i.min_spend || 0,
|
min_spend: i.min_spend || 0,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user