From beddc8530aaf1d396cf3bc8a932fa67e54b96e64 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期日, 19 四月 2026 09:05:35 +0800
Subject: [PATCH] 线路管理班次设置 自动生成行程表

---
 ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_add.html  |   44 ++++++++
 ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_edit.html |   50 +++++++++
 ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_info.js |  192 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 276 insertions(+), 10 deletions(-)

diff --git a/ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_add.html b/ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_add.html
index 999727d..734754a 100644
--- a/ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_add.html
+++ b/ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_add.html
@@ -161,6 +161,38 @@
             <div class="row">
                 <div class="col-sm-11">
                     <div class="form-group">
+                        <label class="col-sm-2 control-label">批量生成:</label>
+                        <label class="col-sm-1 control-label">始发时间:</label>
+                        <div class="col-sm-2">
+                            <input type="text" name="firstShiftTime" id="firstShiftTime" class="form-control" placeholder="始发时间"/>
+                        </div>
+                        <label class="col-sm-1 control-label">末班时间:</label>
+                        <div class="col-sm-2">
+                            <input type="text" name="lastShiftTime" id="lastShiftTime" class="form-control" placeholder="末班时间"/>
+                        </div>
+
+                    </div>
+                    <div class="form-group">
+                        <label class="col-sm-2 control-label"></label>
+                        <label class="col-sm-1 control-label">间隔:</label>
+                        <div class="col-sm-2">
+                            <select class="form-control" id="shiftGap">
+                                <option value="">选择间隔</option>
+                                <option value="30">30分钟</option>
+                                <option value="60">60分钟</option>
+                                <option value="90">90分钟</option>
+                                <option value="120">120分钟</option>
+                            </select>
+                        </div>
+                        <label class="col-sm-1 control-label">车次数:</label>
+                        <div class="col-sm-2">
+                            <input type="text" name="batchCarNum" id="batchCarNum" class="form-control"/>
+                        </div>
+                        <div class="col-sm-2">
+                            <#button btnCss="info" name="生成" id="batchEnsure" icon="fa-check" clickFun="TLineInfoDlg.generateShiftList()"/>
+                        </div>
+                    </div>
+                    <div class="form-group">
                         <label class="col-sm-2 control-label">班次时间:</label>
                         <div class="col-sm-2">
                             <input type="text" name="shiftTime" id="shiftTime" class="form-control" placeholder="选择时间"/>
@@ -170,7 +202,7 @@
                             <input type="text" name="carNum" id="carNum" class="form-control" />
                         </div>
                         <div class="col-sm-2">
-                            <#button btnCss="info" name="添加" id="ensure" icon="fa-check" clickFun="TLineInfoDlg.addShift()"/>
+                            <#button btnCss="info" name="手动添加" id="ensure" icon="fa-check" clickFun="TLineInfoDlg.addShift()"/>
                         </div>
                     </div>
                     <div class="form-group">
@@ -225,6 +257,16 @@
         ,range: '-'
         ,format: 'HH:mm'
     });
+    laydate.render({
+        elem: '#firstShiftTime'
+        ,type: 'time'
+        ,format: 'HH:mm'
+    });
+    laydate.render({
+        elem: '#lastShiftTime'
+        ,type: 'time'
+        ,format: 'HH:mm'
+    });
     var regDouble = /^(0|[1-9]\d{0,2})(\.\d{1,2})?$/;
     var regXiShu = /^(0(\.\d{1,2})?|1?)$/;
     var regXiShu1 = /^([1-9]{1,})(\.\d{1,2})?$/;
diff --git a/ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_edit.html b/ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_edit.html
index 0f0209e..9248906 100644
--- a/ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_edit.html
+++ b/ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_edit.html
@@ -170,6 +170,37 @@
             <div class="row">
                 <div class="col-sm-11">
                     <div class="form-group">
