Skip to content

Commit

Permalink
feat: 用户忘记密码 #1570 (#1575)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuri0528 authored Mar 15, 2024
1 parent ee15a84 commit 36833a2
Show file tree
Hide file tree
Showing 12 changed files with 925 additions and 25 deletions.
62 changes: 41 additions & 21 deletions src/pages/src/app.vue
Original file line number Diff line number Diff line change
@@ -1,40 +1,60 @@
<script setup lang="ts">
import { Message } from 'bkui-vue';
import {
ref,
} from 'vue';
import { ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import HeaderBox from './views/Header.vue';
import { currentUser } from '@/http/api';
import { t } from '@/language/index';
import { useUser } from '@/store/user';
import ResetPassword from '@/views/reset-password/index.vue';
const route = useRoute();
const showPassword = ref(false);
// 判断是否是重置密码的路由
watch(() => route.name, (val) => {
if (val === 'password' || val === 'resetPassword') {
showPassword.value = true;
} else {
initUser();
}
});
// 加载完用户数据才会展示页面
const isLoading = ref(true);
const isLoading = ref(false);
// 获取用户数据
const user = useUser();
currentUser()
.then((res) => {
user.setUser(res.data);
isLoading.value = false;
})
.catch(() => {
Message(t('获取用户信息失败,请检查后再试'));
isLoading.value = false;
});
const initUser = async () => {
isLoading.value = true;
currentUser()
.then((res) => {
user.setUser(res.data);
})
.catch(() => {
Message(t('获取用户信息失败,请检查后再试'));
})
.finally(() => {
isLoading.value = false;
});
};
</script>

<template>
<bk-loading
:loading="isLoading"
:class="{
'main-loading': isLoading
}"
>
<HeaderBox v-if="!isLoading" />
</bk-loading>
<div>
<bk-loading
v-if="!showPassword"
:loading="isLoading"
:class="{
'main-loading': isLoading
}"
>
<HeaderBox v-if="!isLoading" />
</bk-loading>
<ResetPassword v-else />
</div>
</template>

