|
|
@@ -0,0 +1,339 @@
|
|
|
+<script setup lang="ts">
|
|
|
+const dialogModel = ref(false)
|
|
|
+const state = ref<'reset' | 'activate'>('activate')
|
|
|
+
|
|
|
+const openDialog = (stateValue: 'reset' | 'activate') => {
|
|
|
+ state.value = stateValue
|
|
|
+ dialogModel.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const loginForm = ref({
|
|
|
+ username: '',
|
|
|
+ oldPassword: '',
|
|
|
+ newPassword: '',
|
|
|
+ confirmPassword: ''
|
|
|
+})
|
|
|
+
|
|
|
+const newPwdErrTips = ref('')
|
|
|
+const loginError: any = ref({
|
|
|
+ oldPassword: false,
|
|
|
+ newPassword: false,
|
|
|
+ confirmPassword: false
|
|
|
+})
|
|
|
+
|
|
|
+const emit = defineEmits(['submit'])
|
|
|
+
|
|
|
+const handleChangePwd = () => {
|
|
|
+ if (loginForm.value.newPassword !== loginForm.value.confirmPassword) {
|
|
|
+ loginError.value.confirmPassword = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (loginForm.value.newPassword.length < 12 || loginForm.value.newPassword.length > 20) {
|
|
|
+ loginError.value.newPassword = true
|
|
|
+ newPwdErrTips.value = 'Password length between 12 - 20'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!/[A-Z]/.test(loginForm.value.newPassword)) {
|
|
|
+ loginError.value.newPassword = true
|
|
|
+ newPwdErrTips.value = 'Password must contain uppercase letters'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!/[a-z]/.test(loginForm.value.newPassword)) {
|
|
|
+ loginError.value.newPassword = true
|
|
|
+ newPwdErrTips.value = 'Password must contain lowercase letters'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!/[0-9]/.test(loginForm.value.newPassword)) {
|
|
|
+ loginError.value.newPassword = true
|
|
|
+ newPwdErrTips.value = 'Password must contain numbers'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ $api
|
|
|
+ .resetPwd({
|
|
|
+ uname: loginForm.value.username,
|
|
|
+ old_password: loginForm.value.oldPassword,
|
|
|
+ password: loginForm.value.newPassword
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ emit('submit')
|
|
|
+ dialogModel.value = false
|
|
|
+ // if (res.code === 200) {
|
|
|
+ // router.push({
|
|
|
+ // name: 'Login',
|
|
|
+ // query: {
|
|
|
+ // isChange: 'true'
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ // } else if (res.code === 400) {
|
|
|
+ // if (res.msg === 'Old password is incorrect') {
|
|
|
+ // loginError.value.oldPassword = true
|
|
|
+ // } else {
|
|
|
+ // loginError.value.newPassword = true
|
|
|
+ // newPwdErrTips.value = res.msg
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const hiddenError = (key: string) => {
|
|
|
+ loginError.value[key] = false
|
|
|
+}
|
|
|
+
|
|
|
+const hasUppercase = ref(false)
|
|
|
+const hasLowercase = ref(false)
|
|
|
+const hasNumber = ref(false)
|
|
|
+const isValidLength = ref(false)
|
|
|
+const checkPassword = () => {
|
|
|
+ const pwd = loginForm.value.newPassword
|
|
|
+ // 检测是否包含大写字母
|
|
|
+ hasUppercase.value = /[A-Z]/.test(pwd)
|
|
|
+ // 检测是否包含小写字母
|
|
|
+ hasLowercase.value = /[a-z]/.test(pwd)
|
|
|
+ // 检测是否包含数字
|
|
|
+ hasNumber.value = /[0-9]/.test(pwd)
|
|
|
+ // 检测长度是否符合要求
|
|
|
+ isValidLength.value = pwd.length >= 12 && pwd.length <= 20
|
|
|
+}
|
|
|
+
|
|
|
+const confirmPwd = () => {
|
|
|
+ if (loginForm.value.confirmPassword !== loginForm.value.newPassword) {
|
|
|
+ loginError.value.confirmPassword = true
|
|
|
+ } else {
|
|
|
+ loginError.value.confirmPassword = false
|
|
|
+ }
|
|
|
+}
|
|
|
+defineExpose({
|
|
|
+ openDialog
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <el-dialog v-model="dialogModel" class="set-password-dialog" width="480">
|
|
|
+ <div class="content">
|
|
|
+ <div class="top-section">
|
|
|
+ <div class="title">Set Your Password</div>
|
|
|
+ <div class="description">
|
|
|
+ Hello Caroline, please create a new password for your account.
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="login-form">
|
|
|
+ <div class="label" style="margin-top: 0">
|
|
|
+ <span>New Password</span>
|
|
|
+ </div>
|
|
|
+ <el-input
|
|
|
+ ref="passWordRef"
|
|
|
+ :class="{ 'is-error': loginError.newPassword }"
|
|
|
+ v-model="loginForm.newPassword"
|
|
|
+ type="password"
|
|
|
+ placeholder="Please input password"
|
|
|
+ show-password
|
|
|
+ @focus="hiddenError('newPassword')"
|
|
|
+ @input="checkPassword"
|
|
|
+ >
|
|
|
+ <template #prefix>
|
|
|
+ <span class="font_family icon-icon_password_b"></span>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <div class="error" v-if="loginError.newPassword">{{ newPwdErrTips }}</div>
|
|
|
+ <div class="limit-tips">
|
|
|
+ <div class="tip-item">
|
|
|
+ <span class="font_family icon-icon_confirm_b" :class="{ active: hasUppercase }"></span>
|
|
|
+ <span>Password must contain uppercase letters</span>
|
|
|
+ </div>
|
|
|
+ <div class="tip-item">
|
|
|
+ <span class="font_family icon-icon_confirm_b" :class="{ active: hasLowercase }"></span>
|
|
|
+ <span>Password must contain lowercase letters</span>
|
|
|
+ </div>
|
|
|
+ <div class="tip-item">
|
|
|
+ <span class="font_family icon-icon_confirm_b" :class="{ active: hasNumber }"></span>
|
|
|
+ <span>Password must contain numbers</span>
|
|
|
+ </div>
|
|
|
+ <div class="tip-item">
|
|
|
+ <span
|
|
|
+ style="padding-top: 2px"
|
|
|
+ class="font_family icon-icon_confirm_b"
|
|
|
+ :class="{ active: isValidLength }"
|
|
|
+ ></span>
|
|
|
+ <span>Password length between12 - 20 </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="label">
|
|
|
+ <span>Confirm New Password</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-input
|
|
|
+ ref="passWordRef"
|
|
|
+ :class="{ 'is-error': loginError.confirmPassword }"
|
|
|
+ v-model="loginForm.confirmPassword"
|
|
|
+ type="password"
|
|
|
+ placeholder="Please input password"
|
|
|
+ show-password
|
|
|
+ @focus="hiddenError('confirmPassword')"
|
|
|
+ @blur="confirmPwd"
|
|
|
+ >
|
|
|
+ <template #prefix>
|
|
|
+ <span class="font_family icon-icon_password_b"></span>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <div class="error" v-if="loginError.confirmPassword">
|
|
|
+ The password does not match. Please try again.
|
|
|
+ </div>
|
|
|
+ <el-button @click="handleChangePwd" class="el-button--dark set-btn">{{
|
|
|
+ state === 'reset' ? 'Reset Password' : 'Set Password & Activate Account'
|
|
|
+ }}</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.set-password-dialog {
|
|
|
+ .content {
|
|
|
+ padding-bottom: 40px;
|
|
|
+ .top-section {
|
|
|
+ width: 100%;
|
|
|
+ height: 158px;
|
|
|
+ padding-top: 64px;
|
|
|
+ background: url(../image/bg-login-card.png) no-repeat;
|
|
|
+ background-position: top left; /* 从左上角开始显示 */
|
|
|
+ background-size: 480px 200px; /* 保持背景图像的原始尺寸 */
|
|
|
+ .title {
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: 700;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .description {
|
|
|
+ margin-top: 16px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .set-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 40px;
|
|
|
+ margin-top: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .login-form {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ padding: 0 40px;
|
|
|
+ .el-input {
|
|
|
+ height: 40px;
|
|
|
+ .confirm-icon {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 16px;
|
|
|
+ width: 16px;
|
|
|
+ margin-right: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #fff;
|
|
|
+ background-color: var(--color-success);
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.is-error {
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
+ box-shadow: 0 0 0 1px var(--color-danger) inset;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-input__prefix) {
|
|
|
+ margin: 0 4px;
|
|
|
+ background-color: transparent;
|
|
|
+ }
|
|
|
+ &.is-disabled {
|
|
|
+ :deep(.el-input__inner) {
|
|
|
+ -webkit-text-fill-color: var(--color-neutral-1);
|
|
|
+ color: var(--color-neutral-1);
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .limit-tips {
|
|
|
+ margin-top: 10px;
|
|
|
+ .tip-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--color-neutral-2);
|
|
|
+ &:nth-last-child(1) {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+ .font_family {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ height: 12px;
|
|
|
+ width: 12px;
|
|
|
+ padding-top: 1px;
|
|
|
+ background-color: #b5b9bf;
|
|
|
+ font-size: 10px;
|
|
|
+ color: white;
|
|
|
+ border-radius: 50%;
|
|
|
+ &.active {
|
|
|
+ background-color: #00a870;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ span {
|
|
|
+ margin-left: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .verification-code {
|
|
|
+ margin-top: 16px;
|
|
|
+ .verification-code-img {
|
|
|
+ width: 130px;
|
|
|
+ height: 38px;
|
|
|
+ object-fit: cover;
|
|
|
+ }
|
|
|
+ :deep(.el-input-group__append) {
|
|
|
+ padding: 0;
|
|
|
+ padding-right: 1px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .el-input.user-name {
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
+ padding-right: 6px;
|
|
|
+ box-shadow: 0 0 0 1px var(--color-input-disabled-border) inset;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .label {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ width: 100%;
|
|
|
+ margin-top: 14px;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 18px;
|
|
|
+
|
|
|
+ span {
|
|
|
+ color: var(--color-neutral-2);
|
|
|
+ }
|
|
|
+
|
|
|
+ .forgot-password {
|
|
|
+ color: var(--color-theme);
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .error {
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--color-danger);
|
|
|
+ line-height: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="scss">
|
|
|
+.set-password-dialog {
|
|
|
+ .el-dialog__header {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ .el-dialog__body {
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|