Merge remote-tracking branch 'origin/main'

main
白封羽 2023-01-07 11:39:22 +08:00
commit 1f73983dfb
6 changed files with 335 additions and 22 deletions

171
src/models/Notice.ts Normal file
View File

@ -0,0 +1,171 @@
export interface NoticeResponse {
/**
*
*/
records: Notice[];
/**
*
*/
total: number;
}
/**
* Notice
*/
export interface Notice {
data: NoticeData;
noticeId: string;
noticeTargetId: string;
noticeTime: string;
}
/**
*
*
*
*
*
*/
export interface NoticeData {
approvalOpinion?: string;
approvalResult?: number;
approvalStaff?: Staff;
/*
const val SUCCESS = 0. toShort()
const val WAITING_ FOR_ DEPARTMENT _MANAGER_ APPROVAL = 1. toShort()
const val WAITING_ FOR_ FINANCIAL_ APPROVAL = 2. toShort()
const val WAITING_ FOR_ FINANCIAL_ MANAGER_ APPROVAL = 3. toShort()
const vaL WAITING_ FOR_ GENERAL_ MANAGER_ APPROVAL = 4. toShort( )
const val REJECTED = 5. toShort()
const val TERMINATED = 6. toShort()
*/
noticeType: number;
reimbursement?: Reimbursement;
invoice?: Invoice;
rejectOpinion?: string;
rejectStaff?: Staff;
count?: number;
}
/**
*
*
* Department
*/
export interface Department {
deleted_at?: null | string;
/**
* ID
*/
departmentId: number;
/**
*
*/
departmentManager?: Staff;
/**
*
*/
departmentName?: string;
/**
*
*/
staff?: Staff[];
}
/**
* Staff
*
*
*/
export interface Staff {
banned?: boolean;
/**
*
*/
managingDepartment?: null | Department;
/**
*
*/
staffBase?: string;
/**
*
*/
staffDepartments?: Department[];
/**
*
*/
staffId: string;
/**
*
*/
staffName: string;
/**
*
*/
staffPassword?: string;
}
export interface Invoice {
/**
*
*/
invoiceAmount: number;
/**
*
*/
invoiceCode: string;
/**
*
*/
invoiceDate: string;
/**
*
*/
invoiceDeparture: null | string;
/**
*
*/
invoiceDestination: null | string;
/**
* Base64
*/
invoiceFileBase64: string;
/**
* ID
*/
invoiceId: number;
/**
*
*/
invoiceKind: number;
/**
*
*/
invoiceName: null | string;
/**
*
*/
invoiceNo: string;
/**
*
*/
invoiceNote: null | string;
/**
*
*/
invoiceUploadTime: string;
/**
*
*/
modified: boolean;
}
export interface Reimbursement {
reimbursementDepartureName: string;
reimbursementDestinationName: string;
reimbursementId: number;
roundTrip: boolean;
}

View File

