基于MySQL数据库的人员区域拖拽分配功能优化咨询
问题描述
我需要制作一个网页,通过拖拽人员到对应区域来分配访问权限,同时同步更新MySQL数据库。目前已实现JavaScript拖拽功能,也能从数据库获取人员列表,但存在两个待解决的需求:
- 找到页面加载时人员按对应区域分类显示的最优方案——原本计划用三个独立PHP页面分别执行
SELECT ... WHERE zoneAccess = 1/2/3查询,但认为该方案效率低下,希望优化。 - 实现人员被拖拽至区域后,将对应区域编号写入数据库的
zoneAccess字段。
现有代码如下:
主页面HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>📌 Drag and Drop</title> <link rel="stylesheet" href="css/style.css" /> </head> <body> <main class="board"> <div class="column column-zone1" ondrop="drop(event)" ondragover="allowDrop(event)"> <h2>Zone 1</h2> <div class="container"> <table> <div class="column column-ip" ondrop="drop(event)" ondragover="allowDrop(event)"> <?php include('EmployesDrag.php') ?> </div> </table> </div> </div> <div class="column column-zone2" ondrop="drop(event)" ondragover="allowDrop(event)"> <h2>Zone 2</h2> </div> <div class="column column-zone3" ondrop="drop(event)" ondragover="allowDrop(event)"> <h2>Zone 3</h2> </div> </main> <script src="js/DragDrop.js"></script> </body> </html>
人员列表PHP(EmployesDrag.php)
<?php include_once "connexion.php"; // 查询人员信息 $sql="SELECT prenom , nom FROM personnel"; $result=mysqli_query($con,$sql); if ($result) { $rowcount=mysqli_num_rows($result); } if($rowcount == 0){ echo "Il n'y a pas encore d'employé ajouter !"; }else { while($row=$result->fetch_assoc()){ ?> <tr> <article class="card" draggable="true" ondragstart="drag(event)" data-id="1"><?=$row['nom']?></td> </tr> <?php } mysqli_free_result($result); } ?>
拖拽逻辑JavaScript(DragDrop.js)
const dragStart = target => { target.classList.add('dragging'); }; const dragEnd = target => { target.classList.remove('dragging'); }; const dragEnter = event => { event.currentTarget.classList.add('drop'); }; const dragLeave = event => { event.currentTarget.classList.remove('drop'); }; const drag = event => { event.dataTransfer.setData('text/html', event.currentTarget.outerHTML); event.dataTransfer.setData('text/plain', event.currentTarget.dataset.id); }; const drop = event => { document.querySelectorAll('.column').forEach(column => column.classList.remove('drop')); document.querySelector(`[data-id="${event.dataTransfer.getData('text/plain')}"]`).remove(); event.preventDefault(); event.currentTarget.innerHTML = event.currentTarget.innerHTML + event.dataTransfer.getData('text/html'); }; const allowDrop = event => { event.preventDefault(); }; document.querySelectorAll('.column').forEach(column => { column.addEventListener('dragenter', dragEnter); column.addEventListener('dragleave', dragLeave); }); document.addEventListener('dragstart', e => { if (e.target.className.includes('card')) { dragStart(e.target); } }); document.addEventListener('dragend', e => { if (e.target.className.includes('card')) { dragEnd(e.target); } });
优化方案
一、页面加载时按区域分类显示的最优实现
无需三次独立查询,只需一次完整查询+后端分组/按需渲染,减少数据库交互次数,提升性能同时保证安全性。
1. 优化人员列表PHP(EmployesDrag.php)
添加区域参数接收逻辑,通过单个PHP文件按需渲染对应区域的人员,同时使用预编译语句防止SQL注入:
<?php include_once "connexion.php"; // 接收目标区域参数,默认值为0 $targetZone = $_GET['zone'] ?? 0; // 验证区域参数合法性 if(!in_array($targetZone, [1,2,3])){ echo "<p>Aucun employé dans cette zone</p>"; exit; } // 预编译查询语句,避免SQL注入 $sql = "SELECT id, prenom, nom FROM personnel WHERE zoneAccess = ?"; $stmt = mysqli_prepare($con, $sql); mysqli_stmt_bind_param($stmt, "i", $targetZone); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); if(mysqli_num_rows($result) == 0){ echo "<p>Aucun employé dans cette zone</p>"; }else { while($row=$result->fetch_assoc()){ ?> <article class="card" draggable="true" ondragstart="drag(event)" data-id="<?= $row['id'] ?>"> <?= $row['prenom'] ?> <?= $row['nom'] ?> </article> <?php } mysqli_free_result($result); } mysqli_stmt_close($stmt); ?>
2. 调整主HTML页面结构
给每个区域容器添加data-zone标识,同时按需引入对应区域的人员列表:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>📌 Drag and Drop</title> <link rel="stylesheet" href="css/style.css" /> </head> <body> <main class="board"> <!-- Zone 1 --> <div class="column column-zone1" data-zone="1" ondrop="drop(event)" ondragover="allowDrop(event)"> <h2>Zone 1</h2> <div class="container"> <?php include('EmployesDrag.php?zone=1') ?> </div> </div> <!-- Zone 2 --> <div class="column column-zone2" data-zone="2" ondrop="drop(event)" ondragover="allowDrop(event)"> <h2>Zone 2</h2> <div class="container"> <?php include('EmployesDrag.php?zone=2') ?> </div> </div> <!-- Zone 3 --> <div class="column column-zone3" data-zone="3" ondrop="drop(event)" ondragover="allowDrop(event)"> <h2>Zone 3</h2> <div class="container"> <?php include('EmployesDrag.php?zone=3') ?> </div> </div> </main> <script src="js/DragDrop.js"></script> </body> </html>
二、拖拽后更新数据库zoneAccess字段
通过AJAX在拖拽完成后发送异步请求,更新数据库对应字段,保证页面显示与数据一致性。
1. 修改JavaScript的drop函数
添加AJAX请求逻辑,获取目标区域编号并发送更新请求:
const drop = event => { document.querySelectorAll('.column').forEach(column => column.classList.remove('drop')); const employeeId = event.dataTransfer.getData('text/plain'); const targetZone = event.currentTarget.dataset.zone; const draggedElement = document.querySelector(`[data-id="${employeeId}"]`); // 移除原元素并添加到目标区域 draggedElement.remove(); event.preventDefault(); event.currentTarget.querySelector('.container').innerHTML += event.dataTransfer.getData('text/html'); // 发送AJAX请求更新数据库 fetch('update_zone.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `employee_id=${employeeId}&zone=${targetZone}` }) .then(response => response.text()) .then(data => { console.log('更新状态:', data); // 可在此添加成功提示 }) .catch(error => { console.error('更新失败:', error); // 失败时可回滚操作,将元素放回原区域 }); };
2. 创建数据库更新PHP(update_zone.php)
处理AJAX请求,使用预编译语句更新数据库:
<?php include_once "connexion.php"; // 获取请求参数 $employeeId = $_POST['employee_id'] ?? 0; $zone = $_POST['zone'] ?? 0; // 验证参数合法性 if(!in_array($zone, [1,2,3]) || !is_numeric($employeeId)){ echo "参数无效"; exit; } // 预编译更新语句 $sql = "UPDATE personnel SET zoneAccess = ? WHERE id = ?"; $stmt = mysqli_prepare($con, $sql); mysqli_stmt_bind_param($stmt, "ii", $zone, $employeeId); if(mysqli_stmt_execute($stmt)){ echo "更新成功"; }else { echo "更新失败: " . mysqli_error($con); } mysqli_stmt_close($stmt); ?>
内容的提问来源于stack exchange,提问作者SinizowN
相关产品推荐
相关产品推荐

