feat(authCar): 添加支付协议勾选功能及弹窗
增加支付协议勾选组件和协议弹窗展示功能 修改认证按钮逻辑,需同意协议方可操作 添加用户协议状态检查及更新逻辑
Showing
3 changed files
with
208 additions
and
6 deletions
| ... | @@ -499,3 +499,85 @@ | ... | @@ -499,3 +499,85 @@ |
| 499 | .popup-content::-webkit-scrollbar-thumb:hover { | 499 | .popup-content::-webkit-scrollbar-thumb:hover { |
| 500 | background: #a8a8a8; | 500 | background: #a8a8a8; |
| 501 | } | 501 | } |
| 502 | + | ||
| 503 | +/* 协议勾选区域样式 */ | ||
| 504 | +.agreement-section { | ||
| 505 | + margin: 32rpx 0; | ||
| 506 | + padding: 0 32rpx; | ||
| 507 | + text-align: center; | ||
| 508 | + | ||
| 509 | + .agreement-checkbox { | ||
| 510 | + font-size: 28rpx; | ||
| 511 | + | ||
| 512 | + .checkbox-text { | ||
| 513 | + white-space: nowrap; | ||
| 514 | + display: inline-block; | ||
| 515 | + } | ||
| 516 | + | ||
| 517 | + .agreement-link { | ||
| 518 | + color: #ffa500; | ||
| 519 | + text-decoration: underline; | ||
| 520 | + cursor: pointer; | ||
| 521 | + } | ||
| 522 | + } | ||
| 523 | +} | ||
| 524 | + | ||
| 525 | +/* 支付协议弹框样式 */ | ||
| 526 | +.protocol-container { | ||
| 527 | + width: 100%; | ||
| 528 | + height: 100vh; | ||
| 529 | + background: white; | ||
| 530 | + display: flex; | ||
| 531 | + flex-direction: column; | ||
| 532 | +} | ||
| 533 | + | ||
| 534 | +.protocol-header { | ||
| 535 | + display: flex; | ||
| 536 | + justify-content: space-between; | ||
| 537 | + align-items: center; | ||
| 538 | + padding: 32rpx 40rpx; | ||
| 539 | + border-bottom: 1rpx solid #eee; | ||
| 540 | + background: white; | ||
| 541 | + position: sticky; | ||
| 542 | + top: 0; | ||
| 543 | + z-index: 10; | ||
| 544 | +} | ||
| 545 | + | ||
| 546 | +.protocol-title { | ||
| 547 | + font-size: 36rpx; | ||
| 548 | + font-weight: bold; | ||
| 549 | + color: #333; | ||
| 550 | +} | ||
| 551 | + | ||
| 552 | +.close-btn { | ||
| 553 | + width: 60rpx; | ||
| 554 | + height: 60rpx; | ||
| 555 | + display: flex; | ||
| 556 | + align-items: center; | ||
| 557 | + justify-content: center; | ||
| 558 | + background: #f5f5f5; | ||
| 559 | + border-radius: 50%; | ||
| 560 | + cursor: pointer; | ||
| 561 | +} | ||
| 562 | + | ||
| 563 | +.close-text { | ||
| 564 | + font-size: 40rpx; | ||
| 565 | + color: #666; | ||
| 566 | + line-height: 1; | ||
| 567 | +} | ||
| 568 | + | ||
| 569 | +.protocol-scroll { | ||
| 570 | + flex: 1; | ||
| 571 | + padding: 0 40rpx; | ||
| 572 | +} | ||
| 573 | + | ||
| 574 | +.protocol-body { | ||
| 575 | + padding: 40rpx 0; | ||
| 576 | +} | ||
| 577 | + | ||
| 578 | +.protocol-text { | ||
| 579 | + font-size: 28rpx; | ||
| 580 | + line-height: 1.8; | ||
| 581 | + color: #333; | ||
| 582 | + white-space: pre-line; | ||
| 583 | +} | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-19 14:11:06 | 2 | * @Date: 2022-09-19 14:11:06 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-08-04 13:29:45 | 4 | + * @LastEditTime: 2025-08-05 20:33:55 |
| 5 | * @FilePath: /jgdl/src/pages/authCar/index.vue | 5 | * @FilePath: /jgdl/src/pages/authCar/index.vue |
| 6 | * @Description: 认证车源 | 6 | * @Description: 认证车源 |
| 7 | --> | 7 | --> |
| ... | @@ -101,17 +101,63 @@ | ... | @@ -101,17 +101,63 @@ |
| 101 | </view> | 101 | </view> |
| 102 | </scroll-view> | 102 | </scroll-view> |
| 103 | 103 | ||
| 104 | + <!-- 协议勾选区域 --> | ||
| 105 | + <div v-if="!hasAgreed" class="agreement-section"> | ||
| 106 | + <nut-checkbox v-model="isChecked" class="agreement-checkbox"> | ||
| 107 | + <view class="checkbox-text"> | ||
| 108 | + <text>我已阅读并同意</text> | ||
| 109 | + <text class="agreement-link" @tap.stop="showProtocol"> | ||
| 110 | + 《支付协议》 | ||
| 111 | + </text> | ||
| 112 | + </view> | ||
| 113 | + </nut-checkbox> | ||
| 114 | + </div> | ||
| 115 | + | ||
| 104 | <!-- 底部按钮 --> | 116 | <!-- 底部按钮 --> |
| 105 | <view class="popup-footer"> | 117 | <view class="popup-footer"> |
| 106 | <nut-button plain class="footer-btn cancel-btn" @click="showAuthInfoPopup = false"> | 118 | <nut-button plain class="footer-btn cancel-btn" @click="showAuthInfoPopup = false"> |
| 107 | 关闭 | 119 | 关闭 |
| 108 | </nut-button> | 120 | </nut-button> |
| 109 | - <nut-button type="warning" class="footer-btn confirm-btn" color="#fb923c" @click="handleConfirmAuth"> | 121 | + <nut-button |
| 122 | + type="warning" | ||
| 123 | + class="footer-btn confirm-btn" | ||
| 124 | + color="#fb923c" | ||
| 125 | + :disabled="!hasAgreed && !isChecked" | ||
| 126 | + @click="handleConfirmAuth" | ||
| 127 | + > | ||
| 110 | 知道了 | 128 | 知道了 |
| 111 | </nut-button> | 129 | </nut-button> |
| 112 | </view> | 130 | </view> |
| 113 | </view> | 131 | </view> |
| 114 | </nut-popup> | 132 | </nut-popup> |
| 133 | + | ||
| 134 | + <!-- 支付协议弹框 --> | ||
| 135 | + <nut-popup | ||
| 136 | + v-model:visible="protocolVisible" | ||
| 137 | + position="right" | ||
| 138 | + :closeable="true" | ||
| 139 | + :close-on-click-overlay="true" | ||
| 140 | + :safe-area-inset-bottom="true" | ||
| 141 | + :style="{ width: '100%', height: '100%' }" | ||
| 142 | + @close="protocolVisible = false" | ||
| 143 | + > | ||
| 144 | + <view class="protocol-container"> | ||
| 145 | + <!-- 标题栏 --> | ||
| 146 | + <view class="protocol-header"> | ||
| 147 | + <text class="protocol-title">支付协议</text> | ||
| 148 | + <view class="close-btn" @click="protocolVisible = false"> | ||
| 149 | + <text class="close-text">×</text> | ||
| 150 | + </view> | ||
| 151 | + </view> | ||
| 152 | + | ||
| 153 | + <!-- 内容区域 --> | ||
| 154 | + <scroll-view class="protocol-scroll" :scroll-y="true"> | ||
| 155 | + <view class="protocol-body"> | ||
| 156 | + <view class="protocol-text">{{ protocolContent }}</view> | ||
| 157 | + </view> | ||
| 158 | + </scroll-view> | ||
| 159 | + </view> | ||
| 160 | + </nut-popup> | ||
| 115 | </view> | 161 | </view> |
| 116 | </template> | 162 | </template> |
| 117 | 163 | ||
| ... | @@ -125,8 +171,13 @@ import './index.less' | ... | @@ -125,8 +171,13 @@ import './index.less' |
| 125 | // 接口导入 | 171 | // 接口导入 |
| 126 | import { getVehicleListAPI, getArticleListAPI } from '@/api/car'; | 172 | import { getVehicleListAPI, getArticleListAPI } from '@/api/car'; |
| 127 | import { getVerificationPriceAPI } from '@/api/other'; | 173 | import { getVerificationPriceAPI } from '@/api/other'; |
| 174 | +import { updateProfileAPI, getProfileAPI } from '@/api/index'; | ||
| 175 | +import { useUserStore } from '@/stores/user'; | ||
| 128 | 176 | ||
| 129 | import { DEFAULT_COVER_IMG } from '@/utils/config' | 177 | import { DEFAULT_COVER_IMG } from '@/utils/config' |
| 178 | + | ||
| 179 | +const userStore = useUserStore() | ||
| 180 | + | ||
| 130 | // Banner数据 | 181 | // Banner数据 |
| 131 | const bannerList = ref([]) | 182 | const bannerList = ref([]) |
| 132 | 183 | ||
| ... | @@ -154,6 +205,20 @@ const toastType = ref('success') | ... | @@ -154,6 +205,20 @@ const toastType = ref('success') |
| 154 | // 认证费用说明弹窗 | 205 | // 认证费用说明弹窗 |
| 155 | const showAuthInfoPopup = ref(false) | 206 | const showAuthInfoPopup = ref(false) |
| 156 | 207 | ||
| 208 | +// 协议相关数据 | ||
| 209 | +const isChecked = ref(false) | ||
| 210 | +const hasAgreed = ref(false) | ||
| 211 | +const protocolVisible = ref(false) | ||
| 212 | + | ||
| 213 | +// 支付协议内容 | ||
| 214 | +const protocolContent = ref(` | ||
| 215 | +1. 用户在使用捡个电驴收款服务时,需遵守相关法律法规。 | ||
| 216 | +2. 平台有权对异常交易进行风险控制。 | ||
| 217 | +3. 用户应确保收款信息的真实性和准确性。 | ||
| 218 | +4. 平台将按照约定收取相应的服务费用。 | ||
| 219 | +5. 如有争议,双方应友好协商解决。 | ||
| 220 | +`) | ||
| 221 | + | ||
| 157 | // 滚动样式 | 222 | // 滚动样式 |
| 158 | const scrollStyle = computed(() => { | 223 | const scrollStyle = computed(() => { |
| 159 | return { | 224 | return { |
| ... | @@ -172,7 +237,30 @@ const handleAuth = () => { | ... | @@ -172,7 +237,30 @@ const handleAuth = () => { |
| 172 | /** | 237 | /** |
| 173 | * 确认认证,跳转到认证页面 | 238 | * 确认认证,跳转到认证页面 |
| 174 | */ | 239 | */ |
| 175 | -const handleConfirmAuth = () => { | 240 | +const handleConfirmAuth = async () => { |
| 241 | + // 如果未同意协议且未勾选,不允许操作 | ||
| 242 | + if (!hasAgreed.value && !isChecked.value) { | ||
| 243 | + return | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + // 如果勾选了但还未同意,先更新协议状态 | ||
| 247 | + if (!hasAgreed.value && isChecked.value) { | ||
| 248 | + try { | ||
| 249 | + const result = await updateProfileAPI({ | ||
| 250 | + is_signed: true | ||
| 251 | + }) | ||
| 252 | + | ||
| 253 | + if (result.code) { | ||
| 254 | + hasAgreed.value = true | ||
| 255 | + if (userStore.userInfo) { | ||
| 256 | + userStore.userInfo.is_signed = true | ||
| 257 | + } | ||
| 258 | + } | ||
| 259 | + } catch (error) { | ||
| 260 | + console.error('更新协议状态失败:', error) | ||
| 261 | + } | ||
| 262 | + } | ||
| 263 | + | ||
| 176 | // 关闭弹窗 | 264 | // 关闭弹窗 |
| 177 | showAuthInfoPopup.value = false | 265 | showAuthInfoPopup.value = false |
| 178 | // 跳转到认证页面 | 266 | // 跳转到认证页面 |
| ... | @@ -194,6 +282,34 @@ const onCarClick = (car) => { | ... | @@ -194,6 +282,34 @@ const onCarClick = (car) => { |
| 194 | const { toggleFavorite } = useFavorite() | 282 | const { toggleFavorite } = useFavorite() |
| 195 | 283 | ||
| 196 | /** | 284 | /** |
| 285 | + * 显示支付协议 | ||
| 286 | + */ | ||
| 287 | +const showProtocol = () => { | ||
| 288 | + protocolVisible.value = true | ||
| 289 | +} | ||
| 290 | + | ||
| 291 | +/** | ||
| 292 | + * 检查用户是否已同意过协议 | ||
| 293 | + */ | ||
| 294 | +const checkAgreementStatus = async () => { | ||
| 295 | + try { | ||
| 296 | + const result = await getProfileAPI() | ||
| 297 | + | ||
| 298 | + if (result.code && result.data) { | ||
| 299 | + hasAgreed.value = result.data.is_signed || false | ||
| 300 | + if (userStore.userInfo) { | ||
| 301 | + userStore.userInfo.is_signed = result.data.is_signed | ||
| 302 | + } | ||
| 303 | + } else { | ||
| 304 | + hasAgreed.value = userStore.userInfo?.is_signed || false | ||
| 305 | + } | ||
| 306 | + } catch (error) { | ||
| 307 | + console.error('获取用户协议状态失败:', error) | ||
| 308 | + hasAgreed.value = userStore.userInfo?.is_signed || false | ||
| 309 | + } | ||
| 310 | +} | ||
| 311 | + | ||
| 312 | +/** | ||
| 197 | * 加载认证车辆数据 | 313 | * 加载认证车辆数据 |
| 198 | * @param {boolean} isLoadMore - 是否为加载更多 | 314 | * @param {boolean} isLoadMore - 是否为加载更多 |
| 199 | */ | 315 | */ |
| ... | @@ -288,6 +404,8 @@ const getVerificationPrice = async () => { | ... | @@ -288,6 +404,8 @@ const getVerificationPrice = async () => { |
| 288 | 404 | ||
| 289 | // 初始化 | 405 | // 初始化 |
| 290 | onMounted(async () => { | 406 | onMounted(async () => { |
| 407 | + // 检查协议状态 | ||
| 408 | + await checkAgreementStatus() | ||
| 291 | // 加载初始认证车辆数据 | 409 | // 加载初始认证车辆数据 |
| 292 | await loadAuthCarData() | 410 | await loadAuthCarData() |
| 293 | // 获取认证费用 | 411 | // 获取认证费用 | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-19 14:11:06 | 2 | * @Date: 2022-09-19 14:11:06 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-08-05 18:35:51 | 4 | + * @LastEditTime: 2025-08-05 20:03:22 |
| 5 | * @FilePath: /jgdl/src/pages/collectionSettings/index.vue | 5 | * @FilePath: /jgdl/src/pages/collectionSettings/index.vue |
| 6 | * @Description: 收款设置 | 6 | * @Description: 收款设置 |
| 7 | --> | 7 | --> |
| ... | @@ -41,7 +41,7 @@ | ... | @@ -41,7 +41,7 @@ |
| 41 | <nut-popup | 41 | <nut-popup |
| 42 | v-model:visible="showAccountModal" | 42 | v-model:visible="showAccountModal" |
| 43 | position="bottom" | 43 | position="bottom" |
| 44 | - :style="{ width: '100%', height: '80%' }" | 44 | + :style="{ width: '100%', height: '85%' }" |
| 45 | :catch-move="true" | 45 | :catch-move="true" |
| 46 | closeable | 46 | closeable |
| 47 | close-icon-position="top-right" | 47 | close-icon-position="top-right" |
| ... | @@ -69,6 +69,7 @@ | ... | @@ -69,6 +69,7 @@ |
| 69 | placeholder="请输入银行账号" | 69 | placeholder="请输入银行账号" |
| 70 | class="form-input" | 70 | class="form-input" |
| 71 | type="number" | 71 | type="number" |
| 72 | + :cursorSpacing="50" | ||
| 72 | /> | 73 | /> |
| 73 | </view> | 74 | </view> |
| 74 | </view> | 75 | </view> |
| ... | @@ -98,7 +99,7 @@ | ... | @@ -98,7 +99,7 @@ |
| 98 | <nut-popup | 99 | <nut-popup |
| 99 | v-model:visible="showIdentityModal" | 100 | v-model:visible="showIdentityModal" |
| 100 | position="bottom" | 101 | position="bottom" |
| 101 | - :style="{ width: '100%', height: '80%' }" | 102 | + :style="{ width: '100%', height: '85%' }" |
| 102 | :catch-move="true" | 103 | :catch-move="true" |
| 103 | closeable | 104 | closeable |
| 104 | close-icon-position="top-right" | 105 | close-icon-position="top-right" |
| ... | @@ -127,6 +128,7 @@ | ... | @@ -127,6 +128,7 @@ |
| 127 | class="form-input" | 128 | class="form-input" |
| 128 | maxlength="18" | 129 | maxlength="18" |
| 129 | @blur="handleIdCardBlur" | 130 | @blur="handleIdCardBlur" |
| 131 | + :cursorSpacing="50" | ||
| 130 | /> | 132 | /> |
| 131 | <text v-if="idCardError" class="error-text">{{ idCardError }}</text> | 133 | <text v-if="idCardError" class="error-text">{{ idCardError }}</text> |
| 132 | </view> | 134 | </view> | ... | ... |
-
Please register or login to post a comment