mirror of https://gitee.com/topiam/eiam
✨ 管理端个人中心
parent
9fce81d45d
commit
4fa0746bfb
|
@ -33,11 +33,13 @@ export default (props: {
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const formRef = useRef<ProFormInstance>();
|
const formRef = useRef<ProFormInstance>();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
formRef.current?.setFieldsValue({ id });
|
formRef.current?.setFieldsValue({ id });
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}, [visible, id]);
|
}, [visible, id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalForm
|
<ModalForm
|
||||||
title={intl.formatMessage({ id: 'pages.setting.administrator.reset_password_modal' })}
|
title={intl.formatMessage({ id: 'pages.setting.administrator.reset_password_modal' })}
|
||||||
|
@ -52,7 +54,7 @@ export default (props: {
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
onCancel: onCancel,
|
onCancel: onCancel,
|
||||||
}}
|
}}
|
||||||
onFinish={(formData: { password: string }) => {
|
onFinish={async (formData: { password: string }) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const password = Base64.encode(formData.password, true);
|
const password = Base64.encode(formData.password, true);
|
||||||
onFinish({ id, password }).finally(() => {
|
onFinish({ id, password }).finally(() => {
|
||||||
|
|
|
@ -22,7 +22,6 @@ import { ModalForm, ProFormCaptcha, ProFormText } from '@ant-design/pro-componen
|
||||||
import { App, Spin } from 'antd';
|
import { App, Spin } from 'antd';
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { FormLayout } from './constant';
|
|
||||||
import { useIntl } from '@@/exports';
|
import { useIntl } from '@@/exports';
|
||||||
|
|
||||||
export default (props: {
|
export default (props: {
|
||||||
|
@ -39,10 +38,12 @@ export default (props: {
|
||||||
const [hasSendCaptcha, setHasSendCaptcha] = useState<boolean>(false);
|
const [hasSendCaptcha, setHasSendCaptcha] = useState<boolean>(false);
|
||||||
const captchaRef = useRef<CaptFieldRef>();
|
const captchaRef = useRef<CaptFieldRef>();
|
||||||
const formRef = useRef<ProFormInstance>();
|
const formRef = useRef<ProFormInstance>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}, [visible]);
|
}, [visible]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ModalForm
|
<ModalForm
|
||||||
|
@ -52,7 +53,12 @@ export default (props: {
|
||||||
labelAlign={'right'}
|
labelAlign={'right'}
|
||||||
preserve={false}
|
preserve={false}
|
||||||
layout={'horizontal'}
|
layout={'horizontal'}
|
||||||
{...FormLayout}
|
labelCol={{
|
||||||
|
span: 4,
|
||||||
|
}}
|
||||||
|
wrapperCol={{
|
||||||
|
span: 20,
|
||||||
|
}}
|
||||||
autoFocusFirstInput
|
autoFocusFirstInput
|
||||||
open={visible}
|
open={visible}
|
||||||
modalProps={{
|
modalProps={{
|
||||||
|
|
|
@ -16,21 +16,12 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { FieldNames } from '../constant';
|
import { FieldNames } from '../constant';
|
||||||
import { changePassword, prepareChangePassword } from '../service';
|
import { changePassword } from '../service';
|
||||||
import { aesEcbEncrypt } from '@/utils/aes';
|
import { ModalForm, ProFormInstance, ProFormText } from '@ant-design/pro-components';
|
||||||
import { onGetEncryptSecret } from '@/utils/utils';
|
|
||||||
import {
|
|
||||||
ModalForm,
|
|
||||||
ProFormCaptcha,
|
|
||||||
ProFormDependency,
|
|
||||||
ProFormInstance,
|
|
||||||
ProFormRadio,
|
|
||||||
ProFormText,
|
|
||||||
} from '@ant-design/pro-components';
|
|
||||||
import { App, Spin } from 'antd';
|
import { App, Spin } from 'antd';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { FormLayout } from './constant';
|
import * as React from 'react';
|
||||||
import { FormattedMessage, useIntl, useModel } from '@@/exports';
|
import { useIntl } from '@umijs/max';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改密码
|
* 修改密码
|
||||||
|
@ -43,12 +34,12 @@ const ModifyPassword = (props: {
|
||||||
setRefresh: (visible: boolean) => void;
|
setRefresh: (visible: boolean) => void;
|
||||||
setVisible: (visible: boolean) => void;
|
setVisible: (visible: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { initialState } = useModel('@@initialState');
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { message } = App.useApp();
|
const { message } = App.useApp();
|
||||||
const { visible, setVisible, setRefresh } = props;
|
const { visible, setVisible, setRefresh } = props;
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const formRef = useRef<ProFormInstance>();
|
const formRef = useRef<ProFormInstance>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@ -63,7 +54,12 @@ const ModifyPassword = (props: {
|
||||||
labelAlign={'right'}
|
labelAlign={'right'}
|
||||||
preserve={false}
|
preserve={false}
|
||||||
layout={'horizontal'}
|
layout={'horizontal'}
|
||||||
{...FormLayout}
|
labelCol={{
|
||||||
|
span: 5,
|
||||||
|
}}
|
||||||
|
wrapperCol={{
|
||||||
|
span: 19,
|
||||||
|
}}
|
||||||
autoFocusFirstInput
|
autoFocusFirstInput
|
||||||
open={visible}
|
open={visible}
|
||||||
modalProps={{
|
modalProps={{
|
||||||
|
@ -74,31 +70,36 @@ const ModifyPassword = (props: {
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
onFinish={async (formData: Record<string, any>) => {
|
onFinish={async (formData: Record<string, any>) => {
|
||||||
const publicSecret = await onGetEncryptSecret();
|
const { success, result } = await changePassword({
|
||||||
if (publicSecret) {
|
oldPassword: formData[FieldNames.NEW_PASSWORD] as string,
|
||||||
//加密传输
|
newPassword: formData[FieldNames.OLD_PASSWORD] as string,
|
||||||
const { success, result } = await changePassword(
|
});
|
||||||
aesEcbEncrypt(
|
if (success && result) {
|
||||||
JSON.stringify({
|
setVisible(false);
|
||||||
...formData,
|
message.success(intl.formatMessage({ id: 'page.user.profile.modify_password.success' }));
|
||||||
newPassword: formData[FieldNames.NEW_PASSWORD] as string,
|
setRefresh(true);
|
||||||
verifyCode: formData[FieldNames.VERIFY_CODE] as string,
|
return Promise.resolve();
|
||||||
channel: formData[FieldNames.CHANNEL] as string,
|
|
||||||
}),
|
|
||||||
publicSecret,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (success && result) {
|
|
||||||
setVisible(false);
|
|
||||||
message.success(intl.formatMessage({ id: 'page.user.profile.modify_password.success' }));
|
|
||||||
setRefresh(true);
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Spin spinning={loading}>
|
<Spin spinning={loading}>
|
||||||
|
<ProFormText.Password
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'page.user.profile.modify_password.form.old_password.placeholder',
|
||||||
|
})}
|
||||||
|
label={intl.formatMessage({ id: 'page.user.profile.modify_password.form.old_password' })}
|
||||||
|
name={FieldNames.OLD_PASSWORD}
|
||||||
|
fieldProps={{ autoComplete: 'off' }}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage({
|
||||||
|
id: 'page.user.profile.modify_password.form.old_password.rule.0',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
<ProFormText.Password
|
<ProFormText.Password
|
||||||
placeholder={intl.formatMessage({
|
placeholder={intl.formatMessage({
|
||||||
id: 'page.user.profile.modify_password.form.new_password.placeholder',
|
id: 'page.user.profile.modify_password.form.new_password.placeholder',
|
||||||
|
@ -115,114 +116,33 @@ const ModifyPassword = (props: {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<ProFormRadio.Group
|
<ProFormText.Password
|
||||||
name={FieldNames.CHANNEL}
|
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
id: 'page.user.profile.modify_password.form.verify-code-type.label',
|
id: 'pages.setting.administrator.reset_password_modal.from.confirm_password',
|
||||||
})}
|
})}
|
||||||
options={[
|
placeholder={intl.formatMessage({
|
||||||
{
|
id: 'pages.setting.administrator.reset_password_modal.from.confirm_password.placeholder',
|
||||||
label: intl.formatMessage({
|
})}
|
||||||
id: 'page.user.profile.modify_password.form.phone.label',
|
name={'confirmPassword'}
|
||||||
}),
|
fieldProps={{ autoComplete: 'off' }}
|
||||||
value: 'sms',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: intl.formatMessage({
|
|
||||||
id: 'page.user.profile.modify_password.form.mail.label',
|
|
||||||
}),
|
|
||||||
value: 'mail',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: intl.formatMessage({
|
message: intl.formatMessage({
|
||||||
id: 'page.user.profile.modify_password.form.verify-code-type.rule.0',
|
id: 'pages.setting.administrator.reset_password_modal.from.confirm_password.rule.0.message',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
]}
|
({ getFieldValue }) => ({
|
||||||
/>
|
validator(_, value) {
|
||||||
<ProFormDependency name={[FieldNames.CHANNEL]}>
|
if (!value || getFieldValue(FieldNames.NEW_PASSWORD) === value) {
|
||||||
{({ channel }) => {
|
return Promise.resolve();
|
||||||
if (channel === 'sms') {
|
}
|
||||||
return (
|
return Promise.reject(
|
||||||
<ProFormText
|
new Error(intl.formatMessage({ id: 'app.password.not_match' })),
|
||||||
key={'sms'}
|
|
||||||
label={intl.formatMessage({
|
|
||||||
id: 'page.user.profile.modify_password.form.phone',
|
|
||||||
})}
|
|
||||||
name={'show'}
|
|
||||||
initialValue={initialState?.currentUser?.phone}
|
|
||||||
readonly
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<ProFormText
|
|
||||||
key={'mail'}
|
|
||||||
label={intl.formatMessage({
|
|
||||||
id: 'page.user.profile.modify_password.form.mail',
|
|
||||||
})}
|
|
||||||
name={'show'}
|
|
||||||
initialValue={initialState?.currentUser?.email}
|
|
||||||
readonly
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</ProFormDependency>
|
|
||||||
<ProFormCaptcha
|
|
||||||
label={intl.formatMessage({ id: 'page.user.profile.modify_password.form.verify-code' })}
|
|
||||||
fieldProps={{
|
|
||||||
maxLength: 6,
|
|
||||||
}}
|
|
||||||
captchaProps={{}}
|
|
||||||
phoneName={'show'}
|
|
||||||
placeholder={intl.formatMessage({
|
|
||||||
id: 'pages.login.captcha.placeholder',
|
|
||||||
})}
|
|
||||||
captchaTextRender={(timing, count) => {
|
|
||||||
if (timing) {
|
|
||||||
return `${count} ${intl.formatMessage({
|
|
||||||
id: 'pages.login.phone.captcha-second-text',
|
|
||||||
})}`;
|
|
||||||
}
|
|
||||||
return intl.formatMessage({
|
|
||||||
id: 'pages.login.phone.get-opt-code',
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
name={FieldNames.VERIFY_CODE}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: <FormattedMessage id="pages.login.captcha.required" />,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
onGetCaptcha={async () => {
|
|
||||||
const validate = await formRef.current?.validateFields([FieldNames.CHANNEL]);
|
|
||||||
if (!validate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let channel = formRef.current?.getFieldValue(FieldNames.CHANNEL);
|
|
||||||
const publicSecret = await onGetEncryptSecret();
|
|
||||||
if (publicSecret) {
|
|
||||||
const { success } = await prepareChangePassword(
|
|
||||||
aesEcbEncrypt(
|
|
||||||
JSON.stringify({
|
|
||||||
channel: channel as string,
|
|
||||||
}),
|
|
||||||
publicSecret,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (success) {
|
|
||||||
message.success(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: 'pages.login.phone.get-opt-code.success',
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
}),
|
||||||
}}
|
]}
|
||||||
/>
|
/>
|
||||||
</Spin>
|
</Spin>
|
||||||
</ModalForm>
|
</ModalForm>
|
||||||
|
|
|
@ -29,7 +29,6 @@ import {
|
||||||
import { App, ConfigProvider, Spin } from 'antd';
|
import { App, ConfigProvider, Spin } from 'antd';
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
import { useContext, useEffect, useRef, useState } from 'react';
|
import { useContext, useEffect, useRef, useState } from 'react';
|
||||||
import { FormLayout } from './constant';
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { ConfigContext } from 'antd/es/config-provider';
|
import { ConfigContext } from 'antd/es/config-provider';
|
||||||
import { useIntl } from '@@/exports';
|
import { useIntl } from '@@/exports';
|
||||||
|
@ -84,7 +83,12 @@ export default (props: {
|
||||||
labelAlign={'right'}
|
labelAlign={'right'}
|
||||||
preserve={false}
|
preserve={false}
|
||||||
layout={'horizontal'}
|
layout={'horizontal'}
|
||||||
{...FormLayout}
|
labelCol={{
|
||||||
|
span: 4,
|
||||||
|
}}
|
||||||
|
wrapperCol={{
|
||||||
|
span: 20,
|
||||||
|
}}
|
||||||
autoFocusFirstInput
|
autoFocusFirstInput
|
||||||
open={visible}
|
open={visible}
|
||||||
modalProps={{
|
modalProps={{
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
* eiam-console - Employee Identity and Access Management
|
|
||||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
export const FormLayout = {
|
|
||||||
labelCol: { span: 4 },
|
|
||||||
wrapperCol: { span: 20 },
|
|
||||||
};
|
|
|
@ -62,6 +62,11 @@ export default {
|
||||||
'page.user.profile.modify_email.form.email.rule.1': '邮箱格式不正确',
|
'page.user.profile.modify_email.form.email.rule.1': '邮箱格式不正确',
|
||||||
'page.user.profile.modify_password.form': '修改密码',
|
'page.user.profile.modify_password.form': '修改密码',
|
||||||
'page.user.profile.modify_password.success': '修改成功,请重新登录',
|
'page.user.profile.modify_password.success': '修改成功,请重新登录',
|
||||||
|
|
||||||
|
'page.user.profile.modify_password.form.old_password': '旧密码',
|
||||||
|
'page.user.profile.modify_password.form.old_password.placeholder': '请输入旧密码',
|
||||||
|
'page.user.profile.modify_password.form.old_password.rule.0': '请输入请输入旧密码',
|
||||||
|
|
||||||
'page.user.profile.modify_password.form.new_password': '新密码',
|
'page.user.profile.modify_password.form.new_password': '新密码',
|
||||||
'page.user.profile.modify_password.form.new_password.placeholder': '请输入新密码',
|
'page.user.profile.modify_password.form.new_password.placeholder': '请输入新密码',
|
||||||
'page.user.profile.modify_password.form.new_password.rule.0': '请输入请输入新密码',
|
'page.user.profile.modify_password.form.new_password.rule.0': '请输入请输入新密码',
|
||||||
|
|
|
@ -109,17 +109,3 @@ export async function changeBaseInfo(
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 准备修改账户密码
|
|
||||||
*/
|
|
||||||
export async function prepareChangePassword(encrypt: string): Promise<API.ApiResult<boolean>> {
|
|
||||||
return request('/api/v1/user/profile/prepare_change_password', {
|
|
||||||
method: 'POST',
|
|
||||||
data: { encrypt: encrypt },
|
|
||||||
skipErrorHandler: true,
|
|
||||||
}).catch(({ response: { data } }) => {
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue