完善消息通知,解决财务统计部分金额未除100
parent
8c370ead0e
commit
90eaf4f871
|
@ -1,4 +1,4 @@
|
|||
import React, {useState, useEffect} from 'react';
|
||||
import React, {useState, useEffect, useRef} from 'react';
|
||||
import {UploadOutlined, UserOutlined, BellOutlined, CloseOutlined} from '@ant-design/icons';
|
||||
import {Layout, Menu, theme, Typography, Button, Dropdown, MenuProps, Popover, Badge} from 'antd';
|
||||
import {useAppDispatch, useAppSelector} from "../models/hooks";
|
||||
|
@ -149,6 +149,8 @@ function HomeView() {
|
|||
|
||||
const [messageCount, setMessageCount] = useState(0)
|
||||
const [reimbursementCount, setReimbursementCount] = useState(0)
|
||||
const messageCountRef = useRef(messageCount);
|
||||
const reimbursementCountRef = useRef(reimbursementCount);
|
||||
const [badgeTop, setBadgeTop] = useState(66 + 3 * 44)
|
||||
const [eventSource, setEventSource] = useState<EventSourcePolyfill | null>(null)
|
||||
|
||||
|
@ -172,13 +174,15 @@ function HomeView() {
|
|||
source.addEventListener("reimbursement", (e) => {
|
||||
console.log("reimbursement==>", e)
|
||||
// @ts-ignore
|
||||
setReimbursementCount(reimbursementCount + Number(e.data))
|
||||
reimbursementCountRef.current+=Number(e.data)
|
||||
setReimbursementCount(reimbursementCountRef.current )
|
||||
})
|
||||
|
||||
source.addEventListener("notice", (e) => {
|
||||
console.log("notice==>", e)
|
||||
// @ts-ignore
|
||||
setMessageCount(messageCount + Number(e.data))
|
||||
messageCountRef.current+=Number(e.data)
|
||||
setMessageCount(messageCountRef.current)
|
||||
})
|
||||
|
||||
source.addEventListener("error", (e) => {
|
||||
|
@ -278,7 +282,8 @@ function HomeView() {
|
|||
let unreadCount = 0
|
||||
for (const notice of data.records)
|
||||
if (!notice.alreadyRead) unreadCount++
|
||||
setMessageCount(unreadCount)
|
||||
messageCountRef.current = unreadCount
|
||||
setMessageCount( messageCountRef.current )
|
||||
}).catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
@ -291,7 +296,8 @@ function HomeView() {
|
|||
}, {skipNulls: true, arrayFormat: 'indices'}),
|
||||
method: 'get'
|
||||
}).then(response => {
|
||||
setReimbursementCount(response.data.total)
|
||||
reimbursementCountRef.current=response.data.total
|
||||
setReimbursementCount( reimbursementCountRef.current)
|
||||
}).catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
@ -347,7 +353,7 @@ function HomeView() {
|
|||
<MainMenu items={menuItems} defaultSelectedKeys={defaultSelectedKeys}/>
|
||||
<div style={{
|
||||
position: "absolute",
|
||||
right: 14,
|
||||
right: 18,
|
||||
top: badgeTop,
|
||||
height: 44,
|
||||
display: "flex",
|
||||
|
@ -355,14 +361,15 @@ function HomeView() {
|
|||
}}>
|
||||
<Badge count={reimbursementCount}/>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</Sider>
|
||||
<Layout>
|
||||
<HeaderBar messageCount={messageCount} onMessageCountChange={(count) => setMessageCount(count)}/>
|
||||
<HeaderBar messageCount={messageCount} onMessageCountChange={(count) => {
|
||||
messageCountRef.current = count
|
||||
setMessageCount(messageCountRef.current)
|
||||
}}/>
|
||||
<Content style={{margin: '0', overflowY: "auto"}}>
|
||||
<Outlet/>
|
||||
</Content>
|
||||
|
|
|
@ -14,7 +14,7 @@ import qs from "qs";
|
|||
|
||||
const {Text, Paragraph} = Typography;
|
||||
|
||||
function InvoiceDetailModal(props: any) {
|
||||
function InvoiceDetailModal(props: { invoiceDetail: any, open: boolean, onClose: () => void, needRefresh?: () => void, isBase64?:boolean }) {
|
||||
//const [open, setOpen] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [invoice, setInvoice] = useState(null as any)
|
||||
|
@ -88,6 +88,7 @@ function InvoiceDetailModal(props: any) {
|
|||
console.log(response.data)
|
||||
setLoading(false)
|
||||
props.onClose()
|
||||
if (props.needRefresh)
|
||||
props.needRefresh()
|
||||
}).catch(function (error) {
|
||||
console.log(error)
|
||||
|
@ -139,11 +140,8 @@ function InvoiceDetailModal(props: any) {
|
|||
</Form>
|
||||
<Image
|
||||
width={'100%'}
|
||||
src={baseUrl + props.invoiceDetail?.invoiceFileUri}
|
||||
src={props.isBase64?('data:image/png;base64,'+props.invoiceDetail?.invoiceFileBase64):(baseUrl + props.invoiceDetail?.invoiceFileUri)}
|
||||
/>
|
||||
{/* <div style={{ position:"absolute", left:0, top: 50, paddingRight: 20,width: '100%', display: "flex", flexDirection: "column", alignItems: "flex-end"}}>
|
||||
|
||||
</div>*/}
|
||||
|
||||
</Modal>
|
||||
)
|
||||
|
|
|
@ -420,7 +420,7 @@ function InvoiceListView(props: { isManagement: boolean }) {
|
|||
searchInvoiceContent(invoiceSearchOption)
|
||||
}} invoiceDetail={invoiceDetail} open={detailModalOpen} onClose={() => {
|
||||
setDetailModalOpen(false)
|
||||
}} showFooter={true}/>
|
||||
}}/>
|
||||
</div>
|
||||
|
||||
)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
.MessageList::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.MessageList::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
|
||||
background: rgba(0,0,0,0.2);
|
||||
}
|
||||
.MessageList::-webkit-scrollbar-track {
|
||||
border-radius: 0;
|
||||
background: rgba(0,0,0,0);
|
||||
}
|
|
@ -7,16 +7,27 @@ import 'dayjs/locale/zh-cn'
|
|||
import axiosInstance from "../utils/axiosInstance";
|
||||
import {setStaff, setToken} from "../models/store";
|
||||
import {Staff} from "../models/Staff";
|
||||
import {invoiceTypeNameMap} from "../models/Invoice";
|
||||
import {InvoiceDetail, invoiceTypeNameMap} from "../models/Invoice";
|
||||
import './MessageList.css';
|
||||
import InvoiceDetailModal from "./Invoice/InvoiceDetailModal";
|
||||
|
||||
const {Text, Title, Paragraph} = Typography
|
||||
const relativeTime = require('dayjs/plugin/relativeTime')
|
||||
dayjs.locale('zh-cn')
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
|
||||
function MessageList(props: { count: number, onCountChange: (count: number) => void }) {
|
||||
const [popoverOpen, setPopoverOpen] = useState(false)
|
||||
const [list, setList] = useState<Notice[]>([])
|
||||
const [initLoading, setInitLoading] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [showLoadMore, setShowLoadMore] = useState(false)
|
||||
const [index, setIndex] = useState(0)
|
||||
const [invoiceModalOpen, setInvoiceModalOpen] = useState(false)
|
||||
const [invoiceDetail, setInvoiceDetail] = useState<any>()
|
||||
|
||||
const pageSize = 10
|
||||
|
||||
const getTitle = (notice: Notice) => {
|
||||
switch (notice.data.noticeType) {
|
||||
|
@ -78,102 +89,119 @@ function MessageList(props: { count: number, onCountChange: (count: number) => v
|
|||
}
|
||||
|
||||
const onMessageListOpen = () => {
|
||||
setLoading(true)
|
||||
setInitLoading(true)
|
||||
axiosInstance({
|
||||
url: 'common/notice',
|
||||
method: 'get',
|
||||
params: {
|
||||
pageNum: 0,
|
||||
pageSize: 10
|
||||
pageSize: pageSize
|
||||
}
|
||||
}).then(response => {
|
||||
console.log(response.data)
|
||||
const data: NoticeResponse = response.data
|
||||
setList(data.records)
|
||||
setLoading(false)
|
||||
setIndex(pageSize)
|
||||
setShowLoadMore(pageSize < data.total)
|
||||
setInitLoading(false)
|
||||
}).catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
/*setList([
|
||||
{
|
||||
"noticeTargetId": "50",
|
||||
"noticeTime": "1981-10-04 06:37:59",
|
||||
"data": {
|
||||
"noticeType": 1,
|
||||
"count": 16
|
||||
},
|
||||
"noticeId": "48"
|
||||
},
|
||||
{
|
||||
"noticeTargetId": "45",
|
||||
"noticeTime": "1980-05-09 20:10:06",
|
||||
"data": {
|
||||
"invoice": {
|
||||
"invoiceId": 23,
|
||||
"invoiceNo": "deserunt enim anim ex voluptate",
|
||||
"invoiceCode": "6",
|
||||
"invoiceDate": "2016-05-11",
|
||||
"invoiceUploadTime": "2019-12-01 07:17:16",
|
||||
"invoiceNote": "consequat laborum",
|
||||
"invoiceKind": 82,
|
||||
"invoiceAmount": 51,
|
||||
"modified": false,
|
||||
"invoiceFileBase64": "nulla enim",
|
||||
"invoiceDeparture": "ea enim fugiat do",
|
||||
"invoiceDestination": null,
|
||||
"invoiceName": "号度前事她状报"
|
||||
},
|
||||
"rejectStaff": {
|
||||
"staffName": "飞百亲治头油手",
|
||||
"staffId": "49",
|
||||
"staffPassword": "velit in incididunt",
|
||||
"staffBase": "eiusmod voluptate Ut Lorem occaecat"
|
||||
},
|
||||
"rejectOpinion": "dolore exercitation irure do",
|
||||
"noticeType": 1
|
||||
},
|
||||
"noticeId": "93"
|
||||
},
|
||||
{
|
||||
"noticeTargetId": "32",
|
||||
"noticeTime": "2014-12-30 09:02:43",
|
||||
"data": {
|
||||
"noticeType": 0,
|
||||
"count": 6
|
||||
},
|
||||
"noticeId": "58"
|
||||
},
|
||||
{
|
||||
"noticeTargetId": "16",
|
||||
"noticeTime": "2014-01-18 21:30:34",
|
||||
"data": {
|
||||
"noticeType": 0,
|
||||
"count": 93
|
||||
},
|
||||
"noticeId": "42"
|
||||
},
|
||||
{
|
||||
"noticeTargetId": "9",
|
||||
"noticeTime": "1997-12-03 08:45:39",
|
||||
"data": {
|
||||
"noticeType": 1,
|
||||
"count": 2
|
||||
},
|
||||
"noticeId": "40"
|
||||
const onLoadMore = () => {
|
||||
setLoading(true);
|
||||
axiosInstance({
|
||||
url: 'common/notice',
|
||||
method: 'get',
|
||||
params: {
|
||||
pageNum: index,
|
||||
pageSize: pageSize
|
||||
}
|
||||
])*/
|
||||
}, []);
|
||||
}).then(response => {
|
||||
console.log(response.data)
|
||||
const data: NoticeResponse = response.data
|
||||
setList(list.concat(data.records))
|
||||
setShowLoadMore(index + pageSize < data.total)
|
||||
setIndex(index + pageSize)
|
||||
setLoading(false)
|
||||
}).catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
const loadMore =
|
||||
!initLoading && showLoadMore ? (
|
||||
<div
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
marginTop: 12,
|
||||
height: 32,
|
||||
lineHeight: '32px',
|
||||
}}
|
||||
>
|
||||
<Button onClick={onLoadMore} loading={loading}>加载更多</Button>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
const readMessage = (item: Notice) => {
|
||||
axiosInstance({
|
||||
url: 'common/notice/' + item.noticeId + '/read',
|
||||
method: 'put',
|
||||
}).then(response => {
|
||||
props.onCountChange(props.count - 1);
|
||||
setList(list.map((value, index, array) => {
|
||||
if (value === item)
|
||||
value.alreadyRead = true;
|
||||
return value;
|
||||
}));
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
const onMessageClick = (item: Notice, e: any) => {
|
||||
if (e.target.innerText === '标为已读')
|
||||
return
|
||||
console.log('onMessageClick')
|
||||
switch (item.data.noticeType) {
|
||||
case 0:
|
||||
const reimbursementId = item.data.reimbursement?.reimbursementId
|
||||
if (reimbursementId) {
|
||||
|
||||
}
|
||||
break
|
||||
case 1:
|
||||
let invoice: any = item.data.invoice
|
||||
if (invoice) {
|
||||
invoice.invoiceAmount /= 100.
|
||||
invoice.invoiceState = -1
|
||||
setInvoiceDetail(invoice)
|
||||
setInvoiceModalOpen(true)
|
||||
}
|
||||
break
|
||||
}
|
||||
setPopoverOpen(false)
|
||||
readMessage(item)
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover placement="bottomLeft" trigger="click" content={
|
||||
<>
|
||||
<Popover placement="bottomLeft" trigger="click"
|
||||
open={popoverOpen}
|
||||
onOpenChange={(newOpen: boolean) => {
|
||||
setPopoverOpen(newOpen)
|
||||
if (newOpen)
|
||||
onMessageListOpen()
|
||||
}}
|
||||
content={
|
||||
<List
|
||||
style={{width: 400}}
|
||||
className={'MessageList'}
|
||||
style={{width: 400, overflowY: 'auto', maxHeight: 600}}
|
||||
itemLayout="horizontal"
|
||||
loading={loading}
|
||||
loading={initLoading}
|
||||
loadMore={loadMore}
|
||||
dataSource={list}
|
||||
renderItem={(item) => (
|
||||
<div style={{
|
||||
|
@ -183,6 +211,7 @@ function MessageList(props: { count: number, onCountChange: (count: number) => v
|
|||
}}>
|
||||
<Button
|
||||
type='text'
|
||||
onClick={(e) => onMessageClick(item, e)}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: "unset",
|
||||
|
@ -196,21 +225,10 @@ function MessageList(props: { count: number, onCountChange: (count: number) => v
|
|||
{
|
||||
key: '1',
|
||||
label: (<span>标为已读</span>),
|
||||
}],
|
||||
}
|
||||
],
|
||||
onClick: ({key}) => {
|
||||
axiosInstance({
|
||||
url: 'common/notice/' + item.noticeId + '/read',
|
||||
method: 'put',
|
||||
}).then(response => {
|
||||
props.onCountChange(props.count-1)
|
||||
setList(list.map((value, index, array) => {
|
||||
if (value === item)
|
||||
value.alreadyRead = true
|
||||
return value
|
||||
}))
|
||||
}).catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
readMessage(item)
|
||||
}
|
||||
}} placement="top" arrow>
|
||||
<div>
|
||||
|
@ -225,8 +243,7 @@ function MessageList(props: { count: number, onCountChange: (count: number) => v
|
|||
<Divider type="vertical"/>
|
||||
<Text>{
|
||||
// @ts-ignore
|
||||
dayjs(item.noticeTime).fromNow()
|
||||
}</Text>
|
||||
dayjs(item.noticeTime).fromNow()}</Text>
|
||||
</div>
|
||||
</Dropdown>
|
||||
{getContent(item)}
|
||||
|
@ -240,26 +257,29 @@ function MessageList(props: { count: number, onCountChange: (count: number) => v
|
|||
url: 'common/notice/' + item.noticeId,
|
||||
method: 'delete',
|
||||
}).then(response => {
|
||||
setList(list.filter(value => value !== item))
|
||||
if(!item.alreadyRead) props.onCountChange(props.count-1)
|
||||
setList(list.filter(value => value !== item));
|
||||
setIndex(index - 1);
|
||||
if (!item.alreadyRead)
|
||||
props.onCountChange(props.count - 1);
|
||||
}).catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
}}>
|
||||
<CloseOutlined/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
)}
|
||||
/>
|
||||
} title="我的消息" arrowPointAtCenter onOpenChange={onMessageListOpen}>
|
||||
)}/>} title="我的消息" arrowPointAtCenter>
|
||||
<Badge count={props.count} size="small" offset={[-10, 10]}>
|
||||
<Button type="text" shape="circle" size="large">
|
||||
<BellOutlined/>
|
||||
</Button>
|
||||
</Badge>
|
||||
</Popover>
|
||||
<InvoiceDetailModal open={invoiceModalOpen} invoiceDetail={invoiceDetail}
|
||||
onClose={() => setInvoiceModalOpen(false)} isBase64={true}/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ function StatView() {
|
|||
for (const departmentStat of temporalDepartmentStat.departmentStats) {
|
||||
let valueMap = departmentAmountMap.get(departmentStat.departmentId)
|
||||
if (valueMap) {
|
||||
valueMap.set(temporalDepartmentStat.value, departmentStat.reimbursementAmount)
|
||||
valueMap.set(temporalDepartmentStat.value, departmentStat.reimbursementAmount/100.)
|
||||
departmentAmountMap.set(departmentStat.departmentId, valueMap)
|
||||
}
|
||||
}
|
||||
|
@ -590,7 +590,7 @@ function StatView() {
|
|||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
show: false,
|
||||
fontSize: 40,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
|
@ -637,7 +637,7 @@ function StatView() {
|
|||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
show: false,
|
||||
fontSize: 40,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue