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);
+ }}
+ />
+
+
+
+ } onClick={() => navigate(`/airticket/invoice`)}>
+ 报账
+
+ } onClick={() => navigate(`/airticket/invoicepaid`)}>
+ 汇款记录
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+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 (
+ <>
+
+ >
+ );
+ };
+
+ 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 && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+
+
+ {isTicketType && (
+ <>
+
+
+
+
+ guestList_OnChange(e)}
+ style={{
+ minWidth: 320,
+ }}>
+ (
+
+ {item.label}
+
+ )}>
+
+ {/*
+ >
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AirticketPlan;