开发: 删除不用的文件

This commit is contained in:
zhengw
2023-04-18 09:57:53 +08:00
parent bc8bb916ee
commit 97348fea9e
14 changed files with 36 additions and 2134 deletions

View File

@@ -1,6 +1,6 @@
import Footer from '@/components/Footer';
import { LinkOutlined } from '@ant-design/icons';
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import { Settings as LayoutSettings } from '@ant-design/pro-components';
import type { RequestConfig, RunTimeLayoutConfig } from '@umijs/max';
import { history, Link } from '@umijs/max';
import { App } from 'antd';
@@ -114,7 +114,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
childrenRender: (children) => {
// if (initialState?.loading) return <PageLoading />;
return (
<>
<div style={{ minHeight: 'calc(100vh - 55px - 60px)' }}>
{children}
{/* <FloatButton
icon={<VerticalAlignTopOutlined />}
@@ -134,7 +134,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
}));
}}
/> */}
</>
</div>
);
},
...initialState?.settings,

View File

@@ -1,20 +1,13 @@
import { DefaultFooter } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import React from 'react';
const Footer: React.FC = () => {
const intl = useIntl();
const defaultMessage = intl.formatMessage({
id: 'app.copyright.produced',
defaultMessage: '2021 - 2028 福州晨丰科技有限公司',
});
return (
<DefaultFooter
style={{
background: 'none',
}}
copyright={`${defaultMessage}`}
copyright={`2021 - 2028 福州晨丰科技有限公司`}
links={[
{
key: 'scrm.antd',

View File

@@ -18,10 +18,6 @@ body,
min-height: 100vh;
}
.ant-pro-page-container {
min-height: calc(100vh - 55px - 60px);
}
.ant-pro-global-footer {
margin-top: 0;
margin-bottom: 0;

View File

@@ -1,4 +1,3 @@
import { useIntl } from '@umijs/max';
import { Button, message, notification } from 'antd';
import defaultSettings from '../config/defaultSettings';
@@ -23,7 +22,7 @@ const clearCache = () => {
if (pwa) {
// Notify user if offline now
window.addEventListener('sw.offline', () => {
message.warning(useIntl().formatMessage({ id: 'app.pwa.offline' }));
message.warning('当前处于离线状态');
});
// Pop up a prompt on the page asking the user if they want to use the latest version
@@ -62,12 +61,12 @@ if (pwa) {
reloadSW();
}}
>
{useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated.ok' })}
</Button>
);
notification.open({
message: useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated' }),
description: useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated.hint' }),
message: '有新内容',
description: '请点击“刷新”按钮或者手动刷新页面',
btn,
key,
onClose: async () => null,

View File

@@ -1,45 +0,0 @@
import { HeartTwoTone, SmileTwoTone } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Alert, Card, Typography } from 'antd';
import React from 'react';
const Admin: React.FC = () => {
const intl = useIntl();
return (
<PageContainer
content={intl.formatMessage({
id: 'pages.admin.subPage.title',
defaultMessage: 'This page can only be viewed by admin',
})}
>
<Card>
<Alert
message={intl.formatMessage({
id: 'pages.welcome.alertMessage',
defaultMessage: 'Faster and stronger heavy-duty components have been released.',
})}
type="success"
showIcon
banner
style={{
margin: -12,
marginBottom: 48,
}}
/>
<Typography.Title level={2} style={{ textAlign: 'center' }}>
<SmileTwoTone /> Ant Design Pro <HeartTwoTone twoToneColor="#eb2f96" /> You
</Typography.Title>
</Card>
<p style={{ textAlign: 'center', marginTop: 24 }}>
Want to add more pages? Please refer to{' '}
<a href="https://pro.ant.design/docs/block-cn" target="_blank" rel="noopener noreferrer">
use block
</a>
</p>
</PageContainer>
);
};
export default Admin;

View File

@@ -70,6 +70,7 @@ export interface IGroup {
export interface IGroupMembers {
avatar: string;
staff_avatar?: string;
cust_id: string;
gender: number;

View File

@@ -186,11 +186,12 @@ const ChatLogs: React.FC = () => {
}).then((res) => {
if (res.err_code == 0) {
if (Array.isArray(res.data)) {
setGroupMembersList(res.data);
groupMembersObjRef.current = {};
res.data.forEach((item: IGroupMembers) => {
item.avatar = item.staff_avatar || item.avatar;
groupMembersObjRef.current[item.user_id] = item;
});
setGroupMembersList(res.data);
page(1);
}
}

View File

@@ -1,209 +0,0 @@
import {
ProFormDateTimePicker,
ProFormRadio,
ProFormSelect,
ProFormText,
ProFormTextArea,
StepsForm,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Modal } from 'antd';
import React from 'react';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.RuleListItem>;
export type UpdateFormProps = {
onCancel: (flag?: boolean, formVals?: FormValueType) => void;
onSubmit: (values: FormValueType) => Promise<void>;
updateModalOpen: boolean;
values: Partial<API.RuleListItem>;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
return (
<StepsForm
stepsProps={{
size: 'small',
}}
stepsFormRender={(dom, submitter) => {
return (
<Modal
width={640}
bodyStyle={{ padding: '32px 40px 48px' }}
destroyOnClose
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleConfig',
defaultMessage: '规则配置',
})}
open={props.updateModalOpen}
footer={submitter}
onCancel={() => {
props.onCancel();
}}
>
{dom}
</Modal>
);
}}
onFinish={props.onSubmit}
>
<StepsForm.StepForm
initialValues={{
name: props.values.name,
desc: props.values.desc,
}}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.basicConfig',
defaultMessage: '基本信息',
})}
>
<ProFormText
name="name"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleName.nameLabel',
defaultMessage: '规则名称',
})}
width="md"
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleName.nameRules"
defaultMessage="请输入规则名称!"
/>
),
},
]}
/>
<ProFormTextArea
name="desc"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleDesc.descLabel',
defaultMessage: '规则描述',
})}
placeholder={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleDesc.descPlaceholder',
defaultMessage: '请输入至少五个字符',
})}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleDesc.descRules"
defaultMessage="请输入至少五个字符的规则描述!"
/>
),
min: 5,
},
]}
/>
</StepsForm.StepForm>
<StepsForm.StepForm
initialValues={{
target: '0',
template: '0',
}}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.title',
defaultMessage: '配置规则属性',
})}
>
<ProFormSelect
name="target"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.object',
defaultMessage: '监控对象',
})}
valueEnum={{
0: '表一',
1: '表二',
}}
/>
<ProFormSelect
name="template"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.templateLabel',
defaultMessage: '规则模板',
})}
valueEnum={{
0: '规则模板一',
1: '规则模板二',
}}
/>
<ProFormRadio.Group
name="type"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.ruleProps.typeLabel',
defaultMessage: '规则类型',
})}
options={[
{
value: '0',
label: '强',
},
{
value: '1',
label: '弱',
},
]}
/>
</StepsForm.StepForm>
<StepsForm.StepForm
initialValues={{
type: '1',
frequency: 'month',
}}
title={intl.formatMessage({
id: 'pages.searchTable.updateForm.schedulingPeriod.title',
defaultMessage: '设定调度周期',
})}
>
<ProFormDateTimePicker
name="time"
width="md"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.schedulingPeriod.timeLabel',
defaultMessage: '开始时间',
})}
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.updateForm.schedulingPeriod.timeRules"
defaultMessage="请选择开始时间!"
/>
),
},
]}
/>
<ProFormSelect
name="frequency"
label={intl.formatMessage({
id: 'pages.searchTable.updateForm.object',
defaultMessage: '监控对象',
})}
width="md"
valueEnum={{
month: '月',
week: '周',
}}
/>
</StepsForm.StepForm>
</StepsForm>
);
};
export default UpdateForm;

