hookehuyr

feat(隐私协议): 完善隐私协议弹窗和收款信息检查逻辑

- 在隐私协议弹窗中添加 catch-move 属性防止滑动穿透
- 简化隐私协议文本内容,移除冗余信息
- 添加收款信息检查逻辑和隐私弹窗触发来源区分
- 重构支付协议弹窗样式和交互,改为右侧弹出并优化滚动体验
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
2 <nut-popup 2 <nut-popup
3 v-model:visible="visible" 3 v-model:visible="visible"
4 position="bottom" 4 position="bottom"
5 + :catch-move="true"
5 :style="{ width: '100%', height: '100%' }" 6 :style="{ width: '100%', height: '100%' }"
6 > 7 >
7 <div class="payment-agreement-modal"> 8 <div class="payment-agreement-modal">
...@@ -73,19 +74,29 @@ ...@@ -73,19 +74,29 @@
73 <!-- 支付协议弹框 --> 74 <!-- 支付协议弹框 -->
74 <nut-popup 75 <nut-popup
75 v-model:visible="protocolVisible" 76 v-model:visible="protocolVisible"
76 - position="bottom" 77 + position="right"
77 - :style="{ width: '100%', height: '70%' }" 78 + :closeable="true"
78 - round 79 + :close-on-click-overlay="true"
79 - closeable 80 + :safe-area-inset-bottom="true"
81 + :style="{ width: '100%', height: '100%' }"
82 + @close="protocolVisible = false"
80 > 83 >
81 - <div class="protocol-modal"> 84 + <view class="protocol-container">
82 - <div class="protocol-header"> 85 + <!-- 标题栏 -->
83 - <h3>支付协议</h3> 86 + <view class="protocol-header">
84 - </div> 87 + <text class="protocol-title">支付协议</text>
85 - <div class="protocol-content"> 88 + <view class="close-btn" @click="protocolVisible = false">
86 - <p>{{ protocolContent }}</p> 89 + <text class="close-text">×</text>
87 - </div> 90 + </view>
88 - </div> 91 + </view>
92 +
93 + <!-- 内容区域 -->
94 + <scroll-view class="protocol-scroll" :scroll-y="true">
95 + <view class="protocol-body">
96 + <view class="protocol-text">{{ protocolContent }}</view>
97 + </view>
98 + </scroll-view>
99 + </view>
89 </nut-popup> 100 </nut-popup>
90 </nut-popup> 101 </nut-popup>
91 </template> 102 </template>
...@@ -219,7 +230,7 @@ const handleClose = () => { ...@@ -219,7 +230,7 @@ const handleClose = () => {
219 } 230 }
220 231
221 // 组件挂载时检查协议状态 232 // 组件挂载时检查协议状态
222 -onMounted(() => { 233 +onMounted(async () => {
223 checkAgreementStatus() 234 checkAgreementStatus()
224 }) 235 })
225 </script> 236 </script>
...@@ -312,35 +323,64 @@ onMounted(() => { ...@@ -312,35 +323,64 @@ onMounted(() => {
312 } 323 }
313 } 324 }
314 325
315 -.protocol-modal { 326 +/* 支付协议弹框样式 */
316 - padding: 32rpx; 327 +.protocol-container {
317 - height: 100%; 328 + width: 100%;
329 + height: 100vh;
330 + background: white;
318 display: flex; 331 display: flex;
319 flex-direction: column; 332 flex-direction: column;
333 +}
320 334
321 - .protocol-header { 335 +.protocol-header {
322 - text-align: center; 336 + display: flex;
323 - margin-bottom: 32rpx; 337 + justify-content: space-between;
338 + align-items: center;
339 + padding: 32rpx 40rpx;
340 + border-bottom: 1rpx solid #eee;
341 + background: white;
342 + position: sticky;
343 + top: 0;
344 + z-index: 10;
345 +}
324 346
325 - h3 { 347 +.protocol-title {
326 - font-size: 32rpx; 348 + font-size: 36rpx;
327 - font-weight: 600; 349 + font-weight: bold;
328 - color: #333; 350 + color: #333;
329 - margin: 0; 351 +}
330 - }
331 - }
332 352
333 - .protocol-content { 353 +.close-btn {
334 - flex: 1; 354 + width: 60rpx;
335 - overflow-y: auto; 355 + height: 60rpx;
356 + display: flex;
357 + align-items: center;
358 + justify-content: center;
359 + background: #f5f5f5;
360 + border-radius: 50%;
361 + cursor: pointer;
362 +}
336 363
337 - p { 364 +.close-text {
338 - font-size: 28rpx; 365 + font-size: 40rpx;
339 - color: #666; 366 + color: #666;
340 - line-height: 1.8; 367 + line-height: 1;
341 - white-space: pre-line; 368 +}
342 - margin: 0; 369 +
343 - } 370 +.protocol-scroll {
344 - } 371 + flex: 1;
372 + height: 0;
373 +}
374 +
375 +.protocol-body {
376 + padding: 40rpx;
377 +}
378 +
379 +.protocol-text {
380 + font-size: 28rpx;
381 + line-height: 1.8;
382 + color: #666;
383 + white-space: pre-line;
384 + word-wrap: break-word;
345 } 385 }
346 </style> 386 </style>
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
6 :close-on-click-overlay="false" 6 :close-on-click-overlay="false"
7 round 7 round
8 :safe-area-inset-bottom="true" 8 :safe-area-inset-bottom="true"
9 + :catch-move="true"
9 class="privacy-modal" 10 class="privacy-modal"
10 > 11 >
11 <view class="privacy-content"> 12 <view class="privacy-content">
...@@ -17,7 +18,7 @@ ...@@ -17,7 +18,7 @@
17 <!-- 内容 --> 18 <!-- 内容 -->
18 <view class="privacy-body"> 19 <view class="privacy-body">
19 <text class="privacy-text"> 20 <text class="privacy-text">
20 - 你好,小程序【手机号】涉及收集、使用和存储用户信息,增加了 21 + 你好,小程序涉及收集、使用和存储用户信息,增加了
21 <text class="privacy-link" @tap="onUserAgreementClick">《用户服务协议》</text> 22 <text class="privacy-link" @tap="onUserAgreementClick">《用户服务协议》</text>
22 23
23 <text class="privacy-link" @tap="onPrivacyPolicyClick">《隐私政策》</text> 24 <text class="privacy-link" @tap="onPrivacyPolicyClick">《隐私政策》</text>
......
...@@ -109,6 +109,8 @@ const userInfo = computed(() => userStore.userInfo) ...@@ -109,6 +109,8 @@ const userInfo = computed(() => userStore.userInfo)
109 109
110 // 隐私政策弹框状态 110 // 隐私政策弹框状态
111 const showPrivacyModal = ref(false) 111 const showPrivacyModal = ref(false)
112 +// 隐私政策弹框触发来源('editProfile' 或 'collectionSettings')
113 +const privacyModalSource = ref('editProfile')
112 114
113 useDidShow(async () => { 115 useDidShow(async () => {
114 await userStore.fetchUserInfo() 116 await userStore.fetchUserInfo()
...@@ -128,6 +130,7 @@ const onEditProfile = async () => { ...@@ -128,6 +130,7 @@ const onEditProfile = async () => {
128 }) 130 })
129 } else { 131 } else {
130 // 未完善资料,显示隐私政策同意弹框 132 // 未完善资料,显示隐私政策同意弹框
133 + privacyModalSource.value = 'editProfile'
131 showPrivacyModal.value = true 134 showPrivacyModal.value = true
132 } 135 }
133 } 136 }
...@@ -136,10 +139,18 @@ const onEditProfile = async () => { ...@@ -136,10 +139,18 @@ const onEditProfile = async () => {
136 * 隐私政策确认 139 * 隐私政策确认
137 */ 140 */
138 const onPrivacyConfirm = () => { 141 const onPrivacyConfirm = () => {
139 - // 用户同意隐私政策后,跳转到编辑资料页面 142 + // 根据触发来源跳转到不同页面
140 - Taro.navigateTo({ 143 + if (privacyModalSource.value === 'editProfile') {
141 - url: '/pages/editProfile/index' 144 + // 从编辑资料触发,跳转到编辑资料页面
142 - }) 145 + Taro.navigateTo({
146 + url: '/pages/editProfile/index'
147 + })
148 + } else if (privacyModalSource.value === 'collectionSettings') {
149 + // 从收款设置触发,跳转到收款设置页面
150 + Taro.navigateTo({
151 + url: '/pages/collectionSettings/index'
152 + })
153 + }
143 } 154 }
144 155
145 /** 156 /**
...@@ -215,10 +226,20 @@ const onFeedback = () => { ...@@ -215,10 +226,20 @@ const onFeedback = () => {
215 /** 226 /**
216 * 收款设置 227 * 收款设置
217 */ 228 */
218 -const onCollectionSettings = () => { 229 +const onCollectionSettings = async () => {
219 - Taro.navigateTo({ 230 + // 检查用户是否已完善收款信息
220 - url: '/pages/collectionSettings/index' 231 + const hasCompleteCollectionInfo = userStore.hasCompleteCollectionInfo
221 - }) 232 +
233 + if (hasCompleteCollectionInfo) {
234 + // 已完善收款信息,直接进入收款设置页面
235 + Taro.navigateTo({
236 + url: '/pages/collectionSettings/index'
237 + })
238 + } else {
239 + // 未完善收款信息,显示隐私政策同意弹框
240 + privacyModalSource.value = 'collectionSettings'
241 + showPrivacyModal.value = true
242 + }
222 } 243 }
223 244
224 /** 245 /**
......
1 /* 1 /*
2 * @Date: 2025-01-08 18:00:00 2 * @Date: 2025-01-08 18:00:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-08-05 17:51:14 4 + * @LastEditTime: 2025-08-05 18:16:58
5 * @FilePath: /jgdl/src/stores/user.js 5 * @FilePath: /jgdl/src/stores/user.js
6 * @Description: 用户状态管理 6 * @Description: 用户状态管理
7 */ 7 */
...@@ -44,6 +44,18 @@ export const useUserStore = defineStore('user', { ...@@ -44,6 +44,18 @@ export const useUserStore = defineStore('user', {
44 }, 44 },
45 45
46 /** 46 /**
47 + * 检查用户是否已完善收款信息(银行信息和身份信息)
48 + */
49 + hasCompleteCollectionInfo: (state) => {
50 + return !!(
51 + state.userInfo.bank && state.userInfo.bank.trim() &&
52 + state.userInfo.bank_no && state.userInfo.bank_no.trim() &&
53 + state.userInfo.name && state.userInfo.name.trim() &&
54 + state.userInfo.idcard && state.userInfo.idcard.trim()
55 + )
56 + },
57 +
58 + /**
47 * 检查用户是否已认证 59 * 检查用户是否已认证
48 */ 60 */
49 isUserAuthenticated: (state) => { 61 isUserAuthenticated: (state) => {
......