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

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. 运行步骤

  1. 创建public目录,将修改后的前端HTML放入其中,命名为index.html
  2. 创建server.js文件,写入上述后端代码
  3. 执行命令启动服务:
    npm install express cors
    node server.js
    
  4. 访问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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:06:29