添加导出功能,重复添加费用信息

main
Ycc 9 months ago
parent 0ad7f3a470
commit 59427a1a3a

@ -23,7 +23,8 @@
"react-i18next": "^14.1.2",
"react-router-dom": "^6.10.0",
"react-to-pdf": "^1.0.1",
"zustand": "^4.5.2"
"zustand": "^4.5.2",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.18.11/xlsx-0.18.11.tgz"
},
"devDependencies": {
"@types/react": "^18.0.28",

@ -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>
);
};

@ -1,11 +1,12 @@
import { useState, useEffect } from "react";
import { Grid, Divider, Layout, Spin, Input, Col, Row, Space, List, Table, Button } from "antd";
import { PhoneOutlined, CustomerServiceOutlined, AudioOutlined,AuditOutlined } from "@ant-design/icons";
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 airTicketStore from "@/stores/Airticket";
import { usingStorage } from "@/hooks/usingStorage";
@ -89,7 +90,9 @@ const Airticket = props => {
const [getPlanList, planList, loading] = airTicketStore(state => [state.getPlanList, state.planList, state.loading]);
const showTotal = total => `合计 ${total} `;
useEffect(() => {}, []);
useEffect(() => {
getPlanList(travelAgencyId, "", dayjs().startOf("M").format(DATE_FORMAT), dayjs().endOf("M").format(DATE_FORMAT));
}, []);
return (
<Space direction="vertical" style={{ width: "100%" }}>
@ -103,7 +106,7 @@ const Airticket = props => {
shows: ["referenceNo", "dates"],
fieldProps: {
referenceNo: { label: "搜索计划" },
dates: { label: "出发日期" ,col:8},
dates: { label: "出发日期", col: 8 },
},
}}
onSubmit={(err, formVal, filedsVal) => {
@ -121,6 +124,7 @@ const Airticket = props => {
<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>

@ -6,6 +6,7 @@ import { isEmpty, formatColonTime } from "@/utils/commons";
import dayjs from "dayjs";
import SearchForm from "@/components/SearchForm";
import BackBtn from "@/components/BackBtn";
import { TableExportBtn } from "@/components/Data";
import airTicketStore from "@/stores/Airticket";
import { usingStorage } from "@/hooks/usingStorage";
@ -82,7 +83,7 @@ const Invoice = props => {
key: "Cost",
},
{
title: "手续费",
title: "服务费",
children: [
{
title: vEIFlightBill && vEIFlightBill.reduce((acc, curr) => acc + curr.ServiceFee, 0),
@ -199,7 +200,9 @@ const Invoice = props => {
<Row>
<Col md={24} lg={24} xxl={24}>
<Table bordered={true} rowKey="CLC_SN" columns={vEIFlightBillColumns} dataSource={vEIFlightBill} loading={loading} pagination={{ defaultPageSize: 100, showTotal: showTotal }} />
<TableExportBtn btnTxt="导出账单" label={`机票账单`} {...{ columns: vEIFlightBillColumns, dataSource: vEIFlightBill }} />
</Col>
<Col md={24} lg={24} xxl={24}></Col>
</Row>
<Row>

@ -80,7 +80,7 @@ const AirticketPlan = props => {
render: (text, record) => (record.CostType == "出票" ? text : "-"),
},
{
title: "手续费",
title: "服务费",
key: "ServiceFee",
dataIndex: "ServiceFee",
},
@ -131,7 +131,7 @@ const AirticketPlan = props => {
wrapperCol={{
span: 16,
}}
initialValues={{...airInfo,StartDate:dayjs(airInfo.StartDate)}}
initialValues={{ ...airInfo, StartDate: dayjs(airInfo.StartDate) }}
onFinish={values => {
postFlightDetail(airInfo.CLF_SN, airInfo.GRI_SN, airInfo.VEI_SN, airInfo, values)
.then(() => {
@ -308,17 +308,21 @@ const AirticketPlan = props => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [isModalOpen_confirmInfo, setisModalOpen_confirmInfo] = useState(false);
const [isTicketType, setisTicketType] = useState(true);
const [isAddNew, setisAddNew] = useState(true); //
const [ticket_form] = Form.useForm();
const [confirmInfo_form] = Form.useForm();
const showModal = ticket => {
setIsModalOpen(true);
ticket_form.resetFields();
if (isEmpty(ticket.CostType)) ticket.CostType = "出票";
ticket.CostType == "出票" ? setisTicketType(true) : setisTicketType(false); //
isEmpty(ticket.CLC_SN) ? setisAddNew(true) : setisAddNew(false); //
ticket_form.setFieldsValue(ticket);
if (isEmpty(ticket.Memo)) ticket_form.setFieldsValue({ Memo: "" });
};
const handleOk = () => {
const handleOk = (close_modal = true) => {
ticket_form
.validateFields()
.then(values => {
@ -344,8 +348,7 @@ const AirticketPlan = props => {
icon: <FrownTwoTone />,
});
});
ticket_form.resetFields();
setIsModalOpen(false);
if (close_modal) setIsModalOpen(false);
})
.catch(info => {
console.log("Validate Failed:", info);
@ -391,7 +394,30 @@ const AirticketPlan = props => {
const TicketModal = () => {
return (
<>
<Modal title="费用信息" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<Modal
title="费用信息"
open={isModalOpen}
onOk={handleOk}
onCancel={handleCancel}
okText="保存"
cancelText="关闭"
footer={(_, { OkBtn, CancelBtn }) => (
<>
<CancelBtn />
{isAddNew ? (
<>
<Button type="primary" onClick={() => handleOk(false)}>
添加并继续新增
</Button>{" "}
<Button type="primary" onClick={() => handleOk(true)}>
添加并关闭
</Button>
</>
) : (
<OkBtn />
)}
</>
)}>
<Form
form={ticket_form}
labelCol={{
@ -423,23 +449,20 @@ const AirticketPlan = props => {
]}
/>
</Form.Item>
<Form.Item label="手续费/费用" name="ServiceFee" rules={[{ required: true }]}>
{isTicketType && (
<>
<Form.Item label="PNR" name="PNR" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item label="票号" name="TicketNo" rules={[{ required: true }]}>
<Input
prefix="¥"
style={{
width: 160,
}}
/>
</Form.Item>
{isTicketType && (
<>
<Form.Item label="PNR" name="PNR">
<Input />
</Form.Item>
<Form.Item label="票号" name="TicketNo">
<Input />
</Form.Item>
<Form.Item label="机票类型" name="FlightType">
<Form.Item label="机票类型" name="FlightType" rules={[{ required: true }]}>
<Select
style={{
width: 160,
@ -460,7 +483,7 @@ const AirticketPlan = props => {
]}
/>
</Form.Item>
<Form.Item label="机票价格" name="Cost">
<Form.Item label="机票价格" name="Cost" rules={[{ required: true }]}>
<Input
placeholder="含基建和税"
prefix="¥"
@ -469,7 +492,19 @@ const AirticketPlan = props => {
}}
/>
</Form.Item>
<Form.Item label="折扣" name="Discount">
</>
)}
<Form.Item label="服务费" name="ServiceFee" rules={[{ required: true }]}>
<Input
prefix="¥"
style={{
width: 160,
}}
/>
</Form.Item>
{isTicketType && (
<>
<Form.Item label="折扣" name="Discount" rules={[{ required: true }]}>
<Input
style={{
width: 160,
@ -477,15 +512,16 @@ const AirticketPlan = props => {
/>
</Form.Item>
<Form.Item label="选择客人" name="MEI_Name66">
<Select onChange={value => guestList_OnChange(value)} options={guestList_select()} />
<Select onChange={value => guestList_OnChange(value)} options={guestList_select()} placeholder="如果列表里面没有客人信息,请手动录到备注里" />
</Form.Item>
</>
)}
<Form.Item label="备注" name="Memo">
<Input.TextArea rows={4} />
</Form.Item>
<Form.Item name="CLF_SN" hidden>
<input />{" "}
<input />
</Form.Item>
<Form.Item name="GRI_SN" hidden>
<input />

Loading…
Cancel
Save