Skip to content

ZealTemplate

使用提供的封装组件,如ZealCard,ZealTableSearch,ZealTablePaginationControl,PopupModal

与antd

Details
tsx
import React, {useEffect, useRef, useState} from "react";
import type {Rule} from "antd/es/form";
import {
    AdDynamicForm, type adDynamicFormRef,
    AdPopupModal, type adPopupModalRef,
    AdZealCard,
    AdZealTablePaginationControl,
    AdZealTableSearch, type adZealTableSearchRef,
    renderInput,
    renderInputNumber,
    useDecorateForm
} from "dynamicformdjx-react/antd";
import {Button, message, Modal, Space, Table, type TableProps} from "antd";
import {useDyForm, usePagination, useReactiveForm} from "dynamicformdjx-react";
import './zealTable.css'

interface SongType {
    id: string
    no: number
    title: string
    length: string
}

const ZealTable = () => {
    const [messageApi, contextHolder] = message.useMessage();
    const [modal, contextModalHolder] = Modal.useModal();
    const {pagination, pageModalRef, setTotal, setPageNo} = usePagination(fetchData);
    const searchFormItems = useDecorateForm<SongType>([
        {
            key: "no",
            label: "No",
            renderType: 'renderInputNumber',
            value: null,
            span: 8
        },
        {
            key: "title",
            label: "Title",
            allowClear: true,
            renderType: 'renderInput',
            value: null,
            span: 8
        },
        {
            key: "length",
            label: "Length",
            allowClear: true,
            renderType: 'renderInput',
            value: null,
            span: 8
        },
    ])
    const [formItems, setFormItems] = useReactiveForm<SongType, Rule | Rule[]>([
        {
            key: "no",
            label: "No",
            value: null,
            required: true,
            render2: (f) => renderInputNumber({}, f)
        },
        {
            key: "title",
            label: "Title",
            value: null,
            allowClear: true,
            required: true,
            requiredHint: (l) => `${l} is not empty`,
            render2: (f) => renderInput({}, f),
        },
        {
            key: "length",
            label: "Length",
            value: null,
            allowClear: true,
            render2: (f) => renderInput({}, f),
        },
    ])
    const [zealData] = useState<SongType[]>([
        {no: 3, title: 'Wonderwall', length: '4:18'},
        {no: 4, title: 'Don\'t Look Back in Anger', length: '4:48'},
        {no: 12, title: 'Champagne Supernova', length: '7:27'},
    ].map(it => ({...it, id: React.useId()})))
    const [referId, setReferId] = useState<string | number>(-1);
    const [selRowKeys, setSelRowKeys] = useState<React.Key[]>([]);
    const [tableData, setTableData] = useState<SongType[]>([])
    const [tableLoading, setTableLoading] = useState<boolean>(false);
    const useForm = useDyForm([formItems, setFormItems])
    const adZealTableSearchRef = useRef<adZealTableSearchRef<SongType>>(null)
    const addFormRef = useRef<adDynamicFormRef<SongType>>(null)
    const upModalRef = useRef<adPopupModalRef>(null)
    const columns: TableProps<SongType>['columns'] = [
        {
            title: 'No',
            dataIndex: 'no',
            key: 'no',
            width: 80
        },
        {
            title: 'Title',
            dataIndex: 'title',
            key: 'title',
        },
        {
            title: 'Length',
            dataIndex: 'length',
            key: 'length',
        },
        {
            title: 'Action',
            key: 'action',
            fixed: 'right',
            width: 160,
            align: 'center',
            render: (_, record) => (
                <Space size="small">
                    <Button size='small' color='orange' variant={'dashed'}
                            onClick={() => upItem(record)}>Update</Button>
                    <Button size='small' color='red' variant={'dashed'} onClick={() => delItem(record)}>Delete</Button>
                </Space>
            ),
        },
    ];

    // function
    async function fetchData(pn?: number, ps?: number) {
        setTableLoading(true)
        // console.log(pn,ps) // new value
        // const {pageNo, pageSize} = pagination // old value
        const {pageNo, pageSize} = pageModalRef.current // correspond new value
        const params = adZealTableSearchRef.current?.getParams()!
        const r = await new Promise<{ data: SongType[], total: number }>((resolve, reject) => {
            setTimeout(() => {
                const start = (pageNo - 1) * pageSize
                const {length, no, title} = params!
                const data = zealData.filter(it => (!length || it.length.includes(length)) && (!title || it.title.includes(title)) && (!no || it.no === no))
                resolve({
                    data: data.slice(start, start + pageSize),
                    total: data.length
                })
            }, 1500)
        })
        setTableData(r.data)
        setTotal(r.total)
        setTableLoading(false)
    }

    const addItem = () => {
        setReferId(-1)
        upModalRef.current?.toggle()
        useForm.onReset()
    }

    function upItem(r: SongType) {
        setReferId(r.id)
        upModalRef.current?.toggle()
        useForm.setValues(r)
    }

    function delItem(r: SongType) {
        setTableData(p => p.filter(it => r.id !== it.id))
        messageApi.success('Delete Successful')
    }

    const delSelect = async () => {
        const confirmed = await modal.confirm({
            title: `Delete?`,
            content: (<>
                <p>Confirm {selRowKeys.toString()} items</p>
            </>)
        })
        if (confirmed) {
            setTableData(p => p.filter(it => !selRowKeys.includes(it.id)))
            message.success(`delete ${selRowKeys} successful`)
            setSelRowKeys([])
        }
    }
    const popSubmit = () => new Promise<boolean>(resolve => {
        addFormRef.current?.validator().then(v => {
            let msg = ''
            if (referId === -1) {
                msg = 'add successful'
                setTableData(p => [...p, {...v, id: Date.now().toString()}])
            } else {
                msg = 'update successful'
                setTableData(p => p.map(it => {
                    if (it.id === referId) return {...it, ...v}
                    return it
                }))
            }
            message.success(msg)
            resolve(true)
            // fetchData()
        }).catch(e => {
            message.error(e?.message || '验证不通过')
            resolve(false)
        })
    })
    useEffect(() => {
        fetchData()
    }, []);
    return (
        <>
            {contextHolder}
            {contextModalHolder}
            <AdZealCard
                outPadding={15}
                footer={({isMobile}) => <AdZealTablePaginationControl
                    prefix={({total}) => <span>Total {total}</span>}
                    isMobile={isMobile}
                    pagination={pagination}
                    onChange={(pn, ps) => {
                        console.log(pn, ps)
                    }}
                />}
                controlBtn={() => <>
                    <Button color={'green'} variant={'dashed'} size='small' onClick={addItem}>Add</Button>
                    <Button color={'red'} variant={'dashed'} size='small' disabled={!selRowKeys.length}
                            onClick={delSelect}>Del</Button>
                </>}
                toolBtn={() => <Button variant={'dashed'} size='small'>Tools...</Button>}
                header={({isMobile}) =>
                    <AdZealTableSearch<SongType>
                        title="zeal test"
                        ref={adZealTableSearchRef}
                        isMobile={isMobile}
                        searchItemsState={searchFormItems}
                        onSearch={(v) => {
                            setPageNo(1)
                            fetchData()
                        }}
                        onReset={() => {
                            setPageNo(1)
                            fetchData()
                        }}
                    />
                }
                rest={() => <AdPopupModal draggable title={referId === -1 ? 'Add item' : 'Update item'} ref={upModalRef}
                                          onSubmit={popSubmit}>
                    <AdDynamicForm items={formItems} ref={addFormRef}/>
                </AdPopupModal>}
            >
                {({tableHeight, footerH}) => (
                    <>
                        <Table
                            loading={tableLoading}
                            scroll={{y: tableHeight - footerH, x: 800}}
                            dataSource={tableData}
                            columns={columns}
                            pagination={false}
                            rowKey={(d) => d.id}
                            rowSelection={{
                                onChange: (selectedRowKeys: React.Key[], selectedRows: SongType[]) => {
                                    setSelRowKeys(selectedRowKeys)
                                }
                            }}
                        />
                    </>
                )}
            </AdZealCard>
        </>)
}
export default ZealTable;
jsx
import React, {useEffect, useRef, useState} from "react";
import {
    AdDynamicForm,
    AdPopupModal,
    AdZealCard,
    AdZealTablePaginationControl,
    AdZealTableSearch,
    renderInput,
    renderInputNumber,
    useDecorateForm
} from "dynamicformdjx-react/antd";
import {Button, message, Modal, Space, Table} from "antd";
import {useDyForm, usePagination, useReactiveForm} from "dynamicformdjx-react";
import './zealTable.css'