<style lang="less" scoped>
Expand Down
29 changes: 28 additions & 1 deletion src/pages/src/components/phoneInput.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div :class="['input-text', { 'input-disabled': disabled }]">
<div :class="['input-text', { 'input-disabled': disabled }, { 'input-style': inputStyle }]">
<input
type="text"
ref="telRef"
Expand Down Expand Up @@ -67,6 +67,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
inputStyle: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['changeCountryCode', 'changeTelError']);
Expand Down Expand Up @@ -213,6 +217,29 @@ const handleInput = () => {
}
}
.input-style {
.iti--separate-dial-code {
&:hover .select-text {
border-color: #979BA5;
}
.select-text {
height: 40px;
line-height: 40px;
background: #F0F1F5;
border: none;
&:hover {
border-color: #979BA5;
}
&:focus {
border-color: #3a84ff;
}
}
}
}
.error-text {
position: absolute;
margin: 2px 0 0;
Expand Down
7 changes: 7 additions & 0 deletions src/pages/src/hooks/use-validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ export default () => {
trigger: 'blur',
};

const verifyCode = {
validator: (value: string) => /^[^\s]{8,}$/.test(value),
message: t('验证码不能少于8位'),
trigger: 'blur',
};

return {
required,
name,
Expand All @@ -99,5 +105,6 @@ export default () => {
apiPath,
sourceField,
checkSpace,
verifyCode,
};
};
26 changes: 26 additions & 0 deletions src/pages/src/http/resetPasswordFiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import http from './fetch';

/**
* 发送短信验证码
*/
export const verificationCodes = (params: any) => http.post('/api/v1/web/passwords/operations/reset/methods/phone/verification-codes/', params);

/**
* 发送重置密码链接到用户邮箱
*/
export const tokenUrls = (params: any) => http.post('/api/v1/web/passwords/operations/reset/methods/email/token-urls/', params);

/**
* 通过短信验证码获取重置密码链接
*/
export const resetPasswordUrl = (params: any) => http.post('/api/v1/web/passwords/operations/reset/methods/verification-code/token-urls/', params);

/**
* 根据 Token 获取可重置密码的租户用户列表
*/
export const getUsers = (params: any) => http.get('/api/v1/web/passwords/operations/reset/methods/token/users/', params);

/**
* 根据 Token 重置密码
*/
export const resetPassword = (params: any) => http.post('/api/v1/web/passwords/operations/reset/methods/token/passwords/', params);
17 changes: 15 additions & 2 deletions src/pages/src/language/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@
"确认密码": "Confirm password",
"两次输入的密码不一致,请重新输入": "The two passwords entered do not match, please re-enter",
"修改密码成功": "Password changed successfully",
"请输入": "Please Enter",
"请输入": "Please enter",
"请填写正确的手机号": "Please enter a valid mobile number",
"由1-64位字符组成": "Consists of 1-64 characters",
"由3-32位字母、数字、连接符(-)字符组成,以字母开头": "Consists of 3-32 letters, numbers, and hyphen (-) characters, starting with a letter",
Expand All @@ -366,5 +366,18 @@
"请将一下回调地址填写到企业微信配置内:": "Please fill in the following callback address into the WeChat Work configuration:",
"系统错误": "System Error",
"确认退出登录?": "Confirm sign out?",
"当前用户不支持修改密码": "The current user cannot change the password"
"当前用户不支持修改密码": "The current user cannot change the password",
"忘记密码": "Forgot Password",
"请输入手机号以接收短信验证码": "Receive CAPTCHA via mobile number",
"请输入邮箱以接收邮件重置密码链接": "Receive a password reset link via email",
"请输入验证码": "Please enter the CAPTCHA",
"获取验证码": "Get CAPTCHA",
"秒后可重发": " s",
"请输入邮箱地址": "Please enter your email address",
"设置新密码": "Set New Password",
"选择账号": "Select account",
"确认新密码": "Confirm new password",
"返回上一级": "Go back to the previous level",
"已发送密码重设邮件": "Password reset email has been sent",
"请查看邮件并根据提示进行操作": "Please check your email and follow the instructions"
}
15 changes: 14 additions & 1 deletion src/pages/src/language/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -366,5 +366,18 @@
"请将一下回调地址填写到企业微信配置内:": "请将一下回调地址填写到企业微信配置内:",
"系统错误": "系统错误",
"确认退出登录?": "确认退出登录?",
"当前用户不支持修改密码": "当前用户不支持修改密码"
"当前用户不支持修改密码": "当前用户不支持修改密码",
"忘记密码": "忘记密码",
"请输入手机号以接收短信验证码": "请输入手机号以接收短信验证码",
"请输入邮箱以接收邮件重置密码链接": "请输入邮箱以接收邮件重置密码链接",
"请输入验证码": "请输入验证码",
"获取验证码": "获取验证码",
"秒后可重发": "秒后可重发",
"请输入邮箱地址": "请输入邮箱地址",
"设置新密码": "设置新密码",
"选择账号": "选择账号",
"确认新密码": "确认新密码",
"返回上一级": "返回上一级",
"已发送密码重设邮件": "已发送密码重设邮件",
"请查看邮件并根据提示进行操作": "请查看邮件并根据提示进行操作"
}
10 changes: 10 additions & 0 deletions src/pages/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ export default createRouter({
name: 'personalCenter',
component: () => import('@/views/personal-center/index.vue'),
},
{
path: '/password/:tenantId?',
name: 'password',
component: () => import('@/views/reset-password/index.vue'),
},
{
path: '/reset-password/:token?',
name: 'resetPassword',
component: () => import('@/views/reset-password/newPassword.vue'),
},
{
path: '/:pathMatch(.*)*',
name: 'notFound',
Expand Down
119 changes: 119 additions & 0 deletions src/pages/src/views/reset-password/email.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<template>
<bk-form ref="formRef" form-type="vertical" :model="formData" :rules="rules">
<bk-form-item property="email" style="margin-bottom: 32px;" error-display-type="tooltips">
<bk-input
:class="['email-input', { 'is-enter': isEnter }]"
size="large"
v-model="formData.email"
:placeholder="$t('请输入邮箱地址')"
@blur="handleBlur"
@keypress="handleKeypress">
</bk-input>
</bk-form-item>
<bk-form-item style="margin-bottom: 12px;">
<bk-button
style="width: 100%;"
theme="primary"
size="large"
@click="handleNextStep"
>
{{ $t('下一步') }}
</bk-button>
</bk-form-item>
<bk-form-item>
<bk-button
style="width: 100%;"
size="large"
@click="logout"
>
{{ $t('取消') }}
</bk-button>
</bk-form-item>
</bk-form>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue';
import { logout } from '@/common/auth';
import useValidate from '@/hooks/use-validate';
import { tokenUrls } from '@/http/resetPasswordFiles';
const validate = useValidate();
const props = defineProps({
tenantId: {
type: String,
default: '',
},
});
const emit = defineEmits(['emailSend']);
const formRef = ref();
const formData = reactive({
email: '',
});
const rules = ref({
email: [validate.email],
});
const handleNextStep = async () => {
try {
await formRef.value.validate();
await tokenUrls({
tenant_id: props.tenantId,
email: formData.email,
});
emit('emailSend', true, formData.email);
} catch (e) {
console.warn(e);
}
};
const isEnter = ref(false);
const handleBlur = () => {
isEnter.value = false;
};
const handleKeypress = () => {
isEnter.value = true;
};
</script>

<style scoped lang="less">
.login-btn {
width: 100%;
margin-top: 10px;
}
.error-text {
color: #ea3636;
text-align: center;
}
::v-deep .email-input {
border: none;
input {
background: #F0F1F5;
border-radius: 2px;
}
}
::v-deep .is-error {
.email-input {
border: 1px solid #ea3636 !important;
}
.is-enter {
border: none !important;
}
}
::v-deep .is-focused {
box-shadow: none !important;
}
</style>
Loading

0 comments on commit 36833a2

Please sign in to comment.