123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- import {AutoColumn, AutoText, isNullOrTrue, Message} from "auto-antd";
- import {Button, Drawer, Modal, Switch, Table, TableProps} from "antd";
- import React, {useEffect, useMemo, useRef, useState} from "react";
- import {ColumnsType} from "antd/lib/table";
- import {CurdForm, ICurdForm, IProps as IFormProps} from "./Form.tsx";
- import {LDAP} from "../../api/ldap.ts";
- import {DeleteOutlined, EditOutlined, LoadingOutlined, PlusOutlined, SyncOutlined} from "@ant-design/icons";
- import './index.less'
- import {ICurdConfig, ICurdData} from "./types.ts";
- import {Cell} from "./cell";
- export type CurdColumn = AutoColumn & {
- search?: boolean
- editable?: boolean // 编辑时是否可编辑
- hidden?: boolean
- addable?: boolean // 添加时可编辑
- onlyAdd?: boolean // 仅新增时展示
- editHide?: boolean // 编辑时隐藏
- ellipsis?: boolean // 完整显示
- }
- type PageResp<T> = { total: number, list: T[], current: number, pageSize: number }
- type IProps<T> = IFormProps<T> & {
- columns: CurdColumn[],
- getList: (query: any) => Promise<PageResp<T> | undefined>,
- getDetail: (data: Partial<T>, add?: boolean) => Promise<T>
- onDelete?: (data: T) => Promise<any>
- config?: ICurdConfig<T>
- onSuccess?: (data: Partial<T>) => void
- operationRender?: React.ReactNode
- operation?: {
- add?: boolean
- delete?: boolean
- },
- expandable?: TableProps<T>['expandable']
- }
- /**
- * 一个完成的增删查改界面
- * @constructor
- */
- export function CurdPage<T extends ICurdData>(
- {
- columns,
- getList,
- config,
- operationRender,
- onSuccess,
- operation,
- expandable,
- ...props
- }: IProps<T>) {
- const [list, setList] = useState<T[]>([]);
- const [total, setTotal] = useState<number>(0)
- const [query, setQuery] = useState<any>({current: 1, pageSize: 10});
- const [loading, setLoading] = useState<boolean>(false);
- // edit or add
- const [visible, setVisible] = useState<boolean>(false);
- const [editData, setEditData] = useState<Partial<T>>()
- const formRef = useRef<ICurdForm<LDAP.Server>>()
- const onAddOrEdit = (edit: Partial<T>, add?: boolean) => {
- setVisible(true)
- if (props.getDetail) {
- setLoading(true)
- props.getDetail?.(edit,add)
- .then(res => {
- setEditData(res)
- })
- .catch(err => {
- Message.warning(err.message)
- setVisible(false)
- })
- .finally(() => {
- setLoading(false)
- })
- } else {
- setEditData({...edit})
- setVisible(true)
- }
- }
- const handleDelete = async (edit: T) => {
- Modal.confirm({
- type: 'warning',
- title: '您确定要删除该数据吗?',
- content: '删除操作不可撤销,请谨慎操作',
- onOk: async () => {
- setLoading(true)
- try {
- await props.onDelete?.(edit)
- setQuery((q: any)=>({...q}))
- }catch(err: any) {
- if(err instanceof Error){
- Message.warning(err.message)
- }else if (typeof err === "string") {
- Message.warning(err)
- }else if (err?.msg) {
- Message.warning('删除失败,错误信息为:'+ err.msg)
- }else {
- Message.warning('删除失败,错误信息为:'+ JSON.stringify(err,null,2))
- }
- }finally {
- setLoading(false)
- }
- }
- })
- }
- const tableColumns = useMemo(() => {
- const cols = columns.filter(item => !item.hidden)
- .map((column: CurdColumn) => {
- const col = {
- ...column,
- dataIndex: column.key,
- title: column.title,
- width: column.width,
- onCell: (record: Partial<T>) => {
- return {
- record,
- config: column,
- dataIndex: column.key,
- }
- }
- }
- if (col.type == 'switch' && !col.render){
- col.render = (value: boolean) => <Switch checked={value} disabled/>
- }
- // @ts-ignore
- if (col.type == 'select' && !col.render && column.mode!='tags'){
- col.render = (value: any) => <AutoText value={value} column={{...col}}/>
- }
- return col;
- }) as ColumnsType<T>
- cols.push({
- dataIndex: "",
- title: "操作",
- width: config?.operationWidth ?? 180,
- render: (_, record, index) => {
- return (<div className="operation-list">
- {
- isNullOrTrue(config?.editable) ?
- (<Button size="small" type="primary" icon={<EditOutlined/>}
- onClick={() => onAddOrEdit(record,false)}/>) : null
- }
- {
- operation?.add ? (<Button size="small" type="primary" icon={<PlusOutlined/>}
- onClick={() => onAddOrEdit(record,true)}/>) : null
- }
- {
- operation?.delete ? (<Button size="small" danger={true} icon={<DeleteOutlined/>}
- onClick={() => handleDelete(record)}/>) : null
- }
- {config?.operationRender?.(record, index, { handleDelete })}
- </div>)
- }
- })
- return cols;
- }, [columns]);
- const onClose = () => {
- setVisible(false)
- setEditData(undefined)
- }
- useEffect(() => {
- setLoading(true)
- getList(query).then(res => {
- if (res) {
- setList(res.list)
- setTotal(res.total)
- } else {
- Message.warning('无数据!')
- }
- }).finally(() => {
- setLoading(false)
- })
- }, [getList, query]);
- const onPageChange = (current: number, pageSize: number) => {
- setQuery((q: any) => ({...q, current, pageSize}))
- }
- const onSaveSuccess = (data: Partial<T>) => {
- setQuery({...query})
- onSuccess?.(data)
- setVisible(false)
- }
- return <div className="curd">
- <div className="curd-header">
- {
- config?.hideAdd ? null : (<Button onClick={() => onAddOrEdit({},true)} icon={<PlusOutlined/>}/>)
- }
- {operationRender}
- <div style={{flex: 1}}/>
- <Button loading={loading} onClick={() => setQuery({...query})} icon={<SyncOutlined/>}/>
- </div>
- <div className="curd-body">
- <Table columns={tableColumns as any}
- dataSource={list as any}
- pagination={ config?.pagination ? {
- total: total,
- pageSize: query.pageSize,
- current: query.current,
- onChange: onPageChange,
- }: { pageSize: query.pageSize }}
- components={{
- body: {
- cell: Cell,
- }
- }}
- size="middle"
- expandable={expandable}
- bordered={config?.bordered}
- rowKey={config?.rowKey ?? 'id'}
- />
- </div>
- <div className="curd-footer">
- </div>
- <Drawer open={visible} destroyOnClose width={config?.editDialogWidth ?? 650}
- title={editData?.id ? '编辑' : '新增'}
- height={400} onClose={onClose}>
- <div className="curd-edit-dialog">
- {
- loading ? (<LoadingOutlined/>) : (
- <CurdForm ref={formRef as any}
- initialData={editData}
- columns={columns}
- onSave={props.onSave as any}
- onSuccess={onSaveSuccess as any}
- onClose={onClose}
- config={config as any}/>
- )
- }
- </div>
- </Drawer>
- </div>
- }
|