@ -1,5 +1,5 @@
import React, {useState, useEffect} from 'react'; import React, {useState, useEffect} from 'react';
import {UploadOutlined, UserOutlined, BellOutlined} from '@ant-design/icons'; import {UploadOutlined, UserOutlined, BellOutlined, CloseOutlined} from '@ant-design/icons';
import {Layout, Menu, theme, Typography, Button, Dropdown, MenuProps, Popover} from 'antd'; import {Layout, Menu, theme, Typography, Button, Dropdown, MenuProps, Popover} from 'antd';
import {useAppDispatch, useAppSelector} from "../models/hooks"; import {useAppDispatch, useAppSelector} from "../models/hooks";
import {getStaff, getToken, setStaff, setToken, store} from "../models/store"; import {getStaff, getToken, setStaff, setToken, store} from "../models/store";
@ -10,7 +10,7 @@ import axiosInstance from "../utils/axiosInstance";
import {Department, Staff, Token} from "../models/Staff"; import {Department, Staff, Token} from "../models/Staff";
import MessageList from "./MessageList"; import MessageList from "./MessageList";
const {Title} = Typography; const {Title, Text, Paragraph} = Typography;
const {Header, Content, Footer, Sider} = Layout; const {Header, Content, Footer, Sider} = Layout;
@ -30,6 +30,7 @@ function HeaderBar(props: any) {
case 'password': case 'password':
break break
case 'logout': case 'logout':
console.log('logout')
axiosInstance({ axiosInstance({
url: 'logout', url: 'logout',
method: 'post', method: 'post',
@ -48,7 +49,6 @@ function HeaderBar(props: any) {
clientSecret: '' clientSecret: ''
})) }))
navigate("/login") navigate("/login")
break break
} }
}; };
@ -89,14 +89,16 @@ function HeaderBar(props: any) {
zIndex: 100, zIndex: 100,
boxShadow: '0px 6px 16px 0px rgba(0, 0, 0, 0.08)' boxShadow: '0px 6px 16px 0px rgba(0, 0, 0, 0.08)'
}}> }}>
<div></div> <div style={{marginLeft: 20}}>
<MessageList/>
</div>
<div style={{ <div style={{
height: '100%', height: '100%',
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
}}> }}>
<MessageList/>
<Dropdown overlayStyle={{minWidth: '150px'}} menu={{items, onClick}} placement="bottomRight" arrow> <Dropdown overlayStyle={{minWidth: '150px'}} menu={{items, onClick}} placement="bottomRight" arrow>
<Button type="text" style={{ <Button type="text" style={{
marginRight: '12px', height: '100%', marginRight: '12px', height: '100%',

View File

@ -97,6 +97,7 @@ function InvoiceDetailModal(props: any) {
return ( return (
<Modal <Modal
centered
open={props.open} open={props.open}
title={"发票详情"+(props.invoiceDetail?.modified ? '(发票信息经过手动修改)' : '')} title={"发票详情"+(props.invoiceDetail?.modified ? '(发票信息经过手动修改)' : '')}
onCancel={handleCancel} onCancel={handleCancel}

View File

@ -167,7 +167,7 @@ function InvoiceSearch(props: { isManagement: boolean, handleSearchData: any })
const getInvoiceKindsRadioButtons: any = () => { const getInvoiceKindsRadioButtons: any = () => {
let options: any[] = [] let options: any[] = []
invoiceTypeNameMap.forEach(function (value, key, map) { invoiceTypeNameMap.forEach(function (value, key, map) {
options.push(<Radio.Button style={{marginBottom: 10}} value={key}>{value}</Radio.Button>) options.push(<Radio.Button style={{marginBottom: 10}} key={key} value={key}>{value}</Radio.Button>)
}) })
return options return options
} }

View File

@ -1,28 +1,167 @@
import {Button, List, Popover} from "antd"; import {Button, Card, List, Popover, Space, Typography, Divider, Badge, Dropdown, MenuProps} from "antd";
import {BellOutlined} from "@ant-design/icons"; import {BellOutlined, CloseOutlined} from "@ant-design/icons";
import React, {useState} from "react"; import React, {useEffect, useState} from "react";
import {Notice} from "../models/Notice";
import dayjs from "dayjs";
import 'dayjs/locale/zh-cn'
import axiosInstance from "../utils/axiosInstance";
import {setToken} from "../models/store";
const {Text, Title, Paragraph} = Typography
const relativeTime = require('dayjs/plugin/relativeTime')
dayjs.locale('zh-cn')
dayjs.extend(relativeTime)
function MessageList() { function MessageList() {
const [list, setList] = useState<any[]>([]); const [list, setList] = useState<Notice[]>([])
const getTitle = (notice: Notice) => {
switch (notice.data.noticeType) {
case 0:
if (notice.data.approvalResult === 5)
return '报销单审批未通过'
else if (notice.data.approvalResult === 0)
return '报销单审批通过'
else
return '报销单状态更新'
break
case 1:
return '发票被打回'
break
}
}
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"
}
])
}, []);
return ( return (
<Popover content={ <Popover placement="bottomLeft" trigger="click" content={
<List <List
style={{width: 400}}
itemLayout="horizontal" itemLayout="horizontal"
dataSource={list} dataSource={list}
renderItem={(item) => ( renderItem={(item) => (
<List.Item <div style={{
actions={[<a key="list-loadmore-edit">edit</a>, <a key="list-loadmore-more">more</a>]} width: '100%',
> display: "flex",
<List.Item.Meta flexDirection: "row",
title={<a href="https://ant.design">{item.name?.last}</a>} }}>
description="Ant Design, a design language for background applications, is refined by Ant UED Team" <Button
/> type='text'
<div>content</div> style={{
</List.Item> width: '100%',
height: "unset",
display: "flex",
flexDirection: "column",
whiteSpace: "unset",
textAlign: "unset"
}}>
<Dropdown menu={{
items: [
{
key: '1',
label: (<span></span>),
}],
onClick: ({key}) => {
}
}} placement="top" arrow>
<div>
<Badge status="processing"/>
<span style={{
fontSize: 16,
fontWeight: "bold",
marginLeft: 10
}}>{getTitle(item)} </span>
<Divider type="vertical"/>
<Text>{
// @ts-ignore
dayjs().fromNow()
}</Text>
</div>
</Dropdown>
<Paragraph>{'Ant Design, a design language for background applications, is refined by Ant UED Team'}</Paragraph>
</Button>
<Button style={{
marginLeft: -30
}} shape='circle'
type='text'><CloseOutlined/></Button>
</div>
)} )}
/> />
} title="我的消息"> } title="我的消息" arrowPointAtCenter>
<Button type="text" shape="circle"> <Button type="text" shape="circle">
<BellOutlined/> <BellOutlined/>
</Button> </Button>

View File

@ -60,7 +60,7 @@ function UserConfig(props: any) {
width: 230, width: 230,
render: (value, record) => ( render: (value, record) => (
<Space size="middle"> <Space size="middle">
<Switch checkedChildren="启用" unCheckedChildren="禁用" checked={!value}/> <Switch style={{display: record.staffId==='manager'?'none':'unset'}} checkedChildren="启用" unCheckedChildren="禁用" checked={!value}/>
<Button danger type="link"> <Button danger type="link">
</Button> </Button>