mitao
2025-10-30 1970dd918e188aef69338e1c69e346bcd197ac1d
场地预约
1个文件已添加
7个文件已修改
814 ■■■■■ 已修改文件
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TSiteController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/BallController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/QuerySiteTimes.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/SiteBooking.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/ITSiteService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/impl/TSiteServiceImpl.java 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/ball/yuyue_add.html 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/ball/yuyue_info.js 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TSiteController.java
@@ -488,6 +488,20 @@
        );
        return ResultUtil.success(prices);
    }
    /**
     * 管理后台 - 获取场地预约时间段数据(供预约新增页面使用)
     */
    @ResponseBody
    @RequestMapping("/querySiteTimes")
    public ResultUtil querySiteTimes(Integer id, String day, String halfName, String siteName, Integer targetAudience) {
        try {
            return ResultUtil.success(siteService.querySiteTimes(id, day, halfName, siteName, targetAudience));
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error("获取时间段失败");
        }
    }
    /**
     *  场地管理首页 选择省 返回市
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/BallController.java
@@ -1492,19 +1492,26 @@
        siteBooking.setAddType(1);
        //存开始和结束时间
        // times格式示例: 2025-10-14 19:00-19:30;2025-10-14 19:30-20:00;2025-10-14 20:00-20:30;2025-10-14 20:30-21:00
        // targetAudience字段会由Spring MVC自动绑定(1=订场,2=散客)
        String times = siteBooking.getTimes();
        String[] dates = times.split(";");
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        try {
            // 提取最早的开始时间
            // dates[0] 格式: 2025-10-14 19:00-19:30
            String start = dates[0];
            String startDateStr = start.substring(0, start.lastIndexOf("-"));
            Date startDate = format.parse(startDateStr);
            // 提取最晚的结束时间
            // dates[dates.length - 1] 格式: 2025-10-14 20:30-21:00
            String end = dates[dates.length - 1];
            String[] str = end.split(" ");
            String endDateStr = str[0] + " " + str[1].substring(str[1].indexOf("-") + 1);
            Date endDate = format.parse(endDateStr);
            siteBooking.setStartTime(startDate);
            siteBooking.setEndTime(endDate);
        } catch (Exception e) {
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/QuerySiteTimes.java
New file
@@ -0,0 +1,30 @@
package com.dsh.guns.modular.system.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author zhibing.pu
 * @date 2023/7/17 17:24
 */
@Data
@ApiModel
public class QuerySiteTimes {
    @ApiModelProperty("时间段")
    private String time;
    @ApiModelProperty("是否可选(0=否,1=是)")
    private Integer selectable;
    @ApiModelProperty("已预约人数")
    private Integer selectCount;
    @ApiModelProperty("最大预约人数")
    private Integer selectMaxCount;
    @ApiModelProperty("是否被订场 0否1是 被定场后不可预约")
    private Integer isReserve;
    @ApiModelProperty(value = "现金价格(元)")
    private BigDecimal cashPrice;
    @ApiModelProperty(value = "玩湃币价格(币)")
    private BigDecimal coinPrice;
}
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/SiteBooking.java
@@ -187,4 +187,7 @@
    private Integer type;
    @TableField("addType")
    private Integer addType;
    // 面向人群 1订场 2散客
    @TableField("targetAudience")
    private Integer targetAudience;
}
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/ITSiteService.java
@@ -1,11 +1,16 @@
package com.dsh.guns.modular.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsh.guns.modular.system.model.QuerySiteTimes;
import com.dsh.guns.modular.system.model.TSite;
import java.text.ParseException;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2023/8/1 17:49
 */
public interface ITSiteService extends IService<TSite> {
    List<QuerySiteTimes> querySiteTimes(Integer id, String day, String halfName, String siteName, Integer targetAudience) throws ParseException;
}
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/impl/TSiteServiceImpl.java
@@ -1,10 +1,30 @@
package com.dsh.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsh.course.entity.SiteLock;
import com.dsh.course.mapper.TSiteMapper;
import com.dsh.guns.modular.system.model.QuerySiteTimes;
import com.dsh.guns.modular.system.model.SiteBooking;
import com.dsh.guns.modular.system.model.TSite;
import com.dsh.guns.modular.system.model.TSitePrice;
import com.dsh.guns.modular.system.service.ISiteBookingService;
import com.dsh.guns.modular.system.service.ISiteLockService;
import com.dsh.guns.modular.system.service.ITSitePriceService;
import com.dsh.guns.modular.system.service.ITSiteService;
import com.dsh.guns.modular.system.util.DateComparisonExample;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * @author zhibing.pu
@@ -12,4 +32,185 @@
 */
