机票计划显示

perf/export-docx
YCC 1 year ago
parent aa501c7f3a
commit e3dc13bc6c

@ -8,6 +8,8 @@ const airTicketStore = create((set, get) => ({
loading: false,
setLoading: loading => set({ loading }),
setPlanList: planList => set({ planList }),
setPlanDetail: planDetail => set({ planDetail }),
setGuestList: guestList => set({ guestList }),
async getPlanList(vei_sn, GRI_Name, TimeStart, TimeEnd) {
const { setLoading, setPlanList } = get();
@ -24,6 +26,27 @@ const airTicketStore = create((set, get) => ({
setPlanList(_result);
setLoading(false);
},
async getPlanDetail(vei_sn, gri_sn) {
const { setPlanDetail } = get();
const searchParams = {
vei_sn: 6376, //vei_sn,
gri_sn: 369040, //gri_sn
};
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetFlightPlanDetail`, searchParams);
const _result = errcode !== 0 ? [] : result;
setPlanDetail(_result);
},
async getGuestList(coli_sn) {
const { setGuestList } = get();
const searchParams = {
COLI_SN: 1097829, //coli_sn,
};
const { errcode, result } = await fetchJSON(`${HT_HOST}/Service_BaseInfoWeb/GetFlightGuestInfo`, searchParams);
const _result = errcode !== 0 ? [] : result;
setGuestList(_result);
},
}));
export default airTicketStore;

@ -139,7 +139,6 @@ export function formatPercent(number) {
return Math.round(number * 100) + "%";
}
/**
* ! 不支持计算 Set Map
* @param {*} val
@ -154,14 +153,14 @@ export function isEmpty(val) {
/**
* 数组排序
*/
export const sortBy = (key) => {
export const sortBy = key => {
return (a, b) => (a[key] > b[key] ? 1 : b[key] > a[key] ? -1 : 0);
};
/**
* Object排序keys
*/
export const sortKeys = (obj) =>
export const sortKeys = obj =>
Object.keys(obj)
.sort()
.reduce((a, k2) => ({ ...a, [k2]: obj[k2] }), {});
@ -182,7 +181,7 @@ export const sortArrayByOrder = (items, keyName, keyOrder) => {
* 合并Object, 递归地
*/
export function merge(...objects) {
const isDeep = objects.some((obj) => obj !== null && typeof obj === 'object');
const isDeep = objects.some(obj => obj !== null && typeof obj === "object");
const result = objects[0] || (isDeep ? {} : objects[0]);
@ -191,19 +190,19 @@ export function merge(...objects) {
if (!obj) continue;
Object.keys(obj).forEach((key) => {
Object.keys(obj).forEach(key => {
const val = obj[key];
if (isDeep) {
if (Array.isArray(val)) {
result[key] = [].concat(Array.isArray(result[key]) ? result[key] : [result[key]], val);
} else if (typeof val === 'object') {
} else if (typeof val === "object") {
result[key] = merge(result[key], val);
} else {
result[key] = val;
}
} else {
result[key] = typeof val === 'boolean' ? val : result[key];
result[key] = typeof val === "boolean" ? val : result[key];
}
});
}
@ -218,7 +217,7 @@ export function merge(...objects) {
*/
export function groupBy(array = [], callback) {
return array.reduce((groups, item) => {
const key = typeof callback === 'function' ? callback(item) : item[callback];
const key = typeof callback === "function" ? callback(item) : item[callback];
if (!groups[key]) {
groups[key] = [];
@ -258,7 +257,7 @@ export function omit(object, keysToOmit) {
*/
export function cloneDeep(value) {
// return structuredClone(value);
if (typeof value !== 'object' || value === null) {
if (typeof value !== "object" || value === null) {
return value;
}
@ -315,20 +314,20 @@ export const fixToInt = curriedFix(0);
export function objectMapper(input, keyMap) {
// Loop through array mapping
if (Array.isArray(input)) {
return input.map((obj) => objectMapper(obj, keyMap));
return input.map(obj => objectMapper(obj, keyMap));
}
if (typeof input === 'object') {
if (typeof input === "object") {
const mappedObj = {};
Object.keys(input).forEach((key) => {
Object.keys(input).forEach(key => {
// Keep original keys not in keyMap
if (!keyMap[key]) {
mappedObj[key] = input[key];
}
// Handle array of maps
if (Array.isArray(keyMap[key])) {
keyMap[key].forEach((map) => {
keyMap[key].forEach(map => {
let value = input[key];
if (map.transform) value = map.transform(value);
mappedObj[map.key] = value;
@ -358,14 +357,14 @@ export function at(obj, path) {
let result;
if (Array.isArray(obj)) {
// array case
const indexes = path.split('.').map((i) => parseInt(i));
const indexes = path.split(".").map(i => parseInt(i));
result = [];
for (let i = 0; i < indexes.length; i++) {
result.push(obj[indexes[i]]);
}
} else {
// object case
const indexes = path.split('.').map((i) => i);
const indexes = path.split(".").map(i => i);
result = [obj];
for (let i = 0; i < indexes.length; i++) {
result = [result[0][indexes[i]]];
@ -392,7 +391,7 @@ export function flush(collection) {
}
return result;
}
if (typeof collection === 'object') {
if (typeof collection === "object") {
result = {};
const keys = Object.keys(collection);
len = keys.length;
@ -411,7 +410,7 @@ export function flush(collection) {
/**
* 千分位 格式化数字
*/
export const numberFormatter = (number) => {
export const numberFormatter = number => {
return new Intl.NumberFormat().format(number);
};
@ -431,30 +430,30 @@ export const getNestedValue = (obj, keyArr) => {
/**
* 计算笛卡尔积
*/
export const cartesianProductArray = (arr, sep = '_', index = 0, prefix = '') => {
export const cartesianProductArray = (arr, sep = "_", index = 0, prefix = "") => {
let result = [];
if (index === arr.length) {
return [prefix];
}
arr[index].forEach((item) => {
arr[index].forEach(item => {
result = result.concat(cartesianProductArray(arr, sep, index + 1, prefix ? `${prefix}${sep}${item}` : `${item}`));
});
return result;
};
export const stringToColour = (str) => {
var hash = 0
export const stringToColour = str => {
var hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash)
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
var colour = '#'
var colour = "#";
for (let i = 0; i < 3; i++) {
var value = (hash >> (i * 8)) & 0xff
value = (value % 150) + 50
colour += ('00' + value.toString(16)).substr(-2)
}
return colour
var value = (hash >> (i * 8)) & 0xff;
value = (value % 150) + 50;
colour += ("00" + value.toString(16)).substr(-2);
}
return colour;
};
export const debounce = (func, wait, immediate) => {
var timeout;
@ -468,44 +467,41 @@ export const debounce = (func, wait, immediate) => {
if (!immediate) func.apply(context, args);
}, wait);
};
}
};
export const removeFormattingChars = (str) => {
export const removeFormattingChars = str => {
const regex = /[\r\n\t\v\f]/g;
str = str.replace(regex, ' ');
str = str.replace(regex, " ");
// Replace more than four consecutive spaces with a single space
str = str.replace(/\s{4,}/g, ' ');
str = str.replace(/\s{4,}/g, " ");
return str;
}
};
export const olog = (text, ...args) => {
console.log(
`%c ${text} `,
'background:#fb923c ; padding: 1px; border-radius: 3px; color: #fff',...args
);
console.log(`%c ${text} `, "background:#fb923c ; padding: 1px; border-radius: 3px; color: #fff", ...args);
};
export const sanitizeFilename = (str) => {
export const sanitizeFilename = str => {
// Remove whitespace and replace with hyphens
str = str.replace(/\s+/g, '-');
str = str.replace(/\s+/g, "-");
// Remove invalid characters and replace with hyphens
str = str.replace(/[^a-zA-Z0-9.-]/g, '-');
str = str.replace(/[^a-zA-Z0-9.-]/g, "-");
// Replace consecutive hyphens with a single hyphen
str = str.replace(/-+/g, '-');
str = str.replace(/-+/g, "-");
// Trim leading and trailing hyphens
str = str.replace(/^-+|-+$/g, '');
str = str.replace(/^-+|-+$/g, "");
return str;
}
};
export const formatBytes = (bytes, decimals = 2) => {
if (bytes === 0) return '';
if (bytes === 0) return "";
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
};
export const calcCacheSizes = async () => {
try {
@ -514,14 +510,14 @@ export const calcCacheSizes = async () => {
let indexedDBSize = 0;
// 1. Get the service worker cache size
if ('caches' in window) {
if ("caches" in window) {
const cacheNames = await caches.keys();
for (const name of cacheNames) {
const cache = await caches.open(name);
const requests = await cache.keys();
for (const request of requests) {
const response = await cache.match(request);
swCacheSize += Number(response.headers.get('Content-Length')) || 0;
swCacheSize += Number(response.headers.get("Content-Length")) || 0;
}
}
}
@ -555,17 +551,17 @@ export const calcCacheSizes = async () => {
return { swCacheSize, diskCacheSize, indexedDBSize, totalSize: Number(swCacheSize) + Number(diskCacheSize) + indexedDBSize };
} catch (error) {
console.error('Error getting cache sizes:', error);
console.error("Error getting cache sizes:", error);
}
};
export const clearAllCaches = async (cb) => {
export const clearAllCaches = async cb => {
try {
// 1. Clear the service worker cache
if ('caches' in window) {
if ("caches" in window) {
// if (navigator.serviceWorker) {
const cacheNames = await caches.keys();
await Promise.all(cacheNames.map((name) => caches.delete(name)));
await Promise.all(cacheNames.map(name => caches.delete(name)));
}
// 2. Clear the disk cache (HTTP cache)
@ -577,38 +573,43 @@ export const clearAllCaches = async (cb) => {
// 3. Clear the IndexedDB cache
const indexedDBNames = await window.indexedDB.databases();
await Promise.all(indexedDBNames.map((dbName) => window.indexedDB.deleteDatabase(dbName.name)));
await Promise.all(indexedDBNames.map(dbName => window.indexedDB.deleteDatabase(dbName.name)));
// Unregister the service worker
const registration = await navigator.serviceWorker.getRegistration();
if (registration) {
await registration.unregister();
console.log('Service worker unregistered');
console.log("Service worker unregistered");
} else {
console.log('No service worker registered');
console.log("No service worker registered");
}
if (typeof cb === 'function' ) {
if (typeof cb === "function") {
cb();
}
} catch (error) {
console.error('Error clearing caches or unregistering service worker:', error);
console.error("Error clearing caches or unregistering service worker:", error);
}
};
export const loadScript = (src) => {
export const loadScript = src => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.type = 'text/javascript';
const script = document.createElement("script");
script.type = "text/javascript";
script.onload = resolve;
script.onerror = reject;
script.crossOrigin = 'anonymous';
script.crossOrigin = "anonymous";
script.src = src;
if (document.head.append) {
document.head.append(script);
} else {
document.getElementsByTagName('head')[0].appendChild(script);
document.getElementsByTagName("head")[0].appendChild(script);
}
});
};
//格式化为冒号时间2010转为20:10
export const formatColonTime = text => {
const hours = text.substring(0, 2);
const minutes = text.substring(2);
return `${hours}:${minutes}`;
};

@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
import { Grid, Divider, Layout, Spin, Input, Col, Row, Space, List, Table } from "antd";
import { PhoneOutlined, CustomerServiceOutlined, AudioOutlined } from "@ant-design/icons";
import { useParams, useHref, useNavigate, NavLink } from "react-router-dom";
import { isEmpty } from "@/utils/commons";
import { isEmpty, formatColonTime } from "@/utils/commons";
import dayjs from "dayjs";
import SearchForm from "@/components/SearchForm";
@ -54,21 +54,19 @@ const planListColumns = [
title: "起飞时间",
key: "FlightTimeStart",
dataIndex: "FlightTimeStart",
render: text => {
const hours = text.substring(0, 2);
const minutes = text.substring(2);
return `${hours}:${minutes}`;
},
render: text => formatColonTime(text),
},
{
title: "落地时间",
key: "FlightTimeEnd",
dataIndex: "FlightTimeEnd",
render: text => {
const hours = text.substring(0, 2);
const minutes = text.substring(2);
return `${hours}:${minutes}`;
render: text => formatColonTime(text),
},
{
title: "是否出票",
key: "COLD_PlanVEI_SN",
dataIndex: "COLD_PlanVEI_SN",
render: (text, record) => "否",
},
{
title: "操作",
@ -82,7 +80,7 @@ const Airticket = props => {
const href = useHref();
const navigate = useNavigate();
const { phonenumber } = useParams();
const {travelAgencyId, } = usingStorage();
const { travelAgencyId } = usingStorage();
const [getPlanList, planList, loading] = airTicketStore(state => [state.getPlanList, state.planList, state.loading]);
const [phone_number, setPhone_number] = useState(phonenumber);
const showTotal = total => `合计 ${total} `;

@ -1,40 +1,194 @@
import { useState, useEffect } from "react";
import { Grid, Divider, Layout, Spin, Input, Col, Row, Space, List, Table, Button } from "antd";
import { PhoneOutlined, CustomerServiceOutlined, AudioOutlined } from "@ant-design/icons";
import { Grid, Divider, Layout, Form, Input, Col, Row, Space, Collapse, Table, Button } from "antd";
import { PhoneOutlined, CustomerServiceOutlined, AudioOutlined, ArrowUpOutlined, ArrowDownOutlined } from "@ant-design/icons";
import { useParams, useHref, useNavigate, NavLink } from "react-router-dom";
import { isEmpty } from "@/utils/commons";
import dayjs from "dayjs";
import { HT_HOST, OFFICEWEBVIEWERURL } from "@/config";
import { isEmpty, formatColonTime } from "@/utils/commons";
import { OFFICEWEBVIEWERURL } from "@/config";
import airTicketStore from "@/stores/Airticket";
import useAuthStore from "@/stores/Auth";
import { usingStorage } from "@/hooks/usingStorage";
const AirticketPlan = props => {
const href = useHref();
const navigate = useNavigate();
const { coli_sn } = useParams();
const [travelAgencyId, loginToken] = useAuthStore(
state => state.loginUser.travelAgencyId,
state => state.loginUser.loginToken
const { travelAgencyId, loginToken } = usingStorage();
const [getPlanDetail, planDetail, getGuestList, guestList, loading] = airTicketStore(state => [state.getPlanDetail, state.planDetail, state.getGuestList, state.guestList, state.loading]);
const reservationUrl = `https://p9axztuwd7x8a7.mycht.cn/Service_BaseInfoWeb/FlightPlanDocx?GRI_SN=${coli_sn}&VEI_SN=${travelAgencyId}`;
const reservationPreviewUrl = OFFICEWEBVIEWERURL + encodeURIComponent(reservationUrl);
console.log(reservationPreviewUrl);
const Airticket_form = props => {
const aitInfo = props.airInfo;
return (
<>
<Form
name="basic"
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
style={{
maxWidth: 600,
}}
initialValues={{
remember: true,
}}
// onFinish={onFinish}
// onFinishFailed={onFinishFailed}
autoComplete="off">
<Form.Item label="日期" name="username" rules={[{ required: true }]}>
<Input value={aitInfo.StartDate} />
</Form.Item>
<Form.Item label="城市" name="password" rules={[{ required: true }]}>
<Space.Compact>
<Input placeholder="出发" prefix={<ArrowUpOutlined />} value={aitInfo.FromCity} />
<Input placeholder="抵达" prefix={<ArrowDownOutlined />} value={aitInfo.ToCity} />
</Space.Compact>
</Form.Item>
<Form.Item label="航班" name="password" rules={[{ required: true }]}>
<Space.Compact>
<Input placeholder="航空公司" />
<Input placeholder="航班号" value={aitInfo.FlightNo} />
</Space.Compact>
</Form.Item>
<Form.Item label="出发" name="password" rules={[{ required: true }]}>
<Space.Compact>
<Input placeholder="机场" />
<Input placeholder="航站楼" />
<Input placeholder="出发时间" value={formatColonTime(aitInfo.FlightTimeStart)} />
</Space.Compact>
</Form.Item>
<Form.Item label="抵达" name="password" rules={[{ required: true }]}>
<Space.Compact>
<Input placeholder="机场" />
<Input placeholder="航站楼" />
<Input placeholder="抵达时间" value={formatColonTime(aitInfo.FlightTimeEnd)} />
</Space.Compact>
</Form.Item>
<Form.Item label="仓位和行李" name="password">
<Space.Compact>
<Input placeholder="仓位" />
<Input placeholder="行李" />
</Space.Compact>
</Form.Item>
{/* <Form.Item
wrapperCol={{
offset: 8,
span: 16,
}}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item> */}
</Form>
<Divider />
<Table bordered={true} rowKey="id" columns={guestListColumns} dataSource={guestList} loading={loading} pagination={false} />
</>
);
const [getPlanList, planList, loading] = airTicketStore(state => [state.getPlanList, state.planList, state.loading]);
const [loginUser] = useAuthStore(state => [state.loginUser]);
};
const reservationUrl = `https://p9axztuwd7x8a7.mycht.cn/service-fileServer/DownloadPlanDoc?GRI_SN=${coli_sn}&VEI_SN=${travelAgencyId}&token=${loginToken}&FileType=1`;
const detail_items = () => {
return planDetail
? planDetail.map(item => {
return {
key: item.id,
label: `${item.StartDate} 计划: ${item.FlightInfo}`,
children: <Airticket_form airInfo={item} />,
};
})
: [];
};
const reservationPreviewUrl = OFFICEWEBVIEWERURL + encodeURIComponent(reservationUrl);
const guestListColumns = [
{
title: "姓名",
key: "MEI_Name",
dataIndex: "MEI_Name",
},
{
title: "证件类型",
key: "MEI_PassportType",
dataIndex: "MEI_PassportType",
},
{
title: "证件号",
key: "MEI_PassportNo",
dataIndex: "MEI_PassportNo",
},
{
title: "证件有效期",
key: "MEI_PassportValidDate",
dataIndex: "MEI_PassportValidDate",
},
{
title: "性别",
key: "MEI_Gender",
dataIndex: "MEI_Gender",
},
{
title: "年龄",
key: "MEI_age",
dataIndex: "MEI_age",
},
{
title: "国籍",
key: "MEI_Country",
dataIndex: "MEI_Country",
},
{
title: "票号",
key: "MEI_SN",
dataIndex: "MEI_SN",
},
{
title: "PNR",
key: "MEI_SN",
dataIndex: "MEI_SN",
},
{
title: "机票费用RMB含基建和税",
key: "MEI_SN",
dataIndex: "MEI_SN",
},
{
title: "折扣",
key: "MEI_SN",
dataIndex: "MEI_SN",
},
{
title: "手续费",
key: "MEI_SN",
dataIndex: "MEI_SN",
},
{
title: "机票类型(成人/儿童/婴儿)",
key: "MEI_SN",
dataIndex: "MEI_SN",
},
];
useEffect(() => {}, []);
useEffect(() => {
getPlanDetail(travelAgencyId, coli_sn);
getGuestList(travelAgencyId, coli_sn);
console.log(detail_items());
}, []);
return (
<Space direction="vertical" style={{ width: "100%" }}>
<Row>
<Col md={24} lg={24} xxl={24} style={{ height: "100%" }}>
<iframe id="msdoc-iframe-reservation" title="msdoc-iframe-reservation" src={reservationPreviewUrl} frameBorder="0" style={{ width: "100%", height: "600px" }}></iframe>
{/* <iframe id="msdoc-iframe-reservation" title="msdoc-iframe-reservation" src={reservationPreviewUrl} frameBorder="0" style={{ width: "100%", height: "600px" }}></iframe> */}
<Button type="link" target="_blank" href={reservationUrl}>
下载
</Button>
</Col>
<Divider orientation="left">出票信息</Divider>
<Col md={24} lg={24} xxl={24}>
<Collapse items={detail_items()} />
</Col>
</Row>
</Space>
);

Loading…
Cancel
Save