1. Geschäftsanforderungen und Implementierungseffekte
Das Projekt betrifft das Bestellmodul. An diesem Tag erhielt ich plötzlich eine Anforderung, dass Bestellungen zwischen zwei Bestellungen mit unterschiedlichen Status eingefügt werden müssen. Der Effekt wird auf der Seite wie folgt dargestellt: Zwei Tabellen links und rechts. Die linke Tabelle enthält Bestellungen mit Status 1 und die rechte Tabelle enthält Bestellungen mit Status 2. Ziehen Sie die Zeilendaten in der linken Tabelle an die angegebene Zeilenposition In der rechten Tabelle wird nach Abschluss des Vorgangs die Tabelle links um eine Zeile verkleinert und die Tabelle rechts um eine Zeile hinzugefügt. Darüber hinaus müssen Sie den Vorgang auch rückgängig machen (entspricht der Strg + Z-Operation), um zum vorherigen Schritt zurückzukehren. Vielleicht lässt Sie die Beschreibung zweimal darüber nachdenken, es zu simulieren. Schauen wir uns zunächst die Renderings an.
1. Schauen Sie sich zunächst den Effekt an, bevor Sie ihn ziehen
2. Dies ist der Effekt des Ziehens der Tabellenzeilendaten nach links
3 , Die Wirkung von Tabellendaten nach dem Ziehen einer Zeile
4 Die Wirkung nach dem zweiten und dritten Ziehen
5. Die Wirkung des Rückgängigmachens in der rechten Tabelle
6. Klicken Sie mehrmals auf „Rückgängig“ und die Tabelle kehrt in den Ausgangszustand zurück
2. Codebeispiele
Das erste, was ich spürte, als ich die Anfrage erhielt, war, dass ich danach in der Bootstrap-Tabellen-API suchen sollte von Open Source ist leistungsstark, und es kann verwandte Beispiele geben. Nach einiger Suche verfügt Bootstrap Table leider nicht über eine solche Operation zwischen zwei Tabellen. Wenn Sie darüber nachdenken, können Sie tatsächlich verstehen, dass Bootstrap Table für die Datenbindung einer bestimmten dynamischen Tabelle konzipiert ist. Der Schwerpunkt liegt beispielsweise auf den Funktionen innerhalb der Tabelle. Es gibt beispielsweise eine gute Lösung für die Drag-and-Drop-Sortierung. Zeilen innerhalb der Tabelle neu anordnen Es scheint, dass spezielle Bedürfnisse wie Blogger selbst realisiert werden sollten.
1. Anforderungsanalyse
Nachdem ich beschlossen habe, es selbst zu schreiben, habe ich begonnen, die Anforderungen zu analysieren. Es scheint, dass der Drag-and-Drop-Effekt der schwierigere Teil ist und Drop-Effekt, es stellt sich heraus, dass es bei der Verwendung von JsPlumb zu häufig verwendet wird, daher denke ich an Draggable.js und Droppable.js in unserer magischen JQuery-Benutzeroberfläche. Nachdem das Drag-and-Drop-Problem nun gelöst ist, gibt es noch eine weitere Schwierigkeit: Was ist zu tun, wenn Sie den Vorgang rückgängig machen? Wir wissen, dass Strg+z Wiederherstellen bedeutet. Was ist Wiederherstellen? Es geht darum, zum Vorgang des vorherigen Schritts zurückzukehren. Die Voraussetzung ist also, dass der Status eines bestimmten Schritts gespeichert werden kann. Blogger wissen, wie das geht Es wird JSON benötigt, das jeweils über drei Schlüssel-Wert-Paare verfügen muss. Es handelt sich um den Index des aktuellen Schritts, die Daten der Tabelle links und die Daten der Tabelle rechts. Es scheint nicht allzu schwierig zu sein, also fangen wir an.
2. Codebeispiele
2.1 cshtml-Seitencode
<html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> @Styles.Render("~/Content/css") @Styles.Render("~/Content/table-css") @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/knockout") @Scripts.Render("~/bundles/bootstrap") @Scripts.Render("~/bundles/bootstrap-table") @RenderSection("Scripts", false) </head> <body> @RenderBody() </body> </html> @{ ViewBag.Title = "订单插单"; Layout = "~/Views/Shared/_Layout.cshtml"; } @Scripts.Render("~/bundles/Order/InsertOrder") @Styles.Render("~/bundles/Order/css") @Scripts.Render("~/Content/bootstrap/datepicker/js") @Styles.Render("~/Content/bootstrap/datepicker/css") <script src="~/Content/jquery-ui-1.11.4.custom/jquery-ui.min.js"></script> <p class="panel-body" style="padding-bottom:0px;"> <p class="panel panel-default" style="margin-bottom:0px;"> <p class="panel-heading">查询条件</p> <p class="panel-body container-fluid"> <p class="row"> <p class="col-md-3"> <label for="txt_search_ordernumber" class="col-sm-4 control-label" style="margin-top:6px;">订单号</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_ordernumber"> </span> </p> <p class="col-md-3"> <label for="txt_search_bodynumber" class="col-sm-3 control-label" style="margin-top:6px;">车身号</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_bodynumber"> </span> </p> <p class="col-md-3"> <label for="txt_search_vinnumber" class="col-sm-4 control-label" style="margin-top:6px;">VIN码</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_vinnumber"> </span> </p> <p class="col-md-3"> <label for="txt_search_engin_code" class="col-sm-4 control-label" style="margin-top:6px;">发动机号</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_engin_code"> </span> </p> </p> <p class="collapse" id="p_more_search"> <p class="row" style="margin-top:15px;"> <p class="col-md-3"> <label for="txt_search_import_startdate" class="col-sm-4 control-label" style="margin-top:6px;">导入时间</label> <span class="col-sm-8"> <input type="text" class="form-control datetimepicker" readonly id="txt_search_import_startdate"> </span> </p> <p class="col-md-3"> <label for="txt_search_import_enddate" class="col-sm-3 control-label" style="margin-top:6px;">至</label> <span class="col-sm-8"> <input type="text" class="form-control datetimepicker" readonly id="txt_search_import_enddate"> </span> </p> <p class="col-md-3"> <label for="txt_search_send_startdate" class="col-sm-4 control-label" style="margin-top:6px;">下发时间</label> <span class="col-sm-8"> <input type="text" class="form-control datetimepicker" readonly id="txt_search_send_startdate"> </span> </p> <p class="col-md-3"> <label for="txt_search_send_enddate" class="col-sm-4 control-label" style="margin-top:6px;">至</label> <span class="col-sm-8"> <input type="text" class="form-control datetimepicker" readonly id="txt_search_send_enddate"> </span> </p> </p> <p class="row" style="margin-top:15px;"> <p class="col-md-3"> <label for="txt_search_carcode" class="col-sm-4 control-label" style="margin-top:6px;">整车编码</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_carcode"> </span> </p> <p class="col-md-3"> <label for="txt_search_vms" class="col-sm-3 control-label" style="margin-top:6px;">VMS号</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_vms"> </span> </p> <p class="col-md-3"> <label for="txt_search_trans_code" class="col-sm-4 control-label" style="margin-top:6px;">变速箱号</label> <span class="col-sm-8"> <input type="text" class="form-control" id="txt_search_trans_code"> </span> </p> </p> </p> <p class="row" style="float:right;margin-right:50px;margin-top:13px;"> <p> <button type="button" id="btn_query" class="btn btn-primary" style="margin-right:20px;width:100px;">查询</button> <button type="submit" id="btn_reset" class="btn btn-default" style="margin-right:20px;width:100px;">重置</button> </p> </p> </p> </p> <p class="collapse_p_outside"> <p class="collapse_p_inside"></p> <span id="span_collapse" href="#p_more_search" class="collapse_p_inside_ele">展开<label class="glyphicon glyphicon-menu-down"></label></span> </p> </p> @*<p id="toolbar_left" class="btn-group"> </p>*@ <p id="toolbar_right" class="btn-group"> <button id="btn_cancel" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-backward aria-hidden="true"></span>撤销 </button> <button id="btn_insertorder" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>插单 </button> </p> <p class="panel-body" style="padding-top:0px;"> <p id="p_tableleft" class="col-md-6"> <table id="tb_order_left"></table> </p> <p id="p_tableright" class="col-md-6"> <table id="tb_order_right"></table> </p> </p>
2.2 js-Code
var i_statuindex = 0; //此数组用于保存撤销操作每一步的数据 var arrdata = []; var m_oTable = null; $(function () { //1.初始化表格 m_oTable = new TableInit(); m_oTable.Init(); //2.初始化按钮事件 var oButtonInit = new ButtonInit(); oButtonInit.Init(); //3.日期控件的初始化 $(".datetimepicker").datetimepicker({ format: 'yyyy-mm-dd hh:ii', autoclose: true, todayBtn: true, }); }); //表格相关事件和方法 var TableInit = function () { var oTableInit = new Object(); oTableInit.Init = function () { //初始化左边表格 $('#tb_order_left').bootstrapTable({ url: '/api/OrderApi/get', method: 'get', striped: true, cache: false, striped: true, pagination: true, height: 600, uniqueId:"TO_ORDER_ID", queryParams: oTableInit.queryParams, queryParamsType: "limit", sidePagination: "server", pageSize: 10, pageList: [10, 25, 50, 100], search: true, strictSearch: true, showColumns: true, showRefresh: true, minimumCountColumns: 2, clickToSelect: true, columns: [{ checkbox: true }, { field: 'ORDER_NO', title: '订单号' }, { field: 'BODY_NO', title: '车身号' }, { field: 'VIN', title: 'VIN码' }, { field: 'TM_MODEL_MATERIAL_ID', title: '整车编码' }, { field: 'ORDER_TYPE', title: '订单类型' }, { field: 'ORDER_STATUS', title: '订单状态' }, { field: 'CREATE_DATE', title: '订单导入时间' }, { field: 'PLAN_DATE', title: '订单计划上线日期' }, { field: 'VMS_NO', title: 'VMS号' }, { field: 'ENGIN_CODE', title: '发动机号' }, { field: 'TRANS_CODE', title: '变速箱号' }, { field: 'OFFLINE_DATE_ACT', title: '实际下线日期' }, { field: 'HOLD_RES', title: 'hold理由' }, { field: 'SPC_FLAG', title: '特殊标记' }, ], onLoadSuccess: function (data) { //表格加载完成之后初始化拖拽 oTableInit.InitDrag(); } }); //初始化右边表格 $('#tb_order_right').bootstrapTable({ url: '/api/OrderApi/get', method: 'get', toolbar: '#toolbar_right', striped: true, cache: false, striped: true, pagination: true, height: 600, queryParams: oTableInit.queryParamsRight, queryParamsType: "limit", //ajaxOptions: { departmentname: "", statu: "" }, sidePagination: "server", pageSize: 10, pageList: [10, 25, 50, 100], search: true, strictSearch: true, showRefresh: true, minimumCountColumns: 2, columns: [ { field: 'ORDER_NO', title: '订单号' }, { field: 'BODY_NO', title: '车身号' }, { field: 'VIN', title: 'VIN码' }, { field: 'TM_MODEL_MATERIAL_ID', title: '整车编码' }, { field: 'ORDER_TYPE', title: '订单类型' }, { field: 'ORDER_STATUS', title: '订单状态' }, { field: 'CREATE_DATE', title: '订单导入时间' }, { field: 'PLAN_DATE', title: '订单计划上线日期' }, { field: 'VMS_NO', title: 'VMS号' }, { field: 'ENGIN_CODE', title: '发动机号' }, { field: 'TRANS_CODE', title: '变速箱号' }, { field: 'OFFLINE_DATE_ACT', title: '实际下线日期' }, { field: 'HOLD_RES', title: 'hold理由' }, { field: 'SPC_FLAG', title: '特殊标记' }, ], onLoadSuccess: function (data) { oTableInit.InitDrop(); } }); }; //注册表格行的draggable事件 oTableInit.InitDrag = function () { $('#tb_order_left tr').draggable({ helper: "clone", start: function (event, ui) { var old_left_data = JSON.stringify($('#tb_order_left').bootstrapTable("getData")); var old_right_data = JSON.stringify($('#tb_order_right').bootstrapTable("getData")); var odata = { index: ++i_statuindex, left_data: old_left_data, right_data: old_right_data }; arrdata.push(odata); }, stop: function (event, ui) { } }); }; //注册右边表格的droppable事件 oTableInit.InitDrop = function () { $("#tb_order_right").droppable({ drop: function (event, ui) { var arrtd = $(ui.helper[0]).find("td"); var rowdata = { ORDER_NO: $(arrtd[1]).text(), BODY_NO: $(arrtd[2]).text(), VIN: $(arrtd[3]).text(), TM_MODEL_MATERIAL_ID: $(arrtd[4]).text(), ORDER_TYPE: $(arrtd[5]).text(), ORDER_STATUS: $(arrtd[6]).text(), CREATE_DATE: $(arrtd[7]).text() == "-" ? null : $(arrtd[7]).text(), PLAN_DATE: $(arrtd[8]).text() == "-" ? null : $(arrtd[8]).text(), VMS_NO: $(arrtd[9]).text(), ENGIN_CODE: $(arrtd[10]).text(), TRANS_CODE: $(arrtd[11]).text(), OFFLINE_DATE_ACT: $(arrtd[12]).text() == "-" ? null : $(arrtd[12]).text(), HOLD_RES: $(arrtd[13]).text(), SPC_FLAG: $(arrtd[14]).text(), TO_ORDER_ID: $(ui.helper[0]).attr("data-uniqueid") }; var oTop = ui.helper[0].offsetTop; var iRowHeadHeight = 40; var iRowHeight = 37; var rowIndex = 0; if (oTop <= iRowHeadHeight + iRowHeight / 2) { rowIndex = 0; } else { rowIndex = Math.ceil((oTop - iRowHeadHeight) / iRowHeight); } //插入右边表格指定位置行数据 $("#tb_order_right").bootstrapTable("insertRow", { index: rowIndex, row: rowdata }); $('#tb_order_left').bootstrapTable("removeByUniqueId", $(ui.helper[0]).attr("data-uniqueid")); oTableInit.InitDrag(); } }); }; oTableInit.queryParams = function (params) { //配置参数 var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的 limit: params.limit, //页面大小 offset: params.offset, //页码 strBodyno: $("#txt_search_bodynumber").val(), strVin: $("#txt_search_vinnumber").val(), strOrderno: $("#txt_search_ordernumber").val(), strEngincode: $("#txt_search_engin_code").val(), strOrderstatus: 0, strTranscode: $("#txt_search_trans_code").val(), strVms: $("#txt_search_vms").val(), strCarcode: $("#txt_search_carcode").val(), strImportStartdate: $("#txt_search_import_startdate").val(), strImportEnddate: $("#txt_search_import_enddate").val(), strSendStartdate: $("#txt_search_send_startdate").val(), strSendEnddate: $("#txt_search_send_enddate").val(), }; return temp; }; oTableInit.queryParamsRight = function (params) { //配置参数 var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的 limit: params.limit, //页面大小 offset: params.offset, //页码 strBodyno: "", strVin: "", strOrderno: "", strEngincode: "", strOrderstatus: 5, strTranscode: "", strVms: "", strCarcode: "", strImportStartdate: "", strImportEnddate: "", strSendStartdate: "", strSendEnddate: "", }; return temp; }; return oTableInit; }; //页面按钮初始化事件 var ButtonInit = function () { var oInit = new Object(); var postdata = {}; oInit.Init = function () { //查询点击事件 $("#btn_query").click(function () { $("#tb_order_left").bootstrapTable('refresh'); }); //重置点击事件 $("#btn_reset").click(function () { $(".container-fluid").find(".form-control").val(""); $("#tb_order_left").bootstrapTable('refresh'); }); //撤销操作点击事件 $("#btn_cancel").click(function () { if (i_statuindex <= 0) { return; } for (var i = 0; i < arrdata.length; i++) { if (arrdata[i].index != i_statuindex) { continue; } var arr_left_data = eval(arrdata[i].left_data); var arr_right_data = eval(arrdata[i].right_data); $('#tb_order_left').bootstrapTable('removeAll'); $('#tb_order_right').bootstrapTable('removeAll'); $('#tb_order_left').bootstrapTable('append', arr_left_data); for (var x = 0; x < arr_right_data.length; x++) { $("#tb_order_right").bootstrapTable("insertRow", { index: x, row: arr_right_data[x] }); } //$('#tb_order_right').bootstrapTable('append', arr_right_data);//append之后不能drop break; } i_statuindex--; //重新注册可拖拽 m_oTable.InitDrag(); //m_oTable.InitDrop(); }); //搜索栏展开收起点击事件 $("#span_collapse").click(function () { if ($(this).text() == "收起") { $(this).html('展开<label class="glyphicon glyphicon-menu-down"></label>'); $("#p_more_search").collapse('hide'); } else { $(this).html('收起<label class="glyphicon glyphicon-menu-up"></label>'); $("#p_more_search").collapse('show') } }); }; return oInit; };
Konzentrieren wir uns an mehreren Stellen auf den Code:
2.2 Nachdem die Tabelle links erfolgreich geladen wurde, können die Tabellenzeilen per Drag & Drop verschoben werden.
$('#tb_order_left tr').draggable({ helper: "clone", start: function (event, ui) { var old_left_data = JSON.stringify($('#tb_order_left').bootstrapTable("getData")); var old_right_data = JSON.stringify($('#tb_order_right').bootstrapTable("getData")); var odata = { index: ++i_statuindex, left_data: old_left_data, right_data: old_right_data }; arrdata.push(odata); }, stop: function (event, ui) { } });
Im Startereignis von Draggable speichern wir alle Daten in der linken und rechten Tabelle, bevor wir sie in die Variable arrdata ziehen. Die globale Variable i_statuindex wird zum Aufzeichnen des Index des aktuellen Schritts verwendet Wird zum Rückgängigmachen von Operationen verwendet.
2.2.2 Nachdem die rechte Tabelle erfolgreich geladen wurde, registrieren Sie das Droppable-Ereignis der Tabelle
$("#tb_order_right").droppable({ drop: function (event, ui) { var arrtd = $(ui.helper[0]).find("td"); var rowdata = { ORDER_NO: $(arrtd[1]).text(), BODY_NO: $(arrtd[2]).text(), VIN: $(arrtd[3]).text(), TM_MODEL_MATERIAL_ID: $(arrtd[4]).text(), ORDER_TYPE: $(arrtd[5]).text(), ORDER_STATUS: $(arrtd[6]).text(), CREATE_DATE: $(arrtd[7]).text() == "-" ? null : $(arrtd[7]).text(), PLAN_DATE: $(arrtd[8]).text() == "-" ? null : $(arrtd[8]).text(), VMS_NO: $(arrtd[9]).text(), ENGIN_CODE: $(arrtd[10]).text(), TRANS_CODE: $(arrtd[11]).text(), OFFLINE_DATE_ACT: $(arrtd[12]).text() == "-" ? null : $(arrtd[12]).text(), HOLD_RES: $(arrtd[13]).text(), SPC_FLAG: $(arrtd[14]).text(), TO_ORDER_ID: $(ui.helper[0]).attr("data-uniqueid") }; var oTop = ui.helper[0].offsetTop; var iRowHeadHeight = 40; var iRowHeight = 37; var rowIndex = 0; if (oTop <= iRowHeadHeight + iRowHeight / 2) { rowIndex = 0; } else { rowIndex = Math.ceil((oTop - iRowHeadHeight) / iRowHeight); } $("#tb_order_right").bootstrapTable("insertRow", { index: rowIndex, row: rowdata }); $('#tb_order_left').bootstrapTable("removeByUniqueId", $(ui.helper[0]).attr("data-uniqueid")); oTableInit.InitDrag(); } });
Erhalten Sie im Drop-Ereignis die aktuell gezogenen Zeilendaten und berechnen Sie die aktuelle Mausposition rechte Tabelle Fügt die gezogenen Zeilendaten an der angegebenen Position ein. Anschließend löschen Sie die aus der linken Tabelle gezogenen Zeilendaten.
2.2.3 Rückgängig-Operationscode
//撤销操作点击事件 $("#btn_cancel").click(function () { if (i_statuindex <= 0) { return; } for (var i = 0; i < arrdata.length; i++) { if (arrdata[i].index != i_statuindex) { continue; } var arr_left_data = eval(arrdata[i].left_data); var arr_right_data = eval(arrdata[i].right_data); $('#tb_order_left').bootstrapTable('removeAll'); $('#tb_order_right').bootstrapTable('removeAll'); $('#tb_order_left').bootstrapTable('append', arr_left_data); for (var x = 0; x < arr_right_data.length; x++) { $("#tb_order_right").bootstrapTable("insertRow", { index: x, row: arr_right_data[x] }); } //$('#tb_order_right').bootstrapTable('append', arr_right_data);//append之后不能drop break; } i_statuindex--; //重写注册可拖拽 m_oTable.InitDrag(); });
Die Rückgängig-Operation bestimmt hauptsächlich basierend auf dem Index in der globalen Variablen arrdata, welcher Schritt rückgängig gemacht werden soll, und entnimmt dann die linken und rechten Tabellendaten des aktuellen Gehen Sie entsprechend dem Index vor und senden Sie die Daten nacheinander an die beiden Tabellen. Anschließend wird i_statuindex nacheinander verringert, bis alle Daten in den linken Tabellenzeilen neu geschrieben und geladen werden um das ziehbare Ereignis erneut zu registrieren. Es sind nur so einfache drei Schritte, um den gewünschten Effekt zu erzielen. ~~
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er wird für das Studium hilfreich sein.
Weitere Artikel zum Implementierungscode für den Drag-Effekt der JS-Komponente Bootstrap Table finden Sie auf der chinesischen PHP-Website!
Verwandte Artikel:
Ausführliche Erklärung zur Implementierung des Grundlayouts mit Bootstrap
Analyse der Verwendung der BootStrap-Tabelle
Verwendung des Bootstrap-Übergangseffekts Übergangsmodalbox (Modal)