suke-mp/src/components/pay-password-dialog.vue

290 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<uni-popup ref="popup" type="center" :safe-area="true" :mask-click="false">
<view class="pay-password-dialog">
<view class="dialog-header">
<text class="title">{{ getDialogTitle }}</text>
<u-icon name="close" size="20" color="#999" @click="hide" />
</view>
<view class="form-container">
<!-- 关闭支付密码选项 -->
<view class="switch-item" v-if="hasOldPassword">
<text>关闭支付密码</text>
<u-switch v-model="isClosePassword" activeColor="#F32B2B" @change="handleSwitchChange" />
</view>
<!-- 旧密码 - 只在修改密码或关闭密码时显示 -->
<view class="form-item" v-if="hasOldPassword">
<text class="label">原密码:</text>
<view class="input-wrapper">
<u-input v-model="oldPassword" type="number" :border="false" placeholder="请输入原密码" :maxlength="6"
:disabled="isClosePassword" :password="!showOldPassword" @input="handleInput($event, 'oldPassword')" />
<u-icon :name="showOldPassword ? 'eye-off' : 'eye-fill'" size="20" color="#999"
v-if="hasOldPassword && !isClosePassword" @click="showOldPassword = !showOldPassword" />
</view>
</view>
<!-- 新密码和确认密码部分 -->
<template v-if="!isClosePassword">
<!-- 新密码 -->
<view class="form-item">
<text class="label">新密码:</text>
<view class="input-wrapper">
<u-input v-model="newPassword" type="number" placeholder="请输入6位数字密码" maxlength="6" :border="false"
:password="!showNewPassword" @input="handleInput($event, 'newPassword')" />
<u-icon :name="showNewPassword ? 'eye-off' : 'eye-fill'" size="20" color="#999"
@click="showNewPassword = !showNewPassword" />
</view>
</view>
<!-- 确认密码 -->
<view class="form-item">
<text class="label">确认密码:</text>
<view class="input-wrapper">
<u-input v-model="confirmPassword" type="number" :border="false" placeholder="请再次输入密码" maxlength="6"
:password="!showConfirmPassword" @input="handleInput($event, 'confirmPassword')" />
<u-icon :name="showConfirmPassword ? 'eye-off' : 'eye-fill'" size="20" color="#999"
@click="showConfirmPassword = !showConfirmPassword" />
</view>
</view>
</template>
</view>
<view class="footer">
<button :class="{ 'primary-button': isFormValid, 'disabled-button': !isFormValid }" :disabled="!isFormValid"
@click.stop='handleConfirm'>
完成
</button>
</view>
</view>
</uni-popup>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useUserStore } from '@/store'
const userStore = useUserStore()
const popup = ref<any>(null)
// 密码显示状态 - 默认都是不可见的
const showOldPassword = ref(false)
const showNewPassword = ref(false)
const showConfirmPassword = ref(false)
// 重置密码可见性
const resetPasswordVisibility = () => {
showOldPassword.value = false
showNewPassword.value = false
showConfirmPassword.value = false
}
// 表单数据
const oldPassword = ref('')
const newPassword = ref('')
const confirmPassword = ref('')
// 是否有旧密码(是否已开启支付密码)
const hasOldPassword = ref(false)
// 是否关闭支付密码
const isClosePassword = ref(false)
// 获取弹框标题
const getDialogTitle = computed(() => {
if (!hasOldPassword.value) return '设置支付密码'
if (isClosePassword.value) return '关闭支付密码'
return '修改支付密码'
})
// 表单验证逻辑更新
const isFormValid = computed(() => {
if (isClosePassword.value) {
// 关闭支付密码时,只要有开关就可以点击完成
return true
} else if (!hasOldPassword.value) {
// 首次设置密码
if (!newPassword.value || !confirmPassword.value) return false
if (newPassword.value.length !== 6 || confirmPassword.value.length !== 6) return false
return newPassword.value === confirmPassword.value
} else {
// 修改密码
if (!oldPassword.value || !newPassword.value || !confirmPassword.value) return false
if (oldPassword.value.length !== 6 || newPassword.value.length !== 6 || confirmPassword.value.length !== 6) return false
return newPassword.value === confirmPassword.value
}
})
// 处理输入限制只能输入数字且最多6位
const handleInput = (value: string, field: 'oldPassword' | 'newPassword' | 'confirmPassword') => {
// 只保留数字且最多6位
const numericValue = value?.replace(/[^\d]/g, '').slice(0, 6)
// 更新对应字段的值
switch (field) {
case 'oldPassword':
oldPassword.value = numericValue
break
case 'newPassword':
newPassword.value = numericValue
break
case 'confirmPassword':
confirmPassword.value = numericValue
break
}
}
// 生成随机6位数字
const generateRandomPassword = () => {
return Math.floor(Math.random() * 1000000).toString().padStart(6, '0')
}
// 重置表单更新
const resetForm = () => {
oldPassword.value = ''
newPassword.value = ''
confirmPassword.value = ''
resetPasswordVisibility()
isClosePassword.value = false
}
// 显示弹框
const show = async () => {
hasOldPassword.value = userStore.userInfo.paywithpwd === 1
isClosePassword.value = false
resetPasswordVisibility()
popup.value?.open('center')
}
// 隐藏弹框
const hide = () => {
popup.value?.close()
resetForm()
}
// 确认按钮处理更新
const handleConfirm = async () => {
try {
await userStore.setPayPassword({
paywithpwd: isClosePassword.value ? 0 : 1,
oldpwd: hasOldPassword.value ? oldPassword.value : '',
newpwd: isClosePassword.value ? '' : newPassword.value,
})
// 更新本地状态
userStore.userInfo.paywithpwd = isClosePassword.value ? 0 : 1
uni.showToast({
title: isClosePassword.value ? '已关闭支付密码' : '设置成功',
icon: 'success',
})
hide()
resetForm()
} catch (error) {
uni.showToast({
title: '操作失败',
icon: 'error',
})
}
}
// 处理开关切换
const handleSwitchChange = (value: boolean) => {
isClosePassword.value = value
// 切换时重置密码输入
if (value) {
newPassword.value = ''
confirmPassword.value = ''
oldPassword.value = generateRandomPassword() // 生成随机6位数字
resetPasswordVisibility()
} else {
oldPassword.value = ''
}
}
// 暴露方法给父组件使用
defineExpose({
show,
hide
})
</script>
<style lang="scss" scoped>
.pay-password-dialog {
width: 600rpx;
padding: 40rpx;
background-color: #fff;
border-radius: 24rpx;
position: relative;
.dialog-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40rpx;
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
}
.form-container {
.switch-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 0;
margin-bottom: 20rpx;
text {
font-size: 28rpx;
color: #333;
}
}
.form-item {
margin-bottom: 30rpx;
.label {
font-size: 30rpx;
color: #333;
margin-bottom: 16rpx;
display: block;
}
.input-wrapper {
display: flex;
align-items: center;
background-color: #f5f5f5;
border-radius: 12rpx;
padding: 20rpx;
height: 50rpx;
:deep(.u-border) {
border-style: hidden;
}
:deep(.u-input) {
flex: 1;
height: 100%;
background-color: transparent;
border: none;
font-size: 10rpx;
}
:deep(.u-input__input) {
height: 100%;
line-height: 60rpx;
font-size: 10rpx;
border: none;
padding: 0;
}
}
}
}
.footer {
padding: 0 30rpx;
}
}
</style>