import React, { useCallback, useState, useMemo } from 'react'; import { LogoutOutlined, LockOutlined } from '@ant-design/icons'; import { Menu, Spin, Form, Modal, message, Avatar } from 'antd'; import { history, useModel } from '@umijs/max'; import { stringify } from 'querystring'; import HeaderDropdown from '../HeaderDropdown'; import styles from './index.less'; import { fakeAccountLoginOut, changePwd } from '@/services/login'; import InitForm from '@/components/InitForm'; import { doFetch } from '@/utils/doFetch'; import { useRequest } from 'ahooks'; import AES from 'crypto-js/aes'; import ECB from 'crypto-js/mode-ecb'; import Pkcs7 from 'crypto-js/pad-pkcs7'; import Utf8 from 'crypto-js/enc-utf8'; import moment from 'moment'; /** * 退出登录,并且将当前的 url 保存 */ const loginOut = async () => { await fakeAccountLoginOut(); const { query = {} } = history.location; const { redirect } = query; // Note: There may be security issues, please note if (window.location.pathname !== '/user/login' && !redirect) { localStorage.clear(); history.replace('/user/login'); } }; const AvatarDropdown = ({ menu }) => { const { initialState, setInitialState } = useModel('@@initialState'); const [visible, cv] = useState(false), [formRef] = Form.useForm(), { run, loading } = useRequest(doFetch, { manual: true, formatResult: (res) => res, onSuccess: (result, params) => { if (result.code == '0000') { cv(false); message.success('密码修改成功,请重新登录', 2, () => { setInitialState((s) => ({ ...s, currentUser: undefined, newMenu: undefined, })); loginOut(); }); } }, }); const fields = useMemo(() => { return { password: { value: null, type: 'password', title: '密码', name: ['password'], required: true, }, newPassword: { value: null, type: 'password', title: '新密码', name: ['newPassword'], required: true, }, confirmPassword: { value: null, type: 'password', title: '确认密码', name: ['confirmPassword'], required: true, checkConfirm: (rule, value) => { if (value && value !== formRef.getFieldValue('newPassword')) { return Promise.reject('2次密码不一致!'); } else { return Promise.resolve(); } }, }, }; }, []); const onMenuClick = useCallback( (event) => { const { key } = event; if (key === 'logout') { setInitialState((s) => ({ ...s, currentUser: undefined, newMenu: undefined, })); loginOut(); return; } else if (key == 'changepwd') { cv(true); return; } history.push(`/account/${key}`); }, [setInitialState], ); const loadings = ( <span className={`${styles.action} ${styles.account}`}> <Spin size="small" style={{ marginLeft: 8, marginRight: 8, }} /> </span> ); if (!initialState) { return loadings; } const { currentUser } = initialState; if (!currentUser || !currentUser.userName) { return loadings; } let saveData = (values) => { let newfields = JSON.parse(JSON.stringify(values)); delete newfields.confirmPassword; let timestamp = moment().valueOf().toString() + 'acb'; let newtimestamp = AES.encrypt(timestamp, Utf8.parse('NANGAODEAESKEY--'), { mode: ECB, padding: Pkcs7, }).toString(); let newPassword = AES.encrypt(values.newPassword, Utf8.parse(timestamp), { mode: ECB, padding: Pkcs7, }).toString(), password = AES.encrypt(values.password, Utf8.parse(timestamp), { mode: ECB, padding: Pkcs7, }).toString(); let postData = { password, newPassword, encryptKey: newtimestamp, }; run({ url: '/ngic-auth/sysUser/changePassword', params: { ...postData } }); }; const menuHeaderDropdown = ( <Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}> <Menu.Item key="changepwd"> <LockOutlined /> 修改密码 </Menu.Item> <Menu.Divider /> <Menu.Item key="logout"> <LogoutOutlined /> 退出登录 </Menu.Item> </Menu> ); return ( <div> <Modal title="修改密码" open={visible} onCancel={() => { cv(false); }} destroyOnClose={true} maskClosable={false} footer={false} > <InitForm formRef={formRef} fields={fields} col={{ span: 24 }} onChange={(changedValues, allValues) => {}} submitData={(values, fn) => { saveData(values, fn); }} submitting={loading || !visible} /> </Modal> <HeaderDropdown overlay={menuHeaderDropdown}> <span className={`${styles.action} ${styles.account}`}> <Avatar style={{ backgroundColor: '#1890ff' }}> {currentUser.userName.substr(0, 1)} </Avatar> <span className={`${styles.name} anticon`} style={{ margin: '0 12px' }}> {currentUser.userName} </span> </span> </HeaderDropdown> </div> ); }; export default AvatarDropdown;