@Service
public class TSiteServiceImpl extends ServiceImpl<TSiteMapper, TSite> implements ITSiteService {
    @Autowired
    private ISiteLockService siteLockService;
    @Autowired
    private ISiteBookingService iSiteBookingService;
    @Autowired
    private ITSitePriceService itSitePriceService;
    @Override
    public List<QuerySiteTimes> querySiteTimes(Integer id, String day, String halfName, String siteName, Integer targetAudience) throws ParseException {
        System.out.println("=======date======" + day);
        List<String> strings = new ArrayList<>();
        List<SiteBooking> siteBookings = iSiteBookingService.list(new QueryWrapper<SiteBooking>().eq("siteId", id).ne("status", 5).eq("nextName", siteName).like("times", day));
        if (StringUtils.isBlank(siteName)) {
            siteBookings = iSiteBookingService.list(new QueryWrapper<SiteBooking>().eq("siteId", id).ne("status", 5).like("times", day));
        }
        System.out.println("=======已预约列表======" + siteBookings);
        for (SiteBooking siteBooking : siteBookings) {
            String[] split = siteBooking.getTimes().split(";");
            if (siteBooking.getIsHalf() == 2) {
                for (String s : split) {
                    String convertedValue = s.substring(11);
                    strings.add(convertedValue + (siteBooking.getTargetAudience() != null ? "," + siteBooking.getTargetAudience() : ",1"));
                }
            } else {
                if (halfName == null) {
                    for (String s : split) {
                        String convertedValue = s.substring(11);
                        strings.add(convertedValue + (siteBooking.getTargetAudience() != null ? "," + siteBooking.getTargetAudience() : ",1"));
                    }
                }
                if (siteBooking.getHalfName().equals(halfName)) {
                    for (String s : split) {
                        String convertedValue = s.substring(11);
                        strings.add(convertedValue + (siteBooking.getTargetAudience() != null ? "," + siteBooking.getTargetAudience() : ",1"));
                    }
                }
            }
        }
        System.out.println("======已经预约时间段=======" + strings);
        TSite site = this.getById(id);
        List<QuerySiteTimes> timeRanges = new ArrayList<>();
        day = day.split(";")[0].split(" ")[0];
        LocalDate date = LocalDate.parse(day);
        DayOfWeek dayOfWeek = date.getDayOfWeek();
        // 通过日期 确定周X 查询设置的可以约时间段和金额 封装基础时间段数据
        LambdaQueryWrapper<TSitePrice> tSitePriceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tSitePriceLambdaQueryWrapper.eq(TSitePrice::getSiteId, id);
        tSitePriceLambdaQueryWrapper.orderByAsc(TSitePrice::getStartTime);
        tSitePriceLambdaQueryWrapper.eq(TSitePrice::getTargetAudience, targetAudience);
        tSitePriceLambdaQueryWrapper.eq(TSitePrice::getDayOfWeek, dayOfWeek.getValue());
        if (StringUtils.isNotBlank(halfName)) {
            tSitePriceLambdaQueryWrapper.eq(TSitePrice::getFieldType, 2);
        } else {
            tSitePriceLambdaQueryWrapper.eq(TSitePrice::getFieldType, 1);
        }
        List<TSitePrice> sitePrice = itSitePriceService.list(tSitePriceLambdaQueryWrapper);
        for (TSitePrice tSitePrice : sitePrice) {
            QuerySiteTimes querySiteTimes = new QuerySiteTimes();
            querySiteTimes.setTime(tSitePrice.getStartTime().substring(0, tSitePrice.getStartTime().length() - 3) + "-" + tSitePrice.getEndTime().substring(0, tSitePrice.getEndTime().length() - 3));
            querySiteTimes.setSelectable(1);
            querySiteTimes.setSelectCount(0);
            querySiteTimes.setSelectMaxCount(site.getWalkinCapacity());
            querySiteTimes.setIsReserve(0);
            querySiteTimes.setCashPrice(tSitePrice.getCashPrice());
            querySiteTimes.setCoinPrice(tSitePrice.getCoinPrice());
            String temp = tSitePrice.getStartTime().substring(0, tSitePrice.getStartTime().length() - 3) + "-" + tSitePrice.getEndTime().substring(0, tSitePrice.getEndTime().length() - 3);
            String timePriceStart = day + " " + tSitePrice.getStartTime().substring(0, tSitePrice.getStartTime().length() - 3);
            String timePriceEnd = day + " " + tSitePrice.getEndTime().substring(0, tSitePrice.getEndTime().length() - 3);
            // 已经预约了 判断是散客模式还是订场模式
            Integer flag = 0;
            // 散客预约人数
            Integer count = 0;
            for (String time : strings) {
                // 先判断时间是否和预约时间有交集
                String s = time.split(",")[1];
                String timeRange = time.split(",")[0];
                String[] split = timeRange.split("-");
                String bookingStart = day + " " + split[0];
                String bookingEnd = day + " " + split[1];
                if (!isTimePeriodsIntersect(timePriceStart, timePriceEnd, bookingStart, bookingEnd)) {
                    // 不相交
                } else {
                    if (s.equals("1")) {
                        // 订场 不可再预约了
                        querySiteTimes.setIsReserve(1);
                        querySiteTimes.setSelectable(0);
                        flag = 1;
                        break;
                    }
                    count++;
                }
            }
            querySiteTimes.setSelectCount(count);
            if (flag == 0) {
                // 当前时间段还没有预约
                Integer walkinCapacity = site.getWalkinCapacity();
                // 计算散客预约人数和最大散客容纳数
                System.err.println("预约人数" + count);
                System.err.println("最大散客容纳数" + walkinCapacity);
                if (walkinCapacity <= count) {
                    // 不可预约 也不能散客
                    System.err.println("不可预约 也不能散客");
                    querySiteTimes.setSelectable(0);
                    querySiteTimes.setIsReserve(0);
                }else{
                    if (targetAudience==2){
                        // 散客只能预约当前时间段
                        Date now = new Date();
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                        String nowStr = simpleDateFormat.format(now);
                        // 判断当前时间有没有在timePriceStart和timePriceEnd之间
                        if (DateComparisonExample.isStringWithinTimeRange(nowStr, simpleDateFormat.parse(timePriceStart),  simpleDateFormat.parse(timePriceEnd))) {
                            querySiteTimes.setSelectable(1);
                        }else{
                            querySiteTimes.setSelectable(0);
                        }
                    }
                }
            }
            // 查出lock
            List<SiteLock> list = siteLockService.list(new LambdaQueryWrapper<SiteLock>().eq(SiteLock::getSiteId, id));
            for (SiteLock siteLock : list) {
                String stime = day + " " + tSitePrice.getStartTime().substring(0, tSitePrice.getStartTime().length() - 3);
                String etime = day + " " + tSitePrice.getEndTime().substring(0, tSitePrice.getEndTime().length() - 3);
                boolean stringDateBetween = DateComparisonExample.isStringDateBetween(stime + " - " + etime, siteLock.getStartTime(), siteLock.getEndTime());
                if (stringDateBetween) {
                    System.err.println("11111预约开始" + stime + "预约结束" + etime);
                    querySiteTimes.setSelectable(0);
                    querySiteTimes.setIsReserve(1);
                }
                if (DateComparisonExample.isStringWithinTimeRange(stime, siteLock.getStartTime(), siteLock.getEndTime())) {
                    System.err.println("22222预约开始" + stime + "预约结束" + etime);
                    querySiteTimes.setSelectable(0);
                    querySiteTimes.setIsReserve(1);
                }
                if (DateComparisonExample.isStringWithinTimeRange(etime, siteLock.getStartTime(), siteLock.getEndTime())) {
                    System.err.println("33333预约开始" + stime + "预约结束" + etime);
                    querySiteTimes.setSelectable(0);
                    querySiteTimes.setIsReserve(1);
                }
            }
            timeRanges.add(querySiteTimes);
        }
        System.out.println("封装后的基础时间段和价格" + site);
        System.out.println("----最后封装的时间段数据------" + timeRanges);
        return timeRanges;
    }
    /**
     * 判断两个时间段是否有交集
     * @param start1 第一个时间段开始时间
     * @param end1 第一个时间段结束时间
     * @param start2 第二个时间段开始时间
     * @param end2 第二个时间段结束时间
     * @return 如果有交集返回true,否则返回false
     */
    private boolean isTimePeriodsIntersect(String start1, String end1, String start2, String end2) {
        // 首先判断是否有任何形式的重叠(包括端点)
        boolean hasOverlap = start1.compareTo(end2) <= 0 && end1.compareTo(start2) >= 0;
        // 判断是否仅仅是端点相接
        boolean onlyTouching = start1.compareTo(end2) == 0 || end1.compareTo(start2) == 0;
        // 有重叠且不是仅仅端点相接才算真正的交集
        return hasOverlap && !onlyTouching;
    }
}
cloud-server-management/src/main/webapp/WEB-INF/view/system/ball/yuyue_add.html
@@ -3,6 +3,59 @@
    .green-button {
        background-color: green;
    }
    /* 时间段表格样式 */
    #timeSlotTable {
        margin-top: 10px;
    }
    #timeSlotTable thead th {
        background-color: #f5f5f5;
        font-weight: bold;
        text-align: center;
    }
    #timeSlotTable tbody tr {
        transition: background-color 0.3s;
    }
    #timeSlotTable tbody tr:not(.disabled):hover {
        background-color: #f0f0f0;
    }
    #timeSlotTable tbody tr.disabled {
        background-color: #f5f5f5;
        color: #999;
    }
    #timeSlotTable tbody td {
        text-align: center;
        vertical-align: middle;
    }
    /* 价格单元格颜色 */
    #timeSlotTable tbody td.price-cell {
        padding: 8px;
    }
    #timeSlotTable tbody td.price-cell.price-unavailable {
        background-color: #ffcccc !important;
        color: #cc0000;
    }
    #timeSlotTable tbody td.price-cell.price-selected {
        background-color: #ccffcc !important;
        color: #006600;
        font-weight: bold;
    }
    /* 散客数量显示 */
    .capacity-info {
        display: block;
        font-size: 12px;
        color: #666;
        margin-top: 3px;
    }
