HTML表单数据保存至config.txt及读取回填功能实现求助
解决方案
1. 前端代码修改(HTML+JS)
先给表单元素添加name属性方便数据收集,同时加入提交按钮,优化克隆/删除逻辑:
<form id="tenantForm"> <!-- 租户模板行,用data-template标识方便克隆 --> <p class="tenant-row" data-template> <label>Tenant Name:</label> <input type="text" name="tenantName" required> <span class="remove">Remove</span><br> <label>Tenant URL:</label> <input type="text" name="tenantUrl" required><br> <label>API Token:</label> <input type="text" name="apiToken" required><br> <input type="checkbox" name="providers[]" value="AWS"> <label> AWS</label><br> <input type="checkbox" name="providers[]" value="Azure"> <label> Azure</label><br> <input type="checkbox" name="providers[]" value="PaaS"> <label> PaaS</label><br><br> </p> <p> <span class="add">Add fields</span> <button type="submit" style="margin-left:10px;">Save Config</button> </p> </form> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> // 克隆租户行 $(".add").click(function() { const template = $("[data-template]").clone(true).removeAttr("data-template"); template.insertBefore("form > p:last-child"); return false; }); // 删除租户行(至少保留一行) $(".remove").click(function() { if ($(".tenant-row").length > 1) { $(this).parent().remove(); } }); // 表单提交:收集数据并发送到后端 $("#tenantForm").submit(async function(e) { e.preventDefault(); const tenants = []; $(".tenant-row").each(function() { const $row = $(this); const tenantName = $row.find("[name='tenantName']").val().trim(); const tenantUrl = $row.find("[name='tenantUrl']").val().trim(); const apiToken = $row.find("[name='apiToken']").val().trim(); const providers = $row.find("[name='providers[]']:checked").map(function() { return $(this).val(); }).get(); tenants.push({ tenantName, tenantUrl, apiToken, providers }); }); try { const response = await fetch("/save-config", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ tenants }) }); const result = await response.json(); alert(result.message); } catch (err) { alert("保存配置失败:" + err.message); } }); // 页面加载时读取现有配置并回填表单 async function loadConfig() { try { const response = await fetch("/load-config"); if (response.ok) { const { tenants } = await response.json(); // 清空模板行默认内容 const $template = $("[data-template]"); $template.find("[name='tenantName']").val(""); $template.find("[name='tenantUrl']").val(""); $template.find("[name='apiToken']").val(""); $template.find("[name='providers[]']").prop("checked", false); // 生成现有租户对应的表单行 if (tenants && tenants.length > 0) { $(".tenant-row:not([data-template])").remove(); tenants.forEach((tenant, index) => { let $row = index === 0 ? $template : $template.clone(true).removeAttr("data-template"); if (index !== 0) $row.insertBefore("form > p:last-child"); // 填充数据 $row.find("[name='tenantName']").val(tenant.tenantName); $row.find("[name='tenantUrl']").val(tenant.tenantUrl); $row.find("[name='apiToken']").val(tenant.apiToken); tenant.providers.forEach(provider => { $row.find(`[name='providers[]'][value='${provider}']`).prop("checked", true); }); }); } } } catch (err) { console.log("无现有配置文件,将创建新文件"); } } // 页面加载完成后执行回填 $(document).ready(loadConfig); </script>
2. 后端实现(Node.js + Express)
前端无法直接读写本地文件,需通过后端处理。以下是Node.js实现:
首先安装依赖:
npm install express cors
创建server.js文件:
const express = require('express'); const fs = require('fs').promises; const path = require('path'); const cors = require('cors'); const app = express(); const PORT = 3000; const CONFIG_PATH = path.join(__dirname, 'config.txt'); app.use(cors()); app.use(express.json()); app.use(express.static('public')); // 前端HTML放在public目录下 // 解析INI格式配置为JSON async function parseIniConfig() { try { const content = await fs.readFile(CONFIG_PATH, 'utf8'); const tenants = []; let currentTenant = null; const lines = content.split('\n').map(line => line.trim()).filter(line => line && !line.startsWith(';')); lines.forEach(line => { if (line.startsWith('[') && line.endsWith(']')) { if (currentTenant) tenants.push(currentTenant); currentTenant = { tenantName: line.slice(1, -1), providers: [] }; } else if (currentTenant) { const [key, value] = line.split('=').map(item => item.trim()); switch(key) { case 'url': currentTenant.tenantUrl = value; break; case 'token': currentTenant.apiToken = value; break; case 'providers': currentTenant.providers = value.split(',').map(p => p.trim()); break; } } }); if (currentTenant) tenants.push(currentTenant); return { tenants }; } catch (err) { if (err.code === 'ENOENT') return { tenants: [] }; // 文件不存在返回空数组 throw err; } } // 将JSON转换为INI格式 function convertToIni(tenants) { let iniContent = "; Tenant Configuration File\n"; tenants.forEach(tenant => { iniContent += `[${tenant.tenantName}]\n`; iniContent += `url=${tenant.tenantUrl}\n`; iniContent += `token=${tenant.apiToken}\n`; iniContent += `providers=${tenant.providers.join(', ')}\n\n`; }); return iniContent; } // 读取配置接口 app.get('/load-config', async (req, res) => { try { const config = await parseIniConfig(); res.json(config); } catch (err) { res.status(500).json({ message: '读取配置失败', error: err.message }); } }); // 保存配置接口 app.post('/save-config', async (req, res) => { try { const { tenants } = req.body; const iniContent = convertToIni(tenants); await fs.writeFile(CONFIG_PATH, iniContent, 'utf8'); res.json({ message: '配置保存成功' }); } catch (err) { res.status(500).json({ message: '保存配置失败', error: err.message }); } }); app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); });
3. 运行步骤
- 创建
public目录,将修改后的前端HTML放入其中,命名为index.html - 创建
server.js文件,写入上述后端代码 - 执行命令启动服务:
npm install express cors node server.js - 访问
http://localhost:3000即可使用表单
生成的INI格式示例
; Tenant Configuration File [Tenant1] url=https://tenant1.example.com token=abc123 providers=AWS, Azure [Tenant2] url=https://tenant2.example.com token=def456 providers=PaaS
内容的提问来源于stack exchange,提问作者Ali987
相关产品推荐
相关产品推荐

