修改问题,新增登陆和修改合规整改

This commit is contained in:
tsui110 2026-03-24 12:10:53 +08:00
parent d643abe7e1
commit 58ad9e8be3
7 changed files with 275 additions and 55 deletions

190
components/PrivacyPopup.vue Normal file
View File

@ -0,0 +1,190 @@
<template>
<view v-if="showPrivacy" class="privacy-popup-mask">
<view class="privacy-popup-content">
<view class="privacy-title">用户隐私保护提示</view>
<view class="privacy-desc">
感谢您使用柯大鸭盲盒小程序我们非常重视您的隐私保护和用户权益
<br /><br />
在您使用我们的服务前请您仔细阅读并充分理解
<text class="privacy-link" @tap="openPrivacyContract">用户隐私保护指引</text>
<br /><br />
当您点击同意并开始使用我们的服务时即表示您已理解并同意该指引内容我们将按照指引内容处理您的个人信息
</view>
<view class="privacy-buttons">
<button class="btn-reject" @tap="handleDisagree">拒绝</button>
<button
class="btn-agree"
id="agree-btn"
open-type="agreePrivacyAuthorization"
@agreeprivacyauthorization="handleAgree"
>
同意
</button>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'PrivacyPopup',
data() {
return {
showPrivacy: false,
resolvePrivacyAuthorization: null
}
},
mounted() {
// #ifdef MP-WEIXIN
this.initPrivacy()
// #endif
},
methods: {
initPrivacy() {
// #ifdef MP-WEIXIN
wx.onNeedPrivacyAuthorization((resolve, eventInfo) => {
console.log('[隐私协议] 触发隐私授权', eventInfo)
this.resolvePrivacyAuthorization = resolve
this.showPrivacy = true
})
wx.getPrivacySetting({
success: (res) => {
console.log('[隐私协议] 隐私设置', res)
if (res.needAuthorization) {
//
} else {
//
this.showPrivacy = false
}
},
fail: (err) => {
console.error('[隐私协议] 获取隐私设置失败', err)
}
})
// #endif
},
openPrivacyContract() {
// #ifdef MP-WEIXIN
wx.openPrivacyContract({
success: () => {
console.log('[隐私协议] 打开隐私协议成功')
},
fail: (err) => {
console.error('[隐私协议] 打开隐私协议失败', err)
}
})
// #endif
},
handleAgree() {
console.log('[隐私协议] 用户同意')
this.showPrivacy = false
if (this.resolvePrivacyAuthorization) {
this.resolvePrivacyAuthorization({
event: 'agree',
buttonId: 'agree-btn'
})
this.resolvePrivacyAuthorization = null
}
this.$emit('agree')
},
handleDisagree() {
console.log('[隐私协议] 用户拒绝')
this.showPrivacy = false
if (this.resolvePrivacyAuthorization) {
this.resolvePrivacyAuthorization({
event: 'disagree'
})
this.resolvePrivacyAuthorization = null
}
this.$emit('disagree')
uni.showModal({
title: '提示',
content: '您拒绝了隐私协议,部分功能可能无法正常使用',
showCancel: false
})
}
}
}
</script>
<style lang="scss" scoped>
.privacy-popup-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.privacy-popup-content {
width: 600rpx;
background: #fff;
border-radius: 24rpx;
padding: 48rpx 40rpx;
box-sizing: border-box;
}
.privacy-title {
font-size: 36rpx;
font-weight: 600;
color: #333;
text-align: center;
margin-bottom: 32rpx;
}
.privacy-desc {
font-size: 28rpx;
color: #666;
line-height: 1.8;
margin-bottom: 40rpx;
}
.privacy-link {
color: #FF6B00;
text-decoration: underline;
}
.privacy-buttons {
display: flex;
gap: 24rpx;
}
.btn-reject {
flex: 1;
height: 88rpx;
line-height: 88rpx;
font-size: 30rpx;
color: #666;
background: #f5f5f5;
border: none;
border-radius: 44rpx;
&::after {
border: none;
}
}
.btn-agree {
flex: 1;
height: 88rpx;
line-height: 88rpx;
font-size: 30rpx;
color: #fff;
background: linear-gradient(135deg, #FF9500, #FF6B00);
border: none;
border-radius: 44rpx;
&::after {
border: none;
}
}
</style>

View File

@ -279,5 +279,8 @@
"^BlessingAnimation": "@/components/BlessingAnimation.vue"
}
},
"mp-weixin": {
"__usePrivacyCheck__": true
},
"uniIdRouter": {}
}

