import { addRule, removeRule, updateRule } from '@/services/ant-design-pro/api';
import { query, queryColumns } from './service';
import { PlusOutlined, FormOutlined } 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 } from '@umijs/max';
import { Button, Drawer, message } from 'antd';
import React, { useRef, useState, useEffect } from 'react';
import type { FormValueType } from './components/UpdateForm';
import UpdateForm from './components/UpdateForm';
import IconStatus from '@/components/IconStatus';
/**
* @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.RoleListItem>[] = [
{
title: '名称',
dataIndex: 'name',
hideInSearch: true,
width: 120,
},
{
title: '启用',
dataIndex: 'enable',
width: 80,
hideInSearch: true,
sorter: true,
render(_, entity) {
return <IconStatus status={entity.enable} />;
},
},
{
title: '系统',
dataIndex: 'isSystem',
width: 80,
hideInSearch: true,
tooltip: '系统。用于业务系统开发使用,不受数据权限约束,禁止修改名称或删除',
sorter: true,
render(_, entity) {
return <IconStatus status={entity.isSystem} />;
},
},
{
title: '排序',
dataIndex: 'sort',
sorter: true,
width: 80,
hideInSearch: true,
},
{
title: '备注',
dataIndex: 'remark',
hideInSearch: true,
},
{
title: '更新者',
dataIndex: 'updateUser',
width: 100,
hideInSearch: true,
},
{
title: '更新时间',
dataIndex: 'updateTime',
width: 160,
hideInSearch: true,
sorter: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
width: 95,
render() {
return [
<Button key={'view'} shape="circle" type={'link'} icon={<FormOutlined />}>
编辑
</Button>,
];
},
},
{
title: '更新日期',
dataIndex: 'updateTimeRange',
hideInTable: true,
hideInForm: true,
hideInDescriptions: true,
hideInSearch: false,
hideInSetting: true,
valueType: 'dateRange',
fieldProps: {
placeholder: ['开始日期', '结束日期'],
},
},
{
title: '关键字',
dataIndex: 'keyword',
hideInTable: true,
hideInForm: true,
hideInDescriptions: true,
hideInSearch: false,
hideInSetting: true,
fieldProps: {
placeholder: '搜索关键字',
},
},
];
const [columnsLoading, setColumnsLoading] = useState<boolean>(true);
// todo 动态列使用这个
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [columnsData, setColumnsData] = useState<ProColumns<API.RoleListItem>[]>([]);
useEffect(() => {
const fetch = async () => {
setColumnsLoading(false);
const res = await queryColumns();
const data = res.data;
setColumnsData(
data
.sort((p) => p.sort)
.map((d) => {
return {
dataIndex: d.name,
title: d.displayName,
width: parseInt(d.width) || 100,
ellipsis: true,
hideInTable: !d.showInList,
hideInSearch: !d.showInSearch,
hideInForm: !d.showInAddForm || !d.showInEditForm,
hideInDescriptions: !d.showInDetailForm,
tooltip: d.description === d.displayName ? undefined : d.description,
render(dom, entity) {
if (d.dataType === 'Boolean') {
return <IconStatus status={entity[d.name]} />;
}
return dom;
},
} as ProColumns<any>;
}),
);
};
if (columnsLoading) {
fetch();
}
}, [columnsLoading]);
return (
<PageContainer>
<ProTable<API.RoleListItem, API.PageParams>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: 'Enquiry form',
})}
actionRef={actionRef}
rowKey="id"
search={{
labelWidth: 120,
}}
toolBarRender={() => [
<Button
type="primary"
key="primary"
onClick={() => {
handleModalOpen(true);
}}
>
<PlusOutlined /> <FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
</Button>,
]}
request={query}
columns={columns}
scroll={{ x: 1000 }}
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="项" />
<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;
|