style: login
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 108 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,11 @@
|
||||
// footer all styles
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
font-size: var(--font-size-middle);
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Space } from 'antd';
|
||||
import './index.less';
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<div className="footer">
|
||||
<div className="footer-content">
|
||||
<div className="footer-content-left">
|
||||
<div className="footer-content-left-text">
|
||||
<Space size={4}>
|
||||
<span>©</span>
|
||||
<span> {new Date().getFullYear()}</span>
|
||||
<span> {intl.formatMessage({ id: 'settings.company' })}</span>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
@@ -35,6 +35,7 @@ const Wrapper: React.FC<WrapperProps> = ({
|
||||
<div
|
||||
className={classNames(
|
||||
wrapperStyle['wrapper-box'],
|
||||
'field-wrapper',
|
||||
wrapperStyle[`validate-status-${status}`],
|
||||
addAfter ? wrapperStyle['seal-input-wrapper-addafter'] : '',
|
||||
disabled ? wrapperStyle['seal-input-wrapper-disabled'] : '',
|
||||
|
||||
+20
-11
@@ -22,6 +22,8 @@ html {
|
||||
--font-weight-medium: 600;
|
||||
--font-weight-bold: 700;
|
||||
--color-text-1: var(--ant-color-text);
|
||||
--color-text-3: rgba(0, 0, 0, 45%);
|
||||
--color-text-2: rgba(0, 0, 0, 65%);
|
||||
--color-bg-light-1: #e6f6ff;
|
||||
--font-size-base: 12px;
|
||||
--font-size-large: 16px;
|
||||
@@ -59,7 +61,7 @@ html {
|
||||
--ant-font-size: var(--font-size-base);
|
||||
|
||||
&.ant-menu-css-var {
|
||||
--ant-menu-item-selected-bg: var(--color-white-1);
|
||||
// --ant-menu-item-selected-bg: var(--color-white-1);
|
||||
--ant-menu-item-border-radius: 8px;
|
||||
--ant-menu-item-selected-color: var(--ant-color-primary);
|
||||
--ant-menu-item-hover-bg: var(--color-white-1);
|
||||
@@ -107,7 +109,7 @@ html {
|
||||
.css-var-ri.ant-menu-css-var,
|
||||
.css-var-rh.ant-menu-css-var {
|
||||
--ant-menu-item-height: 46px;
|
||||
--ant-menu-item-selected-bg: var(--color-white-1);
|
||||
// --ant-menu-item-selected-bg: var(--color-white-1);
|
||||
--ant-menu-item-border-radius: 8px;
|
||||
--ant-menu-item-selected-color: var(--ant-color-primary);
|
||||
--ant-menu-item-hover-bg: var(--color-white-1);
|
||||
@@ -265,6 +267,10 @@ body {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.ant-pro-sider-logo-collapsed {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.ant-pro-sider .ant-layout-sider-children {
|
||||
background-color: var(--color-fill-sider);
|
||||
// box-shadow: var(--box-shadow-base);
|
||||
@@ -394,15 +400,18 @@ body {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
// .login-wrapper {
|
||||
// position: fixed;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// bottom: 0;
|
||||
// right: 0;
|
||||
// background: url('@/assets/images/bg-2.png') center center no-repeat;
|
||||
// background-size: cover;
|
||||
// }
|
||||
|
||||
.login-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
min-height: 100vh;
|
||||
z-index: -1;
|
||||
background: url('@/assets/images/bg-2.png') center center no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.ant-pro-page-container {
|
||||
background: transparent;
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
// This file is generated by Umi automatically
|
||||
// DO NOT CHANGE IT MANUALLY!
|
||||
import GpustackLogo from '@/assets/images/gpustack-logo.png';
|
||||
import SmallLogo from '@/assets/images/small-logo-200x200.png';
|
||||
import React from 'react';
|
||||
|
||||
const LogoIcon: React.FC = () => {
|
||||
return <img src={GpustackLogo} alt="logo" style={{ height: 16 }} />;
|
||||
};
|
||||
const SLogoIcon: React.FC = () => {
|
||||
return <img src={SmallLogo} alt="logo" style={{ height: 24 }} />;
|
||||
};
|
||||
|
||||
export default LogoIcon;
|
||||
export { LogoIcon, SLogoIcon };
|
||||
|
||||
+11
-6
@@ -4,6 +4,7 @@ import { userAtom } from '@/atoms/user';
|
||||
import { logout } from '@/pages/login/apis';
|
||||
import { useAccessMarkedRoutes } from '@@/plugin-access';
|
||||
import { useModel } from '@@/plugin-model';
|
||||
|
||||
import { ProLayout } from '@ant-design/pro-components';
|
||||
import {
|
||||
Link,
|
||||
@@ -17,13 +18,12 @@ import {
|
||||
type IRoute
|
||||
} from '@umijs/max';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import Exception from './Exception';
|
||||
import './Layout.css';
|
||||
import Logo from './Logo';
|
||||
import { LogoIcon, SLogoIcon } from './Logo';
|
||||
import { getRightRenderContent } from './rightRender';
|
||||
import { patchRoutes } from './runtime';
|
||||
|
||||
const loginPath = '/login';
|
||||
|
||||
// 过滤出需要显示的路由, 这里的filterFn 指 不希望显示的层级
|
||||
@@ -84,6 +84,7 @@ export default (props: any) => {
|
||||
const navigate = useNavigate();
|
||||
const intl = useIntl();
|
||||
const { clientRoutes, pluginManager } = useAppData();
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
||||
const initialInfo = (useModel && useModel('@@initialState')) || {
|
||||
initialState: undefined,
|
||||
@@ -94,7 +95,6 @@ export default (props: any) => {
|
||||
|
||||
const userConfig = {
|
||||
title: '',
|
||||
layout: 'mix',
|
||||
locale: true
|
||||
};
|
||||
|
||||
@@ -145,12 +145,18 @@ export default (props: any) => {
|
||||
location={location}
|
||||
title={userConfig.title}
|
||||
navTheme="light"
|
||||
layout="side"
|
||||
disableMobile={true}
|
||||
siderWidth={220}
|
||||
onMenuHeaderClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
navigate('/');
|
||||
}}
|
||||
collapsed={collapsed}
|
||||
onCollapse={(collapsed) => {
|
||||
setCollapsed(collapsed);
|
||||
}}
|
||||
onPageChange={(route) => {
|
||||
const { location } = history;
|
||||
|
||||
@@ -178,9 +184,8 @@ export default (props: any) => {
|
||||
}}
|
||||
formatMessage={formatMessage}
|
||||
menu={{ locale: true }}
|
||||
logo={Logo}
|
||||
logo={collapsed ? SLogoIcon : LogoIcon}
|
||||
menuItemRender={(menuItemProps, defaultDom) => {
|
||||
console.log('meurender=========', { defaultDom });
|
||||
if (menuItemProps.isUrl || menuItemProps.children) {
|
||||
return defaultDom;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
AppstoreOutlined,
|
||||
MailOutlined,
|
||||
SettingOutlined
|
||||
} from '@ant-design/icons';
|
||||
import { Menu, type MenuProps } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
const items: MenuItem[] = [
|
||||
{
|
||||
key: 'sub1',
|
||||
icon: <MailOutlined />,
|
||||
label: 'Navigation One',
|
||||
children: [
|
||||
{
|
||||
key: '1-1',
|
||||
label: 'Item 1',
|
||||
type: 'group',
|
||||
children: [
|
||||
{ key: '1', label: 'Option 1' },
|
||||
{ key: '2', label: 'Option 2' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: '1-2',
|
||||
label: 'Item 2',
|
||||
type: 'group',
|
||||
children: [
|
||||
{ key: '3', label: 'Option 3' },
|
||||
{ key: '4', label: 'Option 4' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'sub2',
|
||||
icon: <AppstoreOutlined />,
|
||||
label: 'Navigation Two',
|
||||
children: [
|
||||
{ key: '5', label: 'Option 5' },
|
||||
{ key: '6', label: 'Option 6' },
|
||||
{
|
||||
key: 'sub3',
|
||||
label: 'Submenu'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'sub4',
|
||||
label: 'Navigation Three',
|
||||
icon: <SettingOutlined />,
|
||||
children: [
|
||||
{ key: '9', label: 'Option 9' },
|
||||
{ key: '10', label: 'Option 10' },
|
||||
{ key: '11', label: 'Option 11' },
|
||||
{ key: '12', label: 'Option 12' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const RenderLinks: React.FC = () => {
|
||||
return <Menu mode="vertical" items={items} />;
|
||||
};
|
||||
|
||||
export default React.memo(RenderLinks);
|
||||
@@ -62,6 +62,7 @@ export function getRightRenderContent(opts: {
|
||||
<SelectLang
|
||||
style={{ padding: '10px 18px', marginBottom: '20px' }}
|
||||
reload={false}
|
||||
mode="vertical"
|
||||
icon={
|
||||
<span style={{ fontSize: '12px' }}>
|
||||
<GlobalOutlined />
|
||||
@@ -113,18 +114,6 @@ export function getRightRenderContent(opts: {
|
||||
history.push('/profile');
|
||||
}
|
||||
},
|
||||
// {
|
||||
// key: 'theme',
|
||||
// label: (
|
||||
// <>
|
||||
// <SunOutlined />
|
||||
// 外观
|
||||
// </>
|
||||
// ),
|
||||
// onClick: () => {
|
||||
// console.log('theme');
|
||||
// }
|
||||
// },
|
||||
{
|
||||
key: 'logout',
|
||||
label: (
|
||||
@@ -158,7 +147,9 @@ export function getRightRenderContent(opts: {
|
||||
};
|
||||
} else {
|
||||
// 需要 antd 4.20.0 以上版本
|
||||
dropdownProps = { overlay: <Menu {...langMenu} mode="vertical" /> };
|
||||
dropdownProps = {
|
||||
overlay: <Menu {...langMenu} mode="vertical" />
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -186,5 +186,6 @@ export default {
|
||||
'common.filter.name': 'Filter by name',
|
||||
'common.form.password': 'Password',
|
||||
'common.form.username': 'Username',
|
||||
'common.login.rember': 'Remember me'
|
||||
'common.login.rember': 'Remember me',
|
||||
'settings.company': 'SEAL'
|
||||
};
|
||||
|
||||
@@ -179,5 +179,6 @@ export default {
|
||||
'common.filter.name': '名称查询',
|
||||
'common.form.password': '密码',
|
||||
'common.form.username': '用户名',
|
||||
'common.login.rember': '记住我'
|
||||
'common.login.rember': '记住我',
|
||||
'settings.company': '数澈软件'
|
||||
};
|
||||
|
||||
@@ -155,7 +155,7 @@ const LoginForm = () => {
|
||||
<div>
|
||||
<Form
|
||||
form={form}
|
||||
style={{ width: '400px', margin: '0 auto', paddingTop: '10%' }}
|
||||
style={{ width: '400px', margin: '0 auto' }}
|
||||
onFinish={handleLogin}
|
||||
>
|
||||
{renderWelCome(intl)}
|
||||
|
||||
@@ -46,7 +46,7 @@ const PasswordForm: React.FC = () => {
|
||||
</div>
|
||||
<Form
|
||||
form={form}
|
||||
style={{ width: '400px', margin: '0 auto', paddingTop: '5%' }}
|
||||
style={{ width: '400px', margin: '0 auto' }}
|
||||
onFinish={handleSubmit}
|
||||
>
|
||||
<h2 className="justify-center m-b-20 flex-column flex-center">
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
:local(.login-form-wrapper) {
|
||||
margin: 0 auto;
|
||||
border-radius: 8px;
|
||||
width: max-content;
|
||||
height: max-content;
|
||||
padding: 32px;
|
||||
background-color: rgba(255, 255, 255, 50%);
|
||||
|
||||
:global(.field-wrapper) {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
:local(.box) {
|
||||
padding-top: 10%;
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import { userAtom } from '@/atoms/user';
|
||||
import Footer from '@/components/footer';
|
||||
import { history } from '@umijs/max';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useEffect } from 'react';
|
||||
import LoginForm from './components/login-form';
|
||||
import PasswordForm from './components/password-form';
|
||||
import styles from './components/styles.less';
|
||||
|
||||
const Login = () => {
|
||||
const [userInfo, setUserInfo] = useAtom(userAtom);
|
||||
@@ -21,9 +23,15 @@ const Login = () => {
|
||||
}, [userInfo]);
|
||||
|
||||
return (
|
||||
<div className="login-wrapper">
|
||||
{userInfo?.require_password_change ? <PasswordForm /> : <LoginForm />}
|
||||
</div>
|
||||
<>
|
||||
<div className="login-wrapper"></div>
|
||||
<div className={styles.box}>
|
||||
<div className={styles['login-form-wrapper']}>
|
||||
{userInfo?.require_password_change ? <PasswordForm /> : <LoginForm />}
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ import AddModal from './components/add-modal';
|
||||
import { FormData, ListItem } from './config/types';
|
||||
const { Column } = Table;
|
||||
|
||||
const Models: React.FC = () => {
|
||||
const Users: React.FC = () => {
|
||||
console.log('users======');
|
||||
const rowSelection = useTableRowSelection();
|
||||
const { sortOrder, setSortOrder } = useTableSort({
|
||||
defaultSortOrder: 'descend'
|
||||
@@ -328,4 +329,4 @@ const Models: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Models;
|
||||
export default Users;
|
||||
|
||||
Reference in New Issue
Block a user