View File

@@ -1,422 +0,0 @@
import { addRule, removeRule, rule, updateRule } from '@/services/ant-design-pro/api';
import { PlusOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns, ProDescriptionsItemProps } from '@ant-design/pro-components';
import {
FooterToolbar,
ModalForm,
PageContainer,
ProDescriptions,
ProFormText,
ProFormTextArea,
ProTable,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl, useModel } from '@umijs/max';
import { Button, Drawer, Input, message } from 'antd';
import React, { useRef, useState } from 'react';
import type { FormValueType } from './components/UpdateForm';
import UpdateForm from './components/UpdateForm';
/**
* @en-US Add node
* @zh-CN 添加节点
* @param fields
*/
const handleAdd = async (fields: API.RuleListItem) => {
const hide = message.loading('正在添加');
try {
await addRule({ ...fields });
hide();
message.success('Added successfully');
return true;
} catch (error) {
hide();
message.error('Adding failed, please try again!');
return false;
}
};
/**
* @en-US Update node
* @zh-CN 更新节点
*
* @param fields
*/
const handleUpdate = async (fields: FormValueType) => {
const hide = message.loading('Configuring');
try {
await updateRule({
name: fields.name,
desc: fields.desc,
key: fields.key,
});
hide();
message.success('Configuration is successful');
return true;
} catch (error) {
hide();
message.error('Configuration failed, please try again!');
return false;
}
};
/**
* Delete node
* @zh-CN 删除节点
*
* @param selectedRows
*/
const handleRemove = async (selectedRows: API.RuleListItem[]) => {
const hide = message.loading('正在删除');
if (!selectedRows) return true;
try {
await removeRule({
key: selectedRows.map((row) => row.key),
});
hide();
message.success('Deleted successfully and will refresh soon');
return true;
} catch (error) {
hide();
message.error('Delete failed, please try again');
return false;
}
};
const TableList: React.FC = () => {
/**
* @en-US Pop-up window of new window
* @zh-CN 新建窗口的弹窗
* */
const [createModalOpen, handleModalOpen] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN 分布更新窗口的弹窗
* */
const [updateModalOpen, handleUpdateModalOpen] = useState<boolean>(false);
const [showDetail, setShowDetail] = useState<boolean>(false);
const actionRef = useRef<ActionType>();
const [currentRow, setCurrentRow] = useState<API.RuleListItem>();
const [selectedRowsState, setSelectedRows] = useState<API.RuleListItem[]>([]);
/**
* @en-US International configuration
* @zh-CN 国际化配置
* */
const intl = useIntl();
const columns: ProColumns<API.RuleListItem>[] = [
{
title: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleName.nameLabel"
defaultMessage="Rule name"
/>
),
dataIndex: 'name',
tip: 'The rule name is the unique key',
render: (dom, entity) => {
return (
<a
onClick={() => {
setCurrentRow(entity);
setShowDetail(true);
}}
>
{dom}
</a>
);
},
},
{
title: <FormattedMessage id="pages.searchTable.titleDesc" defaultMessage="Description" />,
dataIndex: 'desc',
valueType: 'textarea',
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleCallNo"
defaultMessage="Number of service calls"
/>
),
dataIndex: 'callNo',
sorter: true,
hideInForm: true,
renderText: (val: string) =>
`${val}${intl.formatMessage({
id: 'pages.searchTable.tenThousand',
defaultMessage: ' 万 ',
})}`,
},
{
title: <FormattedMessage id="pages.searchTable.titleStatus" defaultMessage="Status" />,
dataIndex: 'status',
hideInForm: true,
valueEnum: {
0: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.default"
defaultMessage="Shut down"
/>
),
status: 'Default',
},
1: {
text: (
<FormattedMessage id="pages.searchTable.nameStatus.running" defaultMessage="Running" />
),
status: 'Processing',
},
2: {
text: (
<FormattedMessage id="pages.searchTable.nameStatus.online" defaultMessage="Online" />
),
status: 'Success',
},
3: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.abnormal"
defaultMessage="Abnormal"
/>
),
status: 'Error',
},
},
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleUpdatedAt"
defaultMessage="Last scheduled time"
/>
),
sorter: true,
dataIndex: 'updatedAt',
valueType: 'dateTime',
renderFormItem: (item, { defaultRender, ...rest }, form) => {
const status = form.getFieldValue('status');
if (`${status}` === '0') {
return false;
}
if (`${status}` === '3') {
return (
<Input
{...rest}
placeholder={intl.formatMessage({
id: 'pages.searchTable.exception',
defaultMessage: 'Please enter the reason for the exception!',
})}
/>
);
}
return defaultRender(item);
},
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="Operating" />,
dataIndex: 'option',
valueType: 'option',
render: (_, record) => [
<a
key="config"
onClick={() => {
handleUpdateModalOpen(true);
setCurrentRow(record);
}}
>
<FormattedMessage id="pages.searchTable.config" defaultMessage="Configuration" />
</a>,
<a key="subscribeAlert" href="https://procomponents.ant.design/">
<FormattedMessage
id="pages.searchTable.subscribeAlert"
defaultMessage="Subscribe to alerts"
/>
</a>,
],
},
];
const { add, minus, counter } = useModel('demo', (ret) => ({
add: ret.increment,
minus: ret.decrement,
counter: ret.counter,
}));
return (
<PageContainer>
<div style={{ marginBottom: 12 }}>
<Button
onClick={() => {
add();
}}
style={{ marginRight: 12 }}
>
+1
</Button>
<Button
onClick={() => {
minus();
}}
style={{ marginRight: 12 }}
>
-1
</Button>
<span>{counter}</span>
</div>
<ProTable<API.RuleListItem, API.PageParams>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: 'Enquiry form',
})}
actionRef={actionRef}
rowKey="key"
search={{
labelWidth: 120,
}}
toolBarRender={() => [
<Button
type="primary"
key="primary"
onClick={() => {
handleModalOpen(true);
}}
>
<PlusOutlined /> <FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
</Button>,
]}
request={rule}
columns={columns}
rowSelection={{
onChange: (_, selectedRows) => {
setSelectedRows(selectedRows);
},
}}
/>
{selectedRowsState?.length > 0 && (
<FooterToolbar
extra={
<div>
<FormattedMessage id="pages.searchTable.chosen" defaultMessage="Chosen" />{' '}
<a style={{ fontWeight: 600 }}>{selectedRowsState.length}</a>{' '}
<FormattedMessage id="pages.searchTable.item" defaultMessage="项" />
&nbsp;&nbsp;
<span>
<FormattedMessage
id="pages.searchTable.totalServiceCalls"
defaultMessage="Total number of service calls"
/>{' '}
{selectedRowsState.reduce((pre, item) => pre + item.callNo!, 0)}{' '}
<FormattedMessage id="pages.searchTable.tenThousand" defaultMessage="万" />
</span>
</div>
}
>
<Button
onClick={async () => {
await handleRemove(selectedRowsState);
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
}}
>
<FormattedMessage
id="pages.searchTable.batchDeletion"
defaultMessage="Batch deletion"
/>
</Button>
<Button type="primary">
<FormattedMessage
id="pages.searchTable.batchApproval"
defaultMessage="Batch approval"
/>
</Button>
</FooterToolbar>
)}
<ModalForm
title={intl.formatMessage({
id: 'pages.searchTable.createForm.newRule',
defaultMessage: 'New rule',
})}
width="400px"
open={createModalOpen}
onOpenChange={handleModalOpen}
onFinish={async (value) => {
const success = await handleAdd(value as API.RuleListItem);
if (success) {
handleModalOpen(false);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
>
<ProFormText
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.ruleName"
defaultMessage="Rule name is required"
/>
),
},
]}
width="md"
name="name"
/>
<ProFormTextArea width="md" name="desc" />
</ModalForm>
<UpdateForm
onSubmit={async (value) => {
const success = await handleUpdate(value);
if (success) {
handleUpdateModalOpen(false);
setCurrentRow(undefined);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
onCancel={() => {
handleUpdateModalOpen(false);
if (!showDetail) {
setCurrentRow(undefined);
}
}}
updateModalOpen={updateModalOpen}
values={currentRow || {}}
/>
<Drawer
width={600}
open={showDetail}
onClose={() => {
setCurrentRow(undefined);
setShowDetail(false);
}}
closable={false}
>
{currentRow?.name && (
<ProDescriptions<API.RuleListItem>
column={2}
title={currentRow?.name}
request={async () => ({
data: currentRow || {},
})}
params={{
id: currentRow?.name,
}}
columns={columns as ProDescriptionsItemProps<API.RuleListItem>[]}
/>
)}
</Drawer>
</PageContainer>
);
};
export default TableList;

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
import Footer from '@/components/Footer';
import { IAjaxReturn, post } from '@/services/ajax';
import { getFakeCaptcha } from '@/services/ant-design-pro/login';
import {
AlipayCircleOutlined,
LockOutlined,
@@ -16,8 +15,8 @@ import {
ProFormText,
} from '@ant-design/pro-components';
import { useEmotionCss } from '@ant-design/use-emotion-css';
import { FormattedMessage, Helmet, history, SelectLang, useIntl, useModel } from '@umijs/max';
import { Alert, App, message, Tabs } from 'antd';
import { FormattedMessage, Helmet, history, SelectLang, useModel } from '@umijs/max';
import { Alert, App, Tabs } from 'antd';
import { stringify as qsStringify } from 'qs';
import React, { useState } from 'react';
import { flushSync } from 'react-dom';
@@ -101,8 +100,6 @@ const Login: React.FC = () => {
};
});
const intl = useIntl();
const fetchUserInfo = async () => {
const userInfo = await initialState?.fetchUserInfo?.();
if (userInfo) {
@@ -148,13 +145,7 @@ const Login: React.FC = () => {
return (
<div className={containerClassName}>
<Helmet>
<title>
{intl.formatMessage({
id: 'menu.login',
defaultMessage: '登录页',
})}
- {Settings.title}
</title>
<title> - {Settings.title}</title>
</Helmet>
{/* <Lang /> */}
<div
@@ -211,28 +202,17 @@ const Login: React.FC = () => {
items={[
{
key: 'account',
label: intl.formatMessage({
id: 'pages.login.accountLogin.tab',
defaultMessage: '账户密码登录',
}),
label: '账户密码登录',
},
// {
// key: 'mobile',
// label: intl.formatMessage({
// id: 'pages.login.phoneLogin.tab',
// defaultMessage: '手机号登录',
// }),
// label: '手机号登录',
// },
]}
/>
{status === 'error' && loginType === 'account' && (
<LoginMessage
content={intl.formatMessage({
id: 'pages.login.accountLogin.errorMessage',
defaultMessage: '账户或密码错误(admin/ant.design)',
})}
/>
<LoginMessage content={'账户或密码错误(admin/ant.design)'} />
)}
{type === 'account' && (
<>
@@ -242,10 +222,7 @@ const Login: React.FC = () => {
size: 'large',
prefix: <UserOutlined />,
}}
placeholder={intl.formatMessage({
id: 'pages.login.username.placeholder',
defaultMessage: '用户名: admin or user',
})}
placeholder={'用户名'}
rules={[
{
required: true,
@@ -264,10 +241,7 @@ const Login: React.FC = () => {
size: 'large',
prefix: <LockOutlined />,
}}
placeholder={intl.formatMessage({
id: 'pages.login.password.placeholder',
defaultMessage: '请输入密码',
})}
placeholder={'请输入密码'}
rules={[
{
required: true,
@@ -292,10 +266,7 @@ const Login: React.FC = () => {
prefix: <MobileOutlined />,
}}
name="mobile"
placeholder={intl.formatMessage({
id: 'pages.login.phoneNumber.placeholder',
defaultMessage: '手机号',
})}
placeholder={'手机号'}
rules={[
{
required: true,
@@ -325,21 +296,12 @@ const Login: React.FC = () => {
captchaProps={{
size: 'large',
}}
placeholder={intl.formatMessage({
id: 'pages.login.captcha.placeholder',
defaultMessage: '请输入验证码',
})}
placeholder={'请输入验证码'}
captchaTextRender={(timing, count) => {
if (timing) {
return `${count} ${intl.formatMessage({
id: 'pages.getCaptchaSecondText',
defaultMessage: '获取验证码',
})}`;
return `${count} 获取验证码`;
}
return intl.formatMessage({
id: 'pages.login.phoneLogin.getVerificationCode',
defaultMessage: '获取验证码',
});
return '获取验证码';
}}
name="captcha"
rules={[
@@ -354,13 +316,13 @@ const Login: React.FC = () => {
},
]}
onGetCaptcha={async (phone) => {
const result = await getFakeCaptcha({
phone,
});
if (!result) {
return;
}
message.success('获取验证码成功验证码为1234');
// const result = await getFakeCaptcha({
// phone,
// });
// if (!result) {
// return;
// }
// message.success('获取验证码成功验证码为1234');
}}
/>
</>

View File

@@ -1,96 +0,0 @@
import { render, fireEvent, act } from '@testing-library/react';
import React from 'react';
import { TestBrowser } from '@@/testBrowser';
// @ts-ignore
import { startMock } from '@@/requestRecordMock';
const waitTime = (time: number = 100) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, time);
});
};
let server: {
close: () => void;
};
describe('Login Page', () => {
beforeAll(async () => {
server = await startMock({
port: 8000,
scene: 'login',
});
});
afterAll(() => {
server?.close();
});
it('should show login form', async () => {
const historyRef = React.createRef<any>();
const rootContainer = render(
<TestBrowser
historyRef={historyRef}
location={{
pathname: '/user/login',
}}
/>,
);
await rootContainer.findAllByText('Ant Design');
act(() => {
historyRef.current?.push('/user/login');
});
expect(rootContainer.baseElement?.querySelector('.ant-pro-form-login-desc')?.textContent).toBe(
'Ant Design is the most influential web design specification in Xihu district',
);
expect(rootContainer.asFragment()).toMatchSnapshot();
rootContainer.unmount();
});
it('should login success', async () => {
const historyRef = React.createRef<any>();
const rootContainer = render(
<TestBrowser
historyRef={historyRef}
location={{
pathname: '/user/login',
}}
/>,
);
await rootContainer.findAllByText('Ant Design');
const userNameInput = await rootContainer.findByPlaceholderText('Username: admin or user');
act(() => {
fireEvent.change(userNameInput, { target: { value: 'admin' } });
});
const passwordInput = await rootContainer.findByPlaceholderText('Password: ant.design');
act(() => {
fireEvent.change(passwordInput, { target: { value: 'ant.design' } });
});
await (await rootContainer.findByText('Login')).click();
// 等待接口返回结果
await waitTime(5000);
await rootContainer.findAllByText('Ant Design Pro');
expect(rootContainer.asFragment()).toMatchSnapshot();
await waitTime(2000);
rootContainer.unmount();
});
});

View File

@@ -1,168 +0,0 @@
import { PageContainer } from '@ant-design/pro-components';
import { useModel } from '@umijs/max';
import { Card, theme } from 'antd';
import React from 'react';
/**
* 每个单独的卡片,为了复用样式抽成了组件
* @param param0
* @returns
*/
const InfoCard: React.FC<{
title: string;
index: number;
desc: string;
href: string;
}> = ({ title, href, index, desc }) => {
const { useToken } = theme;
const { token } = useToken();
return (
<div
style={{
backgroundColor: token.colorBgContainer,
boxShadow: token.boxShadow,
borderRadius: '8px',
fontSize: '14px',
color: token.colorTextSecondary,
lineHeight: '22px',
padding: '16px 19px',
minWidth: '220px',
flex: 1,
}}
>
<div
style={{
display: 'flex',
gap: '4px',
alignItems: 'center',
}}
>
<div
style={{
width: 48,
height: 48,
lineHeight: '22px',
backgroundSize: '100%',
textAlign: 'center',
padding: '8px 16px 16px 12px',
color: '#FFF',
fontWeight: 'bold',
backgroundImage:
"url('https://gw.alipayobjects.com/zos/bmw-prod/daaf8d50-8e6d-4251-905d-676a24ddfa12.svg')",
}}
>
{index}
</div>
<div
style={{
fontSize: '16px',
color: token.colorText,
paddingBottom: 8,
}}
>
{title}
</div>
</div>
<div
style={{
fontSize: '14px',
color: token.colorTextSecondary,
textAlign: 'justify',
lineHeight: '22px',
marginBottom: 8,
}}
>
{desc}
</div>
<a href={href} target="_blank" rel="noreferrer">
{'>'}
</a>
</div>
);
};
const Welcome: React.FC = () => {
const { token } = theme.useToken();
const { initialState } = useModel('@@initialState');
const count = useModel('demo');
return (
<PageContainer>
<span>{count.counter}</span>
<Card
style={{
borderRadius: 8,
}}
bodyStyle={{
backgroundImage:
initialState?.settings?.navTheme === 'realDark'
? 'background-image: linear-gradient(75deg, #1A1B1F 0%, #191C1F 100%)'
: 'background-image: linear-gradient(75deg, #FBFDFF 0%, #F5F7FF 100%)',
}}
>
<div
style={{
backgroundPosition: '100% -30%',
backgroundRepeat: 'no-repeat',
backgroundSize: '274px auto',
backgroundImage:
"url('https://gw.alipayobjects.com/mdn/rms_a9745b/afts/img/A*BuFmQqsB2iAAAAAAAAAAAAAAARQnAQ')",
}}
>
<div
style={{
fontSize: '20px',
color: token.colorTextHeading,
}}
>
使 Ant Design Pro
</div>
<p
style={{
fontSize: '14px',
color: token.colorTextSecondary,
lineHeight: '22px',
marginTop: 16,
marginBottom: 32,
width: '65%',
}}
>
Ant Design Pro umiAnt Design ProComponents
//
</p>
<div
style={{
display: 'flex',
flexWrap: 'wrap',
gap: 16,
}}
>
<InfoCard
index={1}
href="https://umijs.org/docs/introduce/introduce"
title="了解 umi"
desc="umi 是一个可扩展的企业级前端应用框架,umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。"
/>
<InfoCard
index={2}
title="了解 ant design"
href="https://ant.design"
desc="antd 是基于 Ant Design 设计体系的 React UI 组件库,主要用于研发企业级中后台产品。"
/>
<InfoCard
index={3}
title="了解 Pro Components"
href="https://procomponents.ant.design"
desc="ProComponents 是一个基于 Ant Design 做了更高抽象的模板组件,以 一个组件就是一个页面为开发理念,为中后台开发带来更好的体验。"
/>
</div>
</div>
</Card>
</PageContainer>
);
};
export default Welcome;

View File

@@ -10,8 +10,12 @@
display: inline-flex;
flex: 1;
margin-bottom: 12px;
border-right: 1px solid #ddd;
padding-left: 24px;
border-right: 1px solid #ddd;
&:last-child {
border-right: none;
}
}
.dataIconBox {
@@ -41,8 +45,8 @@
}
.dataCard {
flex: 1;
padding: 16px;
border: 1px solid #ddd;
border-radius: 12px;
flex: 1;
}