完善消息通知,解决财务统计部分金额未除100

main
wuyize 2023-01-08 18:49:42 +08:00
parent 8c370ead0e
commit 90eaf4f871
6 changed files with 219 additions and 182 deletions

View File

@ -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>

View File

@ -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>
)

View File

@ -420,7 +420,7 @@ function InvoiceListView(props: { isManagement: boolean }) {
searchInvoiceContent(invoiceSearchOption)
}} invoiceDetail={invoiceDetail} open={detailModalOpen} onClose={() => {
setDetailModalOpen(false)
}} showFooter={true}/>
}}/>
</div>
)

12
src/pages/MessageList.css Normal file
View File

@ -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);
}

View File

@ -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}/>
</>
)
}

View File

@ -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'
}