feat 搭建架构骨架
This commit is contained in:
197
src/views/profile/cpns/ChangePasswordDialog.vue
Normal file
197
src/views/profile/cpns/ChangePasswordDialog.vue
Normal file
@@ -0,0 +1,197 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { AppButton, PasswordStrength, SmsCodeInput } from '@/components'
|
||||
|
||||
interface Props {
|
||||
/** 绑定手机号(脱敏展示) */
|
||||
phone: string
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false })
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [payload: { code: string; password: string; confirm: string }]
|
||||
}>()
|
||||
|
||||
const code = ref('')
|
||||
const password = ref('')
|
||||
const confirm = ref('')
|
||||
const agree = ref(false)
|
||||
|
||||
watch(visible, (open) => {
|
||||
if (!open) return
|
||||
code.value = ''
|
||||
password.value = ''
|
||||
confirm.value = ''
|
||||
agree.value = false
|
||||
})
|
||||
|
||||
function onGetCode(): void {
|
||||
ElMessage.success('验证码已发送')
|
||||
}
|
||||
|
||||
function onSubmit(): void {
|
||||
if (!code.value) {
|
||||
ElMessage.warning('请输入验证码')
|
||||
return
|
||||
}
|
||||
if (!password.value) {
|
||||
ElMessage.warning('请输入新密码')
|
||||
return
|
||||
}
|
||||
if (!agree.value) {
|
||||
ElMessage.warning('请先阅读并同意《用户协议》和《隐私政策》')
|
||||
return
|
||||
}
|
||||
emit('submit', {
|
||||
code: code.value,
|
||||
password: password.value,
|
||||
confirm: confirm.value,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<div v-if="visible" class="change-pwd-dialog" @click.self="visible = false">
|
||||
<div class="change-pwd-dialog__panel">
|
||||
<h3 class="change-pwd-dialog__title">
|
||||
修改密码
|
||||
</h3>
|
||||
|
||||
<div class="change-pwd-dialog__field">
|
||||
<label class="change-pwd-dialog__label">手机号</label>
|
||||
<input
|
||||
class="change-pwd-dialog__input"
|
||||
type="text"
|
||||
:value="props.phone"
|
||||
readonly
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="change-pwd-dialog__field">
|
||||
<label class="change-pwd-dialog__label">验证码</label>
|
||||
<SmsCodeInput v-model:code="code" @get-code="onGetCode" />
|
||||
</div>
|
||||
|
||||
<div class="change-pwd-dialog__field">
|
||||
<label class="change-pwd-dialog__label">设置密码</label>
|
||||
<input
|
||||
v-model="password"
|
||||
class="change-pwd-dialog__input"
|
||||
type="password"
|
||||
placeholder="请输入密码(6-20位)"
|
||||
maxlength="20"
|
||||
>
|
||||
<PasswordStrength :password="password" />
|
||||
</div>
|
||||
|
||||
<div class="change-pwd-dialog__field">
|
||||
<label class="change-pwd-dialog__label">确认密码</label>
|
||||
<input
|
||||
v-model="confirm"
|
||||
class="change-pwd-dialog__input"
|
||||
type="password"
|
||||
placeholder="请再次输入密码"
|
||||
maxlength="20"
|
||||
@keyup.enter="onSubmit"
|
||||
>
|
||||
</div>
|
||||
|
||||
<label class="change-pwd-dialog__agree">
|
||||
<input v-model="agree" type="checkbox">
|
||||
<span>我已阅读并同意《用户协议》和《隐私政策》</span>
|
||||
</label>
|
||||
|
||||
<div class="change-pwd-dialog__footer">
|
||||
<AppButton type="default" @click="visible = false">
|
||||
取消
|
||||
</AppButton>
|
||||
<AppButton type="primary" @click="onSubmit">
|
||||
确认修改
|
||||
</AppButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.change-pwd-dialog {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
.flex(row, center);
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
|
||||
&__panel {
|
||||
width: 440px;
|
||||
max-width: calc(100vw - 32px);
|
||||
padding: @spacing-lg;
|
||||
border-radius: @radius-lg;
|
||||
background: @white;
|
||||
box-shadow: @shadow-lg;
|
||||
.flex(column, flex-start);
|
||||
gap: @spacing-base;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: @font-size-lg;
|
||||
font-weight: 600;
|
||||
color: @heading-color;
|
||||
}
|
||||
|
||||
&__field {
|
||||
.flex(column, flex-start);
|
||||
gap: @spacing-xs;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: @font-size-base;
|
||||
color: @heading-color;
|
||||
}
|
||||
|
||||
&__input {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 0 @spacing-base;
|
||||
border: 1px solid @border-color;
|
||||
border-radius: @radius-base;
|
||||
background: @bg-color-light;
|
||||
font-size: @font-size-base;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
|
||||
&:read-only {
|
||||
color: @text-color-secondary;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
&__agree {
|
||||
.flex(row, flex-start, center);
|
||||
gap: @spacing-sm;
|
||||
font-size: @font-size-sm;
|
||||
color: @text-color;
|
||||
cursor: pointer;
|
||||
|
||||
input {
|
||||
accent-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
.flex(row, flex-end);
|
||||
gap: @spacing-sm;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user