如何基于动态下拉框弹出关联技术人员与定价的表格并填充表单
实现选择职业/任务后弹窗选技术人员并自动填充表单的完整方案
我来帮你梳理一下实现这个需求的完整流程,从后端接口准备到前端交互逻辑,结合你提到的模型、控制器、视图体系来落地:
一、后端:提供关联数据查询接口
首先我们需要写一个接口,用来根据选中的Metier和TacheID,返回对应的技术人员及其关联定价。这里以Laravel框架为例(适配你提到的模型/控制器结构):
1. 控制器方法
在TarificationController或专门的接口控制器中添加如下方法:
use Illuminate\Http\Request; use App\Models\Technicien; public function getTechniciensByMetierTache(Request $request) { // 验证参数合法性 $request->validate([ 'metier_id' => 'required|exists:metiers,id', 'tache_id' => 'required|exists:taches,id', ]); // 通过模型关联查询符合条件的技术人员及对应定价 $techniciens = Technicien::whereHas('taches', function($query) use ($request) { $query->where('taches.id', $request->tache_id) ->where('taches.metier_id', $request->metier_id); }) ->with(['tarifications' => function($query) use ($request) { $query->where('tache_id', $request->tache_id); }]) ->get(); // 整理成前端易处理的格式 $formattedData = $techniciens->map(function($tech) { return [ 'id' => $tech->id, 'full_name' => "{$tech->prenom} {$tech->nom}", 'tarif' => $tech->tarifications->first()?->montant ?? 0, ]; }); return response()->json(['success' => true, 'data' => $formattedData]); }
2. 注册路由
在routes/web.php或routes/api.php中添加路由:
Route::get('/api/techniciens/filter', [TarificationController::class, 'getTechniciensByMetierTache'])->name('api.techniciens.filter');
3. 模型关联补充(如果未配置)
确保模型间的关联正确,方便查询:
// Tache.php public function metier() { return $this->belongsTo(Metier::class); } public function techniciens() { return $this->belongsToMany(Technicien::class)->withPivot('tarif'); // 若用中间表存定价 } // Technicien.php public function tarifications() { return $this->hasMany(Tarification::class); }
二、前端:表单与弹窗交互实现
1. 视图结构(表单+弹窗)
在你的表单视图中添加如下HTML:
<!-- 核心表单 --> <form id="taskForm"> <div class="form-group"> <label for="metier">Métier</label> <select id="metier" name="metier_id" class="form-control"> @foreach($metiers as $metier) <option value="{{ $metier->id }}">{{ $metier->nom }}</option> @endforeach </select> </div> <div class="form-group"> <label for="tache">Tâche</label> <select id="tache" name="tache_id" class="form-control"> <!-- 可根据选中的Metier动态加载,或预先渲染所有选项 --> @foreach($taches as $tache) <option value="{{ $tache->id }}">{{ $tache->nom }}</option> @endforeach </select> </div> <div class="form-group"> <label for="technicien">Technicien</label> <select id="technicien" name="technicien_id" class="form-control" disabled> <option value="">Sélectionner via la fenêtre</option> </select> </div> <div class="form-group"> <label for="tarification">Tarification</label> <input type="number" id="tarification" name="tarification" class="form-control" readonly> </div> <button type="button" id="openTechnicianModal" class="btn btn-primary">Choisir un technicien</button> </form> <!-- 技术人员选择弹窗 --> <div class="modal fade" id="technicianModal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Techniciens disponibles</h5> <button type="button" class="close" data-dismiss="modal">×</button> </div> <div class="modal-body"> <table class="table table-striped" id="technicianTable"> <thead> <tr> <th>Nom complet</th> <th>Tarification (€)</th> <th>Action</th> </tr> </thead> <tbody></tbody> </table> </div> </div> </div> </div>
2. JavaScript交互逻辑
用jQuery实现弹窗触发、数据加载和表单自动填充:
$(document).ready(function() { // 打开弹窗时加载数据 $('#openTechnicianModal').click(function() { const metierId = $('#metier').val(); const tacheId = $('#tache').val(); // 校验是否已选职业和任务 if (!metierId || !tacheId) { alert('Veuillez d\'abord sélectionner un métier et une tâche !'); return; } // 调用后端接口 $.ajax({ url: "{{ route('api.techniciens.filter') }}", method: 'GET', data: { metier_id: metierId, tache_id: tacheId }, success: function(res) { if (res.success && res.data.length) { // 清空表格并填充数据 $('#technicianTable tbody').empty(); res.data.forEach(tech => { const row = `<tr> <td>${tech.full_name}</td> <td>${tech.tarif}</td> <td><button class="btn btn-sm btn-success select-tech" data-id="${tech.id}" data-tarif="${tech.tarif}">Sélectionner</button></td> </tr>`; $('#technicianTable tbody').append(row); }); // 打开弹窗 $('#technicianModal').modal('show'); } else { alert('Aucun technicien disponible pour cette combinaison !'); } }, error: () => alert('Erreur lors de la récupération des données') }); }); // 选择技术人员后填充表单 $(document).on('click', '.select-tech', function() { const techId = $(this).data('id'); const tarif = $(this).data('tarif'); // 填充表单字段 $('#technicien').val(techId).prop('disabled', false); $('#tarification').val(tarif); // 关闭弹窗 $('#technicianModal').modal('hide'); }); });
三、优化建议
- 可以在
Metier选择后动态加载对应的Tache选项,减少用户无效选择; - 弹窗表格添加搜索框,方便快速定位技术人员;
- 给接口添加权限验证(如
auth中间件),防止未授权访问; - 优化异常提示,用更友好的Toast组件替代alert。
内容的提问来源于stack exchange,提问作者chagou2704
相关产品推荐
相关产品推荐

