完成显示发票详情

main
wuyize 2023-01-02 21:03:10 +08:00
parent e711d03dd6
commit a9ba72b612
6 changed files with 331 additions and 222 deletions

View File

@ -25,6 +25,69 @@ export interface Invoice {
reimbursement: Reimbursement; reimbursement: Reimbursement;
} }
type Nullable<T> = T | undefined | null;
export class InvoiceSearchOption {
invoiceNo: Nullable<string>
invoiceCode: Nullable<string>
invoiceUploadTimeStart: Nullable<string>
invoiceUploadTimeEnd: Nullable<string>
invoiceStates: Nullable<any[]>
invoiceKinds: Nullable<any[]>
invoiceDateStart: Nullable<string>
invoiceDateEnd: Nullable<string>
invoiceNote: Nullable<string>
invoiceUploaderId: Nullable<string>
pageNum: number
pageSize: number
constructor() {
this.pageNum = 0
this.pageSize = 20
this.clear()
}
clear() {
this.invoiceNo = null
this.invoiceCode = null
this.invoiceUploadTimeStart = null
this.invoiceUploadTimeEnd = null
this.invoiceStates = null
this.invoiceKinds = null
this.invoiceDateStart = null
this.invoiceDateEnd = null
this.invoiceNote = null
this.invoiceUploaderId = null
this.pageNum = 0
this.pageSize = 20
}
}
export interface InvoiceDetail {
invoiceAmount: number;
invoiceCode: string;
invoiceDate: string |Dayjs;
invoiceDeparture?: string;
invoiceDestination?: string;
invoiceFileUri: string;
invoiceId: number;
invoiceKind: number;
invoiceName?: string;
invoiceNo: string;
invoiceNote: string;
/**
* -1: 0: 1: 2:
*/
invoiceState: number;
invoiceThumbnailUri: string;
invoiceUploader: Staff;
invoiceUploadTime: string|Dayjs;
modified: boolean;
reimbursement: Reimbursement;
}
export interface InvoiceIdentifyResponse { export interface InvoiceIdentifyResponse {
invoiceAmount: number; invoiceAmount: number;
invoiceCheckCode?: string; invoiceCheckCode?: string;
@ -79,14 +142,40 @@ export const invoiceItemsMap = new Map([
]) ])
export const invoiceTypeItemsMap = new Map([ export const invoiceTypeItemsMap = new Map([
[0, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[1, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceCheckCode']],
[2, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[3, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceCheckCode']], [3, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceCheckCode']],
[5, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[8, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceCheckCode']],
[9, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[10, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[11, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceCheckCode']],
[12, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceCheckCode']],
[13, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']], [13, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[15, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceCheckCode']],
[16, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceCheckCode']],
]) ])
export const invoiceTypeExtraItemsMap = new Map([ export const invoiceTypeExtraItemsMap = new Map([
[3, ['合计金额','合计税额', '购买方名称', '销售方名称', '收款人']], [3, ['合计金额','合计税额', '购买方名称', '销售方名称', '收款人']],
[13, ['时间']], [13, ['时间']],
]) ])
export const invoiceTypeShowItemsMap = new Map([
[0, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[1, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate']],
[2, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[3, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate']],
[5, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[8, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate']],
[9, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[10, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[11, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate']],
[12, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate']],
[13, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate', 'invoiceDeparture', 'invoiceDestination']],
[15, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate']],
[16, ['invoiceName', 'invoiceNo', 'invoiceCode', 'invoiceAmount', 'invoiceDate']],
])
/* /*
{ {

View File

@ -19,133 +19,3 @@ export interface Department {
departmentName: string; departmentName: string;
} }
type Nullable<T> = T | undefined | null;
export class InvoiceSearchOption {
invoiceNo: Nullable<string>
invoiceCode: Nullable<string>
invoiceUploadTimeStart: Nullable<string>
invoiceUploadTimeEnd: Nullable<string>
invoiceState: Nullable<number>
invoiceKind: Nullable<string>
invoiceDateStart: Nullable<string>
invoiceDateEnd: Nullable<string>
invoiceNote: Nullable<string>
invoiceUploader: Nullable<string>
pageNum: number
pageSize: number
constructor() {
this.pageNum = 0
this.pageSize = 20
this.clear()
}
clear() {
this.invoiceNo = null
this.invoiceCode = null
this.invoiceUploadTimeStart = null
this.invoiceUploadTimeEnd = null
this.invoiceState = null
this.invoiceKind = null
this.invoiceDateStart = null
this.invoiceDateEnd = null
this.invoiceNote = null
this.invoiceUploader = null
this.pageNum = 0
this.pageSize = 20
}
// toString(){
// let res="pageNum="+this.pageNum+"&pageSize="+this.pageSize
// res+=(this.invoiceNo===undefined||this.invoiceNo===null||this.invoiceNo===""?"":("&invoiceNo="+this.invoiceNo));
// res+=(this.invoiceCode===undefined||this.invoiceCode===null||this.invoiceCode===""?"":("&invoiceCode="+this.invoiceCode));
// res+=(this.invoiceUploadTimeStart===undefined||this.invoiceUploadTimeStart===null?"":("&invoiceUploadTimeStart="+this.invoiceUploadTimeStart));
// res+=(this.invoiceUploadTimeEnd===undefined||this.invoiceUploadTimeEnd===null?"":("&invoiceUploadTimeEnd="+this.invoiceUploadTimeEnd));
// res+=(this.invoiceState===undefined||this.invoiceState===null?"":("&invoiceState="+this.invoiceState));
// res+=(this.invoiceKind===undefined||this.invoiceKind===null?"":("&invoiceKind="+this.invoiceKind));
// res+=(this.invoiceDateStart===undefined||this.invoiceDateStart===null?"":("&invoiceDateStart="+this.invoiceDateStart));
// res+=(this.invoiceDateEnd===undefined||this.invoiceDateEnd===null?"":("&invoiceDateEnd="+this.invoiceDateEnd));
// res+=(this.invoiceNote===undefined||this.invoiceNote===null?"":("&invoiceNote="+this.invoiceNote));
// res+=(this.invoiceUploader===undefined||this.invoiceUploader===null?"":("&invoiceUploader="+this.invoiceUploader));
// return res;
// }
}
export class InvoiceCommit {
invoiceFileName: string
invoiceNo: string
invoiceCode: string
invoiceKind: string
invoiceDate: dayjs.Dayjs
invoiceAmount: number
invoiceAmountWithoutTax: number
invoiceCheckCode: string
invoiceRegionCode: Nullable<string>
invoiceSellerTaxCode: Nullable<string>
invoiceExtraInfo: Nullable<string> | [] | Map<any, string>
constructor() {
this.invoiceFileName = ""
this.invoiceNo = ""
this.invoiceCode = ""
this.invoiceKind = ""
this.invoiceDate = dayjs()
this.invoiceAmount = 0
this.invoiceAmountWithoutTax = 0
this.invoiceCheckCode = "000000"
this.invoiceRegionCode = null
this.invoiceSellerTaxCode = null
this.invoiceExtraInfo = null
}
setValue(props: FormData) {
console.log("1111" + props.toString())
this.invoiceFileName = props.get("invoiceFileName")!.toString()
this.invoiceNo = props.get("invoiceNo")!.toString()
this.invoiceCode = props.get("invoiceCode")!.toString()
this.invoiceKind = props.get("invoiceKind")!.toString()
//this.invoiceDate = new Date(props.get("invoiceDate")!.toString())
//this.invoiceAmount = props.get("invoiceAmount")!.toString()
//this.invoiceAmountWithoutTax = props.get("invoiceAmountWithoutTax")!.toString()
this.invoiceCheckCode = props.get("invoiceCheckCode")!.toString()
this.invoiceRegionCode = props.get("invoiceRegionCode")!.toString()
this.invoiceSellerTaxCode = props.get("invoiceSellerTaxCode")!.toString()
//this.invoiceExtraInfo = props.get("invoiceExtraInfo")!.
}
}
export interface Reimbursement {
/**
*
*/
reimbursementAdditionalAmount: number;
reimbursementDepartureInvoiceId: number;
reimbursementDepartureName: string;
reimbursementDestinationInvoiceId?: number;
reimbursementDestinationName: string;
reimbursementId: number;
/**
*
*/
reimbursementInvoiceAmount: number;
reimbursementNote?: string;
/**
* 0: success
* 1:
* 2:
* 3:
* 4:
* 5:
*/
reimbursementStatus: number;
reimbursementSubmitDepartmentId: number;
reimbursementSubmitStaffId: string;
reimbursementSubmitTime: string;
/**
*
*/
reimbursementTripDuration: number;
}

View File

@ -83,7 +83,9 @@ function HeaderBar(props: any) {
background: colorBgContainer, background: colorBgContainer,
display: 'flex', display: 'flex',
flexDirection: 'row-reverse', flexDirection: 'row-reverse',
alignItems: 'center' alignItems: 'center',
zIndex: 100,
boxShadow: '0px 6px 16px 0px rgba(0, 0, 0, 0.08)'
}}> }}>
<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={{
@ -111,7 +113,7 @@ function MainMenu(props: any) {
else else
return ( return (
<Menu <Menu
style={{height: '100%'}} style={{borderInlineEnd: 'unset'}}
mode="inline" mode="inline"
defaultSelectedKeys={props.defaultSelectedKeys} defaultSelectedKeys={props.defaultSelectedKeys}
items={props.items} items={props.items}
@ -195,7 +197,8 @@ function HomeView() {
<Layout style={{height: '100%'}}> <Layout style={{height: '100%'}}>
<Sider <Sider
width={208} width={208}
style={{background: colorBgContainer, boxShadow: '9px 0px 28px 0px rgba(0, 0, 0, 0.05)'}} style={{background: colorBgContainer,zIndex: 200, boxShadow: '6px 0px 16px 0px rgba(0, 0, 0, 0.08)',
borderInlineEnd: '1px solid rgba(5, 5, 5, 0.06)'}}
breakpoint="lg" breakpoint="lg"
collapsedWidth="0" collapsedWidth="0"
onBreakpoint={(broken) => { onBreakpoint={(broken) => {
@ -212,7 +215,6 @@ function HomeView() {
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
borderInlineEnd: '1px solid rgba(5, 5, 5, 0.06)'
}}> }}>
<Icon component={Logo}/> <Icon component={Logo}/>
<span style={{ <span style={{
@ -222,7 +224,7 @@ function HomeView() {
marginLeft: '4px' marginLeft: '4px'
}}></span> }}></span>
</div> </div>
<MainMenu style={{height: '100%'}} items={menuItems} defaultSelectedKeys={defaultSelectedKeys}/> <MainMenu items={menuItems} defaultSelectedKeys={defaultSelectedKeys}/>
</Sider> </Sider>
<Layout> <Layout>
<HeaderBar/> <HeaderBar/>

View File

@ -0,0 +1,110 @@
import React, {useEffect, useState} from "react";
import {Button, DatePicker, Form, Input, InputNumber, Modal, Select, Typography} from "antd";
import {
InvoiceDetail,
InvoiceIdentifyResponse,
invoiceItemsMap, invoiceTypeExtraItemsMap,
invoiceTypeItemsMap,
invoiceTypeNameMap, invoiceTypeShowItemsMap
} from "../../../models/Invoice";
import axiosInstance from "../../../utils/axiosInstance";
import TextArea from "antd/es/input/TextArea";
import dayjs, {Dayjs} from "dayjs";
const {Text, Paragraph } = Typography;
function InvoiceDetailModal(props: any) {
//const [open, setOpen] = useState(false)
const [loading, setLoading] = useState(false)
const [invoice, setInvoice] = useState(null as any)
const [formItems, setFormItems] = useState(undefined)
//const [form] = Form.useForm();
useEffect(() => {
console.log(props.invoiceDetail)
let i = {...props.invoiceDetail}
setInvoice(i)
refreshFormItems(i.invoiceKind)
}, [props]);
const handleCancel = () => {
props.onClose()
//setOpen(false);
};
const inputComponent = (item: string) => {
if (item === 'invoiceDate')
return <Text>{dayjs(props.invoiceDetail[item]).format('YYYY年MM月DD日')}</Text>
else if (item === 'invoiceAmount')
return <Text>{`${props.invoiceDetail[item]}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</Text>
else
return <Text>{props.invoiceDetail[item]}</Text>
}
const refreshFormItems = (invoiceKind: number) => {
let items = invoiceTypeShowItemsMap.get(invoiceKind)?.map((item, index) => {
return (
<Form.Item
key={index}
name={item}
label={invoiceItemsMap.get(item)}
>
{inputComponent(item)}
</Form.Item>
)
})
let extraItems = invoiceTypeExtraItemsMap.get(invoiceKind)?.map((item, index) => {
return (
<Form.Item
key={index}
name={['invoiceExtraInfo', item]}
label={item}
>
{inputComponent(item)}
</Form.Item>
)
})
// @ts-ignore
setFormItems(<>
{items}
</>
)
}
const onTypeChange = (value: number) => {
refreshFormItems(value)
}
return (
<Modal
open={props.open}
title="发票详情"
onCancel={handleCancel}
footer={null}
>
{
<Form layout="horizontal" labelCol={{span: 4}}
>
<Form.Item
name={`invoiceKind`}
label={`发票类型`}
>
<Text>{invoiceTypeNameMap.get(props.invoiceDetail?.invoiceKind) }</Text>
</Form.Item>
{formItems}
<Form.Item
name={`invoiceNote`}
label={`备注`}
>
<Paragraph style={{marginTop:5}} >{props.invoiceDetail?.invoiceNote }</Paragraph >
</Form.Item>
</Form>
}
</Modal>
)
}
export default InvoiceDetailModal

View File

@ -17,8 +17,16 @@ import {
} from "antd"; } from "antd";
import type {MenuProps, PaginationProps} from 'antd'; import type {MenuProps, PaginationProps} from 'antd';
import {DownOutlined, UploadOutlined} from '@ant-design/icons'; import {DownOutlined, UploadOutlined} from '@ant-design/icons';
import React, {ReactElement, JSXElementConstructor, ReactFragment, ReactPortal, useState, useEffect} from "react"; import React, {
import {InvoiceCommit, InvoiceSearchOption} from "../../../models/Staff" ReactElement,
JSXElementConstructor,
ReactFragment,
ReactPortal,
useState,
useEffect,
ReactNode
} from "react";
import {InvoiceDetail, InvoiceSearchOption} from "../../../models/Invoice"
import {Space, Typography} from 'antd'; import {Space, Typography} from 'antd';
import {SizeType} from "antd/es/config-provider/SizeContext"; import {SizeType} from "antd/es/config-provider/SizeContext";
import axios from "axios"; import axios from "axios";
@ -28,7 +36,17 @@ import change = Simulate.change;
import {useNavigate, useSearchParams} from "react-router-dom"; import {useNavigate, useSearchParams} from "react-router-dom";
import {useAppDispatch} from "../../../models/hooks"; import {useAppDispatch} from "../../../models/hooks";
import InvoiceUploadView from "./InvoiceUploadView"; import InvoiceUploadView from "./InvoiceUploadView";
import {Invoice, invoiceTypeNameMap} from "../../../models/Invoice"; import {
Invoice,
invoiceItemsMap,
invoiceTypeExtraItemsMap,
invoiceTypeItemsMap,
invoiceTypeNameMap
} from "../../../models/Invoice";
import {RadioButtonProps} from "antd/es/radio/radioButton";
import qs from "qs";
import InvoiceDetailModal from "./InvoiceDetailModal";
import dayjs from "dayjs";
const {Meta} = Card; const {Meta} = Card;
@ -36,16 +54,7 @@ const {Search} = Input;
const {Option} = Select const {Option} = Select
let invoices: Array<Invoice> let invoices: Array<Invoice>
const {RangePicker} = DatePicker; const {RangePicker} = DatePicker;
const formItemLayout = {
labelCol: {
xs: {span: 10},
sm: {span: 10},
},
wrapperCol: {
xs: {span: 14},
sm: {span: 14},
},
};
const config = { const config = {
rules: [{type: 'object' as const, required: false, message: 'Please select time!'}], rules: [{type: 'object' as const, required: false, message: 'Please select time!'}],
}; };
@ -87,7 +96,7 @@ function InvoiceSearch(props: { handleSearchData: any; }) {
invoiceSearchOption.clear() invoiceSearchOption.clear()
console.log(allValues) console.log(allValues)
if (allValues['upload-time-picker'] != null && allValues['upload-time-picker'] !== undefined) { if (allValues['upload-time-picker'] !== null && allValues['upload-time-picker'] !== undefined) {
invoiceSearchOption.invoiceUploadTimeStart = allValues['upload-time-picker'][0].format('YYYY-MM-DDtHH:mm:ss') invoiceSearchOption.invoiceUploadTimeStart = allValues['upload-time-picker'][0].format('YYYY-MM-DDtHH:mm:ss')
invoiceSearchOption.invoiceUploadTimeEnd = allValues['upload-time-picker'][1].format('YYYY-MM-DDtHH:mm:ss') invoiceSearchOption.invoiceUploadTimeEnd = allValues['upload-time-picker'][1].format('YYYY-MM-DDtHH:mm:ss')
} }
@ -96,14 +105,15 @@ function InvoiceSearch(props: { handleSearchData: any; }) {
invoiceSearchOption.invoiceDateEnd = allValues['invoice-time-picker'][1].format('YYYY-MM-DD') invoiceSearchOption.invoiceDateEnd = allValues['invoice-time-picker'][1].format('YYYY-MM-DD')
} }
if (allValues['invoice-state'] !== "全部") { if (allValues['invoice-state'] !== "全部") {
invoiceSearchOption.invoiceState = allValues['invoice-state'] invoiceSearchOption.invoiceStates = [allValues['invoice-state']]
} }
if (allValues['invoice-kind'] !== "全部") { if (allValues['invoice-kind'] !== "全部") {
invoiceSearchOption.invoiceKind = allValues['invoice-kind'] invoiceSearchOption.invoiceKinds = [allValues['invoice-kind']]
} }
if (allValues['invoice-uploader'] !== null && allValues['invoice-uploader'] !== undefined && allValues['invoice-uploader'].trim() !== "") { if (allValues['invoice-uploader'] !== null && allValues['invoice-uploader'] !== undefined && allValues['invoice-uploader'].trim() !== "") {
invoiceSearchOption.invoiceUploader = allValues['invoice-uploader'].trim() invoiceSearchOption.invoiceUploaderId = allValues['invoice-uploader'].trim()
} }
props.handleSearchData(invoiceSearchOption)
} }
const onSearch = (value: string) => { const onSearch = (value: string) => {
@ -118,14 +128,28 @@ function InvoiceSearch(props: { handleSearchData: any; }) {
invoiceSearchOption.invoiceCode = null; invoiceSearchOption.invoiceCode = null;
} }
const {handleSearchData} = props props.handleSearchData(invoiceSearchOption)
handleSearchData(invoiceSearchOption)
} }
const getInvoiceKindsRadioButtons: any = () =>{
let options: any[] = []
invoiceTypeNameMap.forEach(function (value, key, map) {
options.push( <Radio.Button style={{marginBottom: 10}} value={key}>{value}</Radio.Button>)
})
return options
}
return ( return (
<div className="headBar"> <div className="headBar">
<div className="simpleSearchBar" style={{height: '72px', padding: '30px',display: "flex",alignItems: 'center', justifyContent: "space-between",backgroundColor: colorBgContainer}}> <div className="simpleSearchBar" style={{
height: '72px',
padding: '30px',
display: "flex",
alignItems: 'center',
justifyContent: "space-between",
backgroundColor: colorBgContainer
}}>
<Search className="simpleSearch" <Search className="simpleSearch"
addonBefore={<Dropdown addonBefore={<Dropdown
menu={{ menu={{
@ -144,7 +168,7 @@ function InvoiceSearch(props: { handleSearchData: any; }) {
placeholder={'请在此输入'} placeholder={'请在此输入'}
allowClear allowClear
onSearch={(value) => onSearch(value)} onSearch={(value) => onSearch(value)}
style={{width: 304}} style={{width: 404}}
enterButton enterButton
/> />
<Checkbox onChange={(e) => { <Checkbox onChange={(e) => {
@ -153,49 +177,40 @@ function InvoiceSearch(props: { handleSearchData: any; }) {
<InvoiceUploadView/> <InvoiceUploadView/>
</div> </div>
{complexEnabled && {complexEnabled &&
<div className="complexSearchBar" style={{display: "flex"}}> <div className="complexSearchBar" style={{margin: '20px',padding: '20px 20px 0px 20px',display: "flex",backgroundColor: colorBgContainer, borderRadius: '20px'}}>
<Form name="complexOption" {...formItemLayout} onValuesChange={onValuesChange}> <Form name="complexOption" onValuesChange={onValuesChange} style={{width: '100%'}}>
<Row>
<Form.Item name="upload-time-picker" label="发票上传时间" {...rangeConfig}> <Form.Item
name={`invoice-kind`}
label={`发票类型`}
>
<Radio.Group defaultValue="全部">
<Radio.Button value="全部"></Radio.Button>
{getInvoiceKindsRadioButtons()}
</Radio.Group>
</Form.Item>
<div style={{marginTop: -10, display:"flex", flexDirection:"row", flexWrap: "wrap"}}>
<Form.Item name="upload-time-picker" label="上传时间" {...rangeConfig} style={{marginRight:100}}>
<RangePicker/> <RangePicker/>
</Form.Item> </Form.Item>
<Form.Item name="invoice-time-picker" label="发票开票日期" {...rangeConfig}> <Form.Item name="invoice-time-picker" label="开票日期" {...rangeConfig}>
<RangePicker/> <RangePicker/>
</Form.Item> </Form.Item>
</Row> </div>
<Row style={{display: "flex", flexWrap: "wrap"}}> <Form.Item
<Form.Item name={`invoice-state`}
name={`invoice-state`} label={`发票状态`}
label={`发票状态`} >
style={{minWidth: 150}} <Radio.Group defaultValue="全部">
><Select defaultValue="全部"> <Radio.Button value="全部"></Radio.Button>
<Option value="全部"></Option> <Radio.Button value="0">使</Radio.Button>
<Option value="0">使</Option> <Radio.Button value="1"></Radio.Button>
<Option value="1"></Option> <Radio.Button value="2"></Radio.Button>
<Option value="2"></Option> </Radio.Group>
</Select> </Form.Item>
</Form.Item>
<Form.Item
name={`invoice-kind`}
label={`发票类型`}
style={{minWidth: 300}}
><Select defaultValue="全部">
<Option value="全部"></Option>
<Option value="增值税普通发票"></Option>
<Option value="增值税专用发票"></Option>
<Option value="增值税电子普通发票"></Option>
<Option value="增值税电子专用发票"></Option>
<Option value="定额发票"></Option>
</Select>
</Form.Item>
<Form.Item
name={`invoice-uploader`}
label={`上传者`}
>
<Input placeholder="任意上传者"/>
</Form.Item>
</Row>
</Form> </Form>
</div>} </div>}
</div> </div>
@ -215,9 +230,14 @@ class InvoiceItem extends React.Component<any, any> {
console.log(this.state.invoiceThumbnailUri) console.log(this.state.invoiceThumbnailUri)
} }
onClick = () => {
this.props.onClick(this.props.invoice)
}
render() { render() {
return ( return (
<Card <Card
onClick={this.onClick}
hoverable hoverable
style={{ style={{
width: 250, width: 250,
@ -242,19 +262,20 @@ class InvoiceItem extends React.Component<any, any> {
function InvoiceListView(props: {}) { function InvoiceListView(props: {}) {
const [totalNum, setTotalNum] = useState(0) const [totalNum, setTotalNum] = useState(0)
const [invoices, setInvoices] = useState([]) const [invoices, setInvoices] = useState([] as any[])
const [search, setSearch] = useSearchParams() const [search, setSearch] = useSearchParams()
const [invoiceSearchOption, setInvoiceSearchOption] = useState(new InvoiceSearchOption()) const [invoiceSearchOption, setInvoiceSearchOption] = useState(new InvoiceSearchOption())
const [detailModalOpen, setDetailModalOpen] = useState(false)
const [invoiceDetail, setInvoiceDetail] = useState(null as InvoiceDetail|null)
const navigate = useNavigate() const navigate = useNavigate()
const handleInvoiceSearchInfo = (invoiceSearch: InvoiceSearchOption) => { const handleInvoiceSearchInfo = (invoiceSearch: InvoiceSearchOption) => {
setInvoiceSearchOption(invoiceSearch) //setInvoiceSearchOption(invoiceSearch)
searchInvoiceContent() searchInvoiceContent(invoiceSearch)
} }
const searchInvoiceContent = () => { const searchInvoiceContent = (invoiceSearch: InvoiceSearchOption) => {
let params: any = invoiceSearchOption setInvoices([])
let params: any = invoiceSearch
Object.keys(params).forEach(key => { Object.keys(params).forEach(key => {
if (params[key] != null && params[key] !== undefined && params[key] === "") { if (params[key] != null && params[key] !== undefined && params[key] === "") {
params[key] = null params[key] = null
@ -269,13 +290,12 @@ function InvoiceListView(props: {}) {
else else
params.pageSize = 10 params.pageSize = 10
axiosInstance({ axiosInstance({
url: 'common/invoice', url: 'common/invoice?'+qs.stringify( params,{skipNulls:true, arrayFormat: 'indices'}),
method: 'get', method: 'get',
params: params
}).then(response => { }).then(response => {
console.log(response.data) console.log(response.data)
setTotalNum(response.data.total) setTotalNum(response.data.total)
setInvoices(response.data.records) setInvoices([...response.data.records])
}).catch(function (error) { }).catch(function (error) {
console.log(error) console.log(error)
}) })
@ -285,31 +305,50 @@ function InvoiceListView(props: {}) {
navigate('/invoice/mine?currentPage=' + pageCurrentNum + '&pageSize=' + pageCurrentSize) navigate('/invoice/mine?currentPage=' + pageCurrentNum + '&pageSize=' + pageCurrentSize)
} }
const onItemClick = (invoice: Invoice) =>{
console.log(invoice)
axiosInstance({
url: 'common/invoice/'+invoice.invoiceId,
method: 'get',
}).then(response => {
console.log(response.data)
let detail:InvoiceDetail = response.data
detail.invoiceAmount/=100.
setInvoiceDetail(detail)
setDetailModalOpen(true)
}).catch(function (error) {
console.log(error)
})
}
useEffect(() => { useEffect(() => {
console.log(search.get('currentPage')) console.log(search.get('currentPage'))
console.log(search.get('pageSize')) console.log(search.get('pageSize'))
searchInvoiceContent() searchInvoiceContent(invoiceSearchOption)
}, [search]); }, [search]);
console.log(invoices)
return ( return (
<div style={{}}> <div style={{}}>
<InvoiceSearch handleSearchData={handleInvoiceSearchInfo}/> <InvoiceSearch handleSearchData={handleInvoiceSearchInfo}/>
<div style={{padding:26,display:"flex", flexDirection: "column", alignItems: "flex-end"}}> <div style={{padding: 26, display: "flex", flexDirection: "column", alignItems: "flex-end"}}>
<div style={{display: "flex", flexWrap: "wrap", justifyContent:'center', width: '100%'}}> <div style={{display: "flex", flexWrap: "wrap", justifyContent: 'center', width: '100%'}}>
{invoices.map((item: Invoice, index: number) => {invoices.map((item: Invoice, index: number) =>
<InvoiceItem invoice={item} key={index}/> <InvoiceItem onClick={onItemClick} invoice={item} key={index}/>
)} )}
</div> </div>
<Pagination showSizeChanger <Pagination showSizeChanger
showQuickJumper showQuickJumper
showTotal={(total) => `${total}`} showTotal={(total) => `${total}`}
current={Number(search.get('currentPage')?search.get('currentPage'):1)} current={Number(search.get('currentPage') ? search.get('currentPage') : 1)}
pageSize={Number(search.get('pageSize')?search.get('pageSize'):10)} pageSize={Number(search.get('pageSize') ? search.get('pageSize') : 10)}
total={totalNum} onChange={onChange}/> total={totalNum} onChange={onChange}/>
</div> </div>
<InvoiceDetailModal invoiceDetail={invoiceDetail} open={detailModalOpen} onClose={()=>{setDetailModalOpen(false)}}/>
</div> </div>
) )
} }
export default InvoiceListView export default InvoiceListView

View File

@ -2,7 +2,6 @@ import React, {useEffect, useRef, useState} from 'react';
import {Button, Modal, UploadProps, message, Upload, UploadFile, Form, Input, DatePicker, Select, InputNumber} from 'antd'; import {Button, Modal, UploadProps, message, Upload, UploadFile, Form, Input, DatePicker, Select, InputNumber} from 'antd';
import {InboxOutlined, UploadOutlined} from '@ant-design/icons'; import {InboxOutlined, UploadOutlined} from '@ant-design/icons';
import axiosInstance from "../../../utils/axiosInstance"; import axiosInstance from "../../../utils/axiosInstance";
import {InvoiceCommit} from "../../../models/Staff";
import dayjs, {Dayjs} from 'dayjs'; import dayjs, {Dayjs} from 'dayjs';
import TextArea from "antd/es/input/TextArea"; import TextArea from "antd/es/input/TextArea";
import {constants} from "http2"; import {constants} from "http2";
@ -50,11 +49,7 @@ class FileUploadView extends React.Component<any, any> {
function UpLoadModal(props: any) { function UpLoadModal(props: any) {
const [open, setOpen] = useState(false)
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
useEffect(() => {
setOpen(props.open)
}, [props]);
const handleOk = () => { const handleOk = () => {
setLoading(true); setLoading(true);
let data = new FormData(); let data = new FormData();
@ -66,7 +61,7 @@ function UpLoadModal(props: any) {
}).then(response => { }).then(response => {
setLoading(false); setLoading(false);
console.log(response.data) console.log(response.data)
setOpen(false); props.onClose()
props.nextStep(response.data) props.nextStep(response.data)
}).catch(function (error) { }).catch(function (error) {
setLoading(false); setLoading(false);
@ -75,12 +70,12 @@ function UpLoadModal(props: any) {
}; };
const handleCancel = () => { const handleCancel = () => {
setOpen(false); props.onClose()
}; };
return ( return (
<Modal <Modal
open={open} open={props.open}
title="上传发票" title="上传发票"
onOk={handleOk} onOk={handleOk}
onCancel={handleCancel} onCancel={handleCancel}
@ -110,7 +105,7 @@ function FormModal(props: any) {
let i = {...props.invoiceIdentifyResponse} let i = {...props.invoiceIdentifyResponse}
setInvoice(i) setInvoice(i)
refreshFormItems(props.invoiceIdentifyResponse?.invoiceKind) refreshFormItems(props.invoiceIdentifyResponse?.invoiceKind)
//TODO: 重置表单 form.resetFields()
form.setFieldsValue(i) form.setFieldsValue(i)
}, [props]); }, [props]);
@ -266,7 +261,11 @@ class InvoiceUploadView extends React.Component<any, any> {
handleNextStep = (response: InvoiceIdentifyResponse) => { handleNextStep = (response: InvoiceIdentifyResponse) => {
response.invoiceDate = dayjs(response.invoiceDate) response.invoiceDate = dayjs(response.invoiceDate)
response.invoiceAmount /= 100. response.invoiceAmount /= 100.
this.setState({uploadModalOpen: false, formModalOpen: true, invoiceIdentifyResponse: response}) this.setState({formModalOpen: true, invoiceIdentifyResponse: response})
}
handleUploadModalClose = () => {
this.setState({uploadModalOpen:false})
} }
handleClose = () => { handleClose = () => {
@ -281,7 +280,7 @@ class InvoiceUploadView extends React.Component<any, any> {
<Button onClick={this.showUploadView} className="uploadButton" type="primary" icon={<UploadOutlined/>}> <Button onClick={this.showUploadView} className="uploadButton" type="primary" icon={<UploadOutlined/>}>
</Button> </Button>
<UpLoadModal open={this.state.uploadModalOpen} nextStep={this.handleNextStep}/> <UpLoadModal open={this.state.uploadModalOpen} nextStep={this.handleNextStep} onClose={this.handleUploadModalClose}/>
<FormModal open={this.state.formModalOpen} onClose={this.handleClose} <FormModal open={this.state.formModalOpen} onClose={this.handleClose}
invoiceIdentifyResponse={this.state.invoiceIdentifyResponse}/> invoiceIdentifyResponse={this.state.invoiceIdentifyResponse}/>
</>); </>);