hookehuyr

feat(用户协议): 添加用户服务协议弹窗组件并集成到隐私协议中

- 创建独立的用户服务协议弹窗组件
- 在隐私协议中集成该组件并实现联动逻辑
- 为隐私协议添加底部确认按钮
...@@ -49,5 +49,6 @@ declare module 'vue' { ...@@ -49,5 +49,6 @@ declare module 'vue' {
49 RouterView: typeof import('vue-router')['RouterView'] 49 RouterView: typeof import('vue-router')['RouterView']
50 SearchPopup: typeof import('./src/components/SearchPopup.vue')['default'] 50 SearchPopup: typeof import('./src/components/SearchPopup.vue')['default']
51 TabBar: typeof import('./src/components/TabBar.vue')['default'] 51 TabBar: typeof import('./src/components/TabBar.vue')['default']
52 + UserServiceAgreementModal: typeof import('./src/components/UserServiceAgreementModal.vue')['default']
52 } 53 }
53 } 54 }
......
...@@ -78,13 +78,27 @@ ...@@ -78,13 +78,27 @@
78 <view class="content-text" v-html="contentText"></view> 78 <view class="content-text" v-html="contentText"></view>
79 </view> 79 </view>
80 </scroll-view> 80 </scroll-view>
81 +
82 + <!-- 底部按钮 -->
83 + <view class="modal-footer">
84 + <nut-button type="primary" block color="#fb923c" @click="onCloseContentModal">
85 + 我已阅读并同意
86 + </nut-button>
87 + </view>
81 </view> 88 </view>
82 </nut-popup> 89 </nut-popup>
90 +
91 + <!-- 用户服务协议弹窗 -->
92 + <UserServiceAgreementModal
93 + v-model:visible="showUserAgreementModal"
94 + @confirm="onUserAgreementConfirm"
95 + />
83 </template> 96 </template>
84 97
85 <script setup> 98 <script setup>
86 import { ref, computed, watch, defineEmits, defineProps } from 'vue' 99 import { ref, computed, watch, defineEmits, defineProps } from 'vue'
87 import Taro from '@tarojs/taro' 100 import Taro from '@tarojs/taro'
101 +import UserServiceAgreementModal from './UserServiceAgreementModal.vue'
88 102
89 // Props 103 // Props
90 const props = defineProps({ 104 const props = defineProps({
...@@ -99,6 +113,7 @@ const emit = defineEmits(['update:visible', 'confirm', 'cancel']) ...@@ -99,6 +113,7 @@ const emit = defineEmits(['update:visible', 'confirm', 'cancel'])
99 113
100 // 响应式数据 114 // 响应式数据
101 const agreed = ref(false) 115 const agreed = ref(false)
116 +const showUserAgreementModal = ref(false)
102 117
103 // 监听弹框显示状态,每次打开时重置agreed 118 // 监听弹框显示状态,每次打开时重置agreed
104 watch(() => props.visible, (newVisible) => { 119 watch(() => props.visible, (newVisible) => {
...@@ -229,9 +244,7 @@ const contentText = ref('') ...@@ -229,9 +244,7 @@ const contentText = ref('')
229 * 点击用户服务协议 244 * 点击用户服务协议
230 */ 245 */
231 const onUserAgreementClick = () => { 246 const onUserAgreementClick = () => {
232 - contentTitle.value = '用户服务协议' 247 + showUserAgreementModal.value = true
233 - contentText.value = userAgreementContent
234 - showContentModal.value = true
235 } 248 }
236 249
237 /** 250 /**
...@@ -262,6 +275,13 @@ const onCancel = () => { ...@@ -262,6 +275,13 @@ const onCancel = () => {
262 } 275 }
263 276
264 /** 277 /**
278 + * 用户服务协议确认
279 + */
280 +const onUserAgreementConfirm = () => {
281 + showUserAgreementModal.value = false
282 +}
283 +
284 +/**
265 * 确认操作 285 * 确认操作
266 */ 286 */
267 const onConfirm = () => { 287 const onConfirm = () => {
...@@ -508,4 +528,13 @@ const onConfirm = () => { ...@@ -508,4 +528,13 @@ const onConfirm = () => {
508 border-top: 2rpx solid #e5e5e5; 528 border-top: 2rpx solid #e5e5e5;
509 font-style: italic; 529 font-style: italic;
510 } 530 }
531 +
532 +.modal-footer {
533 + padding: 32rpx;
534 + border-top: 1rpx solid #eee;
535 + background: white;
536 + position: sticky;
537 + bottom: 0;
538 + z-index: 10;
539 +}
511 </style> 540 </style>
......
1 +<!--
2 + * @Date: 2025-01-27
3 + * @Description: 用户服务协议弹窗组件
4 +-->
5 +<template>
6 + <!-- 内容全屏显示弹框 -->
7 + <nut-popup
8 + v-model:visible="showModal"
9 + position="right"
10 + :closeable="true"
11 + :close-on-click-overlay="true"
12 + :safe-area-inset-bottom="true"
13 + :style="{ width: '100%', height: '100%' }"
14 + @close="closeModal"
15 + >
16 + <view class="content-container">
17 + <!-- 标题栏 -->
18 + <view class="content-header">
19 + <text class="content-title">用户服务协议</text>
20 + <view class="close-btn" @click="closeModal">
21 + <text class="close-text">×</text>
22 + </view>
23 + </view>
24 +
25 + <!-- 内容区域 -->
26 + <scroll-view class="content-scroll" :scroll-y="true">
27 + <view class="content-body">
28 + <view class="agreement-text">
29 + <text class="notice-text">
30 + 【注意】本合同采用线上模式签署,请认真阅读本合同内容,尤其是加粗内容,可能涉及到签署方密切相关的权利义务,请务必仔细阅读后再签署。一旦点击或者勾选即代表认可本合同内容。
31 + </text>
32 +
33 + <text class="title-text">二手电动车交易三方合同</text>
34 +
35 + <text class="content-text">
36 + 甲乙双方通过丙方的捡个电驴平台达成车辆交易,丙方为二手电动车现场和/或在线交易的服务提供方。根据《中华人民共和国民法典》及其他有关法律法规,经友好协商,三方在平等自愿的基础上,就甲乙双方在丙方平台进行车辆交易事项达成如下协议。
37 + </text>
38 +
39 + <text class="section-title">1. 本合同中的专用术语定义</text>
40 + <text class="content-text">
41 + 1.1. "捡个电驴平台",系指丙方提供的二手电动车现场和/或在线交易的服务平台,以下简称"平台"。
42 + </text>
43 + <text class="content-text">
44 + 1.2. "甲方",系指具有完全的民事行为能力的车辆所有权人或处置权人,能够出售或处置本合同约定的交易车辆并有权获取交易价款的企业法人/自然人。
45 + </text>
46 + <text class="content-text">
47 + 1.3. "乙方",系指具有完全的民事行为能力的购买本合同交易车辆并支付交易价款的企业法人/自然人。
48 + </text>
49 + <text class="content-text">
50 + 1.4. "捡个电驴平台规则",系指丙方在"捡个电驴平台"及交易现场公示的交易规则包括但不限于《用户隐私权条款》、《二手电动车交易和处理规则》等。
51 + </text>
52 + <text class="content-text">
53 + 1.5. 代办过户服务:系指丙方接受甲方或乙方的委托,根据委托方的指示代为办理车辆过户等手续等具体事项。
54 + </text>
55 +
56 + <text class="section-title">2. 交易车辆信息</text>
57 + <text class="content-text">
58 + 平台的"商品详情"页面显示的内容,都是甲方提供的,真实有效的交易车辆的信息,包括:品牌型号、交易价格等。
59 + </text>
60 +
61 + <text class="section-title">3. 购车款及支付方式</text>
62 + <text class="content-text">
63 + 3.1. 本合同车辆最终成交价格,平台收到由乙方打款后,钱款暂存至平台,待买家在平台点击"确认收货"后,平台将钱款打至甲方账户。甲乙双方确定共同委托丙方代收本合同车辆价款,丙方系根据甲乙双方委托代为保管购车款并根据本合同约定义务完成情况按照指示将车辆价款支付给甲方。丙方未授权任何员工、第三方收款;乙方未在平台上完成支付,导致损失的,丙方不承担任何责任。
64 + </text>
65 + <text class="content-text">
66 + 3.2. 甲乙双方均确认自丙方将代收车辆价款支付至甲方指定收款账户即视为履行完毕义务。丙方收到车辆价款后于3个工作日内支付至甲方指定收款账户。
67 + </text>
68 +
69 + <text class="section-title">4. 丙方服务项目及相关费用</text>
70 + <text class="content-text">
71 + 4.1. 本合同项下,丙方为甲方、乙方提供的服务事项包括:
72 + </text>
73 + <text class="content-text">
74 + 4.1.1交易撮合服务:提供信息发布、买卖双方沟通及交易促成服务,费用为成交金额的1%
75 + </text>
76 + <text class="content-text">
77 + 4.2服务费用支付
78 + </text>
79 + <text class="content-text">
80 + 4.2. 在平台上完成交易后,系统自动从成交金额里扣除服务费
81 + </text>
82 + <text class="content-text">
83 + 4.3. 丙方提供了本合同交易服务,如交易事项未达成的,已收取的服务费不予退还。
84 + </text>
85 +
86 + <text class="section-title">5. 车辆转移登记</text>
87 + <text class="content-text">
88 + 5.1. 甲乙双方应当相互协助共同配合完成车辆过户手续,办理转移登记手续产生的相关费用(包含税费等)由甲乙双方协商承担。
89 + </text>
90 +
91 + <text class="section-title">6. 车辆保管及交付</text>
92 + <text class="content-text">
93 + 6.1. 车辆保管
94 + </text>
95 + <text class="content-text">
96 + 6.1.1. 甲乙双方均明确在车辆转移登记完成及正式交付前,与车辆有关的意外风险和责任由使用和保管方承担。
97 + </text>
98 + <text class="content-text">
99 + 6.2. 车辆交付
100 + </text>
101 + <text class="content-text">
102 + 6.2.1. 在车辆交付乙方之前所发生的所有风险由甲方承担和负责处理;在车辆交付乙方之后所发生的所有风险由乙方承担和负责处理。
103 + </text>
104 +
105 + <text class="section-title">7. 甲乙双方及丙方承诺</text>
106 + <text class="content-text">
107 + 7.1. 甲方对其委托处置的车辆享有完全合法的所有权或处置权。甲方保证本合同所涉车辆归己方所有或已获得车辆所有权人办理本合同交易相关事项授权。
108 + </text>
109 + <text class="content-text">
110 + 7.2. 甲方负责审核平台发布交易信息的真实性,如未如实披露导致乙方或丙方权益受损的,甲方应承担一切后果及损失。甲方应如实、完整、全面向乙方、丙方披露交易的车辆完整信息,包括但不限于:
111 + </text>
112 + <text class="content-text">
113 + 7.2.1. 车辆发生过的重大事故情况;
114 + </text>
115 + <text class="content-text">
116 + 7.2.2. 车辆全部的手续材料,如有缺失,如实说明;
117 + </text>
118 + <text class="content-text">
119 + 7.2.3. 车辆应缴而未缴的相关费用;
120 + </text>
121 + <text class="content-text">
122 + 7.2.4. 车辆所有权人的真实信息;
123 + </text>
124 + <text class="content-text">
125 + 7.2.5. 车辆来源正规合法,非盗抢车辆;
126 + </text>
127 + <text class="content-text">
128 + 7.2.6. 车辆存在的债权债务纠纷;
129 + </text>
130 + <text class="content-text">
131 + 7.2.7. 其他可能会影响交易的信息。
132 + </text>
133 + <text class="content-text">
134 + 7.3. 甲乙双方在办理车辆过户过程当中应积极配合、提供所需资料。因未及时提供资料造成上述各项手续办理延期的,由甲乙双方根据各自义务承担相应责任,发生争议的,双方可申请丙方协调解决,但丙方不承担任何责任。
135 + </text>
136 + <text class="content-text">
137 + 7.4. 因电动车车辆过户政策各地情况不同,乙方在签订本合同时,必须详细了解购买车辆所需过户政策及所需手续并确保二手电动车能够办理落户,车辆无法办理落户的丙方不承担任何责任。
138 + </text>
139 + <text class="content-text">
140 + 7.5. 丙方保证以严格、审慎和专业的态度履行交易流程中的应尽义务,丙方不得采取欺诈、胁迫和恶意串通等手段促成交易,并应为甲乙双方保守商业秘密。
141 + </text>
142 + <text class="content-text">
143 + 7.6. 在本合同签约或开展业务活动过程中,甲方、乙方及其工作人员不得以现金、银行转账、微信转账、支付宝转账等形式向丙方工作人员支付任何款项,不得私自向丙方工作人员馈赠财物,不得接受丙方工作人员的任何理由的借款请求,不得以其他任何方式直接或间接侵害丙方的合法权益。如存在上述行为的,丙方有权按照涉案金额的十倍收取违约金,由此给丙方造成的全部损失均由违约方承担。
144 + </text>
145 +
146 + <text class="section-title">8. 违约责任</text>
147 + <text class="content-text">
148 + 8.1. 甲方未按合同的约定将车辆及其相关凭证交付乙方的,每逾期一日,应按逾期交付车辆价款金额的1%(百分之一)向甲方支付违约金。超过30日的,乙方有权解除合同、返还车辆并要求甲方返还购车款,平台服务费不予以退换
149 + </text>
150 + <text class="content-text">
151 + 8.2. 车辆转籍、过户相关责任
152 + </text>
153 + <text class="content-text">
154 + 8.2.1. 因甲方原因致使车辆不能办理过户手续的,乙方有权解除合同要求甲方返还车辆价款并承担一切损失。平台服务费不予以退还。
155 + </text>
156 + <text class="content-text">
157 + 8.2.2. 因乙方原因致使车辆不能办理过户手续的,甲方有权解除合同要求乙方返还车辆并承担一切损失,平台服务费不予以退还。
158 + </text>
159 + <text class="content-text">
160 + 8.3. 任何一方有其他违反本合同情形的,应赔偿守约方全部损失。
161 + </text>
162 +
163 + <text class="section-title">9. 特别提示</text>
164 + <text class="content-text">
165 + 甲方、乙方须认真阅读、充分理解上述协议和平台服务规则的条款,特别是其中所涉及的免除及限制捡个电驴平台责任的条款、对甲方、乙方权利限制条款等。丙方有权根据服务的实际需要进行变更及调整平台服务协议规则,变更及调整后的内容将在捡个电驴平台内进行公示或在甲方、乙方的 捡个电驴平台账号内进行通知。甲方、乙方如不同意本合同及上述平台服务规则中任何条款的约定,均应立即停止使用 捡个电驴平台 服务并解除本合同。如果甲方、乙方继续使用丙方服务,则视为甲方、乙方已完全理解并接受丙方对本合同及 捡个电驴平台 所涉内容、服务费标准或交易规则所做的修改,并应遵照修改后的协议进行。
166 + </text>
167 +
168 + <text class="section-title">10. 其他约定</text>
169 + <text class="content-text">
170 + 10.1. 不可抗力
171 + </text>
172 + <text class="content-text">
173 + 10.1.1. 不可抗力定义:指在本合同签署后发生的、本合同签署时不能预见的、其发生与后果是无法避免或克服的、妨碍任何一方全部或部分履约的所有事件。上述事件包括地震、台风、水灾、火灾、战争、国际或国内运输中断、流行病、罢工,以及根据中国法律或一般国际商业惯例认作不可抗力的其他事件。一方缺少资金非为不可抗力事件。
174 + </text>
175 + <text class="content-text">
176 + 10.1.2. 不可抗力的后果:
177 + </text>
178 + <text class="content-text">
179 + (1)如果发生不可抗力事件,影响一方履行其在本合同项下的义务,则在不可抗力造成的延误期内中止履行,而不视为违约。
180 + </text>
181 + <text class="content-text">
182 + (2)宣称发生不可抗力的一方应迅速书面通知其他各方,并在其后的十五天内提供证明不可抗力发生及其持续时间的足够证据。
183 + </text>
184 + <text class="content-text">
185 + (3)如果发生不可抗力事件,各方应立即互相协商,以找到公平的解决办法,并且应尽一切合理努力将不可抗力的影响减少到最低限度。
186 + </text>
187 + <text class="content-text">
188 + (4)金钱债务的迟延责任不得因不可抗力而免除。
189 + </text>
190 + <text class="content-text">
191 + (5)迟延履行期间发生的不可抗力不具有免责效力。
192 + </text>
193 + <text class="content-text">
194 + 10.2. 部分无效处理
195 + </text>
196 + <text class="content-text">
197 + 如任何法院或有权机关认为本合同的任何部分无效、不合法或不可执行,则该部分不应被认为构成本合同的一部分,但不应影响本合同其余部分的合法有效性及可执行性。
198 + </text>
199 +
200 + <text class="section-title">11. 争议解决</text>
201 + <text class="content-text">
202 + 因本合同以及本合同项下订单/附件/补充协议等(如有)引起或有关的任何争议,由合同各方协商解决,也可由有关部门调解。协商或调解不成的,应向丙方所在地有管辖权的人民法院起诉。
203 + </text>
204 + </view>
205 + </view>
206 + </scroll-view>
207 +
208 + <!-- 底部按钮 -->
209 + <view class="modal-footer">
210 + <nut-button type="primary" block color="#fb923c" @click="confirmAgreement">
211 + 我已阅读并同意
212 + </nut-button>
213 + </view>
214 + </view>
215 + </nut-popup>
216 +</template>
217 +
218 +<script setup>
219 +import { ref, watch, defineEmits, defineProps } from 'vue'
220 +
221 +/**
222 + * 组件属性定义
223 + */
224 +const props = defineProps({
225 + visible: {
226 + type: Boolean,
227 + default: false
228 + }
229 +})
230 +
231 +/**
232 + * 组件事件定义
233 + */
234 +const emit = defineEmits(['update:visible', 'confirm'])
235 +
236 +/**
237 + * 响应式数据
238 + */
239 +const showModal = ref(props.visible)
240 +
241 +/**
242 + * 监听props变化
243 + */
244 +watch(() => props.visible, (newVal) => {
245 + showModal.value = newVal
246 +})
247 +
248 +/**
249 + * 关闭弹窗
250 + */
251 +const closeModal = () => {
252 + showModal.value = false
253 + emit('update:visible', false)
254 +}
255 +
256 +/**
257 + * 确认协议
258 + */
259 +const confirmAgreement = () => {
260 + emit('confirm')
261 + closeModal()
262 +}
263 +</script>
264 +
265 +<style lang="less">
266 +.content-container {
267 + width: 100%;
268 + height: 100vh;
269 + background: white;
270 + display: flex;
271 + flex-direction: column;
272 +}
273 +
274 +.content-header {
275 + display: flex;
276 + justify-content: space-between;
277 + align-items: center;
278 + padding: 32rpx 40rpx;
279 + border-bottom: 1rpx solid #eee;
280 + background: white;
281 + position: sticky;
282 + top: 0;
283 + z-index: 10;
284 +}
285 +
286 +.content-title {
287 + font-size: 36rpx;
288 + font-weight: bold;
289 + color: #333;
290 +}
291 +
292 +.close-btn {
293 + width: 60rpx;
294 + height: 60rpx;
295 + display: flex;
296 + align-items: center;
297 + justify-content: center;
298 + background: #f5f5f5;
299 + border-radius: 50%;
300 + cursor: pointer;
301 +}
302 +
303 +.close-text {
304 + font-size: 40rpx;
305 + color: #666;
306 + line-height: 1;
307 +}
308 +
309 +.content-scroll {
310 + flex: 1;
311 + height: 0;
312 +}
313 +
314 +.content-body {
315 + padding: 40rpx;
316 +
317 + .agreement-text {
318 + .notice-text {
319 + display: block;
320 + font-size: 28rpx;
321 + color: #ff4444;
322 + font-weight: 600;
323 + line-height: 1.6;
324 + margin-bottom: 32rpx;
325 + padding: 24rpx;
326 + background: #fff5f5;
327 + border-radius: 12rpx;
328 + border-left: 8rpx solid #ff4444;
329 + }
330 +
331 + .title-text {
332 + display: block;
333 + font-size: 36rpx;
334 + font-weight: 700;
335 + color: #333;
336 + text-align: center;
337 + margin-bottom: 32rpx;
338 + }
339 +
340 + .section-title {
341 + display: block;
342 + font-size: 32rpx;
343 + font-weight: 600;
344 + color: #333;
345 + margin: 32rpx 0 16rpx 0;
346 + }
347 +
348 + .content-text {
349 + display: block;
350 + font-size: 28rpx;
351 + color: #666;
352 + line-height: 1.8;
353 + margin-bottom: 16rpx;
354 + text-align: justify;
355 + }
356 + }
357 +}
358 +
359 +.modal-footer {
360 + padding: 32rpx;
361 + border-top: 1rpx solid #eee;
362 + background: white;
363 + position: sticky;
364 + bottom: 0;
365 + z-index: 10;
366 +}
367 +</style>