|
|
@@ -0,0 +1,232 @@ |
|
|
|
import React, { useState, useEffect, useRef } from 'react'; |
|
|
|
import { useSetState } from 'ahooks'; |
|
|
|
import { Space, Table, Button, Input, Select, Divider, Tag, Card, Badge } from 'antd'; |
|
|
|
import type { TableColumnsType, InputRef } from 'antd'; |
|
|
|
import type { ColumnType, TableProps } from 'antd/es/table'; |
|
|
|
import { t } from '@/utils/i18n'; |
|
|
|
import { PlusOutlined, ExclamationCircleFilled, SearchOutlined } from '@ant-design/icons'; |
|
|
|
import { antdUtils } from '@/utils/antd'; |
|
|
|
import { useRequest } from '@/hooks/use-request'; |
|
|
|
import { formatDate } from '@/utils/formatTime' |
|
|
|
import noticeService from '@/request/service/notice'; |
|
|
|
import { NoticeVO, NoticePageReqVO } from '@/models'; |
|
|
|
|
|
|
|
|
|
|
|
type DataIndex = keyof NoticeVO; |
|
|
|
|
|
|
|
export default () => { |
|
|
|
|
|
|
|
const [editorVisable, seEditorVisable] = useState<boolean>(false); |
|
|
|
const [editNotice, setEditNotice] = useState<NoticeVO>(); |
|
|
|
const [dataSource, setDataSource] = useState<NoticeVO[]>([]); |
|
|
|
|
|
|
|
const { runAsync: getPageData } = useRequest(noticeService.getNoticePageApi, { manual: true }); |
|
|
|
const { runAsync: deleteItem } = useRequest(noticeService.deleteNoticeApi, { manual: true }); |
|
|
|
|
|
|
|
const [searchState, setSearchState] = useSetState<NoticePageReqVO>({}); |
|
|
|
const searchInput = useRef<InputRef>(null); |
|
|
|
const [onSearching, setOnSearching] = useState(false); |
|
|
|
|
|
|
|
const load = async () => { |
|
|
|
console.log(searchState) |
|
|
|
const [error, { code, msg, data }] = await getPageData(searchState); |
|
|
|
setOnSearching(false); |
|
|
|
if (error || code !== 0) { |
|
|
|
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }); |
|
|
|
return |
|
|
|
} |
|
|
|
setDataSource(data.list); |
|
|
|
}; |
|
|
|
|
|
|
|
const showDeleteConfirm = (role: NoticeVO) => { |
|
|
|
antdUtils.modal?.confirm({ |
|
|
|
title: '确认要将该通知删除吗?', |
|
|
|
icon: <ExclamationCircleFilled />, |
|
|
|
content: '请注意删除以后不可恢复!', |
|
|
|
okText: '删除', |
|
|
|
okType: 'danger', |
|
|
|
cancelText: '取消', |
|
|
|
onOk() { |
|
|
|
return new Promise(async (resolve) => { |
|
|
|
const [error, { code, msg }] = await deleteItem(role.id); |
|
|
|
if (error || code !== 0) { |
|
|
|
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }) |
|
|
|
} else { |
|
|
|
antdUtils.message?.open({ type: 'success', content: '删除成功' }) |
|
|
|
} |
|
|
|
await load(); |
|
|
|
resolve('') |
|
|
|
}).catch(() => antdUtils.message?.open({ |
|
|
|
type: 'error', |
|
|
|
content: '操作失败', |
|
|
|
})); |
|
|
|
}, |
|
|
|
onCancel() { |
|
|
|
}, |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const getColumnSearchProps = (dataIndex: DataIndex): ColumnType<NoticeVO> => ({ |
|
|
|
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters, close }) => ( |
|
|
|
<div style={{ padding: 8 }} onKeyDown={(e) => e.stopPropagation()}> |
|
|
|
<Input.Search |
|
|
|
ref={searchInput} |
|
|
|
placeholder={"输入公告标题"} |
|
|
|
value={selectedKeys[0]} |
|
|
|
onChange={(e) => { |
|
|
|
setSelectedKeys(e.target.value && e.target.value !== '' ? [e.target.value] : []) |
|
|
|
}} |
|
|
|
onSearch={(value) => { |
|
|
|
if(value === '' && clearFilters) { |
|
|
|
clearFilters!!() |
|
|
|
} |
|
|
|
confirm(); |
|
|
|
}} |
|
|
|
onPressEnter={()=>confirm()} |
|
|
|
allowClear |
|
|
|
style={{ marginBottom: 8, display: 'block' }} |
|
|
|
enterButton="搜索" |
|
|
|
size="middle" |
|
|
|
loading={onSearching} |
|
|
|
/> |
|
|
|
</div> |
|
|
|
), |
|
|
|
filterIcon: (filtered: boolean) => ( |
|
|
|
<SearchOutlined style={{ color: filtered ? 'primaryColor' : undefined }} /> |
|
|
|
), |
|
|
|
onFilterDropdownOpenChange: (visible) => { |
|
|
|
if (visible) { |
|
|
|
setTimeout(() => searchInput.current?.select(), 100); |
|
|
|
} |
|
|
|
}, |
|
|
|
}); |
|
|
|
|
|
|
|
const columns: TableColumnsType<NoticeVO> = [ |
|
|
|
{ |
|
|
|
title: '序号', |
|
|
|
dataIndex: 'id', |
|
|
|
key: 'id', |
|
|
|
align: 'center', |
|
|
|
width: 100, |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '公告标题', |
|
|
|
dataIndex: 'title', |
|
|
|
key: 'title', |
|
|
|
filterSearch: true, |
|
|
|
align: 'center', |
|
|
|
width: 400, |
|
|
|
...getColumnSearchProps('title') |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '公告类型', |
|
|
|
dataIndex: 'type', |
|
|
|
key: 'type', |
|
|
|
align: 'center', |
|
|
|
width: 150, |
|
|
|
render: (value: number) => { |
|
|
|
return (value === 1 ? <Tag color="purple">通知</Tag> : <Tag color="blue">公告</Tag>) |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '状态', |
|
|
|
key: 'status', |
|
|
|
dataIndex: 'status', |
|
|
|
width: 100, |
|
|
|
align: 'center', |
|
|
|
filters: [ |
|
|
|
{ text: '开启', value: 0 }, |
|
|
|
{ text: '关闭', value: 1 }, |
|
|
|
], |
|
|
|
filterMultiple: false, |
|
|
|
filterSearch: false, |
|
|
|
render: (value: number) => { |
|
|
|
return (value === 0 ? <Badge status="success" text="已开启" /> : <Badge status="error" text="已关闭" />) |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '创建时间', |
|
|
|
key: 'createTime', |
|
|
|
dataIndex: 'createTime', |
|
|
|
width: 200, |
|
|
|
align: 'center', |
|
|
|
render: (value: number) => { |
|
|
|
return formatDate(new Date(value), "YYYY-mm-dd HH:MM:SS") |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: t("QkOmYwne" /* 操作 */), |
|
|
|
key: 'action', |
|
|
|
fixed: 'right', |
|
|
|
align: 'center', |
|
|
|
render: (value: NoticeVO, record) => ( |
|
|
|
<Space size="small" split={(<Divider type='vertical' />)}> |
|
|
|
<a onClick={() => { |
|
|
|
setEditNotice(value); |
|
|
|
seEditorVisable(true); |
|
|
|
}}> |
|
|
|
编辑 |
|
|
|
</a> |
|
|
|
<a onClick={() => { |
|
|
|
|
|
|
|
}}> |
|
|
|
详情 |
|
|
|
</a> |
|
|
|
<a onClick={() => { |
|
|
|
showDeleteConfirm(value); |
|
|
|
}}> |
|
|
|
删除 |
|
|
|
</a> |
|
|
|
</Space> |
|
|
|
), |
|
|
|
}, |
|
|
|
]; |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
load(); |
|
|
|
}, [searchState]); |
|
|
|
|
|
|
|
const onChange: TableProps<NoticeVO>['onChange'] = (pagination, filters, sorter, extra) => { |
|
|
|
const state: NoticePageReqVO = { |
|
|
|
title: filters.title ? filters.title[0] as string : undefined, |
|
|
|
status: filters.status ? filters.status[0] as number : undefined, |
|
|
|
pageNo: pagination.current, |
|
|
|
pageSize: pagination.pageSize |
|
|
|
} |
|
|
|
setOnSearching(true); |
|
|
|
setSearchState(state); |
|
|
|
}; |
|
|
|
|
|
|
|
return ( |
|
|
|
<> |
|
|
|
<div> |
|
|
|
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'> |
|
|
|
<div className='flex justify-end content-center'> |
|
|
|
<div className="py-[4px] flex justify-normal items-center"> |
|
|
|
<Button className="ml-5" type='primary' size='large' icon={<PlusOutlined />} onClick={() => { |
|
|
|
setEditNotice(undefined); |
|
|
|
seEditorVisable(true); |
|
|
|
}}> 新增 </Button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<Table rowKey="id" |
|
|
|
scroll={{ x: true }} |
|
|
|
columns={columns} |
|
|
|
dataSource={dataSource} |
|
|
|
onChange={onChange} |
|
|
|
className='bg-transparent' |
|
|
|
pagination={{ position: ['bottomRight'] }} /> |
|
|
|
</Card> |
|
|
|
</div> |
|
|
|
{/* <NoticeEditor |
|
|
|
onSave={() => { |
|
|
|
loadRoles(); |
|
|
|
seEditorVisable(false); |
|
|
|
}} |
|
|
|
onCancel={() => { seEditorVisable(false) }} |
|
|
|
visible={editorVisable} |
|
|
|
data={editNotice} /> */} |
|
|
|
</> |
|
|
|
); |
|
|
|
}; |