继续报销

main
白封羽 2023-01-01 22:30:39 +08:00
parent d313886764
commit a322dbadda
2 changed files with 292 additions and 129 deletions

View File

@ -71,6 +71,7 @@ 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 = {
@ -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"
@ -336,7 +347,8 @@ class Subpage extends React.Component<any, any> {
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> </Button>
</div> </div>

View File

@ -1,39 +1,68 @@
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,
Card,
Col,
Form,
Input,
InputNumber,
Modal,
Pagination,
PaginationProps,
Popover,
Radio,
Row,
Select, Tag
} 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";
function InvoiceCard(props: { invoice: Invoice }) { function InvoiceCard(props: { invoice: Invoice }) {
const invoice = props.invoice; const invoice = props.invoice;
console.log(invoice);
return ( return (
<Card <Card
style={{width: 300}} // hoverable
cover={ // style={{
<img // width: 250,
alt="example" // height: 300,
src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png" // 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> </Card>
) )
} }
class InvoiceRadioCard extends React.Component<any, any> { class InvoiceRadioCard extends React.Component<any, any> {
constructor(props: { constructor(props: {
invoice: any; invoice: any;
hidden: boolean; hidden: boolean;
selected: boolean; selected: boolean;
index: number; index: number;
click: any; click: any;
afterDay: number | null;
}) { }) {
super(props); super(props);
this.state = { this.state = {
@ -41,7 +70,8 @@ class InvoiceRadioCard extends React.Component<any, any> {
hidden: props.hidden, hidden: props.hidden,
selected: props.selected, selected: props.selected,
index: props.index, index: props.index,
click: props.click click: props.click,
afterDay: props.afterDay,
} }
} }
@ -50,32 +80,63 @@ class InvoiceRadioCard extends React.Component<any, any> {
hidden: boolean; hidden: boolean;
selected: boolean; selected: boolean;
index: number; index: number;
click: any; afterDay: number | null;
}) { }) {
console.log(props);
return { return {
invoice: props.invoice, invoice: props.invoice,
hidden: props.hidden, hidden: props.hidden,
selected: props.selected, selected: props.selected,
index: props.index, index: props.index,
click: props.click afterDay: props.afterDay,
} }
} }
select(e: any) { select(e: any) {
console.log(this.state.afterDay, Number(new Date(this.state.invoice.invoiceDate)))
if (this.state.afterDay !== null && this.state.afterDay > Number(new Date(this.state.invoice.invoiceDate)))
return
if (this.state.selected) if (this.state.selected)
return return
this.setState({selected: true}) this.setState({selected: true})
this.props.click(this.props.index, true) this.props.click(this.props.invoice, true)
} }
render() { render() {
return ( return (
<Card hidden={this.state.hidden} <Card hidden={this.state.hidden}
cover={<img alt="example" src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"/>} hoverable={true}
actions={[<Radio checked={this.state.selected} onClick={(e) => { style={{marginBottom: 30, background: this.state.selected ? "lightskyblue" : "#f0f0f0"}}
onClick={(e) => {
this.select(e) this.select(e)
}} defaultChecked={this.state.selected}/>]}> }}
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.state.afterDay !== null && this.state.afterDay > Number(new Date(this.state.invoice.invoiceDate)) &&
<Popover content={"该票据日期早于出发日期"}>
<Tag color="#f50"></Tag>
</Popover>
)}
</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> </Card>
) )
} }
@ -84,27 +145,89 @@ class InvoiceRadioCard extends React.Component<any, any> {
class SingleInvoiceSelector extends React.Component<any, any> { class SingleInvoiceSelector extends React.Component<any, any> {
value: any value: any
onChange: any onChange: any
availableInvoiceKinds = [0, 2, 5, 9, 10, 13]
constructor(props: { constructor(props: {
disabled: boolean;
pickerOpen: boolean; pickerOpen: boolean;
pickerTitle: string; pickerTitle: string;
value: any; value: any;
onChange: any; onChange: any;
afterDay: number | null;
occupiedInvoices: Invoice[];
}) { }) {
super(props); super(props);
this.value = props.value this.value = props.value
this.onChange = props.onChange this.onChange = props.onChange
this.state = { this.state = {
selectedIndex: -1, disabled: props.disabled,
occupiedInvoices: props.occupiedInvoices,
afterDay: props.afterDay,
selectedInvoice: {}, selectedInvoice: {},
singleLimit: true, singleLimit: true,
invoices: [{invoiceId:1},{invoiceId:2},{invoiceId:3}], invoices: [],
pickerOpen: props.pickerOpen, pickerOpen: props.pickerOpen,
pickerTitle: props.pickerTitle pickerTitle: props.pickerTitle,
currentPage: 1,
pageSize: 4,
total: 0,
searchOptions: {
invoiceNote: "",
invoiceDateStart: 0,
invoiceDateEnd: 0,
invoiceKind: -1,
} }
}
this.requestInvoices(1, this.state.searchOptions)
}
static getDerivedStateFromProps(props: {
afterDay: number | null;
disabled: boolean;
}) {
console.log(props.afterDay);
return {
disabled: props.disabled,
afterDay: props.afterDay,
}
}
requestInvoices(page: number, searchOptions: any) {
let params: any = {
pageNum: page - 1,
pageSize: this.state.pageSize,
invoiceUploaderId: store.getState().token.staffId,
invoiceStatus: 0,
}
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 = () => { invoiceCard = () => {
if (this.state.selectedInvoice.invoiceId === null || this.state.selectedInvoice.invoiceId === undefined) { if (this.state.selectedInvoice.invoiceId === null || this.state.selectedInvoice.invoiceId === undefined) {
return (<>{this.state.pickerTitle}</>) return (<>{this.state.pickerTitle}</>)
@ -112,44 +235,58 @@ class SingleInvoiceSelector extends React.Component<any, any> {
return (<InvoiceCard invoice={this.state.selectedInvoice}/>) return (<InvoiceCard invoice={this.state.selectedInvoice}/>)
} }
pickerOpen = (value: boolean) => { pickerOpen = (value: boolean) => {
if(this.state.disabled){
alert("请先选择出发票据")
}else{
this.setState({pickerOpen: value}) this.setState({pickerOpen: value})
} }
}
confirm = () => { confirm = () => {
this.setState({pickerOpen: false}) this.setState({pickerOpen: false})
} }
cancelSelect = () => { cancelSelect = () => {
this.onChange({}) this.onChange(undefined)
this.setState({selectedIndex: -1, selectedInvoice: {}}) this.setState({selectedInvoice: {}})
} }
click = (index: number, status: boolean) => { click = (invoice: any, status: boolean) => {
if (status) { if (status) {
this.setState({selectedIndex: index, selectedInvoice: this.state.invoices[index]}) this.setState({selectedInvoice: invoice})
this.onChange({invoice: this.state.invoices[index]}) this.onChange(invoice)
} }
} }
changePage: PaginationProps['onChange'] = (page) => {
this.requestInvoices(page, this.state.searchOptions)
};
cardList = () => { cardList = () => {
let cards = [] let cards = []
for (let i = 0; i < this.state.invoices.length; i += 2) { const maxSize = Math.min(4, this.state.invoices.length)
for (let i = 0; i < maxSize; i += 2) {
if (i + 1 >= this.state.invoices.length) { if (i + 1 >= this.state.invoices.length) {
cards.push( cards.push(
<Row gutter={18}> <Row gutter={18} key={i}>
<Col span={12}> <Col span={12}>
<InvoiceRadioCard invoice={this.state.invoices[i]} selected={this.state.selectedIndex === i} <InvoiceRadioCard invoice={this.state.invoices[i]}
hidden={false} index={i} click={this.click}/> selected={this.state.selectedInvoice.invoiceId === this.state.invoices[i].invoiceId}
afterDay={this.state.afterDay}
hidden={false} index={i}
click={this.click}/>
</Col> </Col>
</Row>) </Row>)
} else { } else {
cards.push( cards.push(
<Row gutter={18}> <Row gutter={18} key={i}>
<Col span={12}> <Col span={12}>
<InvoiceRadioCard invoice={this.state.invoices[i]} selected={this.state.selectedIndex === i} <InvoiceRadioCard invoice={this.state.invoices[i]}
hidden={false} index={i} click={this.click}/> selected={this.state.selectedInvoice.invoiceId === this.state.invoices[i].invoiceId}
afterDay={this.state.afterDay} hidden={false} index={i}
click={this.click}/>
</Col> </Col>
<Col span={12}> <Col span={12}>
<InvoiceRadioCard invoice={this.state.invoices[i + 1]} <InvoiceRadioCard invoice={this.state.invoices[i + 1]}
selected={this.state.selectedIndex === i + 1} afterDay={this.state.afterDay}
selected={this.state.selectedInvoice.invoiceId === this.state.invoices[i + 1].invoiceId}
hidden={false} index={i + 1} click={this.click}/> hidden={false} index={i + 1} click={this.click}/>
</Col> </Col>
</Row>) </Row>)
@ -163,9 +300,13 @@ class SingleInvoiceSelector extends React.Component<any, any> {
render() { render() {
return ( return (
<> <>
<Button name={"select"} onClick={() => this.pickerOpen(true)}> <Button name={"select"} onClick={() => this.pickerOpen(true)}>
{this.state.selectedInvoice.invoiceId === null || this.state.selectedInvoice.invoiceId === undefined ?
"选择" : "修改"}
</Button> </Button>
<Popover <Popover
content={this.invoiceCard}> content={this.invoiceCard}>
<ExclamationCircleOutlined style={{marginLeft: 5}}/> <ExclamationCircleOutlined style={{marginLeft: 5}}/>
@ -187,6 +328,8 @@ class SingleInvoiceSelector extends React.Component<any, any> {
> >
{this.cardList()} {this.cardList()}
<Pagination pageSize={this.state.pageSize} current={this.state.currentPage}
onChange={this.changePage} total={this.state.total}/>
</Modal> </Modal>
</>) </>)
} }
@ -232,21 +375,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) => {
@ -272,18 +408,28 @@ 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)
state["duration"] = 0
} else { } else {
this.setState({back: false, duration: 0}) state['back'] = false
this.formRef.current?.setFieldValue('duration', 0) 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)
} }
render() { render() {
@ -300,7 +446,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 +470,19 @@ 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}
afterDay={null} disabled={false}
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)&&
(this.state.destinationInvoice == undefined ||this.state.destinationInvoice == null)}
pickerTitle={"返程票据"} ref={this.invoiceSelector2}
afterDay={this.state.departureInvoice == null || this.state.departureInvoice.invoiceDate == null ?
null : Number(Date.parse(this.state.departureInvoice.invoiceDate))}/>
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>