liuhj преди 1 месец
родител
ревизия
2ea63ab52c
променени са 4 файла, в които са добавени 280 реда и са изтрити 11 реда
  1. 51 2
      src/components/Finance/Cost.vue
  2. 1 2
      src/components/Finance/FeesPage.vue
  3. 1 1
      src/components/OP/NewAirTicket.vue
  4. 227 6
      src/store/flightParser.js

+ 51 - 2
src/components/Finance/Cost.vue

@@ -5335,7 +5335,6 @@ export default {
             return sum;
         },
         matchRooms(hotelRooms, flights, roomTypes, flightType, result) {
-            console.log(hotelRooms, flights, roomTypes, flightType, result, 'matchRoomsmatchRooms');
             for (let roomType of roomTypes) {
                 while (hotelRooms[roomType] > 0 && flights[flightType] > 0) {
                     hotelRooms[roomType]--;
@@ -6492,6 +6491,7 @@ export default {
             this.CheckBoxListSelect.filter(item => item.cbType == 'Top')[0].cbValues = topResultArr;
         },
         GivePeopleNumber() {
+            console.log(this.AGroupCostParameter,this.BGroupCostParameter)
             var number = this.grouptitleinfo.visitPNumber;
             if (this.AGroupCostParameter.visaRS == 0) {
                 this.AGroupCostParameter.visaRS = number;
@@ -6508,7 +6508,38 @@ export default {
             if (this.AGroupCostParameter.gwrs == 0) {
                 this.AGroupCostParameter.gwrs = number;
             }
-            //b
+            //A段酒店
+            console.log(this.costTypeHotelNumbers,this.costTypevalue)
+            if(this.costTypevalue=='A'){
+                const numberzong = this.costTypeHotelNumbers.filter(item => item.type == 'Default');
+                if (this.AGroupCostParameter.tbrNumber == 0) {
+                    this.AGroupCostParameter.tbrNumber = numberzong[0].tbr;
+                }
+                if (this.AGroupCostParameter.sgrNumber == 0) {
+                    this.AGroupCostParameter.sgrNumber = numberzong[0].sgr;
+                }
+                if (this.AGroupCostParameter.jsesNumber == 0) {
+                    this.AGroupCostParameter.jsesNumber = numberzong[0].jses;
+                }
+                if (this.AGroupCostParameter.suiteNumber == 0) {
+                    this.AGroupCostParameter.suiteNumber = numberzong[0].suite;
+                }
+            }else if(this.costTypevalue=='B'){
+                const numberzongA = this.costTypeHotelNumbers.filter(item => item.type == 'A');
+                if (this.AGroupCostParameter.tbrNumber == 0) {
+                    this.AGroupCostParameter.tbrNumber = numberzongA[0].tbr ;
+                }
+                if (this.AGroupCostParameter.sgrNumber == 0) {
+                    this.AGroupCostParameter.sgrNumber = numberzongA[0].sgr;
+                }
+                if (this.AGroupCostParameter.jsesNumber == 0) {
+                    this.AGroupCostParameter.jsesNumber = numberzongA[0].jses;
+                }
+                if (this.AGroupCostParameter.suiteNumber == 0) {
+                    this.AGroupCostParameter.suiteNumber = numberzongA[0].suite;
+                }
+            }
+            //b段赋值
             var numbers=this.BGroupCostParameter.costTypenumber
             if (this.BGroupCostParameter.visaRS == 0) {
                 this.BGroupCostParameter.visaRS = numbers;
@@ -6525,6 +6556,20 @@ export default {
             if (this.BGroupCostParameter.gwrs == 0) {
                 this.BGroupCostParameter.gwrs = numbers;
             }
+            //b段酒店赋值
+            const numberzongB = this.costTypeHotelNumbers.filter(item => item.type == 'B');
+            if (this.BGroupCostParameter.tbrNumber == 0) {
+                this.BGroupCostParameter.tbrNumber = numberzongB[0].tbr ;
+            }
+            if (this.BGroupCostParameter.sgrNumber == 0) {
+                this.BGroupCostParameter.sgrNumber = numberzongB[0].sgr;
+            }
+            if (this.BGroupCostParameter.jsesNumber == 0) {
+                this.BGroupCostParameter.jsesNumber = numberzongB[0].jses;
+            }
+            if (this.BGroupCostParameter.suiteNumber == 0) {
+                this.BGroupCostParameter.suiteNumber = numberzongB[0].suite;
+            }
         },
         lableSetPrice(lable, total, single) {
             //遍历this.columnTotalData
@@ -7362,6 +7407,10 @@ export default {
         }
 
         document.querySelectorAll('.el-table__footer')[0].style.display = "none";
+        // const footers = document.querySelectorAll('.el-table__footer');
+        // if (footers && footers.length > 0 && footers[0]) {
+        //     footers[0].style.display = "none";
+        // }
         if (costLoadData) {
             var JSONP = JSON.parse(costLoadData);
             var diidP = Number(JSONP.diid);

+ 1 - 2
src/components/Finance/FeesPage.vue

@@ -193,7 +193,7 @@ export default {
         },
         //获取详情
         getPostSearchGrpCreditCardPayment() {
-            console.log(this.activeName)
+            this.tableData = [];
             var url = "/api/Groups/PostSearchGrpCreditCardPayment"
             var that = this
             this.$axios({
@@ -211,7 +211,6 @@ export default {
                     auditStatus: that.formInline.Status
                 }
             }).then(function (res) {
-                console.log(res);
                 if (res.data.code == 200) {
                     that.tableData = res.data.data.data.detailList;
                     document.querySelector('.payable').innerHTML = res.data.data.data.totalStr1;

+ 1 - 1
src/components/OP/NewAirTicket.vue

@@ -227,7 +227,7 @@
                 <div style="display: flex;flex-wrap: wrap;">
                     <div style="width: 385px;">
                         <el-form-item label="团组名称:" label-width="150px">
-                            <el-select v-model="DiIdSelect" clearable filterable placeholder="团组选择" remote :remote-method="GroupFeeKeywordSearch" :loading="selectLoading" 
+                            <el-select v-model="DiIdSelect" filterable placeholder="团组选择" remote :remote-method="GroupFeeKeywordSearch" :loading="selectLoading" 
                                 @change="AirTicketResChange" :disabled="isShow" style="width: 100%;">
                                 <el-option v-for="item in AirTicketResSelectDatas" :key="item.id" :label="item.teamName"
                                     :value="item.id">

+ 227 - 6
src/store/flightParser.js

@@ -13,7 +13,7 @@ export function parseFlightCode(code) {
   let codeStr = code.trim()
   
   // 去除开头的序号(如 "1."、"2."、"3."、"4." 等)
-  codeStr = codeStr.replace(/^\d+\./, '')
+  codeStr = codeStr.replace(/^\d+\.\s*/, '')
   
   if (codeStr.length === 0) {
     return { error: '航班代码不能为空' }
@@ -22,6 +22,12 @@ export function parseFlightCode(code) {
   // 按空格分割
   const parts = codeStr.trim().split(/\s+/)
   
+  // 黑屏格式:航班号 舱位 星期日期 航线 状态 起飞 到达 [机型/经停/餐食/电子客票/航站楼等]
+  // 仅在原有字段数量无法正确解析,或末尾包含黑屏航站楼标识时启用,避免影响原有识别逻辑
+  if (shouldUseBlackScreenParser(parts)) {
+    return parseBlackScreenFormat(parts)
+  }
+  
   // 根据字段数量判断格式
   if (parts.length === 9) {
     // 格式: 航班号 操作码+日期 航线 起飞时间 到达时间 预订码 航站楼 机型 时长
@@ -34,21 +40,156 @@ export function parseFlightCode(code) {
     // 格式: 航班号 操作码+日期 航线 起飞时间 到达时间 航站楼 预订码 机型 时长
     // 例如: CA431 TU27MAY TFUFRA 0135 0645 T1 1 359 11H10M
     return parseFormat11(parts)
+  } else if (parts.length === 12) {
+    // 格式: 航班号 舱位 操作码+日期 航线 状态码 起飞时间 到达时间 机型 经停 服务等级 航站楼 序号
+    // 例如: LH172 U WE10JUN FRABER DK1 0645 0755 321 0 E 1 1
+    return parseFormat12(parts)
   } else {
     return { 
       error: '航班代码格式错误,字段数量不正确',
-      expected: '9、10或11个字段',
+      expected: '9、10、11、12个字段或标准黑屏格式',
       received: parts.length + '个字段',
       parts: parts
     }
   }
 }
 
+/**
+ * 判断是否为标准黑屏格式:
+ * 航班号 舱位 星期日期 航线 状态码 起飞时间 到达时间 ...
+ */
+function isBlackScreenFormat(parts) {
+  return parts.length >= 7 &&
+    /^[A-Z0-9]{2,8}$/.test(parts[0]) &&
+    /^[A-Z][A-Z0-9]?$/.test(parts[1]) &&
+    /^[A-Z]{2}\d{2}[A-Z]{3}$/.test(parts[2]) &&
+    /^[A-Z]{6}$/.test(parts[3]) &&
+    /^[A-Z]{2}\d+$/.test(parts[4]) &&
+    /^\d{4}$/.test(parts[5]) &&
+    /^\d{4}(\+\d+)?$/.test(parts[6])
+}
+
+/**
+ * 是否使用新增黑屏解析器。
+ * - 7/13/14等原逻辑不支持的黑屏字段数直接启用
+ * - 10/11字段若第3列才是日期,原解析会错位,启用
+ * - 12字段保留原 parseFormat12;仅当扩展字段中出现 T2--、--T2、T1 等航站楼标识时启用
+ */
+function shouldUseBlackScreenParser(parts) {
+  if (!isBlackScreenFormat(parts)) return false
+
+  if (parts.length === 12) {
+    return parts.slice(7).some(isTerminalToken)
+  }
+
+  return parts.length !== 9
+}
+
+/**
+ * 解析黑屏航班格式
+ * 例:
+ * MU5191 Y SA09AUG TFUJHG DK1 0925 1105 32L 0 R E T2--
+ * CA4418 Y WE13AUG KMGCTU DK1 1750 1925 32N 0 R E --T2
+ * 3U8673 B SU28SEP CTUKMG HK1 1350 1540
+ */
+function parseBlackScreenFormat(parts) {
+  const [
+    flightNumber,
+    cabin,
+    actionDate,
+    route,
+    statusCode,
+    departureTime,
+    arrivalTimeRaw,
+    ...extras
+  ] = parts
+
+  const actionCode = actionDate.slice(0, 2)
+  const dateStr = actionDate.slice(2)
+  const origin = route.slice(0, 3)
+  const destination = route.slice(3)
+
+  let arrivalTime = arrivalTimeRaw
+  let plusDays = 0
+  if (arrivalTimeRaw && arrivalTimeRaw.includes('+')) {
+    const [time, days] = arrivalTimeRaw.split('+')
+    arrivalTime = time
+    plusDays = parseInt(days)
+  }
+
+  const terminalInfo = parseBlackScreenTerminals(extras)
+  const nonTerminalExtras = extras.filter(item => !isTerminalToken(item))
+  const aircraft = nonTerminalExtras[0] || ''
+  const stopCount = nonTerminalExtras.find(item => /^\d+$/.test(item)) || ''
+  const remainingExtras = nonTerminalExtras.filter((item, index) => index !== 0 && item !== stopCount)
+  const serviceClass = remainingExtras.length > 0 ? remainingExtras[remainingExtras.length - 1] : ''
+  const sequence = remainingExtras.length > 1 ? remainingExtras.slice(0, -1).join(' ') : ''
+
+  const duration = calculateDuration(departureTime, arrivalTime, plusDays)
+
+  return buildFlightInfo({
+    flightNumber,
+    actionCode,
+    dateStr,
+    origin,
+    destination,
+    departureTime,
+    arrivalTime,
+    terminal: terminalInfo.arrivalTerminal,
+    bookingCode: terminalInfo.departureTerminal,
+    aircraft,
+    duration,
+    plusDays,
+    cabin,
+    statusCode,
+    stopCount,
+    serviceClass,
+    sequence,
+    blackScreenExtras: extras
+  })
+}
+
+/**
+ * 黑屏航站楼标识:
+ * T2-- 表示出发航站楼 T2;--T2 表示到达航站楼 T2;T1 作为单独末尾字段时按到达航站楼处理
+ */
+function isTerminalToken(value) {
+  return /^T\d+--$/.test(value) ||
+    /^--T\d+$/.test(value) ||
+    /^T\d+$/.test(value) ||
+    /^T\d+T\d+$/.test(value)
+}
+
+function parseBlackScreenTerminals(extras) {
+  let departureTerminal = ''
+  let arrivalTerminal = ''
+
+  extras.forEach(item => {
+    if (/^T\d+--$/.test(item)) {
+      departureTerminal = item.replace('--', '')
+    } else if (/^--T\d+$/.test(item)) {
+      arrivalTerminal = item.replace('--', '')
+    } else if (/^T\d+$/.test(item)) {
+      arrivalTerminal = item
+    } else if (/^T\d+T\d+$/.test(item)) {
+      const terminals = item.match(/T\d+/g) || []
+      departureTerminal = terminals[0] || departureTerminal
+      arrivalTerminal = terminals[1] || arrivalTerminal
+    }
+  })
+
+  return {
+    departureTerminal,
+    arrivalTerminal
+  }
+}
+
 /**
  * 解析9字段格式(最常用)
  * CA878 SA31MAY CPHPEK 1905 1000+1 3 T3 359 08H55M
  */
 function parseFormat9(parts) {
+  console.log(parts) // 调试用,确认文件被正确加载
   const [flightNumber, actionDate, route, departureTime, arrivalTimeRaw, bookingCode, terminal, aircraft, duration] = parts
   
   // 提取操作码和日期
@@ -137,6 +278,77 @@ function parseFormat11(parts) {
   })
 }
 
+/**
+ * 解析12字段格式
+ * LH172 U WE10JUN FRABER DK1 0645 0755 321 0 E 1 1
+ */
+function parseFormat12(parts) {
+  const [
+    flightNumber,
+    cabin,
+    actionDate,
+    route,
+    statusCode,
+    departureTime,
+    arrivalTimeRaw,
+    aircraft,
+    stopCount,
+    serviceClass,
+    terminal,
+    sequence
+  ] = parts
+
+  const actionCode = actionDate.slice(0, 2)
+  const dateStr = actionDate.slice(2)
+  const origin = route.slice(0, 3)
+  const destination = route.slice(3)
+
+  let arrivalTime = arrivalTimeRaw
+  let plusDays = 0
+  if (arrivalTimeRaw && arrivalTimeRaw.includes('+')) {
+    const [time, days] = arrivalTimeRaw.split('+')
+    arrivalTime = time
+    plusDays = parseInt(days)
+  }
+
+  const duration = calculateDuration(departureTime, arrivalTime, plusDays)
+
+  return buildFlightInfo({
+    flightNumber, actionCode, dateStr, origin, destination,
+    departureTime, arrivalTime, terminal, bookingCode: statusCode, aircraft, duration,
+    plusDays, cabin, statusCode, stopCount, serviceClass, sequence
+  })
+}
+
+/**
+ * 根据起飞和到达时间计算航班时长
+ */
+function calculateDuration(departureTime, arrivalTime, plusDays = 0) {
+  const depHour = parseInt(departureTime.slice(0, 2))
+  const depMinute = parseInt(departureTime.slice(2))
+  const arrHour = parseInt(arrivalTime.slice(0, 2))
+  const arrMinute = parseInt(arrivalTime.slice(2))
+
+  if ([depHour, depMinute, arrHour, arrMinute].some(value => Number.isNaN(value))) {
+    return '00H00M'
+  }
+
+  const depTotalMinutes = depHour * 60 + depMinute
+  const arrTotalMinutes = arrHour * 60 + arrMinute
+  let totalMinutes = arrTotalMinutes - depTotalMinutes
+
+  if (plusDays > 0) {
+    totalMinutes += plusDays * 24 * 60
+  } else if (totalMinutes < 0) {
+    totalMinutes += 24 * 60
+  }
+
+  const hours = Math.floor(totalMinutes / 60)
+  const minutes = totalMinutes % 60
+
+  return hours.toString().padStart(2, '0') + 'H' + minutes.toString().padStart(2, '0') + 'M'
+}
+
 /**
  * 构建航班信息对象
  */
@@ -144,7 +356,7 @@ function buildFlightInfo(params) {
   const {
     flightNumber, actionCode, dateStr, origin, destination,
     departureTime, arrivalTime, terminal, bookingCode, aircraft, duration,
-    plusDays = 0
+    plusDays = 0, cabin, statusCode, stopCount, serviceClass, sequence
   } = params
   
   // 解析日期
@@ -220,6 +432,11 @@ function buildFlightInfo(params) {
       formatted: formatTime(arrHour, arrMinute)
     },
     terminal: terminal,
+    cabin: cabin,
+    statusCode: statusCode,
+    stopCount: stopCount,
+    serviceClass: serviceClass,
+    sequence: sequence,
     // bookingCode: parseInt(bookingCode),
     bookingCode: bookingCode,
     aircraft: aircraft,
@@ -382,7 +599,11 @@ function getAirportName(code) {
  */
 export function validateFlightCode(code) {
   if (!code || typeof code !== 'string') return false
-  var cleanCode = code.trim().replace(/^\d+\./, '')
+  var cleanCode = code.trim().replace(/^\d+\.\s*/, '')
   var parts = cleanCode.split(/\s+/)
-  return parts.length === 9 || parts.length === 10 || parts.length === 11
-}
+  return parts.length === 9 ||
+    parts.length === 10 ||
+    parts.length === 11 ||
+    parts.length === 12 ||
+    isBlackScreenFormat(parts)
+}