View File

@ -3,10 +3,7 @@
<!-- 顶部装饰背景 - 漂浮光球 -->
<view class="bg-decoration"></view>
<!-- 自定义 tabBar -->
<!-- #ifdef MP-WEIXIN -->
<customTabBar />
<!-- #endif -->
<!-- 自定义 tabBar (仅抖音小程序) -->
<!-- #ifdef MP-TOUTIAO -->
<customTabBarToutiao />
<!-- #endif -->
@ -256,11 +253,7 @@ import { onShow, onReachBottom, onShareAppMessage, onPullDownRefresh } from '@dc
import { getInventory, getProductDetail, redeemInventory, requestShipping, cancelShipping, listAddresses, getShipments, createAddressShare, createShippingFeeOrder } from '@/api/appUser'
import { getSynthesisRecipes, doSynthesis } from '@/api/synthesis.js'
import { vibrateShort } from '@/utils/vibrate.js'
import { checkPhoneBound, checkPhoneBoundSync } from '@/utils/checkPhone.js'
import { executePaymentFlow } from '@/utils/payment.js'
// #ifdef MP-WEIXIN
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif
@ -318,9 +311,6 @@ async function fetchProductMeta(productId) {
}
onShow(() => {
//
if (!checkPhoneBoundSync()) return
// Check for external tab switch request
try {
const targetTab = uni.getStorageSync('cabinet_target_tab')
@ -334,7 +324,9 @@ onShow(() => {
if (!token) {
uni.showModal({
title: '提示',
content: '请先登录',
content: '请先登录后查看盒柜内容',
showCancel: true,
cancelText: '稍后再说',
confirmText: '去登录',
success: (res) => {
if (res.confirm) {

View File

@ -6,10 +6,7 @@
<!-- 品牌级背景装饰系统 - 统一漂浮光球 -->
<view class="bg-decoration"></view>
<!-- 自定义 tabBar -->
<!-- #ifdef MP-WEIXIN -->
<customTabBar />
<!-- #endif -->
<!-- 自定义 tabBar (仅抖音小程序) -->
<!-- #ifdef MP-TOUTIAO -->
<customTabBarToutiao />
<!-- #endif -->
@ -144,10 +141,6 @@
<script>
import { authRequest, request } from '../../utils/request.js'
import SplashScreen from '@/components/SplashScreen.vue'
import { checkPhoneBound, checkPhoneBoundSync } from '../../utils/checkPhone.js'
// #ifdef MP-WEIXIN
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif
@ -155,9 +148,6 @@ import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
export default {
components: {
SplashScreen
// #ifdef MP-WEIXIN
, customTabBar
// #endif
// #ifdef MP-TOUTIAO
, customTabBarToutiao
// #endif
@ -214,9 +204,6 @@ export default {
return
// #endif
// ()
if (!checkPhoneBoundSync()) return
// 200ms Token/Session
//
setTimeout(() => {

View File

@ -1,5 +1,10 @@
<template>
<view class="page-login">
<!-- 隐私协议弹窗 (仅微信小程序) -->
<!-- #ifdef MP-WEIXIN -->
<PrivacyPopup ref="privacyPopup" @agree="onPrivacyAgree" @disagree="onPrivacyDisagree" />
<!-- #endif -->
<!-- 背景装饰 -->
<view class="bg-decoration"></view>
@ -66,6 +71,10 @@
>
{{ loading ? '获取中...' : '一键获取手机号' }}
</button>
<button class="btn-cancel" @tap="handleCancelLogin">
取消登录
</button>
</view>
<!-- #endif -->
@ -89,6 +98,10 @@
>
{{ loading ? '登录中...' : '抖音用户授权登录' }}
</button>
<button class="btn-cancel" @tap="handleCancelLogin">
取消登录
</button>
</view>
<!-- #endif -->
@ -144,6 +157,10 @@
{{ loading ? '登录中...' : '登录 / 注册' }}
</button>
<button class="btn-cancel" @tap="handleCancelLogin">
取消登录
</button>
<text class="hint-text">未注册的手机号将自动创建账号</text>
</view>
</view>
@ -179,10 +196,38 @@ import { request } from '../../utils/request'
import { wechatLogin, douyinLogin, bindPhone, bindDouyinPhone, getUserStats, getPointsBalance, sendSmsCode, smsLogin, getUserInfo } from '../../api/appUser'
import { authRequest } from '../../utils/request'
import { vibrateShort } from '@/utils/vibrate.js'
// #ifdef MP-WEIXIN
import PrivacyPopup from '@/components/PrivacyPopup.vue'
// #endif
const loading = ref(false)
const agreementChecked = ref(false)
// #ifdef MP-WEIXIN
const privacyPopup = ref(null)
function onPrivacyAgree() {
console.log('[隐私协议] 用户已同意隐私协议')
}
function onPrivacyDisagree() {
console.log('[隐私协议] 用户拒绝隐私协议')
uni.showToast({
title: '您拒绝了隐私协议,部分功能可能无法正常使用',
icon: 'none'
})
}
// #endif
function handleCancelLogin() {
const pages = getCurrentPages()
if (pages.length > 1) {
uni.navigateBack()
} else {
uni.switchTab({ url: '/pages/index/index' })
}
}
//
// #ifdef MP-WEIXIN
const loginMode = ref('wechat')
@ -1017,6 +1062,20 @@ function fetchExtraData(userId) {
}
}
/* 取消登录按钮 */
.btn-cancel {
width: 100%;
height: 88rpx;
font-size: 28rpx;
color: $text-sub;
background: transparent;
border: 2rpx solid $border-color;
border-radius: $radius-round;
margin-top: 24rpx;
&::after { border: none; }
}
.hint-text {
display: block;
text-align: center;

View File

@ -3,10 +3,7 @@
<!-- 顶部背景装饰 -->
<view class="bg-decoration"></view>
<!-- 自定义 tabBar -->
<!-- #ifdef MP-WEIXIN -->
<customTabBar />
<!-- #endif -->
<!-- 自定义 tabBar (仅抖音小程序) -->
<!-- #ifdef MP-TOUTIAO -->
<customTabBarToutiao />
<!-- #endif -->
@ -499,19 +496,12 @@ import {
getUserInfo, getUserStats, getPointsBalance, getUserPoints, getUserCoupons, getItemCards,
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile, bindDouyinID, getPublicConfig
} from '../../api/appUser.js'
import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
// #ifdef MP-WEIXIN
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif
export default {
components: {
// #ifdef MP-WEIXIN
customTabBar,
// #endif
// #ifdef MP-TOUTIAO
customTabBarToutiao,
// #endif
@ -595,9 +585,6 @@ export default {
}).catch(console.error)
},
onShow() {
//
if (!checkPhoneBoundSync()) return
this.loadUserInfo()
},
onShareAppMessage() {
@ -617,16 +604,18 @@ export default {
}
},
methods: {
//
checkPhoneBound() {
if (!this.mobile) {
uni.showModal({
title: '需要绑定手机号',
content: '为了账号安全,请先绑定手机号',
showCancel: false,
showCancel: true,
cancelText: '取消',
confirmText: '去绑定',
success: () => {
uni.navigateTo({ url: '/pages/login/index?mode=sms' })
success: (res) => {
if (res.confirm) {
uni.navigateTo({ url: '/pages/login/index?mode=sms' })
}
}
})
return false

View File

@ -2,10 +2,7 @@
<view class="page">
<view class="bg-decoration"></view>
<!-- 自定义 tabBar -->
<!-- #ifdef MP-WEIXIN -->
<customTabBar />
<!-- #endif -->
<!-- 自定义 tabBar (仅抖音小程序) -->
<!-- #ifdef MP-TOUTIAO -->
<customTabBarToutiao />
<!-- #endif -->
@ -167,11 +164,7 @@
import { onShow, onReachBottom } from '@dcloudio/uni-app'
import { ref, watch, onUnmounted } from 'vue'
import { getStoreItems, redeemProductByPoints, redeemCouponByPoints, redeemItemCardByPoints, getProductCategories } from '../../api/appUser'
import { checkPhoneBound, checkPhoneBoundSync } from '../../utils/checkPhone.js'
import { vibrateShort } from '@/utils/vibrate.js'
// #ifdef MP-WEIXIN
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif
@ -545,9 +538,6 @@ function onCategorySelect(id) {
}
onShow(() => {
//
if (!checkPhoneBoundSync()) return
const token = uni.getStorageSync('token')
if (token) {
//
@ -559,6 +549,16 @@ onShow(() => {
fetchCategories()
hasInitialized = true
}
} else {
//
if (!hasInitialized) {
page.value = 1
hasMore.value = true
allItems.value = []
loadItems()
fetchCategories()
hasInitialized = true
}
}
})