feact: 个人中心模块开发

develop
JINGYJ 1 year ago
parent 1ed2ce6800
commit bef3a5cc59

@ -311,4 +311,16 @@ export default [
path: '/notice',
component: 'Notice',
},
{
name: 'account',
path: '/account',
routes: [
{
name: 'center',
path: '/account/center',
component: 'Account/Center',
access: 'canReadMenu',
},
],
},
];

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 130 KiB

@ -88,8 +88,8 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
src: SERVER_HOST + initialState?.currentUser?.avatarUrl,
title: <AvatarName />,
render: (_, avatarChildren) => {
// console.log(avatarChildren,'')
return <AvatarDropdown>{avatarChildren}</AvatarDropdown>;
console.log(avatarChildren,'111111111')
return <AvatarDropdown menu={true}>{avatarChildren}</AvatarDropdown>;
},
},
pageTitleRender: () => {

@ -7,7 +7,8 @@ import type { NotificationPlacement } from 'antd/es/notification/interface';
// import { getallnotices, getUidNotices } from "@/api/caravan/User";
import styles from "./index.module.scss";
import styles from "./index.module.less";
import { useNavigate } from "react-router-dom";
enum EventStatus {
todo = "rgba(255,255,255,1)",
@ -19,6 +20,7 @@ enum EventStatus {
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
const { TabPane} = Tabs;
const Context = React.createContext({ name: 'Default' });
const Notice: React.FC = () => {
@ -32,7 +34,10 @@ const Notice: React.FC = () => {
const noticeListFilter = <T extends any>(type: T) => {
return noticeList.filter(notice => notice.type === type) as any[];
};
const navigate = useNavigate();
const toManagePage = () => {
navigate("/notice");
};
const getNotice = async () => {
//查看我是否有新消息 无论如何
// setLoading(true);
@ -117,7 +122,7 @@ const Notice: React.FC = () => {
<List
dataSource={tabsData}
renderItem={item => (
<List.Item>
<List.Item onClick={() => toManagePage()} style={{ cursor: "pointer" }}>
<List.Item.Meta
description={
<div>
@ -163,7 +168,7 @@ const Notice: React.FC = () => {
{/* <BellOutlined style={{ fontSize: "18px" }} /> */}
<NoticeSvg style={{ fontSize: "18px" }} />
</span>
</Badge>
</Badge>
{/* </Tooltip> */}
</Popover>
</div>

@ -63,6 +63,10 @@ export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu, childre
const onMenuClick = useCallback(
(event: MenuInfo) => {
const { key } = event;
if (key === 'center') {
history.push(`/account/${key}`);
return;
}
if (key === 'logout') {
flushSync(() => {
setInitialState((s) => ({ ...s, currentUser: undefined, menuData: undefined }));
@ -105,11 +109,11 @@ export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu, childre
icon: <UserOutlined />,
label: '个人中心',
},
{
key: 'settings',
icon: <SettingOutlined />,
label: '个人设置',
},
// {
// key: 'settings',
// icon: <SettingOutlined />,
// label: '个人设置',
// },
{
type: 'divider' as const,
},
@ -121,7 +125,7 @@ export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu, childre
label: '退出登录',
},
];
console.log(menuItems,'menuItems');
return (
<HeaderDropdown
menu={{

@ -6,6 +6,7 @@
* @FilePath: \general-ai-platform-web\src\locales\zh-CN.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import * as accountZh from '@/locales/zh-CN/account';
import * as noticeZh from '@/locales/zh-CN/notice';
import * as contactZh from '@/locales/zh-CN/contact';
import * as DCSDevice from '@/locales/zh-CN/DCSDevice';
@ -71,4 +72,5 @@ export default {
...Object.assign({}, ...Object.values(contactZh)),
...Object.assign({}, ...Object.values(alarmLangs)),
...Object.assign({}, ...Object.values(noticeZh)),
...Object.assign({}, ...Object.values(accountZh)),
};

@ -0,0 +1,14 @@
export const account_center: { [key: string]: string } = {
'account.account_center.table.list.id': 'ID',
'account.account_center.table.list.account': '登录账号',
'account.account_center.table.list.originalPassword': '原密码',
'account.account_center.table.list.newPassword': '新密码',
'account.account_center.table.list.confirmPassword': '确认密码',
'account.account_center.table.rule.required.account': '登录账号为必填项',
'account.account_center.table.rule.required.originalPassword': '原登录密码为必填项',
'account.account_center.table.rule.required.newPassword': '新登录密码为必填项',
'account.account_center.table.rule.required.confirmPassword': '确认登录密码为必填项',
'account.account_center.table.list.editor': '修改',
'account.account_center.table.list.UpdateAccountForm': '修改账号',
'account.account_center.table.list.UpdatePasswordForm': '修改密码',
};

@ -0,0 +1,24 @@
.infoBox {
margin-left: 78px;
padding-top: 5px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
height: 90px;
color: #333;
}
.infoBoxRight {
margin-left: 65px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
height: 90px;
color: #333;
}
.spanStyle {
display: inline-block;
width: 68px;
color: #666;
}

@ -0,0 +1,92 @@
import { putProjectUpdateProject } from '@/services/project/Project';
import {
ModalForm,
ProForm,
ProFormText,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import { proFormSmallItemStyleProps, proFormSmallModelWidth } from '../../../../../config/defaultForm';
import React from 'react';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.Project>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.Project>;
reload: any;
};
const UpdateAccountForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.Project>();
return (
<ModalForm<API.Project>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'account.account_center.table.list.UpdateAccountForm',
defaultMessage: '$$$',
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
putProjectUpdateProject(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={<FormattedMessage id="account.account_center.table.list.account" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'account.account_center.table.list.account',
defaultMessage: '$$$',
})}`}
required={true}
initialValue={props.values.name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="account.account_center.table.rule.required.account"
defaultMessage="account is required"
/>
),
},
]}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateAccountForm;

@ -0,0 +1,144 @@
import { putProjectUpdateProject } from '@/services/project/Project';
import {
ModalForm,
ProForm,
ProFormText,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import { proFormSmallItemStyleProps, proFormSmallModelWidth } from '../../../../../config/defaultForm';
import React from 'react';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.Project>;
export type UpdateFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Partial<API.Project>;
reload: any;
};
const UpdatePasswordForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.Project>();
return (
<ModalForm<API.Project>
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'account.account_center.table.list.UpdatePasswordForm',
defaultMessage: '$$$',
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
putProjectUpdateProject(values)
.then(() => {
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }));
props.reload();
})
.catch(() => {
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }));
});
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={<FormattedMessage id="account.account_center.table.list.originalPassword" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'account.account_center.table.list.originalPassword',
defaultMessage: '$$$',
})}`}
required={true}
initialValue={props.values.name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="account.account_center.table.rule.required.originalPassword"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={<FormattedMessage id="account.account_center.table.list.newPassword" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'account.account_center.table.list.newPassword',
defaultMessage: '$$$',
})}`}
required={true}
initialValue={props.values.name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="account.account_center.table.rule.required.newPassword"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={<FormattedMessage id="account.account_center.table.list.confirmPassword" defaultMessage="$$$" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'account.account_center.table.list.confirmPassword',
defaultMessage: '$$$',
})}`}
required={true}
initialValue={props.values.name}
disabled={false}
rules={[
{
required: true,
message: (
<FormattedMessage
id="account.account_center.table.rule.required.confirmPassword"
defaultMessage="name is required"
/>
),
},
]}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdatePasswordForm;

@ -0,0 +1,167 @@
import { PageContainer, ProCard } from '@ant-design/pro-components';
import React, { useEffect, useRef, useState } from 'react';
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, message, Upload } from 'antd';
import type { UploadChangeParam } from 'antd/es/upload';
import type { RcFile, UploadFile, UploadProps } from 'antd/es/upload/interface';
import type { ActionType } from '@ant-design/pro-components';
// svg 转组件
import { ReactComponent as AvatarSvg } from '../../../../public/icons/avatar.svg';
import styles from "./center.less";
import UpdateAccountForm from './components/UpdateAccountForm';
import UpdatePasswordForm from './components/UpdatePasswordForm';
import { FormattedMessage } from '@umijs/max';
const getBase64 = (img: RcFile, callback: (url: string) => void) => {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result as string));
reader.readAsDataURL(img);
};
const beforeUpload = (file: RcFile) => {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
};
/**
* @
* @returns
*/
const AccountCenter: React.FC = () => {
const [loading, setLoading] = useState(false);
const [imageUrl, setImageUrl] = useState<string>();
const actionRef = useRef<ActionType>();
const [updateAccountModalOpen, setUpdateAccountModalOpen] = useState<boolean>(false);
const [updatePasswordModalOpen, setUpdatePasswordModalOpen] = useState<boolean>(false);
const [currentRow, setCurrentRow] = useState<API.Project>();
const handleUpdateAccountModal = () => {
if (updateAccountModalOpen) {
setUpdateAccountModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdateAccountModalOpen(true);
}
};
const handleUpdatePasswordModal = () => {
if (updatePasswordModalOpen) {
setUpdatePasswordModalOpen(false);
setCurrentRow(undefined);
} else {
setUpdatePasswordModalOpen(true);
}
};
const handleChange: UploadProps['onChange'] = (info: UploadChangeParam<UploadFile>) => {
if (info.file.status === 'uploading') {
setLoading(true);
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj as RcFile, (url) => {
setLoading(false);
setImageUrl(url);
});
}
console.log(info);
};
const uploadButton = (
<div style={{ width: 100,height: 100, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
{loading ? <LoadingOutlined /> : <AvatarSvg />}
{/* <div style={{ marginTop: 8 }}>Upload</div> */}
</div>
);
return (
<PageContainer>
<ProCard
style={{ background: 'white' }}
bodyStyle={{
padding: 40,
margin: 0,
display: 'flex'
}}
gutter={24}
wrap
ghost
>
<Upload
name="avatar"
// listType="picture-card"
// className="avatar-uploader"
showUploadList={false}
maxCount={1}
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
beforeUpload={beforeUpload}
onChange={handleChange}
>
{imageUrl ? <img src={imageUrl} alt="avatar" style={{ width: 100,height: 100 }} /> : uploadButton}
</Upload>
<div className={styles.infoBox}>
<div>
<span className={styles.spanStyle}>:</span>
</div>
<div>
<span className={styles.spanStyle}>ID:</span>awtk-55975980
</div>
<div>
<span className={styles.spanStyle}>:</span>2012-10-16 23:55:35
</div>
</div>
<div className={styles.infoBoxRight}>
<div>
<span className={styles.spanStyle}>:</span>wangliqun
<Button
type="link"
color="#154DDD"
onClick={() => {
setUpdateAccountModalOpen(true);
setCurrentRow({});
}}>
<FormattedMessage id="account.account_center.table.list.editor" defaultMessage="editor" />
</Button>
</div>
<div>
<span className={styles.spanStyle}>:</span>wangliqun
<Button
type="link"
color="#154DDD"
onClick={() => {
setUpdatePasswordModalOpen(true);
setCurrentRow({});
}}>
<FormattedMessage id="account.account_center.table.list.editor" defaultMessage="editor" />
</Button>
</div>
</div>
</ProCard>
<UpdateAccountForm
updateModalOpen={updateAccountModalOpen}
values={currentRow || {}}
handleModal={handleUpdateAccountModal}
reload={actionRef.current?.reload}
/>
<UpdatePasswordForm
updateModalOpen={updatePasswordModalOpen}
values={currentRow || {}}
handleModal={handleUpdatePasswordModal}
reload={actionRef.current?.reload}
/>
</PageContainer>
);
};
export default AccountCenter;

@ -37,6 +37,7 @@ const ProjectList: React.FC = () => {
const access = useAccess();
const intl = useIntl();
const actionRef = useRef<ActionType>();
console.log(actionRef,'actionRef');
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const [currentRow, setCurrentRow] = useState<API.Project>();

Loading…
Cancel
Save