拖拽式事件调度器的拖拽复制逻辑实现求助
拖拽式事件调度器的拖拽复制逻辑实现求助
嘿,我完全懂你现在的困扰——这个拖拽复制的规则确实有点绕,不过你的基础框架已经搭得很扎实了,只需要针对LeadIn事件的特殊需求调整几个回调逻辑就行。咱们一步步来搞定它:
核心需求回顾
先再理一遍你要的规则,确保咱们没跑偏:
- 从Events列拖拽LeadIn到Screen列:原LeadIn留在Events,复制一份到目标Screen
- 从Screen列拖拽LeadIn到另一个Screen列:直接移动过去
- 从Screen列拖拽LeadIn到Events列:移除这个Screen里的LeadIn,Events里保持原有那一个
- Events列永远只能有一个LeadIn
代码修改方案
咱们主要修改sortable的回调函数,加上拖拽开始的判断,以及调整receive、remove的逻辑,同时强化LeadIn的唯一性校验:
$(document).ready(function () { // Call the sort function on page load to alphabetize the Events column sortEventsInEventsColumn(); // 全局变量记录拖拽的源信息 let dragSourceColumnId; let isDraggingLeadIn; $(function() { $(".sortable-list").sortable({ connectWith: ".sortable-list", placeholder: "event-placeholder", start: function(event, ui) { // 记录拖拽开始时的源列ID和是否是LeadIn dragSourceColumnId = $(this).closest(".column").attr("id"); isDraggingLeadIn = ui.item.hasClass("lead-in-event"); }, receive: function (event, ui) { const $targetColumn = $(this).closest(".column"); const targetColumnId = $targetColumn.attr("id"); // 处理LeadIn的特殊逻辑 if (isDraggingLeadIn) { // 场景1:从Events拖到Screen列,需要复制,保留原LeadIn if (dragSourceColumnId === "events" && targetColumnId !== "events") { // 复制原LeadIn放回Events列 const originalLeadIn = $("#leadIn").clone(true); $("#events .sortable-list").append(originalLeadIn); // 重新排序Events列,确保LeadIn在顶部 sortEventsInEventsColumn(); } // 场景2:从Screen拖到Events列,直接移除拖拽的这个LeadIn else if (targetColumnId === "events") { ui.item.remove(); // 确保Events列只有一个LeadIn ensureSingleLeadInInEvents(); return; // 跳过后续时间计算逻辑 } } // 常规时间计算逻辑(非LeadIn或者Screen之间的LeadIn移动) if (targetColumnId !== "events") { recalculateColumnTimes($targetColumn); updateTotalDuration($targetColumn); } else { updateEventTimes(ui.item, "", ""); sortEventsInEventsColumn(); } }, update: function (event, ui) { const $targetColumn = $(this).closest(".column"); const targetColumnId = $targetColumn.attr("id"); if (targetColumnId !== "events") { recalculateColumnTimes($targetColumn); updateTotalDuration($targetColumn); } else { updateEventTimes(ui.item, "", ""); // 确保Events列只有一个LeadIn ensureSingleLeadInInEvents(); sortEventsInEventsColumn(); } }, remove: function (event, ui) { const $sourceColumn = $(this).closest(".column"); const sourceColumnId = $sourceColumn.attr("id"); if (sourceColumnId !== "events") { recalculateColumnTimes($sourceColumn); updateTotalDuration($sourceColumn); } } }).disableSelection(); }); // 新增函数:确保Events列只有一个LeadIn function ensureSingleLeadInInEvents() { const $eventsColumn = $("#events"); const $leadIns = $eventsColumn.find(".lead-in-event"); if ($leadIns.length > 1) { // 保留第一个,移除其他多余的LeadIn $leadIns.slice(1).remove(); } } // 以下是你原有的函数,保持不变 function recalculateColumnTimes($column) { var $events = $column.find(".event"); var startTime = $column.data("start-time"); $events.each(function (index) { var $event = $(this); var duration = $event.data("duration"); var endTime = calculateEndTime(startTime, duration); updateEventTimes($event, "Start: " + formatTimeAMPM(startTime), "End: " + formatTimeAMPM(endTime)); startTime = endTime; }); } function updateEventTimes($event, startTime, endTime) { $event.find(".event-start-time").text(startTime); $event.find(".event-end-time").text(endTime); } function calculateEndTime(startTime, duration) { var start = moment(startTime, "HH:mm:ss"); var dur = moment.duration(duration); var end = start.clone().add(dur); return end.format("HH:mm:ss"); } function formatTimeAMPM(time) { return moment(time, "HH:mm:ss").format("h:mm:ss A"); } function sortEventsInEventsColumn() { var $eventsColumn = $("#events"); var $eventList = $eventsColumn.find(".sortable-list"); var events = $eventList.children(".event").get(); events.sort(function (a, b) { var titleA = $(a).find(".event-title").text(); var titleB = $(b).find(".event-title").text(); if (titleA === "LeadIn") { return -1; } else if (titleB === "LeadIn") { return 1; } return titleA.localeCompare(titleB); }); $.each(events, function (index, event) { $eventList.append(event); }); // 排序后也要确保只有一个LeadIn ensureSingleLeadInInEvents(); } function updateTotalDuration($column) { var $eventList = $column.find(".sortable-list"); var totalDuration = moment.duration(); $eventList.find(".event").each(function () { var duration = moment.duration($(this).data("duration")); totalDuration.add(duration); }); var formattedTotalDuration = formatDuration(totalDuration); $column.find(".column-total-duration").text("Total Duration: " + formattedTotalDuration); } function formatDuration(duration) { var hours = duration.hours(); var minutes = duration.minutes(); return hours + "h " + minutes + "m"; } });
修改点说明
start回调:新增这个回调来记录拖拽的源列ID和当前元素是否是LeadIn,后续的逻辑都依赖这个判断。receive回调:针对三种场景分别处理:- 从Events到Screen:复制原LeadIn放回Events,保证原元素不被移走。
- 从Screen到Events:直接删除拖拽的LeadIn,不让它进入Events列。
- 新增
ensureSingleLeadInInEvents函数:专门用来校验Events列的LeadIn数量,确保永远只有一个,不管是拖拽还是排序后都调用它。 sortEventsInEventsColumn函数:最后加上ensureSingleLeadInInEvents的调用,防止排序时出现多个LeadIn。
这样调整后,你的拖拽规则就完全符合需求啦,你可以测试一下各个场景,应该都能正常工作~
备注:内容来源于stack exchange,提问作者Trick Kramer
相关产品推荐
相关产品推荐

