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

求助:用JS+PHP实现餐厅后台菜单JSON文件无刷新编辑功能

问题描述

我正在为餐厅老板开发后台管理面板,需实现菜单板块的编辑功能。目前已通过JSON文件动态生成菜单表格,但无法实现通过表格内的文本输入框修改内容,点击“确认”按钮后无刷新更新JSON文件的功能,附上相关代码寻求解决方案。

HTML文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="script.js"></script>
    <link href="style.css" rel="stylesheet">
    <title>Menu</title>
</head>
<body>
    <div class="menu-container">
        <h1>Menu del Ristorante</h1>
        <table>
            <thead>
                <tr>
                    <th>Tipologia</th>
                    <th class="nome">Nome</th>
                    <th>Modifica</th>
                    <th>Nuovo testo</th>
                    <th>Conferma</th>
                </tr>
            </thead>
            <tbody id="menu-table">
                <!-- I dati verranno caricati qui dinamicamente -->
            </tbody>
        </table>
        
    </div>
</body>
</html>

JSON文件(menu.json)

[
    {
        "tipologia": "Antipasto",
        "nome": "Misto di Mare caldo e freddo (min. per 2 persone)"
    },
    {
        "tipologia": "Antipasto",
        "nome": "Carpaccio di Gambero rosso, Cetriolo, Panna acida"
    },
    {
        "tipologia": "Antipasto",
        "nome": "Tartare di Pescato, Guacamole e Pane Carasau"
    },
    {
        "tipologia": "Antipasto",
        "nome": "Bresaola di Tonno e insalata di Pesche Noci"
    },
    {
        "tipologia": "Antipasto",
        "nome": "Altra voce del menu senza descrizione"
    },
    {
        "tipologia": "Antipasto",
        "nome": "Ancora un'altra voce del menu senza descrizione"
    }
]

PHP文件(save-menu.php)

<?php
// Percorso del file JSON
$jsonFile = 'menu.json';

// Controlla se è una richiesta PUT
if ($_SERVER['REQUEST_METHOD'] === 'PUT') {
    // Leggi i dati inviati dalla richiesta PUT
    $data = file_get_contents('php://input');

    // Decodifica i dati JSON
    $jsonData = json_decode($data, true);

    // Verifica se la decodifica è riuscita
    if ($jsonData !== null) {
        // Codifica nuovamente i dati come JSON
        $jsonString = json_encode($jsonData, JSON_PRETTY_PRINT);

        // Sovrascrivi il file JSON con i nuovi dati
        file_put_contents($jsonFile, $jsonString);

        // Restituisci una risposta di successo
        http_response_code(200);
        echo json_encode(array('message' => 'Modifiche salvate con successo.'));
    } else {
        // Errore nella decodifica JSON
        http_response_code(400);
        echo json_encode(array('message' => 'Errore nella decodifica JSON.'));
    }
} else {
    // Tipo di richiesta non supportato
    http_response_code(405);
    echo json_encode(array('message' => 'Metodo non consentito.'));
}
?>

JavaScript文件(script.js)

let menuData; // Variabile per archiviare i dati del menu

// Funzione per inizializzare la tabella del menu
async function initMenuTable() {
    const menuTable = document.getElementById('menu-table');

    // Carica i dati del menu dal file JSON
    try {
        const response = await fetch('menu.json');
        if (!response.ok) {
            throw new Error('Errore nel caricamento dei dati del menu.');
        }
        menuData = await response.json();

        // Popola la tabella con i dati del menu
        menuData.forEach((item, index) => {
            const row = menuTable.insertRow();
            row.innerHTML = `<td>${item.tipologia}</td><td>${item.nome}</td><td><button onclick="modificaVoceMenu(${index})">Modifica</button></td><td><input type="text" id="nuovo-titolo-${index}" value="${item.nome}" disabled></td><td><button onclick="confermaModifica(${index})">Conferma</button></td>`;
        });
    } catch (error) {
        console.error(error);
    }
}

// Funzione per abilitare la modifica di una voce del menu
function modificaVoceMenu(index) {
    const input = document.getElementById(`nuovo-titolo-${index}`);
    input.removeAttribute('disabled');
    input.focus();
}

// Funzione per confermare la modifica e aggiornare i dati
function confermaModifica(index) {
    const nuovoTitolo = document.getElementById(`nuovo-titolo-${index}`).value.trim();
    if (!nuovoTitolo) return; // 防止空值提交
    
    // Aggiorna il titolo nel menuData
    menuData[index].nome = nuovoTitolo;

    // Aggiorna la cella HTML con il nuovo valore
    const row = document.getElementById('menu-table').rows[index];
    row.cells[1].textContent = nuovoTitolo;

    // Disabilita l'input
    document.getElementById(`nuovo-titolo-${index}`).setAttribute('disabled', 'true');

    // Salva il menuData aggiornato nel file JSON
    salvaMenuData(menuData);
}

// Funzione per salvare il menuData aggiornato nel file JSON
function salvaMenuData(data) {
    fetch('save-menu.php', { // 修改为请求PHP处理文件
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(data),
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('Errore nel salvataggio delle modifiche.');
        }
        return response.json();
    })
    .then(result => {
        console.log(result.message);
    })
    .catch(error => {
        console.error(error);
    });
}

// Chiama la funzione per inizializzare la tabella del menu quando la pagina si carica
window.addEventListener('load', initMenuTable);
解决方案说明
  1. 请求目标修正:原JS中salvaMenuData函数请求静态menu.json文件,静态文件无法处理PUT请求,需改为请求PHP处理文件(如save-menu.php),由PHP完成JSON文件的写入操作。
  2. 输入框初始化优化:生成表格时将当前菜品名称填入输入框,方便用户直接修改,无需重新输入完整内容。
  3. DOM选择器优化:替换原getElementsByTagName为更可靠的表格行选择方式,避免页面其他表格干扰导致的选择错误。
  4. 空值校验:确认修改时添加空值校验,防止提交空的菜品名称。
  5. 用户体验优化:点击“Modifica”时自动聚焦输入框,提升操作流畅度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 22:17:04