Merge remote-tracking branch 'origin/main' into main

# Conflicts:
#	src/pages/Invoice/mine/InvoiceListView.tsx
main
wuyize 2023-01-02 14:24:47 +08:00
commit 83f000fe47
4 changed files with 984 additions and 280 deletions

View File

@ -70,7 +70,8 @@ const statusEnum = {
class Subpage extends React.Component<any, any> { class Subpage extends React.Component<any, any> {
tableAction = React.createRef<ActionType>(); tableAction = React.createRef<ActionType>();
departments=new Map<number,string>() departments = new Map<number, string>()
constructor(props: {}) { constructor(props: {}) {
super(props); super(props);
this.state = { this.state = {
@ -207,7 +208,7 @@ class Subpage extends React.Component<any, any> {
result.push({ result.push({
id: value[i].reimbursementSubmitDepartment.departmentId, id: value[i].reimbursementSubmitDepartment.departmentId,
beginDate: Date.parse(value[i].reimbursementDepartureInvoice.invoiceDate), beginDate: Date.parse(value[i].reimbursementDepartureInvoice.invoiceDate),
endDate: Date.parse(value[i].reimbursementDepartureInvoice.invoiceDate)+value[i].reimbursementTripDuration*24*60*60*1000, endDate: Date.parse(value[i].reimbursementDepartureInvoice.invoiceDate) + value[i].reimbursementTripDuration * 24 * 60 * 60 * 1000,
duration: value[i].reimbursementTripDuration, duration: value[i].reimbursementTripDuration,
OD: [value[i].reimbursementDepartureName, value[i].reimbursementDestinationName], OD: [value[i].reimbursementDepartureName, value[i].reimbursementDestinationName],
amount: value[i].reimbursementInvoiceAmount + value[i].reimbursementAdditionalAmount, amount: value[i].reimbursementInvoiceAmount + value[i].reimbursementAdditionalAmount,
@ -249,10 +250,20 @@ class Subpage extends React.Component<any, any> {
pageSize: pageSize, pageSize: pageSize,
} }
if (filter.status !== undefined && filter.status !== null && filter.status.length !== 0) { if (filter.status !== undefined && filter.status !== null && filter.status.length !== 0) {
params['reimbursementStatuses'] = qs.stringify({reimbursementStatuses: filter.status}, {arrayFormat: 'indices'}) params['reimbursementStatuses'] = ""
for (let i = 0; i < filter.status.length; i++) {
if (i !== 0)
params['reimbursementStatuses'] += ','
params['reimbursementStatuses'] += filter.status[i].toString()
}
} }
if (filter.departmentId !== undefined && filter.departmentId !== null && filter.departmentId.length !== 0) { if (filter.departmentId !== undefined && filter.departmentId !== null && filter.departmentId.length !== 0) {
params['reimbursementSubmitDepartments'] = qs.stringify({reimbursementSubmitDepartments: filter.departmentId}, {arrayFormat: 'indices'}) params['reimbursementSubmitDepartments'] = ""
for (let i = 0; i < filter.departmentId.length; i++) {
if (i !== 0)
params['reimbursementSubmitDepartments'] += ','
params['reimbursementSubmitDepartments'] += filter.departmentId[i].toString()
}
} }
if (sort.id !== undefined && sort.id !== null) { if (sort.id !== undefined && sort.id !== null) {
params['sortBy'] = "reimbursementId" params['sortBy'] = "reimbursementId"
@ -266,7 +277,7 @@ class Subpage extends React.Component<any, any> {
params['sortBy'] = "reimbursementSubmitTime" params['sortBy'] = "reimbursementSubmitTime"
params['asc'] = (sort.submitDateTime === "ascend") params['asc'] = (sort.submitDateTime === "ascend")
} }
if(sort.beginDate !== undefined && sort.beginDate !== null){ if (sort.beginDate !== undefined && sort.beginDate !== null) {
params['sortBy'] = "reimbursementDepartureDate" params['sortBy'] = "reimbursementDepartureDate"
params['asc'] = (sort.beginDate === "ascend") params['asc'] = (sort.beginDate === "ascend")
} }
@ -293,69 +304,70 @@ class Subpage extends React.Component<any, any> {
render() { render() {
return ( return (
<> <>
<ReimbursementCreate ref={this.createRef} open={this.state.onCreated} wrapClassName="Subpage" /> <ReimbursementCreate ref={this.createRef} open={this.state.onCreated} wrapClassName="Subpage"/>
<ProTable<TableListItem> <ProTable<TableListItem>
actionRef={this.tableAction} actionRef={this.tableAction}
columns={this.columns} columns={this.columns}
request={async (params, sorter, filter) => { request={async (params, sorter, filter) => {
// 表单搜索项会从 params 传入,传递给后端接口。 // 表单搜索项会从 params 传入,传递给后端接口。
console.log(params, sorter, filter); console.log(params, sorter, filter);
return this.updateRequest(params.current, params.pageSize, sorter, filter) return this.updateRequest(params.current, params.pageSize, sorter, filter)
}} }}
rowKey="key" rowKey="key"
pagination={{ pagination={{
defaultPageSize: 5, defaultPageSize: 5,
pageSizeOptions: [5, 10, 20, 50, 100], pageSizeOptions: [5, 10, 20, 50, 100],
showQuickJumper: true, showQuickJumper: true,
}} }}
// toolbar={{ // toolbar={{
// title: '这里是标题', // title: '这里是标题',
// subTitle: '这里是子标题', // subTitle: '这里是子标题',
// tooltip: '这是一个段描述', // tooltip: '这是一个段描述',
// search: { // search: {
// onSearch: (value: string) => { // onSearch: (value: string) => {
// alert(value); // alert(value);
// }, // },
// }, // },
// }} // }}
search={{ search={{
defaultCollapsed: false, defaultCollapsed: false,
labelWidth: 'auto', labelWidth: 'auto',
optionRender: ({searchText}, {form}, dom) => { optionRender: ({searchText}, {form}, dom) => {
// console.log(searchConfig, formProps, dom) // console.log(searchConfig, formProps, dom)
return [ return [
<div style={{flexWrap: "nowrap", display: "flex", justifyContent: "flex-end"}}> <div style={{flexWrap: "nowrap", display: "flex", justifyContent: "flex-end"}}>
<Search className="searchBar" <Search className="searchBar"
addonBefore={"报销单号:"} addonBefore={"报销单号:"}
placeholder={""} placeholder={""}
allowClear allowClear
onSearch={(value) => { onSearch={(value) => {
this.search(value, form, dom) this.search(value, form, dom)
}} }}
enterButton enterButton
/> />
<Button key="create" type="primary" onClick={() => this.create()} style={{width: 100}}> <Button key="create" type="primary" onClick={() => this.create()}
style={{width: 100}}>
</Button>
</div> </Button>
] </div>
} ]
}} }
}}
dateFormatter="string" dateFormatter="string"
// toolBarRender={() => [ // toolBarRender={() => [
// <Button key="show">查看日志</Button>, // <Button key="show">查看日志</Button>,
// <Button key="out"> // <Button key="out">
// 导出数据 // 导出数据
// <DownOutlined /> // <DownOutlined />
// </Button>, // </Button>,
// <Button type="primary" key="primary"> // <Button type="primary" key="primary">
// 创建应用 // 创建应用
// </Button>, // </Button>,
// ]} // ]}
/> />
</>); </>);
} }
} }

View File

@ -1,202 +1,44 @@
import React, {Key, ReactNode} from "react"; import React, {Key, ReactNode} from "react";
import {ReimbursementApplication} from "../../../models/Reimbursement"; import {ReimbursementApplication} from "../../../models/Reimbursement";
import {Button, Card, Col, Form, Input, InputNumber, Modal, Popover, Radio, Row, Select} from "antd"; import {
Button,
Col,
Form,
Input,
InputNumber,
Modal, notification,
Row
} from "antd";
import {FormInstance} from "antd/es/form"; import {FormInstance} from "antd/es/form";
import {Invoice} from "../../../models/Reimbursement"; import {Invoice} from "../../../models/Reimbursement";
import axiosInstance from "../../../utils/axiosInstance"; import axiosInstance, {baseUrl} from "../../../utils/axiosInstance";
import Column from "antd/es/table/Column"; import Column from "antd/es/table/Column";
import type {MenuProps} from 'antd'; import type {MenuProps} from 'antd';
import {ExclamationCircleOutlined, UserOutlined} from "@ant-design/icons"; import {ExclamationCircleOutlined, UserOutlined} from "@ant-design/icons";
import {Dropdown, message, Space, Tooltip} from 'antd'; import {Dropdown, message, Space, Tooltip} from 'antd';
import {store} from "../../../models/store"; import {store} from "../../../models/store";
import {FieldData} from "rc-field-form/lib/interface"; import {FieldData} from "rc-field-form/lib/interface";
import {invoiceTypeNameMap} from "../../../models/Invoice";
import SingleInvoiceSelector from "./component/SingleInvoiceSelector";
import MultiInvoiceSelector from "./component/MultiInvoiceSelector";
import {StatisticCard} from "@ant-design/pro-components";
function InvoiceCard(props: { invoice: Invoice }) { const {Operation} = StatisticCard;
const invoice = props.invoice;
return (
<Card
style={{width: 300}}
cover={
<img
alt="example"
src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
/>
}
>
</Card>
)
}
class InvoiceRadioCard extends React.Component<any, any> {
constructor(props: {
invoice: any;
hidden: boolean;
selected: boolean;
index: number;
click: any;
}) {
super(props);
this.state = {
invoice: props.invoice,
hidden: props.hidden,
selected: props.selected,
index: props.index,
click: props.click
}
}
static getDerivedStateFromProps(props: {
invoice: any;
hidden: boolean;
selected: boolean;
index: number;
click: any;
}) {
return {
invoice: props.invoice,
hidden: props.hidden,
selected: props.selected,
index: props.index,
click: props.click
}
}
select(e: any) {
if (this.state.selected)
return
this.setState({selected: true})
this.props.click(this.props.index, true)
}
render() {
return (
<Card hidden={this.state.hidden}
cover={<img alt="example" src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"/>}
actions={[<Radio checked={this.state.selected} onClick={(e) => {
this.select(e)
}} defaultChecked={this.state.selected}/>]}>
</Card>
)
}
}
class SingleInvoiceSelector extends React.Component<any, any> {
value: any
onChange: any
constructor(props: {
pickerOpen: boolean;
pickerTitle: string;
value: any;
onChange: any;
}) {
super(props);
this.value = props.value
this.onChange = props.onChange
this.state = {
selectedIndex: -1,
selectedInvoice: {},
singleLimit: true,
invoices: [{invoiceId:1},{invoiceId:2},{invoiceId:3}],
pickerOpen: props.pickerOpen,
pickerTitle: props.pickerTitle
}
}
invoiceCard = () => {
if (this.state.selectedInvoice.invoiceId === null || this.state.selectedInvoice.invoiceId === undefined) {
return (<>{this.state.pickerTitle}</>)
}
return (<InvoiceCard invoice={this.state.selectedInvoice}/>)
}
pickerOpen = (value: boolean) => {
this.setState({pickerOpen: value})
}
confirm = () => {
this.setState({pickerOpen: false})
}
cancelSelect = () => {
this.onChange({})
this.setState({selectedIndex: -1, selectedInvoice: {}})
}
click = (index: number, status: boolean) => {
if (status) {
this.setState({selectedIndex: index, selectedInvoice: this.state.invoices[index]})
this.onChange({invoice: this.state.invoices[index]})
}
}
cardList = () => {
let cards = []
for (let i = 0; i < this.state.invoices.length; i += 2) {
if (i + 1 >= this.state.invoices.length) {
cards.push(
<Row gutter={18}>
<Col span={12}>
<InvoiceRadioCard invoice={this.state.invoices[i]} selected={this.state.selectedIndex === i}
hidden={false} index={i} click={this.click}/>
</Col>
</Row>)
} else {
cards.push(
<Row gutter={18}>
<Col span={12}>
<InvoiceRadioCard invoice={this.state.invoices[i]} selected={this.state.selectedIndex === i}
hidden={false} index={i} click={this.click}/>
</Col>
<Col span={12}>
<InvoiceRadioCard invoice={this.state.invoices[i + 1]}
selected={this.state.selectedIndex === i + 1}
hidden={false} index={i + 1} click={this.click}/>
</Col>
</Row>)
}
}
return (
<>{cards}</>
)
}
render() {
return (
<>
<Button name={"select"} onClick={() => this.pickerOpen(true)}>
</Button>
<Popover
content={this.invoiceCard}>
<ExclamationCircleOutlined style={{marginLeft: 5}}/>
</Popover>
<Modal
open={this.state.pickerOpen}
title={this.state.pickerTitle + "选择"}
onOk={this.confirm}
onCancel={() => this.pickerOpen(false)}
destroyOnClose={true}
footer={[
<Button key="clear" type="primary" onClick={this.cancelSelect}>
</Button>,
<Button key="confirm" type="primary" onClick={this.confirm}>
</Button>
]}
>
{this.cardList()}
</Modal>
</>)
}
}
const openNotification = (hint: string) => {
notification.open({
message: hint,
duration: 1,
onClick: () => {
console.log('Notification Clicked!');
},
});
};
class ReimbursementCreate extends React.Component<any, any> { class ReimbursementCreate extends React.Component<any, any> {
formRef = React.createRef<FormInstance>(); formRef = React.createRef<FormInstance>();
invoiceSelector1 = React.createRef<SingleInvoiceSelector>(); invoiceSelector1 = React.createRef<SingleInvoiceSelector>();
invoiceSelector2 = React.createRef<SingleInvoiceSelector>(); invoiceSelector2 = React.createRef<SingleInvoiceSelector>();
//invoiceSelector3 = React.createRef<InvoiceSelector>(); invoiceSelector3 = React.createRef<MultiInvoiceSelector>();
departments: { departmentId: number, departmentName: string }[] = []; departments: { departmentId: number, departmentName: string }[] = [];
constructor(props: {}) { constructor(props: {}) {
@ -207,6 +49,7 @@ class ReimbursementCreate extends React.Component<any, any> {
departmentName: store.getState().staff.managingDepartment.departmentName, departmentName: store.getState().staff.managingDepartment.departmentName,
}) })
} }
console.log(store.getState().staff.staffDepartments)
store.getState().staff.staffDepartments.forEach((item) => { store.getState().staff.staffDepartments.forEach((item) => {
this.departments.push({ this.departments.push({
departmentId: item.departmentId, departmentId: item.departmentId,
@ -221,6 +64,7 @@ class ReimbursementCreate extends React.Component<any, any> {
icon: <UserOutlined/>, icon: <UserOutlined/>,
}) })
}) })
console.log(store.getState().staff.staffDepartments)
this.state = { this.state = {
loading: false, loading: false,
open: this.props.open, open: this.props.open,
@ -232,21 +76,14 @@ class ReimbursementCreate extends React.Component<any, any> {
}, },
back: false, back: false,
duration: 0, duration: 0,
departureInvoice: null,
destinationInvoice: null,
otherInvoices: [],
departureName: "",
destinationName: "",
note: "",
departmentId: -1,
} }
let params = {
pageNum: 0,
pageSize: 100,
invoiceStatus: 0,
invoiceUploaderId: store.getState().token.staffId,
}
axiosInstance.get("common/invoice", {
params: params
}).then((res) => {
this.setState({
invoices: res.data.records
})
this.formRef.current?.setFieldValue("invoices", this.state.invoices)
})
} }
handleMenuClick: MenuProps['onClick'] = (e) => { handleMenuClick: MenuProps['onClick'] = (e) => {
@ -260,9 +97,44 @@ class ReimbursementCreate extends React.Component<any, any> {
//console.log('click', e.key,this.departments.find((item)=>item.departmentId.toString()===e.key)); //console.log('click', e.key,this.departments.find((item)=>item.departmentId.toString()===e.key));
}; };
submitCheck = () => {
return {ok:true,msg:""}
}
submit = () => { submit = () => {
console.log(this.formRef.current?.getFieldsValue()) let checkResult = this.submitCheck()
if(!checkResult.ok){
openNotification(checkResult.msg)
return
}
let otherInvoices = null
if(this.state.otherInvoices?.length>0){
otherInvoices = ""
for(let i=0;i<this.state.otherInvoices.length;i++){
if(i!==0){
otherInvoices += ","
}
otherInvoices += this.state.otherInvoices[i].invoiceId.toString()
}
}
let params={
submitDepartmentId:this.state.selectedDepartment.id,
reimbursementNote:this.state.note?this.state.note:"",
reimbursementDepartureInvoiceId: this.state.departureInvoice.invoiceId,
reimbursementDestinationInvoiceId: this.state.destinationInvoice?.invoiceId,
reimbursementOtherInvoiceIds: otherInvoices,
reimbursementDepartureName: this.state.departureName,
reimbursementDestinationName: this.state.destinationName,
reimbursementDuration: this.state.duration,
}
axiosInstance.post("common/reimbursement", params).then(response => {
openNotification("提交成功")
this.setState({open: false})
}).catch(error => {
console.log(error)
openNotification("提交失败")
})
} }
cancel = () => { cancel = () => {
this.setState({open: false}) this.setState({open: false})
@ -272,23 +144,57 @@ class ReimbursementCreate extends React.Component<any, any> {
value = 0 value = 0
this.setState({duration: value}) this.setState({duration: value})
} }
formFieldsChange = (changedFields: any, allFields: any) => { formValuesChange = (changedValues: any, allValues: any) => {
let start = allFields['departureInvoiceId'] let state: any = {}
let end = allFields['destinationInvoiceId'] console.log(allValues)
if (start !== undefined && end !== undefined && start.invoiceDate !== undefined && end.invoiceDate !== undefined) { if (allValues.departureInvoice !== undefined && allValues.departureInvoice !== null && allValues.destinationInvoice !== undefined && allValues.destinationInvoice !== null) {
let x = Math.floor((Date.parse(end.invoiceDate) - Date.parse(start.invoiceDate)) / 24 / 60 / 60 / 1000) + 1 state['back'] = true
this.setState({back: true, duration: x}) state["duration"] = (Number(Date.parse(allValues.destinationInvoice.invoiceDate)) - Number(Date.parse(allValues.departureInvoice.invoiceDate))) / 1000 / 60 / 60 / 24 + 1
this.formRef.current?.setFieldValue('duration', x) if (state["duration"] < 0)
}else{ state["duration"] = 0
this.setState({back: false, duration: 0}) } else {
this.formRef.current?.setFieldValue('duration', 0) state['back'] = false
state["duration"] = 0
} }
console.log(allFields) this.formRef.current?.setFieldsValue({duration: state["duration"]})
state['departureInvoice'] = allValues.departureInvoice
state["destinationInvoice"] = allValues.destinationInvoice
state["otherInvoices"] = allValues.otherInvoices
state["departureName"] = allValues.departureName
state["destinationName"] = allValues.destinationName
state["note"] = changedValues.note
state["departmentId"] = allValues.departmentId
this.setState(state)
}
getOccupiedInvoices = (type: number) => {
let res = []
if (type === 1) {
this.state.otherInvoices?.forEach((item: Invoice) => {
res.push(item)
})
if (this.state.destinationInvoice !== null && this.state.destinationInvoice !== undefined)
res.push(this.state.destinationInvoice)
} else if (type === 2) {
this.state.otherInvoices?.forEach((item: Invoice) => {
res.push(item)
})
if (this.state.departureInvoice !== null && this.state.departureInvoice !== undefined)
res.push(this.state.departureInvoice)
} else if (type === 3) {
if (this.state.departureInvoice !== null && this.state.departureInvoice !== undefined)
res.push(this.state.departureInvoice)
if (this.state.destinationInvoice !== null && this.state.destinationInvoice !== undefined)
res.push(this.state.destinationInvoice)
}
return res
} }
render() { render() {
return ( return (
<Modal <Modal
width={800}
open={this.state.open} open={this.state.open}
title="出差报销单" title="出差报销单"
onOk={this.submit} onOk={this.submit}
@ -300,7 +206,7 @@ class ReimbursementCreate extends React.Component<any, any> {
</Button>]} </Button>]}
> >
<Form ref={this.formRef} onFieldsChange={this.formFieldsChange} <Form ref={this.formRef} onValuesChange={this.formValuesChange}
initialValues={{ initialValues={{
departmentId: this.state.selectedDepartment.id, departmentId: this.state.selectedDepartment.id,
destinationName: '', destinationName: '',
@ -324,14 +230,20 @@ class ReimbursementCreate extends React.Component<any, any> {
<Row gutter={18}> <Row gutter={18}>
<Col span={12}> <Col span={12}>
<Form.Item help="" label="出发票据" name="departureInvoice" rules={[{required: true}]}> <Form.Item help="" label="出发票据" name="departureInvoice" rules={[{required: true}]}>
<SingleInvoiceSelector invoices={[]} pickerOpen={false} <SingleInvoiceSelector pickerOpen={false} after={0}
before={this.state.destinationInvoice !== null && this.state.destinationInvoice !== undefined ? Number(Date.parse(this.state.destinationInvoice.invoiceDate)) : 0}
occupiedInvoices={this.getOccupiedInvoices(1)}
pickerTitle={"出发票据"} ref={this.invoiceSelector1}/> pickerTitle={"出发票据"} ref={this.invoiceSelector1}/>
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={12}> <Col span={12}>
<Form.Item label="返程票据" name="destinationInvoice" rules={[{required: false}]}> <Form.Item label="返程票据" name="destinationInvoice" rules={[{required: false}]}>
<SingleInvoiceSelector invoices={[]} pickerOpen={false} <SingleInvoiceSelector pickerOpen={false}
pickerTitle={"返程票据"} ref={this.invoiceSelector2}/> //disabled={this.state.departureInvoice === null || this.state.departureInvoice === undefined}
after={this.state.departureInvoice !== null && this.state.departureInvoice !== undefined ? Number(Date.parse(this.state.departureInvoice.invoiceDate)) : 0}
before={0} occupiedInvoices={this.getOccupiedInvoices(2)}
pickerTitle={"返程票据"} ref={this.invoiceSelector2}
/>
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
@ -356,11 +268,51 @@ class ReimbursementCreate extends React.Component<any, any> {
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
<Form.Item label="附加票据" name="otherInvoices" rules={[{required: false}]}>
<MultiInvoiceSelector pickerOpen={false}
after={0}
//after={this.state.departureInvoice !== null && this.state.departureInvoice !== undefined ? Number(Date.parse(this.state.departureInvoice.invoiceDate)) : 0}
before={0} occupiedInvoices={this.getOccupiedInvoices(3)}
pickerTitle={"附加票据"} ref={this.invoiceSelector3}
/>
</Form.Item>
<Form.Item label="备注信息" name="note" rules={[{required: false}]}> <Form.Item label="备注信息" name="note" rules={[{required: false}]}>
<Input.TextArea/> <Input.TextArea/>
</Form.Item> </Form.Item>
<StatisticCard.Group>
<StatisticCard
statistic={{
title: '出发票据金额',
value: this.state.departureInvoice !== null && this.state.departureInvoice !== undefined ? (this.state.departureInvoice.invoiceAmount/100.0).toFixed(2): 0,
}}
/>
<Operation>+</Operation>
<StatisticCard
statistic={{
title: '返程票据金额',
value: this.state.destinationInvoice !== null && this.state.destinationInvoice !== undefined ? (this.state.destinationInvoice.invoiceAmount/100.0).toFixed(2) : 0,
}}
/>
<Operation>+</Operation>
<StatisticCard
statistic={{
title: '附加票据金额',
value: this.state.otherInvoices!==null&&this.state.otherInvoices!==undefined&&this.state.otherInvoices.length > 0 ?
(this.state.otherInvoices.map((item:Invoice) => item.invoiceAmount).reduce((a:number, b:number) => a + b)/100.0).toFixed(2) : 0,
}}
/>
<Operation>=</Operation>
<StatisticCard
statistic={{
title: '票据总金额',
value: (((this.state.departureInvoice !== null && this.state.departureInvoice !== undefined ? this.state.departureInvoice.invoiceAmount: 0)
+(this.state.destinationInvoice !== null && this.state.destinationInvoice !== undefined ? this.state.destinationInvoice.invoiceAmount : 0)
+(this.state.otherInvoices!==null&&this.state.otherInvoices!==undefined&&this.state.otherInvoices.length > 0 ?
this.state.otherInvoices.map((item:Invoice) => item.invoiceAmount).reduce((a:number, b:number) => a + b) : 0))/100.0).toFixed(2) ,
suffix: '元',
}}
/>
</StatisticCard.Group>
</Form> </Form>
</Modal>) </Modal>)
} }

View File

@ -0,0 +1,371 @@
import {Invoice} from "../../../../models/Reimbursement";
import {Button, Card, Col, Modal, Pagination, PaginationProps, Popover, Row, Tag} from "antd";
import axiosInstance, {baseUrl} from "../../../../utils/axiosInstance";
import {invoiceTypeNameMap} from "../../../../models/Invoice";
import React from "react";
import {store} from "../../../../models/store";
import {ExclamationCircleOutlined} from "@ant-design/icons";
class InvoiceCheckboxCard extends React.Component<any, any> {
constructor(props: {
invoice: any;
hidden: boolean;
selected: number;
index: number;
click: any;
}) {
super(props);
this.state = {
invoice: props.invoice,
hidden: props.hidden,
selected: props.selected,
index: props.index,
click: props.click,
}
}
static getDerivedStateFromProps(props: {
invoice: any;
hidden: boolean;
selected: number;
index: number;
}) {
return {
invoice: props.invoice,
hidden: props.hidden,
selected: props.selected,
index: props.index,
}
}
select(e: any) {
if (this.state.selected === 0) {
this.setState({selected: 1})
this.props.click(this.state.invoice, true)
} else if (this.state.selected === 1) {
this.setState({selected: 0})
this.props.click(this.state.invoice, false)
}
}
getTag = () => {
if (this.state.selected === 1)
return <Popover content={"已选作报销凭证"}><Tag color="blue"></Tag></Popover>
else if (this.state.selected === 0)
return <Popover content={"可用于报销"}><Tag color="green"></Tag></Popover>
else if (this.state.selected === -1)
return <Popover content={"早于出发日期"}><Tag color="red"></Tag></Popover>
else if (this.state.selected === -2)
return <Popover content={"晚于返程日期"}><Tag color="red"></Tag></Popover>
else if (this.state.selected === -3)
return <Popover content={"已作其他用途"}><Tag color="red"></Tag></Popover>
}
render() {
return (
<Card hidden={this.state.hidden}
hoverable={true}
style={{
marginBottom: 30, background: (this.state.selected === 1 ? "lightskyblue" : "#f0f0f0"),
opacity: (this.state.selected >= 0 ? 1 : 0.7)
}}
onClick={(e) => {
this.select(e)
}}
cover={<img alt="thumbnail"
src={baseUrl + this.state.invoice.invoiceThumbnailUri}
width="300" height="120"/>}
// actions={[<Radio checked={this.state.selected} onClick={(e) => {
// this.select(e)
// }} defaultChecked={this.state.selected}/>]}
>
<div style={{marginTop: -20, height: 80}}>
<li style={{
fontWeight: "bold",
fontSize: 18
}}>¥{(this.state.invoice.invoiceAmount / 100.0).toFixed(2)}
{this.getTag()}
</li>
<li>{invoiceTypeNameMap.get(this.state.invoice.invoiceKind)}</li>
<li>{this.state.invoice.invoiceName}</li>
<li>{this.state.invoice.invoiceNote}</li>
<li>{this.state.invoice.invoiceDate}</li>
</div>
</Card>
)
}
}
class MultiInvoiceSelector extends React.Component<any, any> {
value: any
onChange: any
availableInvoiceKinds = [0, 2, 5, 9, 10, 13]
constructor(props: {
disabled: boolean;
pickerOpen: boolean;
pickerTitle: string;
value: any;
onChange: any;
after: number;
before: number;
occupiedInvoices: Invoice[];
}) {
super(props);
this.value = props.value
this.onChange = props.onChange
this.state = {
disabled: props.disabled,
occupiedInvoices: props.occupiedInvoices,
selectedInvoice: [],
singleLimit: false,
invoices: [],
pickerOpen: props.pickerOpen,
pickerTitle: props.pickerTitle,
currentPage: 1,
pageSize: 6,
total: 0,
after: props.after,
before: props.before,
searchOptions: {
invoiceNote: "",
invoiceDateStart: 0,
invoiceDateEnd: 0,
invoiceKind: -1,
}
}
this.requestInvoices(1, this.state.searchOptions)
}
requestInvoices(page: number, searchOptions: any) {
let params: any = {
pageNum: page - 1,
pageSize: this.state.pageSize,
invoiceUploaderId: store.getState().token.staffId,
invoiceStatus: 0,
sortBy: "invoiceDate",
asc: true,
}
if (searchOptions.invoiceNote !== "") {
params.invoiceNote = searchOptions.invoiceNote
}
if (searchOptions.invoiceDateStart !== 0) {
params.invoiceDateStart = searchOptions.invoiceDateStart
}
if (searchOptions.invoiceDateEnd !== 0) {
params.invoiceDateEnd = searchOptions.invoiceDateEnd
}
if (searchOptions.invoiceKind !== -1) {
params.invoiceKinds = searchOptions.invoiceKind
} else {
// params.invoiceKinds = "0,2,5,9,10,13"
}
console.log(params)
axiosInstance.get('common/invoice', {params: params}).then(response => {
this.setState({
total: response.data.total, invoices: response.data.records,
currentPage: page, searchOptions: searchOptions
})
}).catch(error => {
console.log(error)
})
}
static getDerivedStateFromProps(props: {
after: number;
before: number;
occupiedInvoices: Invoice[];
onChange: any;
}, state: any) {
let prev = state.selectedInvoice
let changed = false
if (props.after !== 0) {
for (let i = 0; i < prev.length; i++) {
if (Number(Date.parse(prev[i].invoiceDate) < props.after)) {
prev.splice(i, 1)
changed = true
}
}
}
if (!changed)
return {
after: props.after,
before: props.before,
occupiedInvoices: props.occupiedInvoices,
}
return {
selectedInvoice: prev,
after: props.after,
before: props.before,
occupiedInvoices: props.occupiedInvoices,
}
}
setSearchOptions = (options: any) => {
this.setState({searchOptions: options})
}
pickerOpen = (value: boolean) => {
if (this.state.disabled) {
alert("请先选择出发票据")
} else {
this.setState({pickerOpen: value})
}
}
confirm = () => {
this.setState({pickerOpen: false})
}
cancelSelect = () => {
this.onChange(undefined)
this.setState({selectedInvoice: []})
}
click = (invoice: any, status: boolean) => {
console.log(invoice)
if (status) {
let prev = this.state.selectedInvoice
for (let i = 0; i < prev.length; i++) {
if (prev[i].invoiceId === invoice.invoiceId) {
return
}
}
prev.push(invoice)
this.setState({selectedInvoice: prev})
this.onChange(prev)
} else {
let prev = this.state.selectedInvoice
console.log(prev)
for (let i = 0; i < prev.length; i++) {
if (prev[i].invoiceId === invoice.invoiceId) {
prev.splice(i, 1)
this.setState({selectedInvoice: prev})
this.onChange(prev)
return
}
}
}
}
changePage: PaginationProps['onChange'] = (page) => {
console.log(this.state.ocuppiedInvoices)
this.requestInvoices(page, this.state.searchOptions)
};
checkSelected = (invoice: Invoice) => {
for (let i = 0; i < this.state.occupiedInvoices.length; i++) {
if (this.state.occupiedInvoices[i].invoiceId === invoice.invoiceId) {
return -3
}
}
if (this.state.after !== 0 && this.state.after > Number(Date.parse(invoice.invoiceDate)))
return -1
// if (this.state.before !== 0 && this.state.before < Number(Date.parse(invoice.invoiceDate)))
// return -2
for (let i = 0; i < this.state.selectedInvoice.length; i++) {
if (this.state.selectedInvoice[i] === invoice) {
return 1
}
}
return 0
}
cardList = () => {
let cards = []
const maxSize = Math.min(this.state.pageSize, this.state.invoices.length)
for (let i = 0; i < maxSize; i += 3) {
if (i + 1 >= this.state.invoices.length) {
cards.push(
<Row gutter={18} key={i}>
<Col span={8}>
<InvoiceCheckboxCard invoice={this.state.invoices[i]}
selected={this.checkSelected(this.state.invoices[i])}
hidden={false} index={i}
click={this.click}/>
</Col>
</Row>)
} else if (i + 2 >= this.state.invoices.length) {
cards.push(
<Row gutter={18} key={i}>
<Col span={8}>
<InvoiceCheckboxCard invoice={this.state.invoices[i]}
selected={this.checkSelected(this.state.invoices[i])}
hidden={false} index={i}
click={this.click}/>
</Col>
<Col span={8}>
<InvoiceCheckboxCard invoice={this.state.invoices[i + 1]}
selected={this.checkSelected(this.state.invoices[i + 1])}
hidden={false} index={i + 1} click={this.click}/>
</Col>
</Row>)
} else {
cards.push(
<Row gutter={18} key={i}>
<Col span={8}>
<InvoiceCheckboxCard invoice={this.state.invoices[i]}
selected={this.checkSelected(this.state.invoices[i])}
hidden={false} index={i}
click={this.click}/>
</Col>
<Col span={8}>
<InvoiceCheckboxCard invoice={this.state.invoices[i + 1]}
selected={this.checkSelected(this.state.invoices[i + 1])}
hidden={false} index={i + 1} click={this.click}/>
</Col>
<Col span={8}>
<InvoiceCheckboxCard invoice={this.state.invoices[i + 2]}
selected={this.checkSelected(this.state.invoices[i + 2])}
hidden={false} index={i + 2} click={this.click}/>
</Col>
</Row>)
}
}
return (
<>{cards}</>
)
}
render() {
return (
<>
<Button name={"select"} onClick={() => this.pickerOpen(true)}>
{this.state.selectedInvoice === null || this.state.selectedInvoice === undefined ||
this.state.selectedInvoice.length === 0 ?
"选择" : "修改"}
</Button>
<Modal
width={1000}
open={this.state.pickerOpen}
title={this.state.pickerTitle + "选择"}
onOk={this.confirm}
onCancel={() => this.pickerOpen(false)}
destroyOnClose={true}
footer={[
<Button key="clear" type="primary" onClick={this.cancelSelect}>
</Button>,
<Button key="confirm" type="primary" onClick={this.confirm}>
</Button>
]}
>
{this.cardList()}
<Pagination pageSize={this.state.pageSize} current={this.state.currentPage}
onChange={this.changePage} total={this.state.total}/>
</Modal>
</>)
}
}
export default MultiInvoiceSelector;

View File

@ -0,0 +1,369 @@
import {Invoice} from "../../../../models/Reimbursement";
import {Button, Card, Col, Modal, Pagination, PaginationProps, Popover, Row, Tag, notification} from "antd";
import axiosInstance, {baseUrl} from "../../../../utils/axiosInstance";
import {invoiceTypeNameMap} from "../../../../models/Invoice";
import React from "react";
import {store} from "../../../../models/store";
import {ExclamationCircleOutlined} from "@ant-design/icons";
const openNotification = (hint: string) => {
notification.open({
message: hint,
duration: 1,
onClick: () => {
console.log('Notification Clicked!');
},
});
};
function InvoiceCard(props: { invoice: Invoice }) {
const invoice = props.invoice;
console.log(invoice);
return (
<Card
// hoverable
// style={{
// width: 250,
// height: 300,
// margin: 30
// }}
style={{background: "#f0f0f0"}}
cover={<img alt="thumbnail"
src={baseUrl + invoice.invoiceThumbnailUri}
width="220" height="180"/>}
>
<div style={{marginTop: -20}}>
<li style={{fontWeight: "bold", fontSize: 20}}>¥{(invoice.invoiceAmount / 100.0).toFixed(2)}</li>
<li>{invoiceTypeNameMap.get(invoice.invoiceKind)}</li>
{(invoice.invoiceDeparture !== null && invoice.invoiceDestination !== null &&
<li>{invoice.invoiceDeparture}{" → "}
{invoice.invoiceDestination}</li>)}
<li>{invoice.invoiceDate}</li>
</div>
</Card>
)
}
class InvoiceRadioCard extends React.Component<any, any> {
constructor(props: {
invoice: any;
hidden: boolean;
selected: number;
index: number;
click: any;
}) {
super(props);
this.state = {
invoice: props.invoice,
hidden: props.hidden,
selected: props.selected,
index: props.index,
click: props.click,
}
}
static getDerivedStateFromProps(props: {
invoice: any;
hidden: boolean;
selected: number;
index: number;
}) {
return {
invoice: props.invoice,
hidden: props.hidden,
selected: props.selected,
index: props.index,
}
}
select(e: any) {
if (this.state.selected !== 0)
return
this.setState({selected: 1})
this.props.click(this.props.invoice, true)
}
getTag = () => {
if (this.state.selected === 1)
return <Popover content={"已选作报销凭证"}><Tag color="blue"></Tag></Popover>
else if (this.state.selected === 0)
return <Popover content={"可用于报销"}><Tag color="green"></Tag></Popover>
else if (this.state.selected === -1)
return <Popover content={"早于出发日期"}><Tag color="red"></Tag></Popover>
else if (this.state.selected === -2)
return <Popover content={"晚于返程日期"}><Tag color="red"></Tag></Popover>
else if (this.state.selected === -3)
return <Popover content={"已作其他用途"}><Tag color="red"></Tag></Popover>
}
render() {
return (
<Card hidden={this.state.hidden}
hoverable={true}
style={{
marginBottom: 30, background: (this.state.selected === 1 ? "lightskyblue" : "#f0f0f0"),
opacity: (this.state.selected >= 0 ? 1 : 0.7)
}}
onClick={(e) => {
this.select(e)
}}
cover={<img alt="thumbnail"
src={baseUrl + this.state.invoice.invoiceThumbnailUri}
width="300" height="120"/>}
// actions={[<Radio checked={this.state.selected} onClick={(e) => {
// this.select(e)
// }} defaultChecked={this.state.selected}/>]}
>
<div style={{marginTop: -20, height: 80}}>
<li style={{
fontWeight: "bold",
fontSize: 18
}}>¥{(this.state.invoice.invoiceAmount / 100.0).toFixed(2)}
{this.getTag()}
</li>
<li>{invoiceTypeNameMap.get(this.state.invoice.invoiceKind)}</li>
{(this.state.invoice.invoiceDeparture !== null && this.state.invoice.invoiceDestination !== null &&
<li>{this.state.invoice.invoiceDeparture}{" → "}
{this.state.invoice.invoiceDestination}</li>)}
<li>{this.state.invoice.invoiceDate}</li>
</div>
</Card>
)
}
}
class SingleInvoiceSelector extends React.Component<any, any> {
value: any
onChange: any
availableInvoiceKinds = [0, 2, 5, 9, 10, 13]
constructor(props: {
disabled: boolean;
pickerOpen: boolean;
pickerTitle: string;
value: any;
onChange: any;
after: number;
before: number;
occupiedInvoices: Invoice[];
}) {
super(props);
this.value = props.value
this.onChange = props.onChange
this.state = {
disabled: props.disabled,
occupiedInvoices: props.occupiedInvoices,
selectedInvoice: {},
singleLimit: true,
invoices: [],
pickerOpen: props.pickerOpen,
pickerTitle: props.pickerTitle,
currentPage: 1,
pageSize: 6,
total: 0,
after: props.after,
before: props.before,
searchOptions: {
invoiceNote: "",
invoiceDateStart: 0,
invoiceDateEnd: 0,
invoiceKind: -1,
}
}
this.requestInvoices(1, this.state.searchOptions)
}
requestInvoices(page: number, searchOptions: any) {
let params: any = {
pageNum: page - 1,
pageSize: this.state.pageSize,
invoiceUploaderId: store.getState().token.staffId,
invoiceStatus: 0,
sortBy: "invoiceDate",
asc: true,
}
if (searchOptions.invoiceNote !== "") {
params.invoiceNote = searchOptions.invoiceNote
}
if (searchOptions.invoiceDateStart !== 0) {
params.invoiceDateStart = searchOptions.invoiceDateStart
}
if (searchOptions.invoiceDateEnd !== 0) {
params.invoiceDateEnd = searchOptions.invoiceDateEnd
}
if (searchOptions.invoiceKind !== -1) {
params.invoiceKinds = searchOptions.invoiceKind
} else {
params.invoiceKinds = "0,2,5,9,10,13"
}
console.log(params)
axiosInstance.get('common/invoice', {params: params}).then(response => {
this.setState({
total: response.data.total, invoices: response.data.records,
currentPage: page, searchOptions: searchOptions
})
}).catch(error => {
console.log(error)
})
}
setSearchOptions = (options: any) => {
this.setState({searchOptions: options})
}
invoiceCard = () => {
if (this.state.selectedInvoice.invoiceId === null || this.state.selectedInvoice.invoiceId === undefined) {
return (<>{this.state.pickerTitle}</>)
}
return (<InvoiceCard invoice={this.state.selectedInvoice}/>)
}
pickerOpen = (value: boolean) => {
if (this.state.disabled) {
openNotification("请先选择出发票据")
} else {
this.setState({pickerOpen: value})
}
}
confirm = () => {
this.setState({pickerOpen: false})
}
cancelSelect = () => {
this.onChange(undefined)
this.setState({selectedInvoice: {}})
}
click = (invoice: any, status: boolean) => {
if (status) {
this.setState({selectedInvoice: invoice})
this.onChange(invoice)
}
}
static getDerivedStateFromProps(nextProps: any, prevState: any) {
return {
after: nextProps.after,
before: nextProps.before,
occupiedInvoices: nextProps.occupiedInvoices,
disabled: nextProps.disabled,
}
}
changePage: PaginationProps['onChange'] = (page) => {
console.log(this.state.ocuppiedInvoices)
this.requestInvoices(page, this.state.searchOptions)
};
checkSelected = (invoice: Invoice) => {
for (let i = 0; i < this.state.occupiedInvoices.length; i++) {
if (this.state.occupiedInvoices[i].invoiceId === invoice.invoiceId) {
return -3
}
}
if (this.state.after !== 0 && this.state.after > Number(Date.parse(invoice.invoiceDate)))
return -1
if (this.state.before !== 0 && this.state.before < Number(Date.parse(invoice.invoiceDate)))
return -2
if (this.state.selectedInvoice.invoiceId === invoice.invoiceId)
return 1
return 0
}
cardList = () => {
let cards = []
const maxSize = Math.min(this.state.pageSize, this.state.invoices.length)
for (let i = 0; i < maxSize; i += 3) {
if (i + 1 >= this.state.invoices.length) {
cards.push(
<Row gutter={18} key={i}>
<Col span={8}>
<InvoiceRadioCard invoice={this.state.invoices[i]}
selected={this.checkSelected(this.state.invoices[i])}
hidden={false} index={i}
click={this.click}/>
</Col>
</Row>)
} else if (i + 2 >= this.state.invoices.length) {
cards.push(
<Row gutter={18} key={i}>
<Col span={8}>
<InvoiceRadioCard invoice={this.state.invoices[i]}
selected={this.checkSelected(this.state.invoices[i])}
hidden={false} index={i}
click={this.click}/>
</Col>
<Col span={8}>
<InvoiceRadioCard invoice={this.state.invoices[i + 1]}
selected={this.checkSelected(this.state.invoices[i + 1])}
hidden={false} index={i + 1} click={this.click}/>
</Col>
</Row>)
} else {
cards.push(
<Row gutter={18} key={i}>
<Col span={8}>
<InvoiceRadioCard invoice={this.state.invoices[i]}
selected={this.checkSelected(this.state.invoices[i])}
hidden={false} index={i}
click={this.click}/>
</Col>
<Col span={8}>
<InvoiceRadioCard invoice={this.state.invoices[i + 1]}
selected={this.checkSelected(this.state.invoices[i + 1])}
hidden={false} index={i + 1} click={this.click}/>
</Col>
<Col span={8}>
<InvoiceRadioCard invoice={this.state.invoices[i + 2]}
selected={this.checkSelected(this.state.invoices[i + 2])}
hidden={false} index={i + 2} click={this.click}/>
</Col>
</Row>)
}
}
return (
<>{cards}</>
)
}
render() {
return (
<>
<Button name={"select"} onClick={() => this.pickerOpen(true)}>
{this.state.selectedInvoice.invoiceId === null || this.state.selectedInvoice.invoiceId === undefined ?
"选择" : "修改"}
</Button>
<Popover
content={this.invoiceCard}>
<ExclamationCircleOutlined style={{marginLeft: 5}}/>
</Popover>
<Modal
width={1000}
open={this.state.pickerOpen}
title={this.state.pickerTitle + "选择"}
onOk={this.confirm}
onCancel={() => this.pickerOpen(false)}
destroyOnClose={true}
footer={[
<Button key="clear" type="primary" onClick={this.cancelSelect}>
</Button>,
<Button key="confirm" type="primary" onClick={this.confirm}>
</Button>
]}
>
{this.cardList()}
<Pagination pageSize={this.state.pageSize} current={this.state.currentPage}
onChange={this.changePage} total={this.state.total}/>
</Modal>
</>)
}
}
export default SingleInvoiceSelector