const ZealTable = () => {
    const [messageApi, contextHolder] = message.useMessage();
    const [modal, contextModalHolder] = Modal.useModal();
    const {pagination, pageModalRef, setTotal, setPageNo} = usePagination(fetchData);

    const searchFormItems = useDecorateForm([
        {
            key: "no",
            label: "No",
            renderType: 'renderInputNumber',
            value: null,
            span: 8
        },
        {
            key: "title",
            label: "Title",
            allowClear: true,
            renderType: 'renderInput',
            value: null,
            span: 8
        },
        {
            key: "length",
            label: "Length",
            allowClear: true,
            renderType: 'renderInput',
            value: null,
            span: 8
        },
    ])

    const [formItems, setFormItems] = useReactiveForm([
        {
            key: "no",
            label: "No",
            value: null,
            required: true,
            render2: (f) => renderInputNumber({}, f)
        },
        {
            key: "title",
            label: "Title",
            value: null,
            allowClear: true,
            required: true,
            requiredHint: (l) => `${l} is not empty`,
            render2: (f) => renderInput({}, f),
        },
        {
            key: "length",
            label: "Length",
            value: null,
            allowClear: true,
            render2: (f) => renderInput({}, f),
        },
    ])

    const [zealData] = useState([
        {no: 3, title: 'Wonderwall', length: '4:18'},
        {no: 4, title: 'Don\'t Look Back in Anger', length: '4:48'},
        {no: 12, title: 'Champagne Supernova', length: '7:27'},
    ].map(it => ({...it, id: React.useId()})))

    const [referId, setReferId] = useState(-1);
    const [selRowKeys, setSelRowKeys] = useState([]);
    const [tableData, setTableData] = useState([])
    const [tableLoading, setTableLoading] = useState(false);
    const useForm = useDyForm([formItems, setFormItems])
    const adZealTableSearchRef = useRef(null)
    const addFormRef = useRef(null)
    const upModalRef = useRef(null)

    const columns = [
        {
            title: 'No',
            dataIndex: 'no',
            key: 'no',
            width: 80
        },
        {
            title: 'Title',
            dataIndex: 'title',
            key: 'title',
        },
        {
            title: 'Length',
            dataIndex: 'length',
            key: 'length',
        },
        {
            title: 'Action',
            key: 'action',
            fixed: 'right',
            width: 160,
            align: 'center',
            render: (_, record) => (
                <Space size="small">
                    <Button size='small' color='orange' variant={'dashed'}
                            onClick={() => upItem(record)}>Update</Button>
                    <Button size='small' color='red' variant={'dashed'} onClick={() => delItem(record)}>Delete</Button>
                </Space>
            ),
        },
    ];

    async function fetchData(pn, ps) {
        setTableLoading(true)
        const {pageNo, pageSize} = pageModalRef.current
        const params = adZealTableSearchRef.current?.getParams()
        const r = await new Promise((resolve, reject) => {
            setTimeout(() => {
                const start = (pageNo - 1) * pageSize
                const {length, no, title} = params || {}
                const data = zealData.filter(it => (!length || it.length.includes(length)) && (!title || it.title.includes(title)) && (!no || it.no === no))
                resolve({
                    data: data.slice(start, start + pageSize),
                    total: data.length
                })
            }, 1500)
        })
        setTableData(r.data)
        setTotal(r.total)
        setTableLoading(false)
    }

    const addItem = () => {
        setReferId(-1)
        upModalRef.current?.toggle()
        useForm.onReset()
    }

    function upItem(r) {
        setReferId(r.id)
        upModalRef.current?.toggle()
        useForm.setValues(r)
    }

    function delItem(r) {
        setTableData(p => p.filter(it => r.id !== it.id))
        messageApi.success('Delete Successful')
    }

    const delSelect = async () => {
        const confirmed = await modal.confirm({
            title: `Delete?`,
            content: (<>
                <p>Confirm {selRowKeys.toString()} items</p>
            </>)
        })
        if (confirmed) {
            setTableData(p => p.filter(it => !selRowKeys.includes(it.id)))
            message.success(`delete ${selRowKeys} successful`)
            setSelRowKeys([])
        }
    }

    const popSubmit = () => new Promise(resolve => {
        addFormRef.current?.validator().then(v => {
            let msg = ''
            if (referId === -1) {
                msg = 'add successful'
                setTableData(p => [...p, {...v, id: Date.now().toString()}])
            } else {
                msg = 'update successful'
                setTableData(p => p.map(it => {
                    if (it.id === referId) return {...it, ...v}
                    return it
                }))
            }
            message.success(msg)
            resolve(true)
        }).catch(e => {
            message.error(e?.message || '验证不通过')
            resolve(false)
        })
    })

    useEffect(() => {
        fetchData()
    }, []);

    return (
        <>
            {contextHolder}
            {contextModalHolder}
            <AdZealCard
                outPadding={15}
                footer={({isMobile}) => <AdZealTablePaginationControl
                    prefix={({total}) => <span>Total {total}</span>}
                    isMobile={isMobile}
                    pagination={pagination}
                    onChange={(pn, ps) => {
                        console.log(pn, ps)
                    }}
                />}
                controlBtn={() => <>
                    <Button color={'green'} variant={'dashed'} size='small' onClick={addItem}>Add</Button>
                    <Button color={'red'} variant={'dashed'} size='small' disabled={!selRowKeys.length}
                            onClick={delSelect}>Del</Button>
                </>}
                toolBtn={() => <Button variant={'dashed'} size='small'>Tools...</Button>}
                header={({isMobile}) =>
                    <AdZealTableSearch
                        title="zeal test"
                        ref={adZealTableSearchRef}
                        isMobile={isMobile}
                        searchItemsState={searchFormItems}
                        onSearch={(v) => {
                            setPageNo(1)
                            fetchData()
                        }}
                        onReset={() => {
                            setPageNo(1)
                            fetchData()
                        }}
                    />
                }
                rest={() => <AdPopupModal draggable title={referId === -1 ? 'Add item' : 'Update item'} ref={upModalRef}
                                          onSubmit={popSubmit}>
                    <AdDynamicForm items={formItems} ref={addFormRef}/>
                </AdPopupModal>}
            >
                {({tableHeight, footerH}) => (
                    <>
                        <Table
                            loading={tableLoading}
                            scroll={{y: tableHeight - footerH, x: 800}}
                            dataSource={tableData}
                            columns={columns}
                            pagination={false}
                            rowKey={(d) => d.id}
                            rowSelection={{
                                onChange: (selectedRowKeys, selectedRows) => {
                                    setSelRowKeys(selectedRowKeys)
                                }
                            }}
                        />
                    </>
                )}
            </AdZealCard>
        </>
    )
}
export default ZealTable;
css
body{
    padding: 15px;
}
.zealCard .ant-card .ant-card-body .ant-table .ant-table-body{
    overflow:auto !important;
}