longz
2026-04-20 606d0a6f3a7b47adcaa2da627a4b7d58334c134e
排班管理
2个文件已添加
8个文件已修改
1151 ■■■■■ 已修改文件
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/specialTrain/TLineController.java 429 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/LineShiftDriverMapper.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/LineShiftDriverMapper.xml 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TLineCompanyMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/LineShiftDriver.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TLineCompany.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine.html 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_schedule.html 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine.js 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_schedule.js 337 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/specialTrain/TLineController.java
@@ -12,6 +12,7 @@
import com.stylefeng.guns.core.util.SinataUtil;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.*;
import com.stylefeng.guns.modular.system.dao.LineShiftDriverMapper;
import com.stylefeng.guns.modular.system.service.*;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
@@ -24,7 +25,9 @@
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.math.BigDecimal;
@@ -67,6 +70,12 @@
    
    @Autowired
    private ITLineCompanyService itLineCompanyService;
    @Autowired
    private LineShiftDriverMapper lineShiftDriverMapper;
    @Autowired
    private ITDriverService tDriverService;
    
    /**
     * 跳转到跨城站点管理首页
@@ -420,10 +429,337 @@
                lineCompany.setCompanyId(jsonObject.getInteger("companyId"));
                lineCompany.setInsertTime(new Date());
                lineCompany.setInsertUserId(ShiroKit.getUser().getId());
                lineCompany.setAutoPlan(2);
                itLineCompanyService.insert(lineCompany);
            }
        }
        return SUCCESS_TIP;
    }
    /**
     * 查询线路已分配企业
     */
    @RequestMapping(value = "/lineCompanyList")
    @ResponseBody
    public Object lineCompanyList(Integer lineId) {
        if (lineId == null) {
            return ResultUtil.error("线路ID不能为空");
        }
        return ResultUtil.success(tLineService.getLineCompanyList(lineId));
    }
    /**
     * 排班管理页面
     */
    @RequestMapping(value = "/schedulePage")
    public String schedulePage(Integer lineId, Integer companyId, Model model) {
        TLine line = tLineService.selectById(lineId);
        TCompany company = itCompanyService.selectById(companyId);
        TLineCompany lineCompany = itLineCompanyService.selectOne(new EntityWrapper<TLineCompany>()
                .eq("lineId", lineId).eq("companyId", companyId));
        model.addAttribute("lineId", lineId);
        model.addAttribute("companyId", companyId);
        model.addAttribute("lineName", line == null ? "" : line.getName());
        model.addAttribute("companyName", company == null ? "" : company.getName());
        model.addAttribute("autoPlan", lineCompany == null || lineCompany.getAutoPlan() == null ? 2 : lineCompany.getAutoPlan());
        return PREFIX + "tLine_schedule.html";
    }
    /**
     * 排班管理-月份数据
     */
    @RequestMapping(value = "/schedule/month")
    @ResponseBody
    public Object scheduleMonth(Integer lineId, Integer companyId, String month) {
        try {
            TLineCompany lineCompany = checkLineCompany(lineId, companyId);
            if (lineCompany == null) {
                return ResultUtil.error("线路未关联该企业");
            }
            if (SinataUtil.isEmpty(month)) {
                month = new SimpleDateFormat("yyyy-MM").format(new Date());
            }
            SimpleDateFormat monthSdf = new SimpleDateFormat("yyyy-MM");
            Date monthDate = monthSdf.parse(month);
            Calendar cal = Calendar.getInstance();
            cal.setTime(monthDate);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            String monthStart = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
            int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
            cal.set(Calendar.DAY_OF_MONTH, maxDay);
            String monthEnd = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
            Integer companyType = getCompanyType(companyId);
            List<Map<String, Object>> stats = lineShiftDriverMapper.getMonthScheduleStats(lineId, monthStart, monthEnd, companyId, companyType);
            Map<String, Integer> dayAssignMap = new HashMap<>();
            for (Map<String, Object> stat : stats) {
                dayAssignMap.put(String.valueOf(stat.get("dayStr")), Integer.parseInt(String.valueOf(stat.get("assignNum"))));
            }
            List<TLineShift> shifts = itLineShiftService.selectList(new EntityWrapper<TLineShift>().eq("lineId", lineId).ne("state", 3));
            int totalNeed = 0;
            for (TLineShift shift : shifts) {
                totalNeed += (shift.getCarNum() == null ? 0 : shift.getCarNum());
            }
            List<Map<String, Object>> dayList = new ArrayList<>();
            cal.setTime(monthDate);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            for (int i = 1; i <= maxDay; i++) {
                cal.set(Calendar.DAY_OF_MONTH, i);
                String dayStr = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
                int assignNum = dayAssignMap.get(dayStr) == null ? 0 : dayAssignMap.get(dayStr);
                Map<String, Object> obj = new HashMap<>();
                obj.put("day", dayStr);
                obj.put("assignNum", assignNum);
                obj.put("totalNeed", totalNeed);
                if (totalNeed <= 0) {
                    obj.put("status", 0);
                    obj.put("statusText", "无班次");
                } else if (assignNum >= totalNeed) {
                    obj.put("status", 1);
                    obj.put("statusText", "已排班");
                } else {
                    obj.put("status", 2);
                    obj.put("statusText", "未排满");
                }
                dayList.add(obj);
            }
            Map<String, Object> result = new HashMap<>();
            result.put("month", month);
            result.put("totalNeed", totalNeed);
            result.put("days", dayList);
            return ResultUtil.success(result);
        } catch (Exception ex) {
            ex.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 排班管理-某天班次详情
     */
    @RequestMapping(value = "/schedule/dayDetail")
    @ResponseBody
    public Object scheduleDayDetail(Integer lineId, Integer companyId, String day) {
        try {
            TLineCompany lineCompany = checkLineCompany(lineId, companyId);
            if (lineCompany == null) {
                return ResultUtil.error("线路未关联该企业");
            }
            Integer companyType = getCompanyType(companyId);
            List<Map<String, Object>> shiftList = lineShiftDriverMapper.getDayShiftSchedule(lineId, day, companyId, companyType);
            for (Map<String, Object> shift : shiftList) {
                Integer lineShiftId = Integer.valueOf(String.valueOf(shift.get("lineShiftId")));
                List<Map<String, Object>> drivers = lineShiftDriverMapper.getDayShiftDrivers(lineShiftId, day, companyId, companyType);
                int carNum = shift.get("carNum") == null ? 0 : Integer.parseInt(String.valueOf(shift.get("carNum")));
                int assignNum = shift.get("assignNum") == null ? 0 : Integer.parseInt(String.valueOf(shift.get("assignNum")));
                shift.put("drivers", drivers);
                shift.put("remainNum", Math.max(carNum - assignNum, 0));
                shift.put("canAdd", assignNum < carNum ? 1 : 0);
            }
            return ResultUtil.success(shiftList);
        } catch (Exception ex) {
            ex.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 排班管理-可添加司机
     */
    @RequestMapping(value = "/schedule/drivers")
    @ResponseBody
    public Object scheduleDrivers(Integer lineId, Integer companyId, Integer lineShiftId, String day) {
        try {
            TLineCompany lineCompany = checkLineCompany(lineId, companyId);
            if (lineCompany == null) {
                return ResultUtil.error("线路未关联该企业");
            }
            Integer companyType = getCompanyType(companyId);
            return ResultUtil.success(lineShiftDriverMapper.getAvailableDrivers(lineId, lineShiftId, day, companyId, companyType));
        } catch (Exception ex) {
            ex.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 排班管理-新增排班
     */
    @RequestMapping(value = "/schedule/add")
    @ResponseBody
    public Object scheduleAdd(Integer lineId, Integer companyId, Integer lineShiftId, String day, @RequestParam String driverIds) {
        try {
            TLineCompany lineCompany = checkLineCompany(lineId, companyId);
            if (lineCompany == null) {
                return ResultUtil.error("线路未关联该企业");
            }
            TLineShift shift = itLineShiftService.selectById(lineShiftId);
            if (shift == null || shift.getState() == 3 || !shift.getLineId().equals(lineId)) {
                return ResultUtil.error("班次不存在");
            }
            Date dayDate = parseDay(day);
            Integer companyType = getCompanyType(companyId);
            List<Map<String, Object>> currentDrivers = lineShiftDriverMapper.getDayShiftDrivers(lineShiftId, day, companyId, companyType);
            int currentAssignNum = currentDrivers == null ? 0 : currentDrivers.size();
            int carNum = shift.getCarNum() == null ? 0 : shift.getCarNum();
            if (currentAssignNum >= carNum) {
                return ResultUtil.error("当前班次已排满");
            }
            List<Integer> driverIdList = parseIdList(driverIds);
            if (driverIdList.size() <= 0) {
                return ResultUtil.error("请选择司机");
            }
            List<Map<String, Object>> availableDrivers = lineShiftDriverMapper.getAvailableDrivers(lineId, lineShiftId, day, companyId, companyType);
            Map<Integer, Integer> seatMap = new HashMap<>();
            for (Map<String, Object> driver : availableDrivers) {
                Integer driverId = Integer.valueOf(String.valueOf(driver.get("driverId")));
                Integer seatNum = driver.get("seatNum") == null ? 5 : Integer.valueOf(String.valueOf(driver.get("seatNum")));
                seatMap.put(driverId, seatNum);
            }
            List<Integer> validDriverIds = new ArrayList<>();
            for (Integer driverId : driverIdList) {
                if (seatMap.containsKey(driverId)) {
                    validDriverIds.add(driverId);
                }
            }
            if (validDriverIds.size() <= 0) {
                return ResultUtil.error("没有可添加的司机");
            }
            if (currentAssignNum + validDriverIds.size() > carNum) {
                return ResultUtil.error("可排班人数不足,当前班次最多还能添加" + (carNum - currentAssignNum) + "名司机");
            }
            for (Integer driverId : validDriverIds) {
                Integer count = lineShiftDriverMapper.countExistsSchedule(lineShiftId, driverId, day);
                if (count != null && count > 0) {
                    continue;
                }
                int seatNum = seatMap.get(driverId) == null ? 5 : seatMap.get(driverId);
                if (seatNum <= 0) {
                    seatNum = 5;
                }
                LineShiftDriver record = new LineShiftDriver();
                record.setLineShiftId(lineShiftId);
                record.setDriverId(driverId);
                record.setDay(dayDate);
                record.setTotalSeat(seatNum);
                record.setLaveSeat(seatNum);
                record.setLaveSeatNumber(buildSeatNoStr(seatNum));
                record.setInserTime(new Date());
                record.setAssignType(2);
                lineShiftDriverMapper.insert(record);
            }
            return ResultUtil.success();
        } catch (Exception ex) {
            ex.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 排班管理-删除手动排班
     */
    @RequestMapping(value = "/schedule/delete")
    @ResponseBody
    public Object scheduleDelete(Integer scheduleId, Integer lineId, Integer companyId) {
        try {
            TLineCompany lineCompany = checkLineCompany(lineId, companyId);
            if (lineCompany == null) {
                return ResultUtil.error("线路未关联该企业");
            }
            LineShiftDriver record = lineShiftDriverMapper.selectById(scheduleId);
            if (record == null) {
                return ResultUtil.error("排班记录不存在");
            }
            if (record.getAssignType() == null || record.getAssignType() != 2) {
                return ResultUtil.error("仅支持删除手动排班记录");
            }
            TLineShift shift = itLineShiftService.selectById(record.getLineShiftId());
            if (shift == null || !shift.getLineId().equals(lineId)) {
                return ResultUtil.error("排班记录线路不匹配");
            }
            TDriver driver = tDriverService.selectById(record.getDriverId());
            if (driver == null || !checkDriverBelongCompany(driver, companyId)) {
                return ResultUtil.error("司机企业信息不匹配");
            }
            lineShiftDriverMapper.deleteById(scheduleId);
            return ResultUtil.success();
        } catch (Exception ex) {
            ex.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 排班管理-复制排班
     */
    @RequestMapping(value = "/schedule/copy")
    @ResponseBody
    public Object scheduleCopy(Integer lineId, Integer companyId, String sourceStart, String sourceEnd, String targetStart) {
        try {
            TLineCompany lineCompany = checkLineCompany(lineId, companyId);
            if (lineCompany == null) {
                return ResultUtil.error("线路未关联该企业");
            }
            Date sourceStartDate = parseDay(sourceStart);
            Date sourceEndDate = parseDay(sourceEnd);
            Date targetStartDate = parseDay(targetStart);
            if (sourceEndDate.before(sourceStartDate)) {
                return ResultUtil.error("复制结束日期不能早于开始日期");
            }
            Integer companyType = getCompanyType(companyId);
            List<LineShiftDriver> sourceList = lineShiftDriverMapper.getManualSchedulesForCopy(lineId, sourceStart, sourceEnd, companyId, companyType);
            int addNum = 0;
            int skipNum = 0;
            for (LineShiftDriver source : sourceList) {
                int diff = getDayDiff(sourceStartDate, source.getDay());
                Date targetDay = addDays(targetStartDate, diff);
                String targetDayStr = formatDay(targetDay);
                Integer count = lineShiftDriverMapper.countExistsSchedule(source.getLineShiftId(), source.getDriverId(), targetDayStr);
                if (count != null && count > 0) {
                    skipNum++;
                    continue;
                }
                LineShiftDriver target = new LineShiftDriver();
                target.setLineShiftId(source.getLineShiftId());
                target.setDriverId(source.getDriverId());
                target.setDay(targetDay);
                target.setLaveSeat(source.getLaveSeat());
                target.setLaveSeatNumber(source.getLaveSeatNumber());
                target.setTotalSeat(source.getTotalSeat());
                target.setInserTime(new Date());
                target.setAssignType(2);
                lineShiftDriverMapper.insert(target);
                addNum++;
            }
            Map<String, Object> result = new HashMap<>();
            result.put("addNum", addNum);
            result.put("skipNum", skipNum);
            return ResultUtil.success(result);
        } catch (Exception ex) {
            ex.printStackTrace();
            return ResultUtil.runErr();
        }
    }
    /**
     * 排班管理-保存智能排班开关
     */
    @RequestMapping(value = "/schedule/autoPlan")
    @ResponseBody
    public Object scheduleAutoPlan(Integer lineId, Integer companyId, Integer autoPlan) {
        if (autoPlan == null || (autoPlan != 1 && autoPlan != 2)) {
            return ResultUtil.error("智能排班参数错误");
        }
        TLineCompany lineCompany = checkLineCompany(lineId, companyId);
        if (lineCompany == null) {
            return ResultUtil.error("线路未关联该企业");
        }
        lineCompany.setAutoPlan(autoPlan);
        itLineCompanyService.updateById(lineCompany);
        return ResultUtil.success();
    }
    /**
     * 修改跨城站点管理
@@ -601,4 +937,97 @@
        return ResultUtil.success();
    }
    private TLineCompany checkLineCompany(Integer lineId, Integer companyId) {
        if (lineId == null || companyId == null) {
            return null;
        }
        return itLineCompanyService.selectOne(new EntityWrapper<TLineCompany>().eq("lineId", lineId).eq("companyId", companyId));
    }
    private Integer getCompanyType(Integer companyId) {
        TCompany company = itCompanyService.selectById(companyId);
        return company == null ? null : company.getType();
    }
    private boolean checkDriverBelongCompany(TDriver driver, Integer companyId) {
        if (driver == null || companyId == null) {
            return false;
        }
        Integer companyType = getCompanyType(companyId);
        if (companyType == null) {
            return false;
        }
        if (companyType == 2) {
            return driver.getCompanyId() != null && driver.getCompanyId().intValue() == companyId.intValue();
        }
        if (companyType == 3) {
            return driver.getFranchiseeId() != null && driver.getFranchiseeId().intValue() == companyId.intValue();
        }
        return false;
    }
    private Date parseDay(String day) throws Exception {
        return new SimpleDateFormat("yyyy-MM-dd").parse(day);
    }
    private String formatDay(Date day) {
        return new SimpleDateFormat("yyyy-MM-dd").format(day);
    }
    private int getDayDiff(Date start, Date end) {
        long oneDay = 24L * 60L * 60L * 1000L;
        long startTime = start.getTime() / oneDay;
        long endTime = end.getTime() / oneDay;
        return (int) (endTime - startTime);
    }
    private Date addDays(Date date, int days) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH, days);
        return cal.getTime();
    }
    private String buildSeatNoStr(int seatNum) {
        StringBuilder builder = new StringBuilder();
        for (int i = 1; i <= seatNum; i++) {
            if (i > 1) {
                builder.append(",");
            }
            builder.append(i);
        }
        return builder.toString();
    }
    private List<Integer> parseIdList(String ids) {
        List<Integer> list = new ArrayList<>();
        if (SinataUtil.isEmpty(ids)) {
            return list;
        }
        try {
            if (ids.startsWith("[")) {
                JSONArray array = JSON.parseArray(ids);
                for (int i = 0; i < array.size(); i++) {
                    Integer id = array.getInteger(i);
                    if (id != null && !list.contains(id)) {
                        list.add(id);
                    }
                }
            } else {
                String[] arr = ids.split(",");
                for (String s : arr) {
                    if (SinataUtil.isNotEmpty(s)) {
                        Integer id = Integer.valueOf(s.trim());
                        if (!list.contains(id)) {
                            list.add(id);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return list;
    }
}
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/LineShiftDriverMapper.java
@@ -28,4 +28,54 @@
     * @return
     */
    List<Map<String, Object>> queryNotInLineShiftDriver(@Param("lineShiftId") Integer lineShiftId, @Param("time") Date time);
    /**
     * 获取线路指定月份排班统计
     */
    List<Map<String, Object>> getMonthScheduleStats(@Param("lineId") Integer lineId,
                                                    @Param("monthStart") String monthStart,
                                                    @Param("monthEnd") String monthEnd,
                                                    @Param("companyId") Integer companyId,
                                                    @Param("companyType") Integer companyType);
    /**
     * 获取线路指定日期班次排班数据
     */
    List<Map<String, Object>> getDayShiftSchedule(@Param("lineId") Integer lineId,
                                                  @Param("day") String day,
                                                  @Param("companyId") Integer companyId,
                                                  @Param("companyType") Integer companyType);
    /**
     * 获取班次在某天已排司机
     */
    List<Map<String, Object>> getDayShiftDrivers(@Param("lineShiftId") Integer lineShiftId,
                                                 @Param("day") String day,
                                                 @Param("companyId") Integer companyId,
                                                 @Param("companyType") Integer companyType);
    /**
     * 获取可排班司机列表
     */
    List<Map<String, Object>> getAvailableDrivers(@Param("lineId") Integer lineId,
                                                  @Param("lineShiftId") Integer lineShiftId,
                                                  @Param("day") String day,
                                                  @Param("companyId") Integer companyId,
                                                  @Param("companyType") Integer companyType);
    /**
     * 获取复制源的手动排班记录
     */
    List<LineShiftDriver> getManualSchedulesForCopy(@Param("lineId") Integer lineId,
                                                    @Param("sourceStart") String sourceStart,
                                                    @Param("sourceEnd") String sourceEnd,
                                                    @Param("companyId") Integer companyId,
                                                    @Param("companyType") Integer companyType);
    /**
     * 统计某天某班次某司机是否已有排班
     */
    Integer countExistsSchedule(@Param("lineShiftId") Integer lineShiftId,
                                @Param("driverId") Integer driverId,
                                @Param("day") String day);
}
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/LineShiftDriverMapper.xml
@@ -12,6 +12,7 @@
        <result column="laveSeatNumber" property="laveSeatNumber"/>
        <result column="totalSeat" property="totalSeat"/>
        <result column="inserTime" property="inserTime"/>
        <result column="assignType" property="assignType"/>
    </resultMap>
@@ -25,7 +26,8 @@
        laveSeat as laveSeat,
        laveSeatNumber as laveSeatNumber,
        totalSeat as totalSeat,
        inserTime as inserTime
        inserTime as inserTime,
        assignType as assignType
        from t_line_shift_driver where 1 = 1
        <if test="null != lineShiftId">
            and lineShiftId = #{lineShiftId}
@@ -58,4 +60,133 @@
            where ls.id = #{lineShiftId} and DATE_FORMAT(lsd.`day`, '%Y-%m-%d') = DATE_FORMAT(#{time}, '%Y-%m-%d')
        )
    </select>
</mapper>
    <select id="getMonthScheduleStats" resultType="map">
        select
            DATE_FORMAT(lsd.`day`, '%Y-%m-%d') as dayStr,
            COUNT(lsd.id) as assignNum,
            SUM(case when lsd.assignType = 2 then 1 else 0 end) as manualNum
        from t_line_shift_driver lsd
        left join t_line_shift ls on lsd.lineShiftId = ls.id
        left join t_driver d on d.id = lsd.driverId
        where ls.lineId = #{lineId}
          and ls.state != 3
          and DATE_FORMAT(lsd.`day`, '%Y-%m-%d') between #{monthStart} and #{monthEnd}
          and d.flag != 3
        <if test="companyType == 2">
            and d.companyId = #{companyId}
        </if>
        <if test="companyType == 3">
            and d.franchiseeId = #{companyId}
        </if>
        group by DATE_FORMAT(lsd.`day`, '%Y-%m-%d')
    </select>
    <select id="getDayShiftSchedule" resultType="map">
        select
            ls.id as lineShiftId,
            ls.startTime as startTime,
            ls.endTime as endTime,
            ls.carNum as carNum,
            COUNT(lsd.id) as assignNum,
            SUM(case when lsd.assignType = 2 then 1 else 0 end) as manualNum
        from t_line_shift ls
        left join t_line_shift_driver lsd on ls.id = lsd.lineShiftId and DATE_FORMAT(lsd.`day`, '%Y-%m-%d') = #{day}
        left join t_driver d on d.id = lsd.driverId
        where ls.lineId = #{lineId}
          and ls.state != 3
          and (lsd.id is null or d.flag != 3)
        <if test="companyType == 2">
            and (lsd.id is null or d.companyId = #{companyId})
        </if>
        <if test="companyType == 3">
            and (lsd.id is null or d.franchiseeId = #{companyId})
        </if>
        group by ls.id, ls.startTime, ls.endTime, ls.carNum
        order by ls.startTime asc
    </select>
    <select id="getDayShiftDrivers" resultType="map">
        select
            lsd.id as id,
            lsd.driverId as driverId,
            d.`name` as driverName,
            d.phone as driverPhone,
            lsd.assignType as assignType
        from t_line_shift_driver lsd
        left join t_driver d on d.id = lsd.driverId
        where lsd.lineShiftId = #{lineShiftId}
          and DATE_FORMAT(lsd.`day`, '%Y-%m-%d') = #{day}
          and d.flag != 3
        <if test="companyType == 2">
            and d.companyId = #{companyId}
        </if>
        <if test="companyType == 3">
            and d.franchiseeId = #{companyId}
        </if>
        order by d.`name` asc, d.phone asc
    </select>
    <select id="getAvailableDrivers" resultType="map">
        select
            d.id as driverId,
            d.`name` as driverName,
            d.phone as driverPhone,
            ifnull(cm.seat, 5) as seatNum
        from t_driver d
        left join t_driver_line dl on dl.driverId = d.id
        left join t_car c on c.id = d.carId
        left join t_car_model cm on cm.id = c.carModelId
        where d.flag != 3
          and d.authState = 2
          and dl.lineId = #{lineId}
        <if test="companyType == 2">
            and d.companyId = #{companyId}
        </if>
        <if test="companyType == 3">
            and d.franchiseeId = #{companyId}
        </if>
          and d.id not in (
            select driverId from t_line_shift_driver
            where lineShiftId = #{lineShiftId}
              and DATE_FORMAT(`day`, '%Y-%m-%d') = #{day}
          )
        order by d.`name` asc, d.phone asc
    </select>
    <select id="getManualSchedulesForCopy" resultType="LineShiftDriver">
        select
            lsd.id as id,
            lsd.lineShiftId as lineShiftId,
            lsd.driverId as driverId,
            lsd.`day` as `day`,
            lsd.laveSeat as laveSeat,
            lsd.laveSeatNumber as laveSeatNumber,
            lsd.totalSeat as totalSeat,
            lsd.inserTime as inserTime,
            lsd.assignType as assignType
        from t_line_shift_driver lsd
        left join t_line_shift ls on ls.id = lsd.lineShiftId
        left join t_driver d on d.id = lsd.driverId
        where lsd.assignType = 2
          and ls.lineId = #{lineId}
          and ls.state != 3
          and DATE_FORMAT(lsd.`day`, '%Y-%m-%d') between #{sourceStart} and #{sourceEnd}
          and d.flag != 3
        <if test="companyType == 2">
            and d.companyId = #{companyId}
        </if>
        <if test="companyType == 3">
            and d.franchiseeId = #{companyId}
        </if>
        order by lsd.`day`, lsd.lineShiftId, lsd.driverId
    </select>
    <select id="countExistsSchedule" resultType="java.lang.Integer">
        select count(1)
        from t_line_shift_driver
        where lineShiftId = #{lineShiftId}
          and driverId = #{driverId}
          and DATE_FORMAT(`day`, '%Y-%m-%d') = #{day}
    </select>
</mapper>
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TLineCompanyMapper.xml
@@ -9,11 +9,12 @@
        <result column="companyId" property="companyId" />
        <result column="insertTime" property="insertTime" />
        <result column="insertUserId" property="insertUserId" />
        <result column="autoPlan" property="autoPlan" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, lineId, companyId, insertTime, insertUserId
        id, lineId, companyId, insertTime, insertUserId, autoPlan
    </sql>
</mapper>
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/LineShiftDriver.java
@@ -53,6 +53,11 @@
     */
    @TableField("inserTime")
    private Date inserTime;
    /**
     * 排班来源(1=司机自领,2=手动排班)
     */
    @TableField("assignType")
    private Integer assignType;
    public Integer getId() {
        return id;
@@ -118,6 +123,14 @@
        this.inserTime = inserTime;
    }
    public Integer getAssignType() {
        return assignType;
    }
    public void setAssignType(Integer assignType) {
        this.assignType = assignType;
    }
    @Override
    public String toString() {
        return "LineShiftDriver{" +
@@ -129,6 +142,7 @@
                ", laveSeatNumber='" + laveSeatNumber + '\'' +
                ", totalSeat=" + totalSeat +
                ", inserTime=" + inserTime +
                ", assignType=" + assignType +
                '}';
    }
}
ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TLineCompany.java
@@ -41,6 +41,10 @@
     * 添加用户ID
     */
    private Integer insertUserId;
    /**
     * 是否智能排班(1=是,2=否)
     */
    private Integer autoPlan;
    public Integer getId() {
@@ -83,6 +87,14 @@
        this.insertUserId = insertUserId;
    }
    public Integer getAutoPlan() {
        return autoPlan;
    }
    public void setAutoPlan(Integer autoPlan) {
        this.autoPlan = autoPlan;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
@@ -96,6 +108,7 @@
        ", companyId=" + companyId +
        ", insertTime=" + insertTime +
        ", insertUserId=" + insertUserId +
        ", autoPlan=" + autoPlan +
        "}";
    }
}
ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine.html
@@ -52,6 +52,9 @@
                            @if(shiro.hasPermission("/tLine/addCompany")){
                                <#button name="分配企业" icon="fa-plus" clickFun="TLine.addCompany()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/tLine/addCompany")){
                                <#button name="排班管理" icon="fa-calendar" clickFun="TLine.openScheduleManage()" space="true"/>
                            @}
                        </div>
                        <#table id="TLineTable"/>
                    </div>
ManagementYKDTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tLine/tLine_schedule.html
New file
@@ -0,0 +1,98 @@
@layout("/common/_container.html"){
<style>
    .schedule-wrap { padding: 10px 20px; }
    .schedule-header { margin-bottom: 15px; }
    .schedule-header .line { font-size: 18px; font-weight: 700; margin-bottom: 12px; }
    .schedule-copy { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
    .schedule-copy .lbl { color: #333; min-width: 60px; }
    .schedule-copy input { width: 130px; }
    .schedule-switch { margin-left: 20px; display: flex; align-items: center; gap: 6px; }
    .calendar-panel { border: 1px solid #e5e6e7; margin-top: 15px; }
    .calendar-toolbar { height: 48px; display: flex; align-items: center; justify-content: center; gap: 16px; border-bottom: 1px solid #e5e6e7; }
    .calendar-toolbar .nav-btn { cursor: pointer; color: #1ab394; }
    .calendar-table { width: 100%; table-layout: fixed; border-collapse: collapse; }
    .calendar-table th, .calendar-table td { border: 1px solid #e5e6e7; vertical-align: top; height: 88px; padding: 6px; }
    .calendar-table th { height: 36px; text-align: center; font-weight: 600; }
    .calendar-day { cursor: pointer; position: relative; }
    .calendar-day.other { color: #aaa; background: #fafafa; cursor: default; }
    .calendar-day.active { outline: 2px solid #1ab394; outline-offset: -2px; }
    .calendar-day .num { font-size: 14px; font-weight: 600; }
    .calendar-day .tag { margin-top: 6px; display: inline-block; padding: 2px 6px; border-radius: 2px; color: #fff; font-size: 12px; }
    .calendar-day .tag.ok { background: #1c84c6; }
    .calendar-day .tag.warn { background: #f8ac59; }
    .calendar-day .tag.none { background: #999; }
    .shift-panel { margin-top: 16px; display: none; }
    .driver-tag { display: inline-block; margin: 2px 4px 2px 0; padding: 3px 8px; border-radius: 2px; color: #fff; background: #1c84c6; }
    .driver-tag.manual { background: #f8ac59; }
    .driver-tag .del { margin-left: 8px; cursor: pointer; }
</style>
<div class="schedule-wrap">
    <input type="hidden" id="lineId" value="${lineId!}"/>
    <input type="hidden" id="companyId" value="${companyId!}"/>
    <input type="hidden" id="autoPlanValue" value="${autoPlan!2}"/>
    <div class="schedule-header">
        <div class="line">排班管理</div>
        <div style="margin-bottom: 10px;">线路名称:<b id="lineName">${lineName!}</b>&nbsp;&nbsp;&nbsp;企业:<b id="companyName">${companyName!}</b></div>
        <div class="schedule-copy">
            <span class="lbl">排班复制</span>
            <span>复制日期</span>
            <input type="text" class="form-control" id="copyStartDate" placeholder="开始日期"/>
            <span>至</span>
            <input type="text" class="form-control" id="copyEndDate" placeholder="结束日期"/>
            <span>粘贴起始日期</span>
            <input type="text" class="form-control" id="targetStartDate" placeholder="选择日期"/>
            <button class="btn btn-primary btn-sm" onclick="TLineSchedule.copySchedule()">确认复制</button>
            <div class="schedule-switch">
                <span>开启智能排班</span>
                <input type="checkbox" id="autoPlanSwitch" onchange="TLineSchedule.onAutoPlanChange(this)">
            </div>
        </div>
    </div>
    <div class="calendar-panel">
        <div class="calendar-toolbar">
            <span class="nav-btn" onclick="TLineSchedule.prevMonth()">&lt; 上月</span>
            <span id="calendarMonthText"></span>
            <span class="nav-btn" onclick="TLineSchedule.nextMonth()">下月 &gt;</span>
        </div>
        <table class="calendar-table">
            <thead>
            <tr>
                <th>星期一</th>
                <th>星期二</th>
                <th>星期三</th>
                <th>星期四</th>
                <th>星期五</th>
                <th>星期六</th>
                <th>星期日</th>
            </tr>
            </thead>
            <tbody id="calendarBody"></tbody>
        </table>
    </div>
    <div class="shift-panel" id="shiftPanel">
        <h4 id="selectedDayText"></h4>
        <table class="table table-striped table-bordered">
            <thead>
            <tr>
                <th style="width: 20%;">班次</th>
                <th style="width: 10%;">车次数</th>
                <th style="width: 55%;">司机(黄色为后台手动排班)</th>
                <th style="width: 15%;">操作</th>
            </tr>
            </thead>
            <tbody id="shiftTableBody"></tbody>
        </table>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/tLine/tLine_schedule.js"></script>
<script>
    laydate.render({elem: '#copyStartDate'});
    laydate.render({elem: '#copyEndDate'});
    laydate.render({elem: '#targetStartDate'});
</script>
@}
ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine.js
@@ -149,6 +149,75 @@
};
/**
 * 排班管理
 */
TLine.openScheduleManage = function () {
    if (!this.check()) {
        return;
    }
    if (!TLine.seItem.companyNum || parseInt(TLine.seItem.companyNum, 10) <= 0) {
        Feng.info("暂未关联企业");
        return;
    }
    var ajax = new $ax(Feng.ctxPath + "/tLine/lineCompanyList", function (res) {
        var list = [];
        if (res && res.status == 200 && res.data) {
            list = res.data;
        } else if ($.isArray(res)) {
            list = res;
        }
        if (!list || list.length <= 0) {
            Feng.info("暂未关联企业");
            return;
        }
        if (list.length == 1) {
            TLine.openSchedulePage(TLine.seItem.id, list[0].companyId);
            return;
        }
        var options = "";
        for (var i = 0; i < list.length; i++) {
            options += '<option value="' + list[i].companyId + '">' + (list[i].companyName || ('企业' + list[i].companyId)) + '</option>';
        }
        var html = '<div style="padding:20px 30px;">' +
            '<div style="margin-bottom:10px;">请选择企业:</div>' +
            '<select id="scheduleCompanyId" class="form-control">' + options + '</select>' +
            '</div>';
        layer.open({
            type: 1,
            title: '选择企业',
            area: ['420px', '220px'],
            btn: ['确定', '取消'],
            content: html,
            yes: function (index) {
                var companyId = $("#scheduleCompanyId").val();
                if (!companyId) {
                    Feng.info("请选择企业");
                    return;
                }
                layer.close(index);
                TLine.openSchedulePage(TLine.seItem.id, companyId);
            }
        });
    }, function () {
        Feng.error("获取企业列表失败");
    });
    ajax.set("lineId", TLine.seItem.id);
    ajax.start();
};
TLine.openSchedulePage = function (lineId, companyId) {
    var index = layer.open({
        type: 2,
        title: '排班管理',
        area: ['100%', '100%'],
        fix: false,
        maxmin: true,
        content: Feng.ctxPath + '/tLine/schedulePage?lineId=' + lineId + '&companyId=' + companyId
    });
    this.layerIndex = index;
};
/**
 * 删除跨城站点管理
 */
TLine.opt = function (type) {
ManagementYKDTravel/guns-admin/src/main/webapp/static/modular/system/tLine/tLine_schedule.js
New file
@@ -0,0 +1,337 @@
var TLineSchedule = {
    lineId: null,
    companyId: null,
    currentYear: null,
    currentMonth: null,
    selectedDay: null,
    monthStatsMap: {}
};
TLineSchedule.init = function () {
    this.lineId = $("#lineId").val();
    this.companyId = $("#companyId").val();
    var now = new Date();
    this.currentYear = now.getFullYear();
    this.currentMonth = now.getMonth() + 1;
    var autoPlan = $("#autoPlanValue").val();
    $("#autoPlanSwitch").prop("checked", autoPlan == "1");
    this.loadMonthData();
};
TLineSchedule.getMonthStr = function () {
    return this.currentYear + "-" + (this.currentMonth < 10 ? "0" + this.currentMonth : this.currentMonth);
};
TLineSchedule.prevMonth = function () {
    if (this.currentMonth == 1) {
        this.currentMonth = 12;
        this.currentYear -= 1;
    } else {
        this.currentMonth -= 1;
    }
    this.selectedDay = null;
    $("#shiftPanel").hide();
    this.loadMonthData();
};
TLineSchedule.nextMonth = function () {
    if (this.currentMonth == 12) {
        this.currentMonth = 1;
        this.currentYear += 1;
    } else {
        this.currentMonth += 1;
    }
    this.selectedDay = null;
    $("#shiftPanel").hide();
    this.loadMonthData();
};
TLineSchedule.loadMonthData = function () {
    var _this = this;
    var ajax = new $ax(Feng.ctxPath + "/tLine/schedule/month", function (res) {
        if (!res || res.status != 200) {
            Feng.error((res && res.msg) || "加载月份排班失败");
            return;
        }
        _this.monthStatsMap = {};
        var days = res.data && res.data.days ? res.data.days : [];
        for (var i = 0; i < days.length; i++) {
            _this.monthStatsMap[days[i].day] = days[i];
        }
        _this.renderCalendar();
    }, function () {
        Feng.error("加载月份排班失败");
    });
    ajax.set("lineId", this.lineId);
    ajax.set("companyId", this.companyId);
    ajax.set("month", this.getMonthStr());
    ajax.start();
};
TLineSchedule.renderCalendar = function () {
    $("#calendarMonthText").text(this.currentYear + "年 " + this.currentMonth + "月");
    var firstDay = new Date(this.currentYear, this.currentMonth - 1, 1);
    var firstWeekDay = (firstDay.getDay() + 6) % 7;
    var maxDay = new Date(this.currentYear, this.currentMonth, 0).getDate();
    var prevMaxDay = new Date(this.currentYear, this.currentMonth - 1, 0).getDate();
    var html = "";
    var dayNum = 1;
    var nextNum = 1;
    for (var row = 0; row < 6; row++) {
        html += "<tr>";
        for (var col = 0; col < 7; col++) {
            var index = row * 7 + col;
            if (index < firstWeekDay) {
                var prevDay = prevMaxDay - firstWeekDay + index + 1;
                html += '<td class="calendar-day other"><div class="num">' + prevDay + '</div></td>';
            } else if (dayNum > maxDay) {
                html += '<td class="calendar-day other"><div class="num">' + nextNum + '</div></td>';
                nextNum++;
            } else {
                var dayStr = this.currentYear + "-" + this.pad2(this.currentMonth) + "-" + this.pad2(dayNum);
                var stat = this.monthStatsMap[dayStr];
                var tagHtml = "";
                if (stat) {
                    if (stat.status == 1) {
                        tagHtml = '<div class="tag ok">' + stat.assignNum + ' 已排班</div>';
                    } else if (stat.status == 2) {
                        tagHtml = '<div class="tag warn">' + stat.assignNum + ' 未排满</div>';
                    } else {
                        tagHtml = '<div class="tag none">无班次</div>';
                    }
                }
                var activeCls = this.selectedDay == dayStr ? " active" : "";
                html += '<td class="calendar-day' + activeCls + '" data-day="' + dayStr + '" onclick="TLineSchedule.clickDay(this)">' +
                    '<div class="num">' + dayNum + '</div>' + tagHtml + '</td>';
                dayNum++;
            }
        }
        html += "</tr>";
    }
    $("#calendarBody").html(html);
};
TLineSchedule.clickDay = function (el) {
    var day = $(el).attr("data-day");
    if (!day) {
        return;
    }
    this.selectedDay = day;
    $("#calendarBody .calendar-day").removeClass("active");
    $(el).addClass("active");
    this.loadDayDetail(day);
};
TLineSchedule.loadDayDetail = function (day) {
    var _this = this;
    var ajax = new $ax(Feng.ctxPath + "/tLine/schedule/dayDetail", function (res) {
        if (!res || res.status != 200) {
            Feng.error((res && res.msg) || "加载排班详情失败");
            return;
        }
        $("#shiftPanel").show();
        $("#selectedDayText").text(day + " 排班信息");
        _this.renderShiftTable(res.data || []);
    }, function () {
        Feng.error("加载排班详情失败");
    });
    ajax.set("lineId", this.lineId);
    ajax.set("companyId", this.companyId);
    ajax.set("day", day);
    ajax.start();
};
TLineSchedule.renderShiftTable = function (shiftList) {
    var html = "";
    for (var i = 0; i < shiftList.length; i++) {
        var shift = shiftList[i];
        var drivers = shift.drivers || [];
        var driverHtml = "";
        for (var j = 0; j < drivers.length; j++) {
            var d = drivers[j];
            var cls = d.assignType == 2 ? "driver-tag manual" : "driver-tag";
            var del = d.assignType == 2 ? '<span class="del" onclick="TLineSchedule.deleteSchedule(' + d.id + ')">x</span>' : "";
            driverHtml += '<span class="' + cls + '">' + this.escapeHtml((d.driverName || "") + "-" + (d.driverPhone || "")) + del + '</span>';
        }
        if (driverHtml === "") {
            driverHtml = "-";
        }
        var canAdd = shift.canAdd == 1;
        var addBtn = canAdd ? ('<a href="javascript:;" onclick="TLineSchedule.openAddDialog(' + shift.lineShiftId + ',' + shift.remainNum + ')">添加</a>') : '<span style="color:#999;">已满</span>';
        html += '<tr>' +
            '<td>' + this.escapeHtml((shift.startTime || "") + " - " + (shift.endTime || "")) + '</td>' +
            '<td>' + (shift.carNum || 0) + '</td>' +
            '<td>' + driverHtml + '</td>' +
            '<td>' + addBtn + '</td>' +
            '</tr>';
    }
    $("#shiftTableBody").html(html);
};
TLineSchedule.openAddDialog = function (lineShiftId, remainNum) {
    var _this = this;
    var ajax = new $ax(Feng.ctxPath + "/tLine/schedule/drivers", function (res) {
        if (!res || res.status != 200) {
            Feng.error((res && res.msg) || "获取可排司机失败");
            return;
        }
        var list = res.data || [];
        if (list.length <= 0) {
            Feng.info("暂无可添加司机");
            return;
        }
        var itemsHtml = "";
        for (var i = 0; i < list.length; i++) {
            itemsHtml += '<label style="display:block;margin-bottom:6px;">' +
                '<input type="checkbox" name="scheduleDriverCheck" value="' + list[i].driverId + '"> ' +
                _this.escapeHtml((list[i].driverName || "") + "-" + (list[i].driverPhone || "")) +
                '</label>';
        }
        var html = '<div style="padding:15px 20px;max-height:360px;overflow:auto;">' +
            '<div style="margin-bottom:8px;">可添加人数:' + remainNum + '</div>' + itemsHtml + '</div>';
        layer.open({
            type: 1,
            title: '选择司机',
            area: ['420px', '520px'],
            btn: ['确定', '取消'],
            content: html,
            yes: function (index) {
                var ids = [];
                $("input[name='scheduleDriverCheck']:checked").each(function () {
                    ids.push(parseInt($(this).val(), 10));
                });
                if (ids.length <= 0) {
                    Feng.info("请至少选择一名司机");
                    return;
                }
                if (ids.length > remainNum) {
                    Feng.info("最多只能添加" + remainNum + "名司机");
                    return;
                }
                _this.addSchedule(lineShiftId, ids, function () {
                    layer.close(index);
                });
            }
        });
    }, function () {
        Feng.error("获取可排司机失败");
    });
    ajax.set("lineId", this.lineId);
    ajax.set("companyId", this.companyId);
    ajax.set("lineShiftId", lineShiftId);
    ajax.set("day", this.selectedDay);
    ajax.start();
};
TLineSchedule.addSchedule = function (lineShiftId, driverIds, callback) {
    var _this = this;
    var ajax = new $ax(Feng.ctxPath + "/tLine/schedule/add", function (res) {
        if (!res || res.status != 200) {
            Feng.error((res && res.msg) || "添加排班失败");
            return;
        }
        Feng.success("添加成功");
        if (callback) {
            callback();
        }
        _this.loadDayDetail(_this.selectedDay);
        _this.loadMonthData();
    }, function () {
        Feng.error("添加排班失败");
    });
    ajax.set("lineId", this.lineId);
    ajax.set("companyId", this.companyId);
    ajax.set("lineShiftId", lineShiftId);
    ajax.set("day", this.selectedDay);
    ajax.set("driverIds", JSON.stringify(driverIds));
    ajax.start();
};
TLineSchedule.deleteSchedule = function (scheduleId) {
    var _this = this;
    layer.confirm("确认删除该手动排班记录吗?", {icon: 3, title: "提示"}, function (index) {
        layer.close(index);
        var ajax = new $ax(Feng.ctxPath + "/tLine/schedule/delete", function (res) {
            if (!res || res.status != 200) {
                Feng.error((res && res.msg) || "删除失败");
                return;
            }
            Feng.success("删除成功");
            _this.loadDayDetail(_this.selectedDay);
            _this.loadMonthData();
        }, function () {
            Feng.error("删除失败");
        });
        ajax.set("scheduleId", scheduleId);
        ajax.set("lineId", _this.lineId);
        ajax.set("companyId", _this.companyId);
        ajax.start();
    });
};
TLineSchedule.copySchedule = function () {
    var sourceStart = $("#copyStartDate").val();
    var sourceEnd = $("#copyEndDate").val();
    var targetStart = $("#targetStartDate").val();
    if (!sourceStart || !sourceEnd || !targetStart) {
        Feng.info("请完整填写复制日期与粘贴起始日期");
        return;
    }
    var _this = this;
    var ajax = new $ax(Feng.ctxPath + "/tLine/schedule/copy", function (res) {
        if (!res || res.status != 200) {
            Feng.error((res && res.msg) || "复制失败");
            return;
        }
        var data = res.data || {};
        Feng.success("复制完成,新增" + (data.addNum || 0) + "条,跳过" + (data.skipNum || 0) + "条");
        _this.loadMonthData();
        if (_this.selectedDay) {
            _this.loadDayDetail(_this.selectedDay);
        }
    }, function () {
        Feng.error("复制失败");
    });
    ajax.set("lineId", this.lineId);
    ajax.set("companyId", this.companyId);
    ajax.set("sourceStart", sourceStart);
    ajax.set("sourceEnd", sourceEnd);
    ajax.set("targetStart", targetStart);
    ajax.start();
};
TLineSchedule.onAutoPlanChange = function (el) {
    var checked = $(el).prop("checked");
    var autoPlan = checked ? 1 : 2;
    var _this = this;
    var ajax = new $ax(Feng.ctxPath + "/tLine/schedule/autoPlan", function (res) {
        if (!res || res.status != 200) {
            Feng.error((res && res.msg) || "保存失败");
            $(el).prop("checked", !checked);
            return;
        }
        $("#autoPlanValue").val(autoPlan);
        Feng.success("保存成功");
    }, function () {
        $(el).prop("checked", !checked);
        Feng.error("保存失败");
    });
    ajax.set("lineId", this.lineId);
    ajax.set("companyId", this.companyId);
    ajax.set("autoPlan", autoPlan);
    ajax.start();
};
TLineSchedule.pad2 = function (num) {
    return num < 10 ? "0" + num : "" + num;
};
TLineSchedule.escapeHtml = function (str) {
    return (str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
};
$(function () {
    TLineSchedule.init();
});