+                        <label class="col-sm-2 control-label">批量生成:</label>
+                        <label class="col-sm-1 control-label">始发时间:</label>
+                        <div class="col-sm-2">
+                            <input type="text" name="firstShiftTime" id="firstShiftTime" class="form-control" placeholder="始发时间"/>
+                        </div>
+                        <label class="col-sm-1 control-label">末班时间:</label>
+                        <div class="col-sm-2">
+                            <input type="text" name="lastShiftTime" id="lastShiftTime" class="form-control" placeholder="末班时间"/>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label class="col-sm-2 control-label"></label>
+                        <label class="col-sm-1 control-label">间隔:</label>
+                        <div class="col-sm-2">
+                            <select class="form-control" id="shiftGap">
+                                <option value="">选择间隔</option>
+                                <option value="30">30分钟</option>
+                                <option value="60">60分钟</option>
+                                <option value="90">90分钟</option>
+                                <option value="120">120分钟</option>
+                            </select>
+                        </div>
+                        <label class="col-sm-1 control-label">车次数:</label>
+                        <div class="col-sm-2">
+                            <input type="text" name="batchCarNum" id="batchCarNum" class="form-control"/>
+                        </div>
+                        <div class="col-sm-2">
+                            <#button btnCss="info" name="生成" id="batchEnsure" icon="fa-check" clickFun="TLineInfoDlg.generateShiftList()"/>
+                        </div>
+                    </div>
+                    <div class="form-group">
                         <label class="col-sm-2 control-label">班次时间:</label>
                         <div class="col-sm-2">
                             <input type="text" name="shiftTime" id="shiftTime" class="form-control" placeholder="选择时间"/>
@@ -179,7 +210,7 @@
                             <input type="text" name="carNum" id="carNum" class="form-control" />
                         </div>
                         <div class="col-sm-2">
-                            <#button btnCss="info" name="添加" id="ensure" icon="fa-check" clickFun="TLineInfoDlg.addShift()"/>
+                            <#button btnCss="info" name="手动添加" id="ensure" icon="fa-check" clickFun="TLineInfoDlg.addShift()"/>
                         </div>
                     </div>
                     <div class="form-group">
@@ -200,7 +231,12 @@
                                     <tr class="shiftValueClass">
                                         <td style="text-align: center;"><input type="hidden" id="time2Value" name="time2Value" value="${obj.addTime}">${obj.addTime}</td>
                                         <td style="text-align: center;"><input type="hidden" id="shiftTimeValue" name="shiftTimeValue" value="${obj.startTime} - ${obj.endTime}">${obj.startTime} - ${obj.endTime}</td>
-                                        <td style="text-align: center;"><input type="hidden" id="carNumValue" name="carNumValue" value="${obj.carNum}">${obj.carNum}</td>
+                                        <td style="text-align: center;">
+                                            <input type="hidden" id="carNumValue" name="carNumValue" value="${obj.carNum}">
+                                            <button type="button" onclick="TLineInfoDlg.changeCarNum(this,-1)">-</button>
+                                            <input type="text" name="carNumEditValue" value="${obj.carNum}" oninput="TLineInfoDlg.onCarNumInput(this)" onblur="TLineInfoDlg.onCarNumBlur(this)" style="width:60px;text-align:center;margin:0 6px;">
+                                            <button type="button" onclick="TLineInfoDlg.changeCarNum(this,1)">+</button>
+                                        </td>
                                         <td style="text-align: center;"><button onclick="deleteSub(this)">移除</button></td>
                                     </tr>
                                     @}
@@ -240,6 +276,16 @@
         ,range: '-'
         ,format: 'HH:mm'
     });
+    laydate.render({
+        elem: '#firstShiftTime'
+        ,type: 'time'
+        ,format: 'HH:mm'
+    });
+    laydate.render({
+        elem: '#lastShiftTime'
+        ,type: 'time'
+        ,format: 'HH:mm'
+    });
     var regDouble = /^(([1-9]{1}\d*)|(0{1}))(\.\d{0,2})?$/;
     var regXiShu = /^(0(\.\d{1,2})?)$/;
     var regXiShu1 = /^([1-9]{1,})(\.\d{1,2})?$/;
diff --git a/ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_info.js b/ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_info.js
index 26cc99c..d8510b3 100644
--- a/ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_info.js
+++ b/ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_info.js
@@ -162,6 +162,9 @@
         Feng.error("请至少设置一条价格设置");
         return;
     }
+    if(!TLineInfoDlg.validateShiftCarNum()){
+        return;
+    }
     var shuArr=[];
     $(".shiftValueClass").each(function () {
         shuArr.push({
@@ -222,6 +225,9 @@
     });
     if(subArr.length <= 0){
         Feng.error("请至少设置一条价格设置");
+        return;
+    }
+    if(!TLineInfoDlg.validateShiftCarNum()){
         return;
     }
     var shuArr=[];
@@ -411,6 +417,9 @@
     }else if (!regInt.test(carNum)){
         Feng.info("车次数格式不正确");
         return;
+    }else if (parseInt(carNum, 10) <= 0){
+        Feng.info("车次数必须为正整数");
+        return;
     }
 
     times = shiftTime.split(" - ");
@@ -438,18 +447,187 @@
             return;
         }
     }
-    //封装数据
-    var str = '<tr class="shiftValueClass">' +
-        '<td style="text-align: center;"><input type="hidden" id="time2Value" name="time2Value" value="'+getNowFormatDate()+'">' + getNowFormatDate() + '</td>' +
-        '<td style="text-align: center;"><input type="hidden" id="shiftTimeValue" name="shiftTimeValue" value="'+shiftTime+'">'+shiftTime+'</td>' +
-        '<td style="text-align: center;"><input type="hidden" id="carNumValue" name="carNumValue" value="'+carNum+'">'+carNum+'</td>' +
-        '<td style="text-align: center;"><button onclick="deleteSub(this)">移除</button></td></tr>';
-    $("#shiftValue").append(str);
+    TLineInfoDlg.appendShiftRow(shiftTime, carNum);
     //清除数据
     $("#shiftTime").val("");
     $("#carNum").val("");
 }
 
+TLineInfoDlg.appendShiftRow = function (shiftTime, carNum) {
+    var str = '<tr class="shiftValueClass">' +
+        '<td style="text-align: center;"><input type="hidden" id="time2Value" name="time2Value" value="'+getNowFormatDate()+'">' + getNowFormatDate() + '</td>' +
+        '<td style="text-align: center;"><input type="hidden" id="shiftTimeValue" name="shiftTimeValue" value="'+shiftTime+'">'+shiftTime+'</td>' +
+        '<td style="text-align: center;">' +
+        '<input type="hidden" id="carNumValue" name="carNumValue" value="'+carNum+'">' +
+        '<button type="button" onclick="TLineInfoDlg.changeCarNum(this,-1)">-</button>' +
+        '<input type="text" name="carNumEditValue" value="'+carNum+'" oninput="TLineInfoDlg.onCarNumInput(this)" onblur="TLineInfoDlg.onCarNumBlur(this)" style="width:60px;text-align:center;margin:0 6px;">' +
+        '<button type="button" onclick="TLineInfoDlg.changeCarNum(this,1)">+</button>' +
+        '</td>' +
+        '<td style="text-align: center;"><button onclick="deleteSub(this)">移除</button></td></tr>';
+    $("#shiftValue").append(str);
+}
+
+TLineInfoDlg.normalizePositiveInt = function (numStr) {
+    var onlyNum = (numStr || "").replace(/[^\d]/g, "");
+    onlyNum = onlyNum.replace(/^0+/, "");
+    return onlyNum;
+}
+
+TLineInfoDlg.syncCarNumValue = function (input) {
+    var $input = $(input);
+    var value = TLineInfoDlg.normalizePositiveInt($input.val());
+    $input.val(value);
+    $input.closest("td").find("input[name='carNumValue']").val(value);
+}
+
+TLineInfoDlg.onCarNumInput = function (input) {
+    TLineInfoDlg.syncCarNumValue(input);
+}
+
+TLineInfoDlg.onCarNumBlur = function (input) {
+    var $input = $(input);
+    var value = TLineInfoDlg.normalizePositiveInt($input.val());
+    if (value == "" || parseInt(value, 10) <= 0) {
+        value = "1";
+    }
+    $input.val(value);
+    $input.closest("td").find("input[name='carNumValue']").val(value);
+}
+
+TLineInfoDlg.changeCarNum = function (btn, step) {
+    var $td = $(btn).closest("td");
+    var $input = $td.find("input[name='carNumEditValue']");
+    var value = TLineInfoDlg.normalizePositiveInt($input.val());
+    var num = parseInt(value, 10);
+    if (isNaN(num) || num <= 0) {
+        num = 1;
+    }
+    num = num + step;
+    if (num <= 0) {
+        num = 1;
+    }
+    $input.val(num);
+    $td.find("input[name='carNumValue']").val(num);
+}
+
+TLineInfoDlg.validateShiftCarNum = function () {
+    var valid = true;
+    $(".shiftValueClass").each(function () {
+        var $row = $(this);
+        var $editInput = $row.find("input[name='carNumEditValue']");
+        if ($editInput.length > 0) {
+            TLineInfoDlg.onCarNumBlur($editInput[0]);
+        }
+        var carNum = $row.find("input[name*='carNumValue']").val();
+        if (!/^[1-9]\d*$/.test(carNum)) {
+            valid = false;
+            return false;
+        }
+    });
+    if (!valid) {
+        Feng.error("班次车次数必须为正整数");
+    }
+    return valid;
+}
+
+TLineInfoDlg.toMinutes = function (timeStr) {
+    var arr = timeStr.split(":");
+    return parseInt(arr[0], 10) * 60 + parseInt(arr[1], 10);
+}
+
+TLineInfoDlg.toTimeStr = function (minutes) {
+    var h = Math.floor(minutes / 60);
+    var m = minutes % 60;
+    return (h < 10 ? "0" + h : "" + h) + ":" + (m < 10 ? "0" + m : "" + m);
+}
+
+/**
+ * 批量生成班次
+ * 规则:
+ * 第一次:始发时间 - 始发时间+间隔
+ * 后续:上次后段时间 - 后段时间+间隔
+ */
+TLineInfoDlg.generateShiftList = function () {
+    var firstShiftTime = $("#firstShiftTime").val();
+    var lastShiftTime = $("#lastShiftTime").val();
+    var shiftGap = $("#shiftGap").val();
+    var batchCarNum = $("#batchCarNum").val();
+
+    if (firstShiftTime == "") {
+        Feng.info("请选择始发时间");
+        return;
+    }
+    if (lastShiftTime == "") {
+        Feng.info("请选择末班时间");
+        return;
+    }
+    if (shiftGap == "") {
+        Feng.info("请选择间隔时间");
+        return;
+    }
+    if (batchCarNum == "") {
+        Feng.info("请填写每班车次数");
+        return;
+    }
+    if (!regInt.test(batchCarNum)) {
+        Feng.info("车次数格式不正确");
+        return;
+    }
+    if (parseInt(batchCarNum, 10) <= 0) {
+        Feng.info("车次数必须为正整数");
+        return;
+    }
+
+    var startMinute = TLineInfoDlg.toMinutes(firstShiftTime);
+    var lastMinute = TLineInfoDlg.toMinutes(lastShiftTime);
+    var gap = parseInt(shiftGap, 10);
+
+    if (startMinute > lastMinute) {
+        Feng.info("始发时间不能大于末班时间");
+        return;
+    }
+
+    var existsMap = {};
+    $(".shiftValueClass").each(function () {
+        var shiftTimeValue = $(this).find("input[name*='shiftTimeValue']").val();
+        if (shiftTimeValue) {
+            shiftTimeValue = shiftTimeValue.replace(/\s+/g, "");
+        }
+        existsMap[shiftTimeValue] = true;
+    });
+
+    var currentStart = startMinute;
+    var generated = 0;
+    var duplicate = 0;
+    while (currentStart <= lastMinute) {
+        var currentEnd = currentStart + gap;
+        if (currentEnd > 24 * 60) {
+            break;
+        }
+        var shiftTime = TLineInfoDlg.toTimeStr(currentStart) + " - " + TLineInfoDlg.toTimeStr(currentEnd);
+        var shiftTimeKey = shiftTime.replace(/\s+/g, "");
+        if (!existsMap[shiftTimeKey]) {
+            TLineInfoDlg.appendShiftRow(shiftTime, batchCarNum);
+            existsMap[shiftTimeKey] = true;
+            generated++;
+        } else {
+            duplicate++;
+        }
+        currentStart = currentEnd;
+    }
+
+    if (generated == 0) {
+        Feng.info("未生成新班次,班次时间可能已存在");
+        return;
+    }
+
+    if (duplicate > 0) {
+        Feng.success("已生成" + generated + "条班次,跳过重复" + duplicate + "条");
+    } else {
+        Feng.success("已生成" + generated + "条班次");
+    }
+}
+
 /**
  * 添加公司
  */

--
Gitblit v1.7.1