继续报销

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

View File

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

View File

@ -1,39 +1,68 @@
import React, {Key, ReactNode} from "react";
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 {Invoice} from "../../../models/Reimbursement";
import axiosInstance from "../../../utils/axiosInstance";
import axiosInstance, {baseUrl} from "../../../utils/axiosInstance";
import Column from "antd/es/table/Column";
import type {MenuProps} from 'antd';
import {ExclamationCircleOutlined, UserOutlined} from "@ant-design/icons";
import {Dropdown, message, Space, Tooltip} from 'antd';
import {store} from "../../../models/store";
import {FieldData} from "rc-field-form/lib/interface";
import {invoiceTypeNameMap} from "../../../models/Invoice";
function InvoiceCard(props: { invoice: Invoice }) {
const invoice = props.invoice;
console.log(invoice);
return (
<Card
style={{width: 300}}
cover={
<img
alt="example"
src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
/>
}
// 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: boolean;
index: number;
click: any;
afterDay: number | null;
}) {
super(props);
this.state = {
@ -41,7 +70,8 @@ class InvoiceRadioCard extends React.Component<any, any> {
hidden: props.hidden,
selected: props.selected,
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;
selected: boolean;
index: number;
click: any;
afterDay: number | null;
}) {
console.log(props);
return {
invoice: props.invoice,
hidden: props.hidden,
selected: props.selected,
index: props.index,
click: props.click
afterDay: props.afterDay,
}
}
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)
return
this.setState({selected: true})
this.props.click(this.props.index, true)
this.props.click(this.props.invoice, 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) => {
hoverable={true}
style={{marginBottom: 30, background: this.state.selected ? "lightskyblue" : "#f0f0f0"}}
onClick={(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>
)
}
@ -84,27 +145,89 @@ class InvoiceRadioCard extends React.Component<any, any> {
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;
afterDay: number | null;
occupiedInvoices: Invoice[];
}) {
super(props);
this.value = props.value
this.onChange = props.onChange
this.state = {
selectedIndex: -1,
disabled: props.disabled,
occupiedInvoices: props.occupiedInvoices,
afterDay: props.afterDay,
selectedInvoice: {},
singleLimit: true,
invoices: [{invoiceId:1},{invoiceId:2},{invoiceId:3}],
invoices: [],
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 = () => {
if (this.state.selectedInvoice.invoiceId === null || this.state.selectedInvoice.invoiceId === undefined) {
return (<>{this.state.pickerTitle}</>)
@ -112,44 +235,58 @@ class SingleInvoiceSelector extends React.Component<any, any> {
return (<InvoiceCard invoice={this.state.selectedInvoice}/>)
}
pickerOpen = (value: boolean) => {
this.setState({pickerOpen: value})
if(this.state.disabled){
alert("请先选择出发票据")
}else{
this.setState({pickerOpen: value})
}
}
confirm = () => {
this.setState({pickerOpen: false})
}
cancelSelect = () => {
this.onChange({})
this.setState({selectedIndex: -1, selectedInvoice: {}})
this.onChange(undefined)
this.setState({selectedInvoice: {}})
}
click = (index: number, status: boolean) => {
click = (invoice: any, status: boolean) => {
if (status) {
this.setState({selectedIndex: index, selectedInvoice: this.state.invoices[index]})
this.onChange({invoice: this.state.invoices[index]})
this.setState({selectedInvoice: invoice})
this.onChange(invoice)
}
}
changePage: PaginationProps['onChange'] = (page) => {
this.requestInvoices(page, this.state.searchOptions)
};
cardList = () => {
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) {
cards.push(
<Row gutter={18}>
<Row gutter={18} key={i}>
<Col span={12}>
<InvoiceRadioCard invoice={this.state.invoices[i]} selected={this.state.selectedIndex === i}
hidden={false} index={i} click={this.click}/>
<InvoiceRadioCard invoice={this.state.invoices[i]}
selected={this.state.selectedInvoice.invoiceId === this.state.invoices[i].invoiceId}
afterDay={this.state.afterDay}
hidden={false} index={i}
click={this.click}/>
</Col>
</Row>)
} else {
cards.push(
<Row gutter={18}>
<Row gutter={18} key={i}>
<Col span={12}>
<InvoiceRadioCard invoice={this.state.invoices[i]} selected={this.state.selectedIndex === i}
hidden={false} index={i} click={this.click}/>
<InvoiceRadioCard invoice={this.state.invoices[i]}
selected={this.state.selectedInvoice.invoiceId === this.state.invoices[i].invoiceId}
afterDay={this.state.afterDay} hidden={false} index={i}
click={this.click}/>
</Col>
<Col span={12}>
<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}/>
</Col>
</Row>)
@ -163,9 +300,13 @@ class SingleInvoiceSelector extends React.Component<any, any> {
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}}/>
@ -187,6 +328,8 @@ class SingleInvoiceSelector extends React.Component<any, any> {
>
{this.cardList()}
<Pagination pageSize={this.state.pageSize} current={this.state.currentPage}
onChange={this.changePage} total={this.state.total}/>
</Modal>
</>)
}
@ -232,21 +375,14 @@ class ReimbursementCreate extends React.Component<any, any> {
},
back: false,
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) => {
@ -272,18 +408,28 @@ class ReimbursementCreate extends React.Component<any, any> {
value = 0
this.setState({duration: value})
}
formFieldsChange = (changedFields: any, allFields: any) => {
let start = allFields['departureInvoiceId']
let end = allFields['destinationInvoiceId']
if (start !== undefined && end !== undefined && start.invoiceDate !== undefined && end.invoiceDate !== undefined) {
let x = Math.floor((Date.parse(end.invoiceDate) - Date.parse(start.invoiceDate)) / 24 / 60 / 60 / 1000) + 1
this.setState({back: true, duration: x})
this.formRef.current?.setFieldValue('duration', x)
}else{
this.setState({back: false, duration: 0})
this.formRef.current?.setFieldValue('duration', 0)
formValuesChange = (changedValues: any, allValues: any) => {
let state: any = {}
console.log(allValues)
if (allValues.departureInvoice !== undefined && allValues.departureInvoice !== null && allValues.destinationInvoice !== undefined && allValues.destinationInvoice !== null) {
state['back'] = true
state["duration"] = (Number(Date.parse(allValues.destinationInvoice.invoiceDate)) - Number(Date.parse(allValues.departureInvoice.invoiceDate))) / 1000 / 60 / 60 / 24 + 1
if (state["duration"] < 0)
state["duration"] = 0
} else {
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)
}
render() {
@ -300,7 +446,7 @@ class ReimbursementCreate extends React.Component<any, any> {
</Button>]}
>
<Form ref={this.formRef} onFieldsChange={this.formFieldsChange}
<Form ref={this.formRef} onValuesChange={this.formValuesChange}
initialValues={{
departmentId: this.state.selectedDepartment.id,
destinationName: '',
@ -324,14 +470,19 @@ class ReimbursementCreate extends React.Component<any, any> {
<Row gutter={18}>
<Col span={12}>
<Form.Item help="" label="出发票据" name="departureInvoice" rules={[{required: true}]}>
<SingleInvoiceSelector invoices={[]} pickerOpen={false}
<SingleInvoiceSelector pickerOpen={false}
afterDay={null} disabled={false}
pickerTitle={"出发票据"} ref={this.invoiceSelector1}/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="返程票据" name="destinationInvoice" rules={[{required: false}]}>
<SingleInvoiceSelector invoices={[]} pickerOpen={false}
pickerTitle={"返程票据"} ref={this.invoiceSelector2}/>
<SingleInvoiceSelector pickerOpen={false}
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>
</Col>
</Row>