Compare commits
144 Commits
perf/expor
...
main
Author | SHA1 | Date |
---|---|---|
|
cf47dd44a8 | 5 days ago |
|
40ca0bdf8d | 5 days ago |
|
87d1e0d3ae | 5 days ago |
|
5694081269 | 5 days ago |
|
2b01fc01ea | 1 week ago |
|
1e3e9b9942 | 1 week ago |
|
534dd60140 | 1 week ago |
|
0a6a630441 | 1 week ago |
|
7e135f349e | 2 weeks ago |
|
894f6e8173 | 3 weeks ago |
|
b845280151 | 1 month ago |
|
4174f33f08 | 1 month ago |
|
093fb9833a | 2 months ago |
|
eda2b2ac2d | 2 months ago |
|
7acc8a91d7 | 2 months ago |
|
062b6e21ee | 2 months ago |
|
f79b4d4caa | 2 months ago |
|
660bec8594 | 2 months ago |
|
d803964131 | 3 months ago |
|
80f9bb1b48 | 3 months ago |
|
f2f8f0216e | 5 months ago |
|
1fd49cd587 | 5 months ago |
|
102774dd64 | 5 months ago |
|
7d4b4d3546 | 6 months ago |
|
0602962a83 | 6 months ago |
|
115f913c7f | 7 months ago |
|
813258881f | 7 months ago |
|
9adf82de12 | 7 months ago |
|
e963322eb0 | 7 months ago |
|
f2b344cae9 | 7 months ago |
|
581d9d1b20 | 7 months ago |
|
563a744629 | 7 months ago |
|
b7f3f2ae14 | 7 months ago |
|
09755c3665 | 7 months ago |
|
0bf5d43599 | 7 months ago |
|
a35b7cf037 | 7 months ago |
|
48acdad5b7 | 7 months ago |
|
87e7c0acc4 | 7 months ago |
|
7b15478640 | 7 months ago |
|
1f85a341f6 | 7 months ago |
|
78834f8f11 | 7 months ago |
|
df1eae2b86 | 8 months ago |
|
fc494b57fc | 8 months ago |
|
b2df11beb3 | 8 months ago |
|
a2ce2534b6 | 8 months ago |
|
be3aea599b | 8 months ago |
|
4b2669227e | 8 months ago |
|
503547de78 | 8 months ago |
|
202ba82042 | 8 months ago |
|
be0b3d2766 | 8 months ago |
|
0f50b5b482 | 8 months ago |
|
2f7e8a9f0f | 8 months ago |
|
9a80374e24 | 8 months ago |
|
aee8f94b40 | 9 months ago |
|
2d3d23e10f | 9 months ago |
|
e4093fcce7 | 9 months ago |
|
e462485057 | 9 months ago |
|
46235a43ac | 9 months ago |
|
575e792481 | 9 months ago |
|
8330244008 | 9 months ago |
|
a7b0c870de | 9 months ago |
|
aa3b055276 | 9 months ago |
|
4baf742268 | 9 months ago |
|
b82c7ef7cb | 9 months ago |
|
43fc1e5e2d | 9 months ago |
|
324d8c0674 | 9 months ago |
|
9c3cdd6ea6 | 9 months ago |
|
001ce6740d | 9 months ago |
|
c29c970c4e | 9 months ago |
|
efd576f487 | 9 months ago |
|
65cfb289a2 | 9 months ago |
|
7917786e9b | 9 months ago |
|
1dd04972c6 | 9 months ago |
|
09d8d99059 | 9 months ago |
|
cbd7bbc8e1 | 9 months ago |
|
e5a0342d7b | 9 months ago |
|
7296ed954c | 9 months ago |
|
0de97b9ea8 | 9 months ago |
|
7ccc775791 | 9 months ago |
|
9d789723a8 | 9 months ago |
|
bb4eca48f6 | 9 months ago |
|
fb48ac668f | 10 months ago |
|
171a5f94c4 | 10 months ago |
|
59427a1a3a | 10 months ago |
|
ef8046d1ae | 10 months ago |
|
024f066075 | 10 months ago |
|
f37e5302a1 | 10 months ago |
|
c28d68960e | 10 months ago |
|
0ad7f3a470 | 10 months ago |
|
eb410adeb5 | 10 months ago |
|
c88adc4b5e | 10 months ago |
|
ad81a60d55 | 10 months ago |
|
5aa4d1766d | 10 months ago |
|
a7954e1114 | 10 months ago |
|
bde0e82ece | 10 months ago |
|
ec2e499abf | 10 months ago |
|
0af62c2e39 | 10 months ago |
|
8c16e0503e | 10 months ago |
|
7c3bfdfefe | 10 months ago |
|
6b396633cb | 10 months ago |
|
b439abba39 | 10 months ago |
|
1407d05f43 | 10 months ago |
|
c6283f0cc2 | 10 months ago |
|
e66597d4fa | 10 months ago |
|
5d56479f35 | 10 months ago |
|
df1a1f43bf | 10 months ago |
|
3bf491d8ad | 10 months ago |
|
f182ded513 | 10 months ago |
|
78793d3ddf | 10 months ago |
|
4dca7ee290 | 10 months ago |
|
0cc9a0bb17 | 10 months ago |
|
596dcbd5b0 | 10 months ago |
|
6cb61a850a | 10 months ago |
|
2e535eedfb | 10 months ago |
|
903efaead2 | 10 months ago |
|
65f2b996aa | 10 months ago |
|
592d396d78 | 10 months ago |
|
741e2e17d4 | 10 months ago |
|
fc78bd3e58 | 10 months ago |
|
ab82ef8d17 | 10 months ago |
|
9054538ce3 | 10 months ago |
|
d0af7acae3 | 10 months ago |
|
9ebab45035 | 10 months ago |
|
0dd8cc7a69 | 10 months ago |
|
7593637786 | 10 months ago |
|
945a1a7a17 | 10 months ago |
|
7d4b7bbba1 | 10 months ago |
|
c5343dd4b2 | 10 months ago |
|
4671179614 | 10 months ago |
|
ff8c072e07 | 10 months ago |
|
d33cbc625b | 10 months ago |
|
4c1855d65b | 10 months ago |
|
5a4a3f0214 | 10 months ago |
|
93cf0e5c5e | 10 months ago |
|
0bb1f24977 | 10 months ago |
|
4951196018 | 10 months ago |
|
3a63b11b3d | 10 months ago |
|
aba7c69a86 | 10 months ago |
|
e3f8262cff | 10 months ago |
|
fe58f01f22 | 10 months ago |
|
7045af0881 | 10 months ago |
|
1f574acab3 | 10 months ago |
|
df64cc306a | 10 months ago |
|
866433419c | 10 months ago |
@ -0,0 +1 @@
|
|||||||
|
npm version patch
|
Binary file not shown.
@ -0,0 +1,94 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { Tag, Button, message } from 'antd';
|
||||||
|
import { CaretUpOutlined, CaretDownOutlined, DownloadOutlined } from '@ant-design/icons';
|
||||||
|
import { utils, writeFile } from "xlsx";
|
||||||
|
import { isEmpty, getNestedValue } from "../utils/commons";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property diffPercent
|
||||||
|
* @property diffData
|
||||||
|
* @property data1
|
||||||
|
* @property data2
|
||||||
|
*/
|
||||||
|
export const VSTag = (props) => {
|
||||||
|
const { diffPercent, diffData, data1, data2 } = props;
|
||||||
|
const CaretIcon = parseInt(diffPercent) < 0 ? CaretDownOutlined : CaretUpOutlined;
|
||||||
|
const tagColor = parseInt(diffPercent) < 0 ? 'gold' : 'lime';
|
||||||
|
return parseInt(diffPercent) === 0 ? (
|
||||||
|
'-'
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
{/* <div>
|
||||||
|
{data1} vs {data2}
|
||||||
|
</div> */}
|
||||||
|
<Tag icon={<CaretIcon />} color={tagColor}>
|
||||||
|
{diffPercent}<span>%</span>{' '}<span>{diffData}</span>
|
||||||
|
</Tag>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出表格数据存为xlsx
|
||||||
|
*/
|
||||||
|
export const TableExportBtn = (props) => {
|
||||||
|
const output_name = `${props.label}`;
|
||||||
|
const [columnsMap, setColumnsMap] = useState([]);
|
||||||
|
const [summaryRow, setSummaryRow] = useState({});
|
||||||
|
useEffect(() => {
|
||||||
|
const r1 = props.columns.reduce((r, v) => ({
|
||||||
|
...r,
|
||||||
|
...(v.children ? v.children.reduce((rc, vc, ci) => ({
|
||||||
|
...rc,
|
||||||
|
...(vc?.titleX ? {[`${v?.titleX || v.title},${vc.titleX}`]: vc.titleX } : {[(v?.titleX || v.title) + (ci || '')]: `${vc?.titleX || vc?.title || ''}`}),
|
||||||
|
}), {}) : {})
|
||||||
|
}), {});
|
||||||
|
const flatCols = props.columns.flatMap((v, k) =>
|
||||||
|
v.children ? v.children.map((vc, ci) => ({ ...vc, title: `${v?.titleX || v.title}` + (vc?.titleX ? `,${vc.titleX}` : (ci || '')) })) : {...v, title: `${v?.titleX || v.title}`}
|
||||||
|
);
|
||||||
|
// .filter((c) => c.dataIndex)
|
||||||
|
// !['string', 'number'].includes(typeof vc.title) ? `${v?.titleX || v.title}` : `${v?.titleX || v.title}-${vc.title || ''}`
|
||||||
|
;
|
||||||
|
setColumnsMap(flatCols);
|
||||||
|
// console.log('flatCols', flatCols);
|
||||||
|
|
||||||
|
setSummaryRow(r1);
|
||||||
|
// console.log('summaryRow', r1);
|
||||||
|
|
||||||
|
return () => {};
|
||||||
|
}, [props.columns]);
|
||||||
|
|
||||||
|
const onExport = () => {
|
||||||
|
if (isEmpty(props.dataSource)) {
|
||||||
|
message.warning('无结果.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const data = props.dataSource.map((item) => {
|
||||||
|
const itemMapped = columnsMap.reduce((sv, kset) => {
|
||||||
|
const render_val = typeof kset?.render === 'function' ? kset.render('', item) : null;
|
||||||
|
const data_val = kset?.dataIndex ? (Array.isArray(kset.dataIndex) ? getNestedValue(item, kset.dataIndex) : item[kset.dataIndex]) : undefined;
|
||||||
|
const x_val = item[`${kset.dataIndex}_X`];
|
||||||
|
// const _title = kset.title.replace('-[object Object]', '');
|
||||||
|
const v = { [kset.title]: x_val || data_val || render_val };
|
||||||
|
return { ...sv, ...v };
|
||||||
|
}, {});
|
||||||
|
return itemMapped;
|
||||||
|
});
|
||||||
|
const ws = utils.json_to_sheet([].concat(isEmpty(summaryRow) ? [] : [summaryRow], data), { header: columnsMap.filter((r) => r.dataIndex).map((r) => r.title) });
|
||||||
|
const wb = utils.book_new();
|
||||||
|
utils.book_append_sheet(wb, ws, 'sheet');
|
||||||
|
writeFile(wb, `${output_name}.xlsx`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
icon={<DownloadOutlined />}
|
||||||
|
size="small"
|
||||||
|
disabled={false}
|
||||||
|
onClick={onExport}
|
||||||
|
>
|
||||||
|
{props.btnTxt || '导出excel'}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,137 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { Grid, Divider, Layout, Spin, Input, Col, Row, Space, Checkbox, Table, Button, App } from "antd";
|
||||||
|
import { PhoneOutlined, CustomerServiceOutlined, FrownTwoTone, LikeTwoTone } from "@ant-design/icons";
|
||||||
|
import { useParams, useHref, useNavigate, NavLink } from "react-router-dom";
|
||||||
|
import { isEmpty, formatColonTime, formatDate, isNotEmpty } from "@/utils/commons";
|
||||||
|
import { DATE_FORMAT } from "@/config";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import SearchForm from "@/components/SearchForm";
|
||||||
|
import BackBtn from "@/components/BackBtn";
|
||||||
|
import { TableExportBtn } from "@/components/Data";
|
||||||
|
import useInvoiceStore from "@/stores/Invoice";
|
||||||
|
import { fetchInvoicePaidDetail } from "@/stores/Invoice";
|
||||||
|
|
||||||
|
import airTicketStore from "@/stores/Airticket";
|
||||||
|
import { usingStorage } from "@/hooks/usingStorage";
|
||||||
|
|
||||||
|
const InvoicePaid = props => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { notification } = App.useApp();
|
||||||
|
const { travelAgencyId } = usingStorage();
|
||||||
|
const [invoicePaidDetail, setInvoicePaidDetail] = useState([]);
|
||||||
|
const [invoiceNO, setInvoiceNO] = useState([]); //显示账单编号
|
||||||
|
const [loading, invoicePaid, fetchInvoicePaid] = useInvoiceStore(state => [state.loading, state.invoicePaid, state.fetchInvoicePaid]);
|
||||||
|
const showTotal = total => `Total ${total} items`;
|
||||||
|
const showTotal_detail = total => `Total ${total} items`;
|
||||||
|
useEffect(() => {
|
||||||
|
// fetchInvoicePaid(travelAgencyId, "", dayjs().subtract(2, "M").startOf("M").format(DATE_FORMAT), dayjs().endOf("M").format(DATE_FORMAT));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const invoicePaidColumns = [
|
||||||
|
{
|
||||||
|
title: "编号",
|
||||||
|
dataIndex: "fl_finaceNo",
|
||||||
|
key: "fl_finaceNo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "报账日期",
|
||||||
|
key: "fl_adddate",
|
||||||
|
dataIndex: "fl_adddate",
|
||||||
|
render: (text, record) => (isNotEmpty(text) ? formatDate(new Date(text)) : ""),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "团数",
|
||||||
|
key: "fcount",
|
||||||
|
dataIndex: "fcount",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "总额",
|
||||||
|
key: "pSum",
|
||||||
|
dataIndex: "pSum",
|
||||||
|
//render: (text, record) => (isNotEmpty(record.GMD_Currency) ? record.GMD_Currency + " " + text : text),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "查看",
|
||||||
|
key: "pSum",
|
||||||
|
dataIndex: "pSum",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
onClick={() => {
|
||||||
|
fetchInvoicePaidDetail(travelAgencyId, record.key).then(res => setInvoicePaidDetail(res));
|
||||||
|
setInvoiceNO(record.fl_finaceNo);
|
||||||
|
}}>
|
||||||
|
查看明细
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const invoicePaidDetailColumns = [
|
||||||
|
{
|
||||||
|
title: "团号",
|
||||||
|
dataIndex: "fl2_GroupName",
|
||||||
|
key: "fl2_GroupName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "金额",
|
||||||
|
key: "fl2_price",
|
||||||
|
dataIndex: "fl2_price",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "报账日期",
|
||||||
|
key: "fl2_ArriveDate",
|
||||||
|
dataIndex: "fl2_ArriveDate",
|
||||||
|
render: (text, record) => (isNotEmpty(text) ? formatDate(new Date(text)) : ""),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "顾问",
|
||||||
|
dataIndex: "fl2_wl",
|
||||||
|
key: "fl2_wl",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space direction="vertical" style={{ width: "100%" }}>
|
||||||
|
<Row>
|
||||||
|
<Col md={20} lg={20} xxl={20}>
|
||||||
|
<SearchForm
|
||||||
|
initialValue={{
|
||||||
|
dates: [dayjs().subtract(2, "M").startOf("M"), dayjs().endOf("M")],
|
||||||
|
}}
|
||||||
|
fieldsConfig={{
|
||||||
|
shows: ["dates"],
|
||||||
|
fieldProps: {
|
||||||
|
dates: { col: 10, label: "报账日期" },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onSubmit={(err, formVal) => {
|
||||||
|
fetchInvoicePaid(travelAgencyId, "", formVal.startdate, formVal.enddate);
|
||||||
|
setInvoicePaidDetail([]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col md={4} lg={4} xxl={4}>
|
||||||
|
<BackBtn to={"/airticket"} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col md={24} lg={16} xxl={16}>
|
||||||
|
<Divider orientation="left">汇款列表</Divider>
|
||||||
|
<Table bordered columns={invoicePaidColumns} dataSource={invoicePaid} loading={loading} pagination={{ defaultPageSize: 20, showTotal: showTotal }} />
|
||||||
|
</Col>
|
||||||
|
<Col md={24} lg={4} xxl={4}></Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col md={24} lg={20} xxl={20}>
|
||||||
|
<Divider orientation="left">账单明细 {invoiceNO}</Divider>
|
||||||
|
<Table bordered columns={invoicePaidDetailColumns} dataSource={invoicePaidDetail} pagination={{ defaultPageSize: 100, showTotal: showTotal_detail }} />
|
||||||
|
<TableExportBtn btnTxt="导出账单明细" label={`机票账单`} {...{ columns: invoicePaidDetailColumns, dataSource: invoicePaidDetail }} />
|
||||||
|
</Col>
|
||||||
|
<Col md={24} lg={4} xxl={4}></Col>
|
||||||
|
</Row>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default InvoicePaid;
|
@ -0,0 +1,130 @@
|
|||||||
|
import { useParams, NavLink, useNavigate } from "react-router-dom";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Row, Col, Space, Table, Image,App } from "antd";
|
||||||
|
import { formatDate, isNotEmpty } from "@/utils/commons";
|
||||||
|
import SearchForm from "@/components/SearchForm";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import BackBtn from "@/components/BackBtn";
|
||||||
|
import { fetchInvoiceDetail } from "@/stores/Invoice";
|
||||||
|
import useInvoiceStore from "@/stores/Invoice";
|
||||||
|
import { usingStorage } from "@/hooks/usingStorage";
|
||||||
|
|
||||||
|
function History() {
|
||||||
|
const { travelAgencyId } = usingStorage();
|
||||||
|
const { GMDSN, GSN } = useParams();
|
||||||
|
const [dataLoading, setDataLoading] = useState(false);
|
||||||
|
const [invoiceZDDetail, setInvoiceZDDetail] = useState([]);
|
||||||
|
const { notification } = App.useApp();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
defaultShow();
|
||||||
|
}, [GMDSN, GSN]);
|
||||||
|
|
||||||
|
function defaultShow() {
|
||||||
|
setDataLoading(true);
|
||||||
|
|
||||||
|
fetchInvoiceDetail(travelAgencyId, GMDSN, GSN)
|
||||||
|
.then((json) => {
|
||||||
|
//console.log("id:"+travelAgencyId+",gmdsn:"+GMDSN+",GSN:"+GSN+"#13"+json);
|
||||||
|
setInvoiceZDDetail(json.invoiceZDDetail);
|
||||||
|
})
|
||||||
|
.catch((ex) => {
|
||||||
|
notification.error({
|
||||||
|
message: `Notification`,
|
||||||
|
description: ex.message,
|
||||||
|
placement: "top",
|
||||||
|
duration: 4,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setDataLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const invoicePaidColumns = [
|
||||||
|
{
|
||||||
|
title: "ID",
|
||||||
|
dataIndex: "GMD_SN",
|
||||||
|
key: "GMD_SN",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Due Date",
|
||||||
|
key: "GMD_PayDate",
|
||||||
|
dataIndex: "GMD_PayDate",
|
||||||
|
render: (text, record) =>
|
||||||
|
isNotEmpty(text) ? formatDate(new Date(text)) : "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Amount",
|
||||||
|
key: "GMD_Cost",
|
||||||
|
dataIndex: "GMD_Cost",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Currency",
|
||||||
|
key: "GMD_Currency",
|
||||||
|
dataIndex: "GMD_Currency",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Status",
|
||||||
|
key: "FKState",
|
||||||
|
dataIndex: "FKState",
|
||||||
|
render: (text, record) => (isNotEmpty(record.FKState) ? invoiceStatus(record.FKState) : text),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Invoice",
|
||||||
|
key: "GMD_Pic",
|
||||||
|
dataIndex: "GMD_Pic",
|
||||||
|
render: showPIc,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const invoiceStatus = (FKState) => {
|
||||||
|
switch (FKState - 1) {
|
||||||
|
case 1:
|
||||||
|
return "Submitted";
|
||||||
|
case 2:
|
||||||
|
return "Travel Advisor";
|
||||||
|
case 3:
|
||||||
|
return "Finance Dept";
|
||||||
|
case 4:
|
||||||
|
return "Paid";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function showPIc(text, record) {
|
||||||
|
let strPic = record.GMD_Pic;
|
||||||
|
//console.log(JSON.parse(strPic));
|
||||||
|
if (isNotEmpty(strPic)) {
|
||||||
|
return JSON.parse(strPic).map((item, index) => {
|
||||||
|
return <Image key={index} width={90} src={item.url} />;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space direction="vertical" style={{ width: "100%" }}>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={20}></Col>
|
||||||
|
<Col span={4}>
|
||||||
|
<BackBtn />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col md={24} lg={24} xxl={24}>
|
||||||
|
<Table
|
||||||
|
rowKey={"GMD_SN"}
|
||||||
|
bordered
|
||||||
|
columns={invoicePaidColumns}
|
||||||
|
dataSource={invoiceZDDetail}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default History;
|
@ -0,0 +1,100 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { Form, Modal, Input, Button, Flex, App } from 'antd'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import useProductsStore from '@/stores/Products/Index'
|
||||||
|
import { useProductsTypesMapVal } from '@/hooks/useProductsSets'
|
||||||
|
import RequireAuth from '@/components/RequireAuth'
|
||||||
|
import { PERM_PRODUCTS_OFFER_PUT } from '@/config'
|
||||||
|
|
||||||
|
export const ContractRemarksModal = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const { notification } = App.useApp()
|
||||||
|
const productsTypesMapVal = useProductsTypesMapVal()
|
||||||
|
const [getRemarkList, saveOrUpdateRemark] = useProductsStore((state) => [
|
||||||
|
state.getRemarkList, state.saveOrUpdateRemark
|
||||||
|
])
|
||||||
|
|
||||||
|
const [isRemarksModalOpen, setRemarksModalOpen] = useState(false)
|
||||||
|
const [remarksForm] = Form.useForm()
|
||||||
|
|
||||||
|
const onRemarksFinish = () => {
|
||||||
|
const remarkList = remarksForm.getFieldsValue().remarkList
|
||||||
|
saveOrUpdateRemark(remarkList)
|
||||||
|
.then(() => {
|
||||||
|
setRemarksModalOpen(false)
|
||||||
|
notification.info({
|
||||||
|
message: 'Notification',
|
||||||
|
description: '合同备注保存成功',
|
||||||
|
placement: 'top',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(ex => {
|
||||||
|
notification.error({
|
||||||
|
message: 'Notification',
|
||||||
|
description: ex.message,
|
||||||
|
placement: 'top',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleContractRemarks = () => {
|
||||||
|
getRemarkList()
|
||||||
|
.then(list => {
|
||||||
|
remarksForm.setFieldsValue({remarkList:list})
|
||||||
|
setRemarksModalOpen(true)
|
||||||
|
})
|
||||||
|
.catch(ex => {
|
||||||
|
notification.error({
|
||||||
|
message: 'Notification',
|
||||||
|
description: ex.message,
|
||||||
|
placement: 'top',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFieldLabel = (field) => {
|
||||||
|
const remarkList = remarksForm.getFieldsValue([['remarkList']]).remarkList
|
||||||
|
return productsTypesMapVal[remarkList[field.key].product_type_id]?.label
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<RequireAuth subject={PERM_PRODUCTS_OFFER_PUT}>
|
||||||
|
<Button size='small' onClick={handleContractRemarks}>{t('products:ContractRemarks')}</Button>
|
||||||
|
</RequireAuth>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
centered
|
||||||
|
title={t('products:ContractRemarks')}
|
||||||
|
width={'640px'}
|
||||||
|
open={isRemarksModalOpen}
|
||||||
|
onOk={() => onRemarksFinish()}
|
||||||
|
onCancel={() => setRemarksModalOpen(false)}
|
||||||
|
destroyOnClose
|
||||||
|
forceRender
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
labelCol={{ span: 3 }}
|
||||||
|
wrapperCol={{ span: 20 }}
|
||||||
|
form={remarksForm}
|
||||||
|
name='remarksForm'
|
||||||
|
autoComplete='off'
|
||||||
|
>
|
||||||
|
<Form.List name='remarkList'>
|
||||||
|
{(fields) => (
|
||||||
|
<Flex gap='middle' vertical>
|
||||||
|
{fields.map((field) => (
|
||||||
|
<Form.Item label={getFieldLabel(field)} name={[field.name, 'Memo']} key={field.key}>
|
||||||
|
<Input.TextArea rows={2}></Input.TextArea>
|
||||||
|
</Form.Item>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</Form.List>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default ContractRemarksModal
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,140 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { Grid, Divider, Layout, Spin, Input, Col, Row, Space, List, Table, Button, Typography } from "antd";
|
||||||
|
import { PhoneOutlined, CustomerServiceOutlined, AudioOutlined, AuditOutlined } from "@ant-design/icons";
|
||||||
|
import { useParams, useHref, useNavigate, NavLink } from "react-router-dom";
|
||||||
|
import { isEmpty, formatColonTime } from "@/utils/commons";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import SearchForm from "@/components/SearchForm";
|
||||||
|
import { DATE_FORMAT } from "@/config";
|
||||||
|
import { TableExportBtn } from "@/components/Data";
|
||||||
|
import trainTicketStore from "@/stores/Trainticket";
|
||||||
|
import { usingStorage } from "@/hooks/usingStorage";
|
||||||
|
|
||||||
|
const planListColumns = [
|
||||||
|
{
|
||||||
|
title: "团名",
|
||||||
|
key: "GRI_No",
|
||||||
|
dataIndex: "GRI_No",
|
||||||
|
// sorter: (a, b) => b.GRI_No - a.GRI_No,
|
||||||
|
render: (text, record) => (
|
||||||
|
<Typography.Text title={record.Memo}>
|
||||||
|
{record.GRI_No} {record.WL}
|
||||||
|
</Typography.Text>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "人数",
|
||||||
|
dataIndex: "PersonNum",
|
||||||
|
key: "PersonNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "出发",
|
||||||
|
key: "FromAirport",
|
||||||
|
dataIndex: "FromAirport",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "抵达",
|
||||||
|
key: "ToAirport",
|
||||||
|
dataIndex: "ToAirport",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "车次",
|
||||||
|
key: "FlightNo",
|
||||||
|
dataIndex: "FlightNo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "出发日期",
|
||||||
|
key: "StartDate",
|
||||||
|
dataIndex: "StartDate",
|
||||||
|
sorter: (a, b) => {
|
||||||
|
const dateA = new Date(a.StartDate);
|
||||||
|
const dateB = new Date(b.StartDate);
|
||||||
|
return dateB.getTime() - dateA.getTime();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "开始时间",
|
||||||
|
key: "FlightStart",
|
||||||
|
dataIndex: "FlightStart",
|
||||||
|
render: text => formatColonTime(text),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "抵达时间",
|
||||||
|
key: "FlightEnd",
|
||||||
|
dataIndex: "FlightEnd",
|
||||||
|
render: text => formatColonTime(text),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: "出票处理",
|
||||||
|
key: "TicketIssued",
|
||||||
|
dataIndex: "TicketIssued",
|
||||||
|
render: (text, record) => record.TicketIssuedName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "计划状态",
|
||||||
|
key: "FlightStatus",
|
||||||
|
dataIndex: "FlightStatus",
|
||||||
|
render: (text, record) => record.FlightStatusName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
key: "FlightInfo",
|
||||||
|
dataIndex: "FlightInfo",
|
||||||
|
render: (text, record) => <NavLink to={`/trainticket/plan/${record.COLI_SN}/${record.GRI_SN}`}>{"编辑"}</NavLink>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const Trainticket = props => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { travelAgencyId } = usingStorage();
|
||||||
|
const [getPlanList, planList, loading] = trainTicketStore(state => [state.getPlanList, state.planList, state.loading]);
|
||||||
|
const showTotal = total => `合计 ${total} `;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
!planList && getPlanList(travelAgencyId, "", dayjs().startOf("M").format(DATE_FORMAT), dayjs().endOf("M").format(DATE_FORMAT), "-1", "-1");
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space direction="vertical" style={{ width: "100%" }}>
|
||||||
|
<Row>
|
||||||
|
<Col md={20} lg={20} xxl={20}>
|
||||||
|
<SearchForm
|
||||||
|
initialValue={{
|
||||||
|
dates: [dayjs().startOf("M"), dayjs().endOf("M")],
|
||||||
|
}}
|
||||||
|
fieldsConfig={{
|
||||||
|
shows: ["referenceNo", "dates", "airticket_state", "plan_state"],
|
||||||
|
fieldProps: {
|
||||||
|
referenceNo: { label: "搜索计划" },
|
||||||
|
dates: { label: "出发日期", col: 8 },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onSubmit={(err, formVal, filedsVal) => {
|
||||||
|
getPlanList(travelAgencyId, formVal.referenceNo, formVal.startdate, formVal.endtime, formVal.plan_state, formVal.airticket_state);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col md={4} lg={4} xxl={4}>
|
||||||
|
<Space>
|
||||||
|
<Button icon={<AuditOutlined />} onClick={() => navigate(`/trainticket/invoice`)}>
|
||||||
|
报账
|
||||||
|
</Button>
|
||||||
|
<Button icon={<AuditOutlined />} onClick={() => navigate(`/trainticket/invoicepaid`)}>
|
||||||
|
汇款记录
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col md={24} lg={24} xxl={24}>
|
||||||
|
<Table bordered={true} rowKey="id" columns={planListColumns} dataSource={planList} loading={loading} pagination={{ defaultPageSize: 20, showTotal: showTotal }} />
|
||||||
|
<TableExportBtn btnTxt="导出计划" label={`出票计划`} {...{ columns: planListColumns, dataSource: planList }} />
|
||||||
|
</Col>
|
||||||
|
<Col md={24} lg={24} xxl={24}></Col>
|
||||||
|
</Row>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Trainticket;
|
@ -0,0 +1,136 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { Grid, Divider, Layout, Spin, Input, Col, Row, Space, Checkbox, Table, Button, App } from "antd";
|
||||||
|
import { PhoneOutlined, CustomerServiceOutlined, FrownTwoTone, LikeTwoTone } from "@ant-design/icons";
|
||||||
|
import { useParams, useHref, useNavigate, NavLink } from "react-router-dom";
|
||||||
|
import { isEmpty, formatColonTime, formatDate, isNotEmpty } from "@/utils/commons";
|
||||||
|
import { DATE_FORMAT } from "@/config";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import SearchForm from "@/components/SearchForm";
|
||||||
|
import BackBtn from "@/components/BackBtn";
|
||||||
|
import { TableExportBtn } from "@/components/Data";
|
||||||
|
import useInvoiceStore from "@/stores/Invoice";
|
||||||
|
import { fetchInvoicePaidDetail } from "@/stores/Invoice";
|
||||||
|
|
||||||
|
import { usingStorage } from "@/hooks/usingStorage";
|
||||||
|
|
||||||
|
const InvoicePaid = props => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { notification } = App.useApp();
|
||||||
|
const { travelAgencyId } = usingStorage();
|
||||||
|
const [invoicePaidDetail, setInvoicePaidDetail] = useState([]);
|
||||||
|
const [invoiceNO, setInvoiceNO] = useState([]); //显示账单编号
|
||||||
|
const [loading, invoicePaid, fetchInvoicePaid] = useInvoiceStore(state => [state.loading, state.invoicePaid, state.fetchInvoicePaid]);
|
||||||
|
const showTotal = total => `Total ${total} items`;
|
||||||
|
const showTotal_detail = total => `Total ${total} items`;
|
||||||
|
useEffect(() => {
|
||||||
|
// fetchInvoicePaid(travelAgencyId, "", dayjs().subtract(2, "M").startOf("M").format(DATE_FORMAT), dayjs().endOf("M").format(DATE_FORMAT));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const invoicePaidColumns = [
|
||||||
|
{
|
||||||
|
title: "编号",
|
||||||
|
dataIndex: "fl_finaceNo",
|
||||||
|
key: "fl_finaceNo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "报账日期",
|
||||||
|
key: "fl_adddate",
|
||||||
|
dataIndex: "fl_adddate",
|
||||||
|
render: (text, record) => (isNotEmpty(text) ? formatDate(new Date(text)) : ""),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "团数",
|
||||||
|
key: "fcount",
|
||||||
|
dataIndex: "fcount",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "总额",
|
||||||
|
key: "pSum",
|
||||||
|
dataIndex: "pSum",
|
||||||
|
//render: (text, record) => (isNotEmpty(record.GMD_Currency) ? record.GMD_Currency + " " + text : text),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "查看",
|
||||||
|
key: "pSum",
|
||||||
|
dataIndex: "pSum",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
onClick={() => {
|
||||||
|
fetchInvoicePaidDetail(travelAgencyId, record.key).then(res => setInvoicePaidDetail(res));
|
||||||
|
setInvoiceNO(record.fl_finaceNo);
|
||||||
|
}}>
|
||||||
|
查看明细
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const invoicePaidDetailColumns = [
|
||||||
|
{
|
||||||
|
title: "团号",
|
||||||
|
dataIndex: "fl2_GroupName",
|
||||||
|
key: "fl2_GroupName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "金额",
|
||||||
|
key: "fl2_price",
|
||||||
|
dataIndex: "fl2_price",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "报账日期",
|
||||||
|
key: "fl2_ArriveDate",
|
||||||
|
dataIndex: "fl2_ArriveDate",
|
||||||
|
render: (text, record) => (isNotEmpty(text) ? formatDate(new Date(text)) : ""),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "顾问",
|
||||||
|
dataIndex: "fl2_wl",
|
||||||
|
key: "fl2_wl",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space direction="vertical" style={{ width: "100%" }}>
|
||||||
|
<Row>
|
||||||
|
<Col md={20} lg={20} xxl={20}>
|
||||||
|
<SearchForm
|
||||||
|
initialValue={{
|
||||||
|
dates: [dayjs().subtract(2, "M").startOf("M"), dayjs().endOf("M")],
|
||||||
|
}}
|
||||||
|
fieldsConfig={{
|
||||||
|
shows: ["dates"],
|
||||||
|
fieldProps: {
|
||||||
|
dates: { col: 10, label: "报账日期" },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onSubmit={(err, formVal) => {
|
||||||
|
fetchInvoicePaid(travelAgencyId, "", formVal.startdate, formVal.enddate);
|
||||||
|
setInvoicePaidDetail([]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col md={4} lg={4} xxl={4}>
|
||||||
|
<BackBtn to={"/trainticket"} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col md={24} lg={16} xxl={16}>
|
||||||
|
<Divider orientation="left">汇款列表</Divider>
|
||||||
|
<Table bordered columns={invoicePaidColumns} dataSource={invoicePaid} loading={loading} pagination={{ defaultPageSize: 20, showTotal: showTotal }} />
|
||||||
|
</Col>
|
||||||
|
<Col md={24} lg={4} xxl={4}></Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col md={24} lg={20} xxl={20}>
|
||||||
|
<Divider orientation="left">账单明细 {invoiceNO}</Divider>
|
||||||
|
<Table bordered columns={invoicePaidDetailColumns} dataSource={invoicePaidDetail} pagination={{ defaultPageSize: 100, showTotal: showTotal_detail }} />
|
||||||
|
<TableExportBtn btnTxt="导出账单明细" label={`车票账单`} {...{ columns: invoicePaidDetailColumns, dataSource: invoicePaidDetail }} />
|
||||||
|
</Col>
|
||||||
|
<Col md={24} lg={4} xxl={4}></Col>
|
||||||
|
</Row>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default InvoicePaid;
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue