From 7acc8a91d78389bcd223b384a6ca64328d61e62e Mon Sep 17 00:00:00 2001 From: Ycc Date: Fri, 16 May 2025 11:35:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E7=81=AB=E8=BD=A6?= =?UTF-8?q?=E5=87=BA=E7=A5=A8=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/locales/en/common.json | 1 + public/locales/zh/common.json | 1 + src/config.js | 4 + src/main.jsx | 12 + src/stores/Trainticket.js | 227 ++++++++ src/views/App.jsx | 3 +- src/views/trainticket/index.jsx | 139 +++++ src/views/trainticket/invoice.jsx | 255 +++++++++ src/views/trainticket/invoicePaid.jsx | 137 +++++ src/views/trainticket/plan.jsx | 722 ++++++++++++++++++++++++++ 10 files changed, 1500 insertions(+), 1 deletion(-) create mode 100644 src/stores/Trainticket.js create mode 100644 src/views/trainticket/index.jsx create mode 100644 src/views/trainticket/invoice.jsx create mode 100644 src/views/trainticket/invoicePaid.jsx create mode 100644 src/views/trainticket/plan.jsx diff --git a/public/locales/en/common.json b/public/locales/en/common.json index ebc8ee7..5fc92b0 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -88,6 +88,7 @@ "Notice": "Notice", "Report": "Report", "Airticket": "AirTicket", + "Trainticket": "TrainTicket", "Products": "Products" }, "Validation": { diff --git a/public/locales/zh/common.json b/public/locales/zh/common.json index e28688f..d749ecd 100644 --- a/public/locales/zh/common.json +++ b/public/locales/zh/common.json @@ -88,6 +88,7 @@ "Notice": "通知", "Report": "质量评分", "Airticket": "机票订票", + "Trainticket": "火车订票", "Products": "产品管理" }, "Validation": { diff --git a/src/config.js b/src/config.js index 2ce6741..dc8ad02 100644 --- a/src/config.js +++ b/src/config.js @@ -34,6 +34,10 @@ export const PERM_DOMESTIC = '/domestic/all' // category: air-ticket export const PERM_AIR_TICKET = '/air-ticket/all' +// 火车票供应商 +// category: train-ticket +export const PERM_TRAIN_TICKET = '/train-ticket/all' + // 价格管理 export const PERM_PRODUCTS_MANAGEMENT = '/products/*'; // 管理 export const PERM_PRODUCTS_NEW = '/products/new'; // 新增产品 diff --git a/src/main.jsx b/src/main.jsx index 1713825..89f74dc 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -31,6 +31,12 @@ import Airticket from '@/views/airticket/Index' import AirticketPlan from '@/views/airticket/Plan' import AirticketInvoice from '@/views/airticket/Invoice' import AirticketInvoicePaid from '@/views/airticket/InvoicePaid' + +import Trainticket from '@/views/trainticket/index' +import TrainticketPlan from '@/views/trainticket/plan' +import TrainticketInvoice from '@/views/trainticket/invoice' +import TrainticketInvoicePaid from '@/views/trainticket/invoicePaid' + import { ThemeContext } from '@/stores/ThemeContext' import { usingStorage } from '@/hooks/usingStorage' import useAuthStore from './stores/Auth' @@ -72,6 +78,12 @@ const initRouter = async () => { { path: 'airticket/plan/:coli_sn/:gri_sn',element:}, { path: 'airticket/invoice',element:}, { path: 'airticket/invoicepaid',element:}, + + { path: 'trainticket',element: }, + { path: 'trainticket/plan/:coli_sn/:gri_sn',element:}, + { path: 'trainticket/invoice',element:}, + { path: 'trainticket/invoicepaid',element:}, + { path: "products",element: }, { path: "products/:travel_agency_id/:use_year/:audit_state/audit",element:}, diff --git a/src/stores/Trainticket.js b/src/stores/Trainticket.js new file mode 100644 index 0000000..f4089c9 --- /dev/null +++ b/src/stores/Trainticket.js @@ -0,0 +1,227 @@ +import { create } from "zustand"; +import { fetchJSON, postForm } from "@/utils/request"; +import { prepareUrl, isNotEmpty } from "@/utils/commons"; +import { HT_HOST, DATE_FORMAT } from "@/config"; +import dayjs from "dayjs"; + +const trainTicketStore = create((set, get) => ({ + loading: false, + setLoading: loading => set({ loading }), + setPlanList: planList => set({ planList }), + setPlanDetail: planDetail => set({ planDetail }), + setGuestList: guestList => set({ guestList }), + setVEIFlightBill: vEIFlightBill => set({ vEIFlightBill }), + setVeiPlanChangeTxt: veiPlanChangeTxt => set({ veiPlanChangeTxt }), + setAirPortList: airPortList => set({ airPortList }), + + async getPlanList(vei_sn, GRI_Name, TimeStart, TimeEnd, plan_state, airticket_state) { + const { setLoading, setPlanList } = get(); + setLoading(true); + const searchParams = { + vei_sn: vei_sn, + FlightDate1: TimeStart, + FlightDate2: TimeEnd, + GRI_Name: GRI_Name, + FlightStatus: plan_state, + TicketIssued: airticket_state, + }; + + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetTrainPlan`, searchParams); + const _result = errcode !== 0 ? [] : result; + console.log("result", result); + setPlanList(_result); + setLoading(false); + }, + + async getPlanDetail(vei_sn, gri_sn) { + const { setPlanDetail } = get(); + const searchParams = { + vei_sn: vei_sn, + gri_sn: gri_sn, + }; + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetFlightPlanDetail`, searchParams); + const _result = errcode !== 0 ? [] : result; + setPlanDetail(_result); + //return _result.filter(item => isNotEmpty(item.GRI_No)); + return "dsadsd"; + }, + + async postFlightDetail(CLF_SN, GRI_SN, VEI_SN, original_values, info_object) { + const formData = new FormData(); + formData.append("CLF_SN", CLF_SN ? CLF_SN : ""); + formData.append("GRI_SN", GRI_SN); + formData.append("VEI_SN", VEI_SN); + for (const [key, value] of Object.entries(original_values)) { + formData.append(key, value); //先用原始数据填充一遍,确保复制了全部数据到新表 + } + for (const [key, value] of Object.entries(info_object)) { + formData.set(key, value); //再用新值覆盖 + } + formData.set("StartDate", dayjs(info_object.StartDate).format(DATE_FORMAT)); //再用新值覆盖 + //是否出票的值,true、false变为1或0 + formData.set("TicketIssued", info_object.TicketIssued ? 1 : 0); + const postUrl = HT_HOST + "/Service_BaseInfoWeb/edit_or_new_flight_info"; + return postForm(postUrl, formData).then(json => { + if (json.errcode == 0) { + return json; + } else { + throw new Error(json.errmsg + ": " + json.errcode); + } + }); + }, + //删除航班信息 + async delete_flight_info(CLF_SN) { + const searchParams = { + CLF_SN: CLF_SN, + }; + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/Delete_flight_info`, searchParams); + const _result = errcode !== 0 ? [] : result; + return _result; + }, + + async getGuestList(coli_sn) { + const { setGuestList } = get(); + const searchParams = { + COLI_SN: coli_sn, + }; + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetFlightGuestInfo`, searchParams); + const _result = errcode !== 0 ? [] : result; + setGuestList(_result); + }, + //获取账单列表 + async getVEIFlightBill(VEI_SN, GRI_Name, CheckStatus, FlightDate1, FlightDate2) { + const { setLoading, setVEIFlightBill } = get(); + setLoading(true); + const searchParams = { + VEI_SN: VEI_SN, + GRI_Name: GRI_Name, + CheckStatus: CheckStatus, + FlightDate1: FlightDate1, + FlightDate2: FlightDate2, + }; + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetVEIFlightBill`, searchParams); + const _result = errcode !== 0 ? [] : result; + setVEIFlightBill(_result); + setLoading(false); + }, + //保存费用 + async postFlightCost(values) { + const formData = new FormData(); + for (const [key, value] of Object.entries(values)) { + formData.append(key, value); //先用原始数据填充一遍,确保复制了全部数据到新表 + } + const postUrl = HT_HOST + "/Service_BaseInfoWeb/edit_or_new_flight_cost"; + return postForm(postUrl, formData).then(json => { + if (json.errcode == 0) { + return json; + } else { + throw new Error(json.errmsg + ": " + json.errcode); + } + }); + }, + //删除费用 + async deleteFlightCost(CLC_SN) { + const searchParams = { + CLC_SN: CLC_SN, + }; + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/Delete_flight_cost`, searchParams); + const _result = errcode !== 0 ? [] : result; + return _result; + }, + //获取变更信息 + async getVeiPlanChange(VEI_SN, GRI_SN) { + const { setVeiPlanChangeTxt } = get(); + const searchParams = { + VEI_SN: VEI_SN, + GRI_SN: GRI_SN, + }; + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetVeiFlightPlanChange`, searchParams); + const _result = errcode !== 0 ? [] : result; + setVeiPlanChangeTxt(_result); + }, + //提交变更确认 + async postVeiFlightPlanConfirm(VEI_SN, GRI_SN, LMI_SN, ConfirmInfo) { + const formData = new FormData(); + formData.append("VEI_SN", VEI_SN); + formData.append("GRI_SN", GRI_SN); + formData.append("LMI_SN", LMI_SN); + formData.append("ConfirmInfo", ConfirmInfo); + const postUrl = HT_HOST + "/Service_BaseInfoWeb/VeiFlightPlanConfirm"; + return postForm(postUrl, formData).then(json => { + if (json.errcode == 0) { + return json; + } else { + throw new Error(json.errmsg + ": " + json.errcode); + } + }); + }, + //提交账单 + async postVEIFlightBillSubmit(VEI_SN, values) { + const formData = new FormData(); + formData.append("vei_sn", VEI_SN); + formData.append("billdata", JSON.stringify(values)); + const postUrl = HT_HOST + "/Service_BaseInfoWeb/VEIFlightBillSubmit"; + return postForm(postUrl, formData).then(json => { + if (json.errcode == 0) { + return json; + } else { + throw new Error(json.errmsg + ": " + json.errcode); + } + }); + }, + //通知顾问查看机票信息 + async ticketIssuedNotifications(LMI_SN, CLF_SN, OPI_SN, FlightMemo_messages) { + const searchParams = { + CLF_SN: CLF_SN, + OPI_SN: OPI_SN, + LMI_SN: LMI_SN, + FlightMemo_messages: FlightMemo_messages, + }; + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/TicketIssuedNotifications`, searchParams); + const _result = errcode !== 0 ? [] : result; + return _result; + }, + //获取机场列表 + async getAirPortList() { + const { setAirPortList } = get(); + const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetAirPortInfo`); + const _result = errcode !== 0 ? [] : result; + setAirPortList(_result); + }, + + airLineList: [ + { label: "CA-国航", value: "国航" }, + { label: "MU-东方航空", value: "东方航空" }, + { label: "FM-上海航空", value: "上海航空" }, + { label: "CZ-南方航空", value: "南方航空" }, + { label: "HO-吉祥航空", value: "吉祥航空" }, + { label: "HU-海南航空", value: "海南航空" }, + { label: "ZH-深圳航空", value: "深圳航空" }, + { label: "MF-厦门航空", value: "厦门航空" }, + { label: "3U-四川航空", value: "四川航空" }, + { label: "SC-山东航空", value: "山东航空" }, + { label: "JD-首都航空", value: "首都航空" }, + { label: "BK-奥凯航空", value: "奥凯航空" }, + { label: "GS-天津航空", value: "天津航空" }, + { label: "CN-大新华", value: "大新华" }, + { label: "KN-中联航", value: "中联航" }, + { label: "TV-西藏航空", value: "西藏航空" }, + { label: "8L-祥鹏航空", value: "祥鹏航空" }, + { label: "KY-昆明航空", value: "昆明航空" }, + { label: "EU-成都航空", value: "成都航空" }, + { label: "G5-华夏航空", value: "华夏航空" }, + { label: "NS-河北航空", value: "河北航空" }, + { label: "QW-青岛航空", value: "青岛航空" }, + { label: "Y8-扬子江", value: "扬子江" }, + { label: "PN-西部航空", value: "西部航空" }, + { label: "DZ-东海航空", value: "东海航空" }, + { label: "GT-桂林航空", value: "桂林航空" }, + { label: "9H-长安航空", value: "长安航空" }, + { label: "GY-多彩航空", value: "多彩航空" }, + { label: "DR-瑞丽航空", value: "瑞丽航空" }, + { label: "GJ-长龙航空", value: "长龙航空" }, + { label: "GX-广西北部", value: "广西北部" }, + ], +})); + +export default trainTicketStore; diff --git a/src/views/App.jsx b/src/views/App.jsx index 8428689..d176c1d 100644 --- a/src/views/App.jsx +++ b/src/views/App.jsx @@ -20,7 +20,7 @@ import { useDefaultLgc } from '@/i18n/LanguageSwitcher' import { appendRequestParams } from '@/utils/request' import { uploadPageSpyLog } from '@/pageSpy'; -import { PERM_ACCOUNT_MANAGEMENT, PERM_ROLE_NEW, PERM_OVERSEA, PERM_AIR_TICKET, PERM_PRODUCTS_MANAGEMENT } from '@/config' +import { PERM_ACCOUNT_MANAGEMENT, PERM_ROLE_NEW, PERM_OVERSEA, PERM_AIR_TICKET, PERM_PRODUCTS_MANAGEMENT,PERM_TRAIN_TICKET } from '@/config' const { Header, Content, Footer } = Layout @@ -115,6 +115,7 @@ function App() { isPermitted(PERM_OVERSEA) ? { key: 'feedback', label: {t('menu.Feedback')} } : null, isPermitted(PERM_OVERSEA) ? { key: 'report', label: {t('menu.Report')} } : null, isPermitted(PERM_AIR_TICKET) ? { key: 'airticket', label: {t('menu.Airticket')} } : null, + isPermitted(PERM_TRAIN_TICKET) ? { key: 'trainticket', label: {t('menu.Trainticket')} } : null, isProductPermitted ? { key: 'products', label: {t('menu.Products')} } : null, { key: 'notice', diff --git a/src/views/trainticket/index.jsx b/src/views/trainticket/index.jsx new file mode 100644 index 0000000..e1d8f85 --- /dev/null +++ b/src/views/trainticket/index.jsx @@ -0,0 +1,139 @@ +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 { 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, + }, + { + title: "组团人", + key: "WL", + dataIndex: "WL", + }, + { + title: "人数", + dataIndex: "PersonNum", + key: "PersonNum", + }, + { + 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: "FromCity", + dataIndex: "FromCity", + }, + { + title: "抵达城市", + key: "ToCity", + dataIndex: "ToCity", + }, + { + title: "航班", + key: "FlightNo", + dataIndex: "FlightNo", + }, + { + 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) => {"编辑"}, + }, +]; + +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().add(3, "M").endOf("M").format(DATE_FORMAT), "-1", "-1"); + }, []); + + return ( + + + + { + getPlanList(travelAgencyId, formVal.referenceNo, formVal.startdate, formVal.endtime, formVal.plan_state, formVal.airticket_state); + }} + /> + + + + + + + + + + + + + + + + + + ); +}; +export default Trainticket; diff --git a/src/views/trainticket/invoice.jsx b/src/views/trainticket/invoice.jsx new file mode 100644 index 0000000..73680e3 --- /dev/null +++ b/src/views/trainticket/invoice.jsx @@ -0,0 +1,255 @@ +import { useState, useEffect } from "react"; +import { Grid, Divider, Layout, Steps, Statistic, Col, Row, Space, Checkbox, Table, Button, App, Typography } from "antd"; +import { PhoneOutlined, CustomerServiceOutlined, FrownTwoTone, LikeTwoTone } 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 BackBtn from "@/components/BackBtn"; +import { TableExportBtn } from "@/components/Data"; + +import airTicketStore from "@/stores/Airticket"; +import { usingStorage } from "@/hooks/usingStorage"; + +const Invoice = props => { + const navigate = useNavigate(); + const { notification } = App.useApp(); + const { travelAgencyId } = usingStorage(); + const [getVEIFlightBill, vEIFlightBill, loading, postVEIFlightBillSubmit] = airTicketStore(state => [state.getVEIFlightBill, state.vEIFlightBill, state.loading, state.postVEIFlightBillSubmit]); + const showTotal = total => `合计 ${total} `; + const [selectedValues, setSelectedValues] = useState([]); + + const vEIFlightBillColumns = [ + { + title: "团名", + key: "GRI_No", + dataIndex: "GRI_No", + render: (text, record) => ( + + {record.GRI_No} {record.WL} + + ), + }, + { + title: "状态", + key: "CostType", + dataIndex: "CostType", + }, + { + 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: "FromCity", + dataIndex: "FromCity", + render: (text, record) => (record.CostType == "出票" ? `${record.FromCity}` : "-"), + }, + { + title: "抵达", + key: "ToCity", + dataIndex: "ToCity", + render: (text, record) => (record.CostType == "出票" ? `${record.ToCity}` : "-"), + }, + { + title: "航班", + key: "FlightNo", + dataIndex: "FlightNo", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + { + title: "PNR", + key: "PNR", + dataIndex: "PNR", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + { + title: "票号", + key: "TicketNo", + dataIndex: "TicketNo", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + { + title: "机票类型", + key: "FlightType", + dataIndex: "FlightType", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + { + title: "机票价格", + children: [ + { + title: vEIFlightBill && vEIFlightBill.reduce((acc, curr) => acc + curr.Cost, 0), + dataIndex: "Cost", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + ], + key: "Cost", + }, + { + title: "服务费", + children: [ + { + title: vEIFlightBill && vEIFlightBill.reduce((acc, curr) => acc + curr.ServiceFee, 0), + dataIndex: "ServiceFee", + }, + ], + }, + { + title: "折扣", + key: "Discount", + dataIndex: "Discount", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + { + title: "审核状态", + children: [ + { + title: ( + + ), + dataIndex: "CheckStatus", //状态小于2,表示还未提交审核 + render: (text, record) => + record.CheckStatus < 2 ? ( + handleCheckboxChange(event, record)} checked={checkboxStates(record.CLC_SN)}> + 待提交 + + ) : ( + + ), + }, + ], + + sorter: (a, b) => { + return b.CheckStatus - a.CheckStatus; + }, + }, + ]; + //获取当前状态 + const checkboxStates = CLC_SN => { + return selectedValues.some(v => v.CLC_SN === CLC_SN); + }; + // 处理checkbox改变事件 + const handleCheckboxChange = (event, data) => { + const value = { CLC_SN: data.CLC_SN, WL: data.WL, OPI_SN: data.OPI_SN, OPI_Email: data.OPI_Email, GRI_SN: data.GRI_SN, GRI_Name: data.GRI_Name, Cost: data.Cost, ServiceFee: data.ServiceFee }; + if (event.target.checked) { + setSelectedValues([...selectedValues, value]); // 如果被选中,则添加到数组 + } else { + setSelectedValues(selectedValues.filter(v => v.CLC_SN !== value.CLC_SN)); // 如果取消选中,则从数组中移除 + } + }; + //提交账单 + const postInvoice = () => { + postVEIFlightBillSubmit(travelAgencyId, selectedValues) + .then(() => { + notification.success({ + message: `成功`, + description: "账单提交成功!", + placement: "top", + duration: 4, + icon: , + }); + setSelectedValues([]); //清空选中的项目 + }) + .catch(() => { + notification.error({ + message: `错误`, + description: "保存失败", + placement: "top", + duration: 4, + icon: , + }); + }); + }; + //全选或不全选 + const checkALL = () => { + if (isEmpty(vEIFlightBill)) return; + const allChecked = selectedValues.length === vEIFlightBill.filter(item => item.CheckStatus < 2).length; + setSelectedValues( + allChecked + ? [] + : vEIFlightBill + .filter(item => item.CheckStatus < 2) + .map(item => ({ CLC_SN: item.CLC_SN, WL: item.WL, OPI_SN: item.OPI_SN, OPI_Email: item.OPI_Email, GRI_SN: item.GRI_SN, GRI_Name: item.GRI_Name, Cost: item.Cost, ServiceFee: item.ServiceFee })) + ); // 如果全选,则清空数组,否则添加所有项 + }; + + useEffect(() => {}, []); + + return ( + + + + { + getVEIFlightBill(travelAgencyId, formVal.referenceNo, formVal.invoiceCheckStatus, formVal.startdate, formVal.endtime); + }} + /> + + + + + + + + +
+ + + + + + + + + + acc + curr.Cost, 0)} /> + + + acc + curr.ServiceFee, 0)} /> + + + + + + + ); +}; +export default Invoice; diff --git a/src/views/trainticket/invoicePaid.jsx b/src/views/trainticket/invoicePaid.jsx new file mode 100644 index 0000000..0a9dcd9 --- /dev/null +++ b/src/views/trainticket/invoicePaid.jsx @@ -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) => ( + + ), + }, + ]; + + 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 ( + + + + { + fetchInvoicePaid(travelAgencyId, "", formVal.startdate, formVal.enddate); + setInvoicePaidDetail([]); + }} + /> + + + + + + + + + 汇款列表 +
+ + + + + + 账单明细 {invoiceNO} +
+ + + + + + ); +}; +export default InvoicePaid; diff --git a/src/views/trainticket/plan.jsx b/src/views/trainticket/plan.jsx new file mode 100644 index 0000000..ee87d93 --- /dev/null +++ b/src/views/trainticket/plan.jsx @@ -0,0 +1,722 @@ +import { useState, useEffect } from "react"; +import { Checkbox, Divider, DatePicker, Modal, Form, Input, Col, Row, Space, Collapse, Table, Button, Select, App, Popconfirm, Switch, Radio, List } from "antd"; +import { PhoneOutlined, FrownTwoTone, LikeTwoTone, ArrowUpOutlined, ArrowDownOutlined, PlusOutlined } from "@ant-design/icons"; +import { useParams, useHref, useNavigate, NavLink } from "react-router-dom"; +import { isEmpty, formatColonTime } from "@/utils/commons"; +import { OFFICEWEBVIEWERURL } from "@/config"; +import dayjs from "dayjs"; +import airTicketStore from "@/stores/Airticket"; +import { usingStorage } from "@/hooks/usingStorage"; +import BackBtn from "@/components/BackBtn"; + +const AirticketPlan = props => { + const { coli_sn, gri_sn } = useParams(); + const { travelAgencyId, loginToken, userId } = usingStorage(); + const [ + getPlanDetail, + planDetail, + getGuestList, + guestList, + loading, + postFlightDetail, + postFlightCost, + deleteFlightCost, + getVeiPlanChange, + veiPlanChangeTxt, + postVeiFlightPlanConfirm, + ticketIssuedNotifications, + delete_flight_info, + getAirPortList, + airPortList, + airLineList, + ] = airTicketStore(state => [ + state.getPlanDetail, + state.planDetail, + state.getGuestList, + state.guestList, + state.loading, + state.postFlightDetail, + state.postFlightCost, + state.deleteFlightCost, + state.getVeiPlanChange, + state.veiPlanChangeTxt, + state.postVeiFlightPlanConfirm, + state.ticketIssuedNotifications, + state.delete_flight_info, + state.getAirPortList, + state.airPortList, + state.airLineList, + ]); + const reservationUrl = `https://p9axztuwd7x8a7.mycht.cn/Service_BaseInfoWeb/FlightPlanDocx?GRI_SN=${gri_sn}&VEI_SN=${travelAgencyId}&token=${loginToken}`; + const reservationPreviewUrl = OFFICEWEBVIEWERURL + encodeURIComponent(reservationUrl); + const [form] = Form.useForm(); + const { notification } = App.useApp(); + //console.log(reservationPreviewUrl); + + //乘客下拉列表 + const guestList_select = () => { + return ( + guestList && + guestList.map(item => { + return { label: `${item.MEI_Name} , ${item.MEI_PassportNo}`, value: `${item.MEI_Name} , ${item.MEI_PassportNo} , ${item.MEI_Country} , ${item.MEI_Gender} , ${item.MEI_age} , ${item.MEI_Birthday}` }; + }) + ); + }; + + const guestList_OnChange = e => { + ticket_form.setFieldsValue({ Memo: `${e.target.value}` }); + }; + //机场下拉列表 + const airPortList_select = () => { + return ( + airPortList && + airPortList.map(item => { + return { label: `${item.AirPort_Code} - ${item.AirPort_Name}`, value: item.AirPort_Name }; + }) + ); + }; + + //费用列表 + const costListColumns = [ + { + title: "客人信息/备注", + key: "Memo", + dataIndex: "Memo", + }, + { + title: "状态", + key: "CostType", + dataIndex: "CostType", + }, + { + title: "票号", + key: "TicketNo", + dataIndex: "TicketNo", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + { + title: "PNR", + key: "PNR", + dataIndex: "PNR", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + + { + title: "机票类型", + key: "FlightType", + dataIndex: "FlightType", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + { + title: "机票价格", + key: "Cost", + dataIndex: "Cost", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + { + title: "服务费", + key: "ServiceFee", + dataIndex: "ServiceFee", + }, + { + title: "折扣", + key: "Discount", + dataIndex: "Discount", + render: (text, record) => (record.CostType == "出票" ? text : "-"), + }, + + { + title: "编辑", + key: "CLC_SN", + dataIndex: "CLC_SN", + render: (text, record) => + record.CheckStatus <= 2 ? ( + + showModal(record)}>编辑 + handleDelete(record.CLC_SN)} okText="是" cancelText="否"> + + + + ) : ( + record.CheckStatusName + ), + }, + ]; + + const Airticket_form = props => { + const airInfo = props.airInfo; + const [airinfo_form] = Form.useForm(); + return ( + <> + { + postFlightDetail(airInfo.CLF_SN, airInfo.GRI_SN, airInfo.VEI_SN, airInfo, values) + .then(() => { + notification.success({ + message: `成功`, + description: "机票信息保存成功!", + placement: "top", + duration: 4, + icon: , + }); + }) + .catch(() => { + notification.error({ + message: `错误`, + description: "保存失败", + placement: "top", + duration: 4, + icon: , + }); + }); + }} + autoComplete="off"> + 航班信息 + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + 出票信息 + + +
+ + + + + + + + + + + + + + + + + + + + + + + + ); + }; + + const detail_items = () => { + return planDetail + ? planDetail.map(item => { + return { + key: item.id, + label: `${item.StartDate} ${item.FlightNo}(${item.FromAirport}${item.FlightStart}-${item.ToAirport}${item.FlightEnd})(${item.FlightCabin})`, + extra: ( + { + delete_flight_info(item.CLF_SN); //删除记录 + getPlanDetail(travelAgencyId, gri_sn); //更新页面计划详情,含费用列表 + }} + okText="是" + cancelText="否"> + + + ), + children: , + }; + }) + : []; + }; + + // 机票信息编辑表单 begin + + 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 = (close_modal = true) => { + ticket_form + .validateFields() + .then(values => { + // 在这里处理表单提交逻辑,例如发送数据到服务器 + console.log("Received values of form: ", values); + postFlightCost(values) + .then(() => { + notification.success({ + message: `成功`, + description: "保存成功!", + placement: "top", + duration: 4, + icon: , + }); + getPlanDetail(travelAgencyId, gri_sn); + }) + .catch(() => { + notification.error({ + message: `错误`, + description: "保存失败", + placement: "top", + duration: 4, + icon: , + }); + }); + if (close_modal) setIsModalOpen(false); + }) + .catch(info => { + console.log("Validate Failed:", info); + }); + }; + + const handleCancel = () => { + ticket_form.resetFields(); + setIsModalOpen(false); + }; + + const handleDelete = CLC_SN => { + deleteFlightCost(CLC_SN) + .then(() => { + notification.success({ + message: `成功`, + description: "删除成功!", + placement: "top", + duration: 4, + icon: , + }); + getPlanDetail(travelAgencyId, gri_sn); + }) + .catch(() => { + notification.error({ + message: `错误`, + description: "删除失败", + placement: "top", + duration: 4, + icon: , + }); + }); + }; + + const onChangeType = value => { + if (value == "出票") { + setisTicketType(true); + } else { + setisTicketType(false); + } + }; + + //变更确认表单 + const showModal_confirmInfo = ConfirmInfo => { + setisModalOpen_confirmInfo(true); + confirmInfo_form.setFieldsValue({ ConfirmInfo: ConfirmInfo }); + }; + const handleCancel_confirmInfo = () => { + setisModalOpen_confirmInfo(false); + confirmInfo_form.resetFields(); + }; + + const handleOk_confirmInfo = () => { + confirmInfo_form + .validateFields() + .then(values => { + console.log("Received values of form: ", values.ConfirmInfo); + postVeiFlightPlanConfirm(travelAgencyId, gri_sn, userId, values.ConfirmInfo) + .then(() => { + notification.success({ + message: `成功`, + description: "保存成功!", + placement: "top", + duration: 4, + icon: , + }); + getVeiPlanChange(travelAgencyId, gri_sn); + }) + .catch(() => { + notification.error({ + message: `错误`, + description: "保存失败", + placement: "top", + duration: 4, + icon: , + }); + }); + confirmInfo_form.resetFields(); + setisModalOpen_confirmInfo(false); + }) + .catch(info => { + console.log("Validate Failed:", info); + }); + }; + + // 机票信息编辑表单 end + + useEffect(() => { + getPlanDetail(travelAgencyId, gri_sn); //计划详情,含费用列表 + getGuestList(coli_sn); //客人列表 + getVeiPlanChange(travelAgencyId, gri_sn); //计划变更信息 + getAirPortList(); //获取机场信息 + }, []); + + return ( + + + + + + + + + + + + + + + + + {planDetail ? `${planDetail[0].GRI_No} - ${planDetail[0].WL}` : ""} + + + + + +
+

+ { + postFlightDetail("", gri_sn, travelAgencyId, { FlightNo: "新的记录", FlightStatus: 1 }, []); //新增加一条记录 + getPlanDetail(travelAgencyId, gri_sn); //计划详情,含费用列表 + }} + okText="是" + cancelText="否"> + + +

+ + + + 计划变更 + + + + + + + + + + + + +
+ + + + +
+ + ( + <> + + {isAddNew ? ( + <> + {" "} + + + ) : ( + + )} + + )}> +
+ + + + + + + + + + + )} + + + + {isTicketType && ( + <> + + + + + guestList_OnChange(e)} + style={{ + minWidth: 320, + }}> + ( + + {item.label} + + )}> + + {/* + + + + + +
+ + ); +}; + +export default AirticketPlan;