</style>
<div class="ibox float-e-margins">
    <div class="ibox-content">
@@ -90,11 +143,27 @@
                </div>
                <div class="form-group">
                    <label class="col-sm-3 control-label">*预约时间段:</label>
                    <div class="col-sm-5" id="ttt1">
                        <div class="layui-btn-group" id="ttt2">
                        </div>
                    <label class="col-sm-3 control-label">*入场方式:</label>
                    <div class="col-sm-4">
                       <input type="radio" name="targetAudience" value="1" checked="" onclick="updateTargetAudience(1)"> 订场
                        <input type="radio" name="targetAudience" value="2" onclick="updateTargetAudience(2)"> 散客
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-3 control-label">*预约时间段:</label>
                    <div class="col-sm-8" id="ttt1">
                        <table class="table table-bordered table-hover" id="timeSlotTable" style="display:none;">
                            <thead>
                                <tr id="tableHeader">
                                    <th>时段</th>
                                    <th id="priceHeader">价格(次)</th>
                                </tr>
                            </thead>
                            <tbody id="timeSlotBody">
                            </tbody>
                        </table>
                        <div id="noDataTip" style="color: #999;">请先选择预约时间</div>
                    </div>
                </div>
@@ -148,6 +217,37 @@
</div>
<script src="${ctxPath}/modular/system/ball/yuyue_info.js"></script>
<script type="text/javascript">
    // 全局变量存储已选择的时间段数据
    var selectedTimeSlots = [];
    // 全局变量存储所有时间段数据
    var allTimeSlots = [];
    // 入场方式切换
    function updateTargetAudience(value) {
        // 更新表头
        var priceHeader = document.getElementById('priceHeader');
        if (value == 1) {
            priceHeader.innerText = '价格(次)';
        } else {
            priceHeader.innerText = '价格(人)';
        }
        // 清空已选择的时间段
        selectedTimeSlots = [];
        // 移除所有价格单元格的选中样式
        $('#timeSlotTable tbody td.price-cell').removeClass('price-selected');
        // 如果已选择日期,重新加载时间段
        if ($('#time').val()) {
            CoursePackageInfo.addTime();
        }
        // 重置价格
        $('#cash').val('');
        $('#play').val('');
    }
    function updateType(o) {
        if(o==1){
            // 选择半场 查询支持半场的场地
@@ -250,6 +350,80 @@
    // 点击表格行选择时间段(支持连续选择)
    function toggleTimeSlot(row, index) {
        var $row = $(row);
        var $priceCell = $row.find('td.price-cell');
        // 如果行是禁用的,不处理
        if ($row.hasClass('disabled')) {
            return;
        }
        var timeSlot = window.allTimeSlots[index];
        // 检查是否已选中
        var selectedIndex = -1;
        for (var i = 0; i < selectedTimeSlots.length; i++) {
            if (selectedTimeSlots[i].index === index) {
                selectedIndex = i;
                break;
            }
        }
        if (selectedIndex > -1) {
            // 已选中,取消选择
            selectedTimeSlots.splice(selectedIndex, 1);
            $priceCell.removeClass('price-selected');
        } else {
            // 未选中,检查是否连续
            if (selectedTimeSlots.length > 0) {
                // 获取已选择的索引
                var selectedIndexes = selectedTimeSlots.map(function(item) {
                    return item.index;
                }).sort(function(a, b) {
                    return a - b;
                });
                var minIndex = selectedIndexes[0];
                var maxIndex = selectedIndexes[selectedIndexes.length - 1];
                // 检查新选择的索引是否与已选择的连续
                if (index !== minIndex - 1 && index !== maxIndex + 1) {
                    Feng.error("只能选择连续的时间段!");
                    return;
                }
            }
            // 添加选择,保存索引
            timeSlot.index = index;
            selectedTimeSlots.push(timeSlot);
            $priceCell.addClass('price-selected');
        }
        // 重新排序
        selectedTimeSlots.sort(function(a, b) {
            return a.index - b.index;
        });
        // 计算总价格
        calculateTotalPrice();
    }
    // 计算总价格
    function calculateTotalPrice() {
        var totalCash = 0;
        var totalCoin = 0;
        for (var i = 0; i < selectedTimeSlots.length; i++) {
            totalCash += parseFloat(selectedTimeSlots[i].cashPrice || 0);
            totalCoin += parseFloat(selectedTimeSlots[i].coinPrice || 0);
        }
        $('#cash').val(totalCash.toFixed(2));
        $('#play').val(totalCoin.toFixed(0));
    }
    function toggleColor(button) {
        button.classList.toggle("green-button");
@@ -284,77 +458,24 @@
    }
    laydate.render({
        elem: '#time'
        ,lang:"CN",
        elem: '#time',
        lang:"CN",
        min:0,
        max:9,
        format:'yyyy-MM-dd',
        done:function (a) {
            console.log("==========="+a)
            var ajax = new $ax(Feng.ctxPath + "/ball/yuyuetimes/"+ $('#siteId').val(), function(data){
                console.log("================"+data)
                if(data!=null){
                    var content='';
                    $.each(data, function(k, v) {
                        var buttonClass = "layui-btn layui-btn-primary";
                        var style = "";
                        if (v.state === 0) {
                            style = "background-color: red;";
                        }
                        var disabledAttribute = v.state === 0 ? "disabled" : "";
                        content += '<button type="button" class="' + buttonClass + '" ' + disabledAttribute + ' style="' + style + '" onclick="toggleColor(this)">' + v.time + '</button>';
                    });
                    $("#ttt2").empty().append(content);
                }
            })
            var siteId = document.getElementById("nextSite");
            var siteName = siteId.options[siteId.selectedIndex].text;
            ajax.set("siteName",siteName);
            if (siteName ==""){
                var siteId = document.getElementById("siteId");
                var siteName = siteId.options[siteId.selectedIndex].text;
                ajax.set("siteName",siteName);
        done:function (date) {
            console.log("选择日期:" + date);
            // 调用addTime方法加载时间段
            if ($('#siteId').val()) {
                CoursePackageInfo.addTime();
            }
            var radios = document.getElementsByName("type");
            var selectedValue;
            for (var i = 0; i < radios.length; i++) {
                if (radios[i].checked) {
                    selectedValue = radios[i].value;
                    break;
                }
            }
            console.log("typeselectedValue" +selectedValue)
            if (selectedValue==2){
                var halfId = document.getElementById("half");
                var halfName = halfId.options[halfId.selectedIndex].text;
                ajax.set("halfName",halfName);
            }
            ajax.set("date",$('#time').val());
            ajax.start()
            // var ajax1 = new $ax(Feng.ctxPath + "/ball/halfName/"+ $('#siteId').val(), function(data){
            //     console.log("================"+data)
            //     if(data!=null){
            //         let htmlStr = '';
            //         for (let i = 0; i < data.length; i++) {
            //             htmlStr += '<option value="' + data[i] + '">' + data[i] + '</option>'
            //         }
            //         $("#half").empty().append(htmlStr);
            //     }
            // })
            // ajax1.start()
        }
    });
    laydate.render({
        elem: '#holitime'
        ,range: true //或 range: '~' 来自定义分割字符
        ,trigger: 'click'
    });
    var avatarUp = new $WebUpload("coverDrawing");
@@ -368,6 +489,7 @@
    var avatarUp1 = new $WebUpload("introduceDrawing");
    avatarUp1.setUploadBarId("progressBar");
    avatarUp1.init();
    function addTime(){
        var i =  $('#dayTime > div').length
@@ -380,8 +502,23 @@
        laydate.render({
            elem: '#classStartTime'+i,
            type: 'time',
            range: true
            range: true,
            trigger: 'click',
        });
    }
    // 监听半场选择变化
    $('#half').change(function() {
        if ($('#time').val()) {
            CoursePackageInfo.addTime();
        }
    });
    // 监听选择场地变化
    $('#nextSite').change(function() {
        if ($('#time').val()) {
            CoursePackageInfo.addTime();
        }
    });
</script>
@}
cloud-server-management/src/main/webapp/static/modular/system/ball/yuyue_info.js
@@ -46,49 +46,135 @@
CoursePackageInfo.addTime = function (a) {
    console.log("==========="+a)
    var ajax = new $ax(Feng.ctxPath + "/ball/yuyuetimes/"+ $('#siteId').val(), function(data){
        console.log("================"+data)
        if(data!=null){
            var content='';
            $.each(data, function(k, v) {
                var buttonClass = "layui-btn layui-btn-primary";
                var style = "";
                if (v.state === 0) {
                    style = "background-color: red;";
                }
                var disabledAttribute = v.state === 0 ? "disabled" : "";
                content += '<button type="button" class="' + buttonClass + '" ' + disabledAttribute + ' style="' + style + '" onclick="toggleColor(this)">' + v.time + '</button>';
            });
            $("#ttt2").empty().append(content);
        }
    })
    ajax.set("date",$('#time').val());
    var siteId = document.getElementById("siteId");
    var siteName = siteId.options[siteId.selectedIndex].text;
    ajax.set("siteName",siteName);
    // 获取入场方式
    var targetAudience = $('input[name="targetAudience"]:checked').val() || 1;
    // 获取半场名称
    var halfId = document.getElementById("half");
    var halfName = halfId.options[halfId.selectedIndex].text;
    ajax.set("halfName",halfName);
    ajax.start()
    // var ajax1 = new $ax(Feng.ctxPath + "/ball/halfName/"+ $('#siteId').val(), function(data){
    //     console.log("================"+data)
    //     if(data!=null){
    //         let htmlStr = '';
    //         for (let i = 0; i < data.length; i++) {
    //             htmlStr += '<option value="' + data[i] + '">' + data[i] + '</option>'
    //         }
    //         $("#half").empty().append(htmlStr);
    //     }
    // })
    // ajax1.start()
    var halfName = halfId && halfId.options[halfId.selectedIndex] ? halfId.options[halfId.selectedIndex].text : "";
    // 获取场地名称
    var nextSiteId = document.getElementById("nextSite");
    var siteName = "";
    if (nextSiteId && nextSiteId.options[nextSiteId.selectedIndex]) {
        siteName = nextSiteId.options[nextSiteId.selectedIndex].text;
    }
    // 调用管理后台接口获取时间段数据
    var ajax = new $ax(Feng.ctxPath + "/tSite/querySiteTimes", function(response){
        console.log("时间段数据:", response)
        if(response && response.code == 200 && response.data){
            var timeSlots = response.data;
            // 清空已选择的时间段
            if (typeof selectedTimeSlots !== 'undefined') {
                selectedTimeSlots = [];
            }
            if(timeSlots.length > 0) {
                // 显示表格,隐藏提示
                $('#timeSlotTable').show();
                $('#noDataTip').hide();
                // 生成表格内容
                var tbody = '';
                $.each(timeSlots, function(k, v) {
                    var priceText = '';
                    var priceClass = 'price-cell';
                    var rowClass = '';
                    var clickable = '';
                    var canBook = true;
                    // 判断是否可预订
                    if (targetAudience == 1) {
                        // 订场模式
                        if (v.isReserve == 1) {
                            // 被订场,不可预订
                            canBook = false;
                        } else if (v.selectCount >= v.selectMaxCount) {
                            // 散客数已满,不可预订
                            canBook = false;
                        }
                    } else {
                        // 散客模式
                        if (v.isReserve == 1) {
                            // 被订场,不可预订
                            canBook = false;
                        } else if (v.selectCount >= v.selectMaxCount) {
                            // 散客数已满,不可预订
                            canBook = false;
                        }
                    }
                    // 构建价格文本
                    var basePriceText = (v.cashPrice || 0) + '元 / ' + (v.coinPrice || 0) + '币';
                    if (!canBook || v.selectable == 0) {
                        // 不可预订
                        priceClass += ' price-unavailable';
                        priceText = basePriceText + '<br><span style="color: red; font-size: 12px;">(不可预订)</span>';
                        rowClass = 'disabled';
                        clickable = 'style="cursor: not-allowed;"';
                    } else {
                        // 可预订
                        priceText = basePriceText;
                        // 散客模式显示预定人数
                        if (targetAudience == 2) {
                            priceText += '<span class="capacity-info">(' + (v.selectCount || 0) + '/' + (v.selectMaxCount || 0) + ')</span>';
                        }
                        var jsonStr = JSON.stringify(v).replace(/"/g, '&quot;');
                        clickable = 'onclick="toggleTimeSlot(this, ' + k + ')" style="cursor: pointer;" data-index="' + k + '"';
                    }
                    tbody += '<tr class="' + rowClass + '" ' + clickable + ' data-time="' + v.time + '">';
                    tbody += '<td>' + v.time + '</td>';
                    tbody += '<td class="' + priceClass + '">' + priceText + '</td>';
                    tbody += '</tr>';
                });
                $('#timeSlotBody').html(tbody);
                // 保存原始数据到全局变量
                window.allTimeSlots = timeSlots;
            } else {
                // 没有数据
                $('#timeSlotTable').hide();
                $('#noDataTip').show();
                $('#noDataTip').text('该日期暂无可预约时间段');
            }
            // 重置价格
            $('#cash').val('');
            $('#play').val('');
        } else {
            $('#timeSlotTable').hide();
            $('#noDataTip').show();
            $('#noDataTip').text('获取时间段失败');
        }
    }, function(error){
        console.error("获取时间段失败:", error);
        Feng.error("获取时间段失败!");
        $('#timeSlotTable').hide();
        $('#noDataTip').show();
        $('#noDataTip').text('获取时间段失败');
    });
    ajax.set("id", $('#siteId').val());
    ajax.set("day", $('#time').val());
    ajax.set("targetAudience", targetAudience);
    if(halfName && halfName != "") {
        ajax.set("halfName", halfName);
    }
    if(siteName && siteName != "") {
        ajax.set("siteName", siteName);
    }
    ajax.start();
};
@@ -178,7 +264,6 @@
};
/**
@@ -208,16 +293,25 @@
    let half = $('#half').val();
    let date = $('#time').val();
    // 获取入场方式
    var targetAudience = $('input[name="targetAudience"]:checked').val() || 1;
    var elements = document.getElementsByClassName("layui-btn layui-btn-primary green-button");
    // 使用新的方式收集选中的时间段
    var values = "";
    for (var i = 0; i < elements.length; i++) {
         values += date +" "+ elements[i].innerText + ";";
    if (typeof selectedTimeSlots !== 'undefined' && selectedTimeSlots.length > 0) {
        for (var i = 0; i < selectedTimeSlots.length; i++) {
            values += date + " " + selectedTimeSlots[i].time + ";";
        }
        values = values.slice(0, -1);
    } else {
        // 兼容旧方式
        var elements = document.getElementsByClassName("layui-btn layui-btn-primary green-button");
        for (var i = 0; i < elements.length; i++) {
             values += date +" "+ elements[i].innerText + ";";
        }
        values = values.slice(0, -1);
    }
// 去除最后一个逗号
    values = values.slice(0, -1);
    console.log("看看预约时间段")
    console.log(values);
@@ -227,51 +321,6 @@
    let play = $('#play').val();
    let booker = $('#booker').val();
    let phone = $('#phone').val();
    // if(null == provinceCode || '' == provinceCode){
    //     Feng.error("所在省不能为空");
    //     return
    // }
    // if(null == cityCode || '' == cityCode){
    //     Feng.error("所在市不能为空");
    //     return
    // }
    // if(null == storeId || '' == storeId){
    //     Feng.error("所属门店不能为空");
    //     return
    // }
    // if(null == coursePackageTypeId || '' == coursePackageTypeId){
    //     Feng.error("课程类型不能为空");
    //     return
    // }
    // if(null == name || '' == name){
    //     Feng.error("课包名称不能为空");
    //     return
    // }
    // if(null == siteId || '' == siteId){
    //     Feng.error("上课场地不能为空");
    //     return
    // }
    // if(null == coachId || '' == coachId){
    //     Feng.error("授课教师不能为空");
    //     return
    // }
    //
    // classWeeks = classWeeks.substring(0, classWeeks.length - 1);
    //
    // if(null == coverDrawing || '' == coverDrawing){
    //     Feng.error("课包封面不能为空");
    //     return
    // }
    // if(null == detailDrawing || '' == detailDrawing){
    //     Feng.error("详情页不能为空");
    //     return
    // }
    // if(null == introduceDrawing || '' == introduceDrawing){
    //     Feng.error("课包介绍不能为空");
    //     return
    // }
    //提交信息
    var ajax = new $ax(Feng.ctxPath + "/ball/ordersave", function (data) {
@@ -304,6 +353,7 @@
    ajax.set("money",cash+","+play);
    ajax.set("booker",booker);
    ajax.set("phone",phone);
    ajax.set("targetAudience",targetAudience);
    ajax.start();
};
@@ -368,51 +418,6 @@
    let booker = $('#booker').val();
    let phone = $('#phone').val();
    let id = $('#id').val();
    // if(null == provinceCode || '' == provinceCode){
    //     Feng.error("所在省不能为空");
    //     return
    // }
    // if(null == cityCode || '' == cityCode){
    //     Feng.error("所在市不能为空");
    //     return
    // }
    // if(null == storeId || '' == storeId){
    //     Feng.error("所属门店不能为空");
    //     return
    // }
    // if(null == coursePackageTypeId || '' == coursePackageTypeId){
    //     Feng.error("课程类型不能为空");
    //     return
    // }
    // if(null == name || '' == name){
    //     Feng.error("课包名称不能为空");
    //     return
    // }
    // if(null == siteId || '' == siteId){
    //     Feng.error("上课场地不能为空");
    //     return
    // }
    // if(null == coachId || '' == coachId){
    //     Feng.error("授课教师不能为空");
    //     return
    // }
    //
    // classWeeks = classWeeks.substring(0, classWeeks.length - 1);
    //
    // if(null == coverDrawing || '' == coverDrawing){
    //     Feng.error("课包封面不能为空");
    //     return
    // }
    // if(null == detailDrawing || '' == detailDrawing){
    //     Feng.error("详情页不能为空");
    //     return
    // }
    // if(null == introduceDrawing || '' == introduceDrawing){
    //     Feng.error("课包介绍不能为空");
    //     return
    // }
    //提交信息