Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 用户忘记密码 #1570 #1575

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading