You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在弹窗中显示关联任务的Technician与Tarification表格并填充表单?

实现基于Metier和Tache选择的技术人员与定价弹窗填充功能

我来帮你一步步实现这个需求,咱们从后端接口、前端视图到交互逻辑逐一处理:

一、后端:新增API接口获取关联数据

首先在InterventionController中添加一个方法,用于根据选中的任务(tache)ID获取对应的技术人员和定价信息:

use Illuminate\Http\Request;
use App\Tarificationtache;

public function getTechniciansByTache(Request $request)
{
    $tacheId = $request->input('tache_id');
    
    // 通过任务ID获取关联的定价记录,同时加载关联的技术人员
    $tarifications = Tarificationtache::with('techniciens')
        ->where('tache_id', $tacheId)
        ->get();
    
    // 整理返回数据,方便前端渲染
    $data = [];
    foreach ($tarifications as $tarif) {
        foreach ($tarif->techniciens as $tech) {
            $data[] = [
                'technicien_id' => $tech->id,
                'technicien_name' => $tech->nom . ' ' . $tech->prenom, // 假设技术人员表有nom和prenom字段
                'tarification_id' => $tarif->id,
                'tarif' => $tarif->tarif
            ];
        }
    }
    
    return response()->json($data);
}

别忘了在routes/web.php中添加对应的路由:

Route::get('/intervention/get-technicians-by-tache', [App\Http\Controllers\InterventionController::class, 'getTechniciansByTache'])->name('intervention.getTechnicians');

二、前端:修改表单视图(intervention/create.blade.php)

调整表单结构,添加模态弹窗,并优化下拉框的联动逻辑(假设你使用Bootstrap框架):

<div class="container mt-4">
    <form action="{{ route('intervention.store') }}" method="POST">
        @csrf
        
        <!-- Metier下拉框 -->
        <div class="mb-3">
            <label for="metier_id" class="form-label">Metier</label>
            <select class="form-select" id="metier_id" name="metier_id">
                <option value="">请选择职业</option>
                @foreach($metiers as $metier)
                    <option value="{{ $metier->id }}">{{ $metier->nom }}</option> <!-- 假设metier表有nom字段 -->
                @endforeach
            </select>
        </div>
        
        <!-- Tache下拉框 -->
        <div class="mb-3">
            <label for="tache_id" class="form-label">Tache</label>
            <select class="form-select" id="tache_id" name="tache_id" disabled>
                <option value="">请先选择职业</option>
            </select>
        </div>
        
        <!-- Technicien和Tarification字段(用隐藏域+显示文本) -->
        <div class="mb-3">
            <label class="form-label">技术人员</label>
            <div id="technicien_display" class="form-control-plaintext text-muted">未选择</div>
            <input type="hidden" id="technicien_id" name="technicien_id">
        </div>
        
        <div class="mb-3">
            <label class="form-label">定价</label>
            <div id="tarification_display" class="form-control-plaintext text-muted">未选择</div>
            <input type="hidden" id="tarification_id" name="tarification_id">
        </div>
        
        <!-- 其他表单字段 -->
        <div class="mb-3">
            <label for="description" class="form-label">Description</label>
            <textarea class="form-control" id="description" name="description"></textarea>
        </div>
        <div class="mb-3">
            <label for="duree_prevu" class="form-label">Durée prévue</label>
            <input type="datetime-local" class="form-control" id="duree_prevu" name="duree_prevu">
        </div>
        <div class="mb-3">
            <div class="form-check">
                <input class="form-check-input" type="checkbox" id="statut" name="statut">
                <label class="form-check-label" for="statut">Statut</label>
            </div>
        </div>
        <div class="mb-3">
            <label for="client_id" class="form-label">Client</label>
            <select class="form-select" id="client_id" name="client_id">
                @foreach($client as $c)
                    <option value="{{ $c->id }}">{{ $c->nom }}</option>
                @endforeach
            </select>
        </div>
        
        <!-- 提交按钮 -->
        <button type="submit" class="btn btn-primary" disabled id="submit_btn">提交</button>
    </form>
</div>

<!-- 技术人员选择弹窗 -->
<div class="modal fade" id="technicianModal" tabindex="-1" aria-labelledby="technicianModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="technicianModalLabel">选择技术人员与定价</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <table class="table table-striped">
                    <thead>
                        <tr>
                            <th>技术人员</th>
                            <th>定价</th>
                        </tr>
                    </thead>
                    <tbody id="technician_table_body">
                        <!-- 数据将通过JS动态渲染 -->
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

三、JavaScript:实现交互逻辑

添加以下JS代码(放在视图底部或外部JS文件):

// 监听Metier选择事件,动态加载对应的Tache选项
document.getElementById('metier_id').addEventListener('change', function() {
    const metierId = this.value;
    const tacheSelect = document.getElementById('tache_id');
    
    tacheSelect.disabled = true;
    tacheSelect.innerHTML = '<option value="">加载中...</option>';
    
    if (metierId) {
        // 调用后端接口获取该职业下的任务
        fetch(`/intervention/get-taches-by-metier?metier_id=${metierId}`)
            .then(response => response.json())
            .then(data => {
                tacheSelect.innerHTML = '<option value="">请选择任务</option>';
                data.forEach(tache => {
                    const option = document.createElement('option');
                    option.value = tache.id;
                    option.textContent = tache.nom; // 假设tache表有nom字段
                    tacheSelect.appendChild(option);
                });
                tacheSelect.disabled = false;
            });
    } else {
        tacheSelect.innerHTML = '<option value="">请先选择职业</option>';
    }
});

// 监听Tache选择事件,弹窗显示技术人员列表
document.getElementById('tache_id').addEventListener('change', function() {
    const metierId = document.getElementById('metier_id').value;
    const tacheId = this.value;
    const modal = new bootstrap.Modal(document.getElementById('technicianModal'));
    const tableBody = document.getElementById('technician_table_body');
    
    if (metierId && tacheId) {
        tableBody.innerHTML = '<tr><td colspan="2" class="text-center">加载中...</td></tr>';
        
        fetch(`{{ route('intervention.getTechnicians') }}?tache_id=${tacheId}`)
            .then(response => response.json())
            .then(data => {
                tableBody.innerHTML = '';
                if (data.length === 0) {
                    tableBody.innerHTML = '<tr><td colspan="2" class="text-center text-muted">暂无相关技术人员</td></tr>';
                    return;
                }
                
                data.forEach(item => {
                    const row = document.createElement('tr');
                    row.style.cursor = 'pointer';
                    row.dataset.technicienId = item.technicien_id;
                    row.dataset.technicienName = item.technicien_name;
                    row.dataset.tarificationId = item.tarification_id;
                    row.dataset.tarif = item.tarif;
                    
                    row.innerHTML = `
                        <td>${item.technicien_name}</td>
                        <td>${item.tarif} €</td>
                    `;
                    
                    // 点击行时填充表单并关闭弹窗
                    row.addEventListener('click', function() {
                        document.getElementById('technicien_id').value = this.dataset.technicienId;
                        document.getElementById('technicien_display').textContent = this.dataset.technicienName;
                        
                        document.getElementById('tarification_id').value = this.dataset.tarificationId;
                        document.getElementById('tarification_display').textContent = `${this.dataset.tarif} €`;
                        
                        document.getElementById('submit_btn').disabled = false;
                        
                        bootstrap.Modal.getInstance(document.getElementById('technicianModal')).hide();
                    });
                    
                    tableBody.appendChild(row);
                });
            });
        
        modal.show();
    }
});

四、补充说明

  1. Metier与Tache的联动接口:你需要补充一个getTachesByMetier后端接口,逻辑类似getTechniciansByTache,根据职业ID返回对应的任务列表。
  2. 模型关系检查:确保Tarificationtache和Technicien的多对多关系中间表technicien_tarificationtache字段(tarificationtache_id、technicien_id)配置正确。
  3. Store方法修正:你的原store方法中$intervention ->tarification_id = $request->tarificationtache_id;应改为$request->input('tarification_id'),和前端隐藏域的name对应。
  4. 表单验证:在InterventionRequest中添加technicien_id和tarification_id的必填规则,防止未选择提交。

内容的提问来源于stack exchange,提问作者IT2704

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:23:13