feat(profile): 添加隐私政策同意弹框组件及逻辑
新增 PrivacyAgreementModal 组件用于展示隐私政策和服务协议 在个人资料页添加隐私政策弹框逻辑,未完善资料的用户需先同意协议
Showing
3 changed files
with
630 additions
and
3 deletions
| ... | @@ -15,6 +15,7 @@ declare module 'vue' { | ... | @@ -15,6 +15,7 @@ declare module 'vue' { |
| 15 | NavBar: typeof import('./src/components/navBar.vue')['default'] | 15 | NavBar: typeof import('./src/components/navBar.vue')['default'] |
| 16 | NutActionSheet: typeof import('@nutui/nutui-taro')['ActionSheet'] | 16 | NutActionSheet: typeof import('@nutui/nutui-taro')['ActionSheet'] |
| 17 | NutButton: typeof import('@nutui/nutui-taro')['Button'] | 17 | NutButton: typeof import('@nutui/nutui-taro')['Button'] |
| 18 | + NutCheckbox: typeof import('@nutui/nutui-taro')['Checkbox'] | ||
| 18 | NutCol: typeof import('@nutui/nutui-taro')['Col'] | 19 | NutCol: typeof import('@nutui/nutui-taro')['Col'] |
| 19 | NutConfigProvider: typeof import('@nutui/nutui-taro')['ConfigProvider'] | 20 | NutConfigProvider: typeof import('@nutui/nutui-taro')['ConfigProvider'] |
| 20 | NutDatePicker: typeof import('@nutui/nutui-taro')['DatePicker'] | 21 | NutDatePicker: typeof import('@nutui/nutui-taro')['DatePicker'] |
| ... | @@ -42,6 +43,7 @@ declare module 'vue' { | ... | @@ -42,6 +43,7 @@ declare module 'vue' { |
| 42 | PayCard: typeof import('./src/components/payCard.vue')['default'] | 43 | PayCard: typeof import('./src/components/payCard.vue')['default'] |
| 43 | Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] | 44 | Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] |
| 44 | PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] | 45 | PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] |
| 46 | + PrivacyAgreementModal: typeof import('./src/components/PrivacyAgreementModal.vue')['default'] | ||
| 45 | RouterLink: typeof import('vue-router')['RouterLink'] | 47 | RouterLink: typeof import('vue-router')['RouterLink'] |
| 46 | RouterView: typeof import('vue-router')['RouterView'] | 48 | RouterView: typeof import('vue-router')['RouterView'] |
| 47 | SearchPopup: typeof import('./src/components/SearchPopup.vue')['default'] | 49 | SearchPopup: typeof import('./src/components/SearchPopup.vue')['default'] | ... | ... |
src/components/PrivacyAgreementModal.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <nut-popup | ||
| 3 | + v-model:visible="modalVisible" | ||
| 4 | + position="bottom" | ||
| 5 | + :closeable="false" | ||
| 6 | + :close-on-click-overlay="false" | ||
| 7 | + round | ||
| 8 | + :safe-area-inset-bottom="true" | ||
| 9 | + class="privacy-modal" | ||
| 10 | + > | ||
| 11 | + <view class="privacy-content"> | ||
| 12 | + <!-- 标题 --> | ||
| 13 | + <view class="privacy-header"> | ||
| 14 | + <text class="privacy-title">隐私政策与用户协议</text> | ||
| 15 | + </view> | ||
| 16 | + | ||
| 17 | + <!-- 内容 --> | ||
| 18 | + <view class="privacy-body"> | ||
| 19 | + <text class="privacy-text"> | ||
| 20 | + 你好,小程序【手机号】涉及收集、使用和存储用户信息,增加了 | ||
| 21 | + <text class="privacy-link" @tap="onUserAgreementClick">《用户服务协议》</text> | ||
| 22 | + 及 | ||
| 23 | + <text class="privacy-link" @tap="onPrivacyPolicyClick">《隐私政策》</text> | ||
| 24 | + ,明确告知收集用户信息的使用目的、方式和用途,并取得用户授权同意后,才能获取用户收集用户信息。 | ||
| 25 | + </text> | ||
| 26 | + </view> | ||
| 27 | + | ||
| 28 | + <!-- 同意选择 --> | ||
| 29 | + <view class="privacy-agreement"> | ||
| 30 | + <nut-checkbox v-model="agreed" class="agreement-checkbox"> | ||
| 31 | + <text class="agreement-text">我已阅读并同意上述协议</text> | ||
| 32 | + </nut-checkbox> | ||
| 33 | + </view> | ||
| 34 | + | ||
| 35 | + <!-- 操作按钮 --> | ||
| 36 | + <view class="privacy-actions"> | ||
| 37 | + <nut-button | ||
| 38 | + class="action-btn cancel-btn" | ||
| 39 | + @click="onCancel" | ||
| 40 | + > | ||
| 41 | + 关闭 | ||
| 42 | + </nut-button> | ||
| 43 | + <nut-button | ||
| 44 | + class="action-btn confirm-btn" | ||
| 45 | + type="primary" | ||
| 46 | + :disabled="!agreed" | ||
| 47 | + @click="onConfirm" | ||
| 48 | + > | ||
| 49 | + 确认进入 | ||
| 50 | + </nut-button> | ||
| 51 | + </view> | ||
| 52 | + </view> | ||
| 53 | + </nut-popup> | ||
| 54 | + | ||
| 55 | + <!-- 内容全屏显示弹框 --> | ||
| 56 | + <nut-popup | ||
| 57 | + v-model:visible="showContentModal" | ||
| 58 | + position="right" | ||
| 59 | + :closeable="true" | ||
| 60 | + :close-on-click-overlay="true" | ||
| 61 | + :safe-area-inset-bottom="true" | ||
| 62 | + :style="{ width: '100%', height: '100%' }" | ||
| 63 | + @close="onCloseContentModal" | ||
| 64 | + > | ||
| 65 | + <view class="content-container"> | ||
| 66 | + <!-- 标题栏 --> | ||
| 67 | + <view class="content-header"> | ||
| 68 | + <text class="content-title">{{ contentTitle }}</text> | ||
| 69 | + <view class="close-btn" @click="onCloseContentModal"> | ||
| 70 | + <text class="close-text">×</text> | ||
| 71 | + </view> | ||
| 72 | + </view> | ||
| 73 | + | ||
| 74 | + <!-- 内容区域 --> | ||
| 75 | + <scroll-view class="content-scroll" :scroll-y="true"> | ||
| 76 | + <view class="content-body"> | ||
| 77 | + <view class="content-text" v-html="contentText"></view> | ||
| 78 | + </view> | ||
| 79 | + </scroll-view> | ||
| 80 | + </view> | ||
| 81 | + </nut-popup> | ||
| 82 | +</template> | ||
| 83 | + | ||
| 84 | +<script setup> | ||
| 85 | +import { ref, computed, defineEmits, defineProps } from 'vue' | ||
| 86 | +import Taro from '@tarojs/taro' | ||
| 87 | + | ||
| 88 | +// Props | ||
| 89 | +const props = defineProps({ | ||
| 90 | + visible: { | ||
| 91 | + type: Boolean, | ||
| 92 | + default: false | ||
| 93 | + } | ||
| 94 | +}) | ||
| 95 | + | ||
| 96 | +// Emits | ||
| 97 | +const emit = defineEmits(['update:visible', 'confirm', 'cancel']) | ||
| 98 | + | ||
| 99 | +// 响应式数据 | ||
| 100 | +const agreed = ref(false) | ||
| 101 | + | ||
| 102 | +// 计算属性 | ||
| 103 | +const modalVisible = computed({ | ||
| 104 | + get() { | ||
| 105 | + return props.visible | ||
| 106 | + }, | ||
| 107 | + set(value) { | ||
| 108 | + emit('update:visible', value) | ||
| 109 | + } | ||
| 110 | +}) | ||
| 111 | + | ||
| 112 | +// 用户服务协议内容 | ||
| 113 | +const userAgreementContent = ` | ||
| 114 | +<div class="agreement-section"> | ||
| 115 | + <div class="section-title">第一条 协议的范围</div> | ||
| 116 | + <div class="section-content"> | ||
| 117 | + <div class="clause-item">1.1 本协议是您与捡个电驴小程序(以下简称"本平台")之间关于您使用本平台服务所订立的协议。</div> | ||
| 118 | + <div class="clause-item">1.2 本协议描述本平台与用户之间关于"捡个电驴"服务相关的权利义务。</div> | ||
| 119 | + </div> | ||
| 120 | +</div> | ||
| 121 | + | ||
| 122 | +<div class="agreement-section"> | ||
| 123 | + <div class="section-title">第二条 服务内容</div> | ||
| 124 | + <div class="section-content"> | ||
| 125 | + <div class="clause-item">2.1 本平台为用户提供二手电动车交易信息发布、浏览、联系等服务。</div> | ||
| 126 | + <div class="clause-item">2.2 用户可以通过本平台发布车辆出售信息、浏览车辆信息、联系买卖双方等。</div> | ||
| 127 | + </div> | ||
| 128 | +</div> | ||
| 129 | + | ||
| 130 | +<div class="agreement-section"> | ||
| 131 | + <div class="section-title">第三条 用户注册</div> | ||
| 132 | + <div class="section-content"> | ||
| 133 | + <div class="clause-item">3.1 用户需要注册账户才能使用本平台的完整服务。</div> | ||
| 134 | + <div class="clause-item">3.2 用户应提供真实、准确、完整的个人信息。</div> | ||
| 135 | + <div class="clause-item">3.3 用户应妥善保管账户信息,对账户下的所有活动承担责任。</div> | ||
| 136 | + </div> | ||
| 137 | +</div> | ||
| 138 | + | ||
| 139 | +<div class="agreement-section"> | ||
| 140 | + <div class="section-title">第四条 用户行为规范</div> | ||
| 141 | + <div class="section-content"> | ||
| 142 | + <div class="clause-item">4.1 用户不得发布虚假信息或进行欺诈行为。</div> | ||
| 143 | + <div class="clause-item">4.2 用户不得发布违法违规内容。</div> | ||
| 144 | + <div class="clause-item">4.3 用户应遵守平台的交易规则和社区准则。</div> | ||
| 145 | + </div> | ||
| 146 | +</div> | ||
| 147 | + | ||
| 148 | +<div class="agreement-section"> | ||
| 149 | + <div class="section-title">第五条 隐私保护</div> | ||
| 150 | + <div class="section-content"> | ||
| 151 | + <div class="clause-item">5.1 本平台重视用户隐私保护,具体内容请参见《隐私政策》。</div> | ||
| 152 | + </div> | ||
| 153 | +</div> | ||
| 154 | + | ||
| 155 | +<div class="agreement-section"> | ||
| 156 | + <div class="section-title">第六条 免责声明</div> | ||
| 157 | + <div class="section-content"> | ||
| 158 | + <div class="clause-item">6.1 本平台仅提供信息发布平台,不参与具体交易。</div> | ||
| 159 | + <div class="clause-item">6.2 用户之间的交易风险由用户自行承担。</div> | ||
| 160 | + </div> | ||
| 161 | +</div> | ||
| 162 | + | ||
| 163 | +<div class="agreement-section"> | ||
| 164 | + <div class="section-title">第七条 协议修改</div> | ||
| 165 | + <div class="section-content"> | ||
| 166 | + <div class="clause-item">7.1 本平台有权根据需要修改本协议。</div> | ||
| 167 | + <div class="clause-item">7.2 修改后的协议将在平台上公布。</div> | ||
| 168 | + </div> | ||
| 169 | +</div> | ||
| 170 | + | ||
| 171 | +<div class="agreement-section"> | ||
| 172 | + <div class="section-title">第八条 争议解决</div> | ||
| 173 | + <div class="section-content"> | ||
| 174 | + <div class="clause-item">8.1 因本协议产生的争议,双方应友好协商解决。</div> | ||
| 175 | + <div class="clause-item">8.2 协商不成的,可向有管辖权的人民法院提起诉讼。</div> | ||
| 176 | + </div> | ||
| 177 | +</div> | ||
| 178 | + | ||
| 179 | +<div class="agreement-footer">本协议自用户点击同意之日起生效。</div> | ||
| 180 | +` | ||
| 181 | + | ||
| 182 | +// 隐私政策内容 | ||
| 183 | +const privacyPolicyContent = ` | ||
| 184 | +<div class="agreement-section"> | ||
| 185 | + <div class="section-title">引言</div> | ||
| 186 | + <div class="section-content"> | ||
| 187 | + <div class="clause-item">捡个电驴小程序(以下简称"我们")非常重视用户的隐私保护。本隐私政策说明了我们如何收集、使用、存储和保护您的个人信息。</div> | ||
| 188 | + </div> | ||
| 189 | +</div> | ||
| 190 | + | ||
| 191 | +<div class="agreement-section"> | ||
| 192 | + <div class="section-title">一、我们收集的信息</div> | ||
| 193 | + <div class="section-content"> | ||
| 194 | + <div class="clause-item">1.1 您主动提供的信息</div> | ||
| 195 | + <div class="clause-list"> | ||
| 196 | + <div class="list-item1">注册信息:手机号码、昵称、头像等</div> | ||
| 197 | + <div class="list-item1">个人资料:性别、学校、生日等</div> | ||
| 198 | + <div class="list-item1">车辆信息:发布的车辆详情、图片等</div> | ||
| 199 | + <div class="list-item1">联系信息:与其他用户的沟通记录</div> | ||
| 200 | + </div> | ||
| 201 | + <div class="clause-item">1.2 自动收集的信息</div> | ||
| 202 | + <div class="clause-list"> | ||
| 203 | + <div class="list-item1">设备信息:设备型号、操作系统版本等</div> | ||
| 204 | + <div class="list-item1">使用信息:访问时间、使用功能、操作记录等</div> | ||
| 205 | + <div class="list-item1">位置信息:用于提供本地化服务(需要您的授权)</div> | ||
| 206 | + </div> | ||
| 207 | + </div> | ||
| 208 | +</div> | ||
| 209 | + | ||
| 210 | +<div class="agreement-section"> | ||
| 211 | + <div class="section-title">二、信息使用目的</div> | ||
| 212 | + <div class="section-content"> | ||
| 213 | + <div class="clause-item">2.1 提供服务</div> | ||
| 214 | + <div class="clause-list"> | ||
| 215 | + <div class="list-item1">账户注册和身份验证</div> | ||
| 216 | + <div class="list-item1">车辆信息发布和展示</div> | ||
| 217 | + <div class="list-item1">用户间沟通和交易撮合</div> | ||
| 218 | + <div class="list-item1">个性化推荐服务</div> | ||
| 219 | + </div> | ||
| 220 | + <div class="clause-item">2.2 改善服务</div> | ||
| 221 | + <div class="clause-list"> | ||
| 222 | + <div class="list-item1">分析用户使用习惯</div> | ||
| 223 | + <div class="list-item1">优化产品功能</div> | ||
| 224 | + <div class="list-item1">提升用户体验</div> | ||
| 225 | + </div> | ||
| 226 | + <div class="clause-item">2.3 安全保障</div> | ||
| 227 | + <div class="clause-list"> | ||
| 228 | + <div class="list-item1">防范欺诈和违法行为</div> | ||
| 229 | + <div class="list-item1">保护用户和平台安全</div> | ||
| 230 | + <div class="list-item1">维护正常的服务秩序</div> | ||
| 231 | + </div> | ||
| 232 | + </div> | ||
| 233 | +</div> | ||
| 234 | + | ||
| 235 | +<div class="agreement-section"> | ||
| 236 | + <div class="section-title">三、信息共享</div> | ||
| 237 | + <div class="section-content"> | ||
| 238 | + <div class="clause-item">3.1 我们不会出售您的个人信息</div> | ||
| 239 | + <div class="clause-item">3.2 在以下情况下,我们可能会共享您的信息:</div> | ||
| 240 | + <div class="clause-list"> | ||
| 241 | + <div class="list-item1">获得您的明确同意</div> | ||
| 242 | + <div class="list-item1">法律法规要求</div> | ||
| 243 | + <div class="list-item1">保护用户或公众的重大利益</div> | ||
| 244 | + <div class="list-item1">与服务提供商共享(仅限于提供服务所需)</div> | ||
| 245 | + </div> | ||
| 246 | + </div> | ||
| 247 | +</div> | ||
| 248 | + | ||
| 249 | +<div class="agreement-section"> | ||
| 250 | + <div class="section-title">四、信息存储和保护</div> | ||
| 251 | + <div class="section-content"> | ||
| 252 | + <div class="clause-item">4.1 存储期限</div> | ||
| 253 | + <div class="clause-list"> | ||
| 254 | + <div class="list-item1">在您使用服务期间持续存储</div> | ||
| 255 | + <div class="list-item1">账户注销后,我们将删除或匿名化处理您的个人信息</div> | ||
| 256 | + </div> | ||
| 257 | + <div class="clause-item">4.2 安全措施</div> | ||
| 258 | + <div class="clause-list"> | ||
| 259 | + <div class="list-item1">采用行业标准的安全技术</div> | ||
| 260 | + <div class="list-item1">定期进行安全评估</div> | ||
| 261 | + <div class="list-item1">限制员工访问权限</div> | ||
| 262 | + <div class="list-item1">建立数据泄露应急响应机制</div> | ||
| 263 | + </div> | ||
| 264 | + </div> | ||
| 265 | +</div> | ||
| 266 | + | ||
| 267 | +<div class="agreement-section"> | ||
| 268 | + <div class="section-title">五、您的权利</div> | ||
| 269 | + <div class="section-content"> | ||
| 270 | + <div class="clause-item">5.1 访问权:您有权了解我们收集的关于您的个人信息</div> | ||
| 271 | + <div class="clause-item">5.2 更正权:您有权要求我们更正不准确的个人信息</div> | ||
| 272 | + <div class="clause-item">5.3 删除权:在特定情况下,您有权要求我们删除您的个人信息</div> | ||
| 273 | + <div class="clause-item">5.4 撤回同意:您有权随时撤回对个人信息处理的同意</div> | ||
| 274 | + </div> | ||
| 275 | +</div> | ||
| 276 | + | ||
| 277 | +<div class="agreement-section"> | ||
| 278 | + <div class="section-title">六、未成年人保护</div> | ||
| 279 | + <div class="section-content"> | ||
| 280 | + <div class="clause-item">我们不会故意收集未满14周岁儿童的个人信息。如果您是未成年人,请在监护人指导下使用我们的服务。</div> | ||
| 281 | + </div> | ||
| 282 | +</div> | ||
| 283 | + | ||
| 284 | +<div class="agreement-section"> | ||
| 285 | + <div class="section-title">七、第三方服务</div> | ||
| 286 | + <div class="section-content"> | ||
| 287 | + <div class="clause-item">我们的服务可能包含第三方链接或服务,这些第三方有自己的隐私政策,我们不对其隐私做法承担责任。</div> | ||
| 288 | + </div> | ||
| 289 | +</div> | ||
| 290 | + | ||
| 291 | +<div class="agreement-section"> | ||
| 292 | + <div class="section-title">八、政策更新</div> | ||
| 293 | + <div class="section-content"> | ||
| 294 | + <div class="clause-item">我们可能会不时更新本隐私政策。重大变更时,我们会通过适当方式通知您。</div> | ||
| 295 | + </div> | ||
| 296 | +</div> | ||
| 297 | + | ||
| 298 | +<div class="agreement-footer">本隐私政策最后更新日期:2024年7月29日</div> | ||
| 299 | +` | ||
| 300 | + | ||
| 301 | +// 显示内容的状态 | ||
| 302 | +const showContentModal = ref(false) | ||
| 303 | +const contentTitle = ref('') | ||
| 304 | +const contentText = ref('') | ||
| 305 | + | ||
| 306 | +/** | ||
| 307 | + * 点击用户服务协议 | ||
| 308 | + */ | ||
| 309 | +const onUserAgreementClick = () => { | ||
| 310 | + contentTitle.value = '用户服务协议' | ||
| 311 | + contentText.value = userAgreementContent | ||
| 312 | + showContentModal.value = true | ||
| 313 | +} | ||
| 314 | + | ||
| 315 | +/** | ||
| 316 | + * 点击隐私政策 | ||
| 317 | + */ | ||
| 318 | +const onPrivacyPolicyClick = () => { | ||
| 319 | + contentTitle.value = '隐私政策' | ||
| 320 | + contentText.value = privacyPolicyContent | ||
| 321 | + showContentModal.value = true | ||
| 322 | +} | ||
| 323 | + | ||
| 324 | +/** | ||
| 325 | + * 关闭内容弹框 | ||
| 326 | + */ | ||
| 327 | +const onCloseContentModal = () => { | ||
| 328 | + showContentModal.value = false | ||
| 329 | + contentTitle.value = '' | ||
| 330 | + contentText.value = '' | ||
| 331 | +} | ||
| 332 | + | ||
| 333 | +/** | ||
| 334 | + * 取消操作 | ||
| 335 | + */ | ||
| 336 | +const onCancel = () => { | ||
| 337 | + agreed.value = false | ||
| 338 | + emit('update:visible', false) | ||
| 339 | + emit('cancel') | ||
| 340 | +} | ||
| 341 | + | ||
| 342 | +/** | ||
| 343 | + * 确认操作 | ||
| 344 | + */ | ||
| 345 | +const onConfirm = () => { | ||
| 346 | + if (!agreed.value) { | ||
| 347 | + Taro.showToast({ | ||
| 348 | + title: '请先同意协议', | ||
| 349 | + icon: 'none' | ||
| 350 | + }) | ||
| 351 | + return | ||
| 352 | + } | ||
| 353 | + | ||
| 354 | + emit('update:visible', false) | ||
| 355 | + emit('confirm') | ||
| 356 | +} | ||
| 357 | +</script> | ||
| 358 | + | ||
| 359 | +<style lang="less"> | ||
| 360 | +.privacy-modal { | ||
| 361 | + // width: 680rpx; | ||
| 362 | +} | ||
| 363 | + | ||
| 364 | +.privacy-content { | ||
| 365 | + padding: 40rpx 32rpx; | ||
| 366 | + background: white; | ||
| 367 | + border-radius: 16rpx; | ||
| 368 | +} | ||
| 369 | + | ||
| 370 | +.privacy-header { | ||
| 371 | + text-align: center; | ||
| 372 | + margin-bottom: 32rpx; | ||
| 373 | +} | ||
| 374 | + | ||
| 375 | +.privacy-title { | ||
| 376 | + font-size: 36rpx; | ||
| 377 | + font-weight: bold; | ||
| 378 | + color: #333; | ||
| 379 | +} | ||
| 380 | + | ||
| 381 | +.privacy-body { | ||
| 382 | + margin-bottom: 32rpx; | ||
| 383 | +} | ||
| 384 | + | ||
| 385 | +.privacy-text { | ||
| 386 | + font-size: 28rpx; | ||
| 387 | + line-height: 1.6; | ||
| 388 | + color: #666; | ||
| 389 | +} | ||
| 390 | + | ||
| 391 | +.privacy-link { | ||
| 392 | + color: #fb923c; | ||
| 393 | + text-decoration: underline; | ||
| 394 | + font-weight: 500; | ||
| 395 | +} | ||
| 396 | + | ||
| 397 | +.privacy-agreement { | ||
| 398 | + margin-bottom: 32rpx; | ||
| 399 | + padding: 16rpx 0; | ||
| 400 | +} | ||
| 401 | + | ||
| 402 | +.agreement-checkbox { | ||
| 403 | + display: flex; | ||
| 404 | + align-items: center; | ||
| 405 | +} | ||
| 406 | + | ||
| 407 | +.agreement-text { | ||
| 408 | + font-size: 28rpx; | ||
| 409 | + color: #666; | ||
| 410 | + margin-left: 16rpx; | ||
| 411 | +} | ||
| 412 | + | ||
| 413 | +.privacy-actions { | ||
| 414 | + display: flex; | ||
| 415 | + gap: 24rpx; | ||
| 416 | +} | ||
| 417 | + | ||
| 418 | +.action-btn { | ||
| 419 | + flex: 1; | ||
| 420 | + height: 88rpx; | ||
| 421 | + border-radius: 44rpx; | ||
| 422 | + font-size: 32rpx; | ||
| 423 | +} | ||
| 424 | + | ||
| 425 | +.cancel-btn { | ||
| 426 | + background: #f5f5f5; | ||
| 427 | + color: #666; | ||
| 428 | + border: none; | ||
| 429 | +} | ||
| 430 | + | ||
| 431 | +.confirm-btn { | ||
| 432 | + background: #fb923c; | ||
| 433 | + border: none; | ||
| 434 | +} | ||
| 435 | + | ||
| 436 | +.confirm-btn:disabled { | ||
| 437 | + background: #ccc; | ||
| 438 | + color: #999; | ||
| 439 | +} | ||
| 440 | + | ||
| 441 | +/* 内容弹框样式 */ | ||
| 442 | +.content-modal { | ||
| 443 | + width: 100vw; | ||
| 444 | + height: 100vh; | ||
| 445 | +} | ||
| 446 | + | ||
| 447 | +.content-container { | ||
| 448 | + width: 100%; | ||
| 449 | + height: 100vh; | ||
| 450 | + background: white; | ||
| 451 | + display: flex; | ||
| 452 | + flex-direction: column; | ||
| 453 | +} | ||
| 454 | + | ||
| 455 | +.content-header { | ||
| 456 | + display: flex; | ||
| 457 | + justify-content: space-between; | ||
| 458 | + align-items: center; | ||
| 459 | + padding: 32rpx 40rpx; | ||
| 460 | + border-bottom: 1rpx solid #eee; | ||
| 461 | + background: white; | ||
| 462 | + position: sticky; | ||
| 463 | + top: 0; | ||
| 464 | + z-index: 10; | ||
| 465 | +} | ||
| 466 | + | ||
| 467 | +.content-title { | ||
| 468 | + font-size: 36rpx; | ||
| 469 | + font-weight: bold; | ||
| 470 | + color: #333; | ||
| 471 | +} | ||
| 472 | + | ||
| 473 | +.close-btn { | ||
| 474 | + width: 60rpx; | ||
| 475 | + height: 60rpx; | ||
| 476 | + display: flex; | ||
| 477 | + align-items: center; | ||
| 478 | + justify-content: center; | ||
| 479 | + background: #f5f5f5; | ||
| 480 | + border-radius: 50%; | ||
| 481 | + cursor: pointer; | ||
| 482 | +} | ||
| 483 | + | ||
| 484 | +.close-text { | ||
| 485 | + font-size: 40rpx; | ||
| 486 | + color: #666; | ||
| 487 | + line-height: 1; | ||
| 488 | +} | ||
| 489 | + | ||
| 490 | +.content-scroll { | ||
| 491 | + flex: 1; | ||
| 492 | + height: 0; | ||
| 493 | +} | ||
| 494 | + | ||
| 495 | +.content-body { | ||
| 496 | + padding: 40rpx; | ||
| 497 | +} | ||
| 498 | + | ||
| 499 | +// .content-text { | ||
| 500 | +// font-size: 28rpx; | ||
| 501 | +// line-height: 1.8; | ||
| 502 | +// color: #333; | ||
| 503 | +// white-space: pre-line; | ||
| 504 | +// word-wrap: break-word; | ||
| 505 | +// } | ||
| 506 | + | ||
| 507 | +// 协议内容样式 | ||
| 508 | +.agreement-title { | ||
| 509 | + font-size: 36rpx; | ||
| 510 | + font-weight: bold; | ||
| 511 | + color: #333; | ||
| 512 | + text-align: center; | ||
| 513 | + margin-bottom: 40rpx; | ||
| 514 | + padding-bottom: 20rpx; | ||
| 515 | + border-bottom: 2rpx solid #e5e5e5; | ||
| 516 | +} | ||
| 517 | + | ||
| 518 | +.agreement-section { | ||
| 519 | + margin-bottom: 30rpx; | ||
| 520 | +} | ||
| 521 | + | ||
| 522 | +.section-title { | ||
| 523 | + font-size: 32rpx; | ||
| 524 | + font-weight: bold; | ||
| 525 | + color: #333; | ||
| 526 | + margin-bottom: 20rpx; | ||
| 527 | + padding-left: 10rpx; | ||
| 528 | + border-left: 6rpx solid #007aff; | ||
| 529 | +} | ||
| 530 | + | ||
| 531 | +.section-content { | ||
| 532 | + padding-left: 20rpx; | ||
| 533 | +} | ||
| 534 | + | ||
| 535 | +.clause-item { | ||
| 536 | + font-size: 28rpx; | ||
| 537 | + color: #666; | ||
| 538 | + line-height: 1.6; | ||
| 539 | + margin-bottom: 15rpx; | ||
| 540 | +} | ||
| 541 | + | ||
| 542 | +.clause-list { | ||
| 543 | + margin: 15rpx 0; | ||
| 544 | + padding-left: 20rpx; | ||
| 545 | +} | ||
| 546 | + | ||
| 547 | +.list-item { | ||
| 548 | + font-size: 26rpx; | ||
| 549 | + color: #666; | ||
| 550 | + line-height: 1.5; | ||
| 551 | + margin-bottom: 10rpx; | ||
| 552 | + padding-left: 20rpx; | ||
| 553 | + position: relative; | ||
| 554 | +} | ||
| 555 | + | ||
| 556 | +.list-item::before { | ||
| 557 | + content: '•'; | ||
| 558 | + position: absolute; | ||
| 559 | + left: 0; | ||
| 560 | + color: #007aff; | ||
| 561 | + font-weight: bold; | ||
| 562 | +} | ||
| 563 | +.list-item1 { | ||
| 564 | + font-size: 26rpx; | ||
| 565 | + color: #666; | ||
| 566 | + line-height: 1.5; | ||
| 567 | + margin-bottom: 10rpx; | ||
| 568 | + padding-left: 20rpx; | ||
| 569 | + position: relative; | ||
| 570 | +} | ||
| 571 | + | ||
| 572 | +.list-item1::before { | ||
| 573 | + content: '•'; | ||
| 574 | + position: absolute; | ||
| 575 | + left: 0; | ||
| 576 | + color: #007aff; | ||
| 577 | + font-weight: bold; | ||
| 578 | +} | ||
| 579 | + | ||
| 580 | +.agreement-footer { | ||
| 581 | + font-size: 28rpx; | ||
| 582 | + color: #999; | ||
| 583 | + text-align: center; | ||
| 584 | + margin-top: 40rpx; | ||
| 585 | + padding-top: 20rpx; | ||
| 586 | + border-top: 2rpx solid #e5e5e5; | ||
| 587 | + font-style: italic; | ||
| 588 | +} | ||
| 589 | +</style> |
| ... | @@ -74,16 +74,23 @@ | ... | @@ -74,16 +74,23 @@ |
| 74 | 74 | ||
| 75 | <!-- 自定义TabBar --> | 75 | <!-- 自定义TabBar --> |
| 76 | <TabBar /> | 76 | <TabBar /> |
| 77 | + | ||
| 78 | + <!-- 隐私政策同意弹框 --> | ||
| 79 | + <PrivacyAgreementModal | ||
| 80 | + v-model:visible="showPrivacyModal" | ||
| 81 | + @confirm="onPrivacyConfirm" | ||
| 82 | + @cancel="onPrivacyCancel" | ||
| 83 | + /> | ||
| 77 | </view> | 84 | </view> |
| 78 | </template> | 85 | </template> |
| 79 | 86 | ||
| 80 | <script setup> | 87 | <script setup> |
| 81 | -import { computed } from 'vue' | 88 | +import { computed, ref } from 'vue' |
| 82 | import { Heart, Clock, Notice, Cart, Message, Tips, Right, StarN } from '@nutui/icons-vue-taro' | 89 | import { Heart, Clock, Notice, Cart, Message, Tips, Right, StarN } from '@nutui/icons-vue-taro' |
| 83 | import Taro, { useDidShow } from '@tarojs/taro' | 90 | import Taro, { useDidShow } from '@tarojs/taro' |
| 84 | import TabBar from '@/components/TabBar.vue' | 91 | import TabBar from '@/components/TabBar.vue' |
| 92 | +import PrivacyAgreementModal from '@/components/PrivacyAgreementModal.vue' | ||
| 85 | import { useUserStore } from '@/stores/user' | 93 | import { useUserStore } from '@/stores/user' |
| 86 | -// import { checkPermission, PERMISSION_TYPES } from '@/utils/permission' | ||
| 87 | 94 | ||
| 88 | // 默认头像 | 95 | // 默认头像 |
| 89 | const defaultAvatar = 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg' | 96 | const defaultAvatar = 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg' |
| ... | @@ -94,6 +101,9 @@ const userStore = useUserStore() | ... | @@ -94,6 +101,9 @@ const userStore = useUserStore() |
| 94 | // 用户信息计算属性 | 101 | // 用户信息计算属性 |
| 95 | const userInfo = computed(() => userStore.userInfo) | 102 | const userInfo = computed(() => userStore.userInfo) |
| 96 | 103 | ||
| 104 | +// 隐私政策弹框状态 | ||
| 105 | +const showPrivacyModal = ref(false) | ||
| 106 | + | ||
| 97 | useDidShow(async () => { | 107 | useDidShow(async () => { |
| 98 | await userStore.fetchUserInfo() | 108 | await userStore.fetchUserInfo() |
| 99 | }) | 109 | }) |
| ... | @@ -101,10 +111,36 @@ useDidShow(async () => { | ... | @@ -101,10 +111,36 @@ useDidShow(async () => { |
| 101 | /** | 111 | /** |
| 102 | * 编辑个人资料 | 112 | * 编辑个人资料 |
| 103 | */ | 113 | */ |
| 104 | -const onEditProfile = () => { | 114 | +const onEditProfile = async () => { |
| 115 | + // 检查用户是否已完善资料 | ||
| 116 | + const hasCompleteProfile = userStore.hasCompleteProfile | ||
| 117 | + | ||
| 118 | + if (hasCompleteProfile) { | ||
| 119 | + // 已完善资料,直接进入编辑页面 | ||
| 105 | Taro.navigateTo({ | 120 | Taro.navigateTo({ |
| 106 | url: '/pages/editProfile/index' | 121 | url: '/pages/editProfile/index' |
| 107 | }) | 122 | }) |
| 123 | + } else { | ||
| 124 | + // 未完善资料,显示隐私政策同意弹框 | ||
| 125 | + showPrivacyModal.value = true | ||
| 126 | + } | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | +/** | ||
| 130 | + * 隐私政策确认 | ||
| 131 | + */ | ||
| 132 | +const onPrivacyConfirm = () => { | ||
| 133 | + // 用户同意隐私政策后,跳转到编辑资料页面 | ||
| 134 | + Taro.navigateTo({ | ||
| 135 | + url: '/pages/editProfile/index' | ||
| 136 | + }) | ||
| 137 | +} | ||
| 138 | + | ||
| 139 | +/** | ||
| 140 | + * 隐私政策取消 | ||
| 141 | + */ | ||
| 142 | +const onPrivacyCancel = () => { | ||
| 143 | + // 用户取消,不做任何操作 | ||
| 108 | } | 144 | } |
| 109 | 145 | ||
| 110 | /** | 146 | /** | ... | ... |
-
Please register or login to post a comment