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

JavaScript基于JSON生成表格并邮件发送为空问题解决

邮件中表格为空问题的解决方案:正确填充JSON数据到格式化表格

问题背景

我用JavaScript编写了循环添加表格的函数,期望将JSON数据填充到格式化表格后发送至邮箱,但发送的邮件中表格始终为空。需求是自动将所有数据插入表格,最终效果需符合指定样式(忽略exp和status列)。

问题根源

  1. 前端JS逻辑缺陷:无效的条件判断(data[j].org != data[j].org永远为假)导致数据遍历异常,且表格标签未正确闭合,邮件客户端无法解析无效HTML结构。
  2. 依赖客户端JS执行:邮件客户端普遍禁用JavaScript,前端动态生成表格的逻辑完全无法生效。
  3. HTML与样式问题:重复使用ID、冲突的CSS类、不完整的标签结构,导致样式失效或渲染混乱。

解决方案

核心思路:后端预生成完整HTML表格

避免依赖邮件客户端的JS执行,直接在后端完成数据分组、表格HTML生成,再注入到模板中发送。

修正后的代码

后端处理函数

async function listItems(){
  try {
    console.log('========data scan=======');
    const data = await docClient.scan( params ).promise();
    
    // 按org字段分组数据,避免重复生成表头
    const groupedData = data.Items.reduce((acc, item) => {
      if (!acc[item.org]) {
        acc[item.org] = [];
      }
      acc[item.org].push(item);
      return acc;
    }, {});

    // 生成完整的表格HTML内容
    let tableHtml = '';
    Object.keys(groupedData).forEach(org => {
      // 生成组织专属表头
      tableHtml += `
        <thead>
          <tr><th class="tc-head" colspan="3">${org}</th></tr>
          <tr>
            <td class="tc-row">ID</td>
            <td class="tc-row">EndPoint</td>
            <td class="tc-row">Status</td>
          </tr>
        </thead>
        <tbody>`;
      // 生成该组织下的数据行
      groupedData[org].forEach(item => {
        const statusClass = item.online ? 'green' : 'red';
        tableHtml += `
          <tr>
            <td class="tc-col">${item.id}</td>
            <td class="tc-col">${item.endpoint}</td>
            <td class="tc-col ${statusClass}">${item.online ? '在线' : '离线'}</td>
          </tr>`;
      });
      tableHtml += `</tbody>`;
    });

    // 读取HTML模板并替换表格占位符
    let scanning = fs.readFileSync(`./table.html`, "utf8");
    scanning = scanning.replace('{{tableContent}}', tableHtml);

    const filter = data.Items.filter( item => !item.online && item.exp <= Math.floor( (new Date()).getTime() / 1000.0 ) );
    console.log('filter', filter);

    if (filter.length >= 1) {
      const to = 'myemail@gmail.com';
      const subject = 'EV Scanning Data!!!';
      // 直接发送预生成好的完整HTML邮件
      const send = await sendEmail(to, subject, scanning);
      console.log('send', send, 'data', data);

      // 改用Promise批量更新数据,确保异步操作完成
      await Promise.all(filter.map(item => {
        const putItemParams = {
          TableName: tableListStation,
          Item: {
            id: item.id,
            org: item.org,
            online: item.online,
            endpoint: item.endpoint,
            exp: Math.floor( (new Date(Date.now() + 172800000)).getTime() / 1000.0 ),
            updatedAt: momentGetDateJKT()
          }
        };
        console.log('item params', putItemParams);
        return docClient.put(putItemParams).promise();
      }));
    }
    return data;
  } catch (err) {
    return err;
  }
}

HTML模板(table.html)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Charger Station Status</title>
    <style type="text/css">
      .tc {
        border-collapse: collapse;
        border-color: #9abad9;
        border-spacing: 0;
        width: 100%;
        margin-bottom: 20px;
      }
      .tc td {
        background-color: #ebf5ff;
        border-color: #9abad9;
        border-style: solid;
        border-width: 1px;
        color: #444;
        font-family: Arial, sans-serif;
        font-size: 14px;
        padding: 10px 5px;
        word-break: normal;
      }
      .tc th {
        background-color: #409cff;
        border-color: #9abad9;
        border-style: solid;
        border-width: 1px;
        color: #fff;
        font-family: Arial, sans-serif;
        font-size: 14px;
        padding: 10px 5px;
      }
      .tc .tc-row {
        background-color: #efefef;
        text-align: center;
        font-weight: bold;
      }
      .tc .tc-head {
        background-color: #9aff99;
        font-weight: bold;
        text-align: center;
      }
      .tc .tc-col{
        text-align: left;
      }
      .red{
        background-color: #ffcccc;
        color: #cc0000;
      }
      .green{
        background-color: #ccffcc;
        color: #006600;
      }
      @media screen and (max-width: 767px) {
        .tc-wrap {
          overflow-x: auto;
          -webkit-overflow-scrolling: touch;
        }
      }
    </style>
  </head>
  <body>
    <header>EV Charger Station Status</header>
    <div class="tc-wrap">
      <table class="tc">
        {{tableContent}}
      </table>
    </div>
  </body>
</html>

关键修改说明

  1. 数据分组优化:用reduce按org分组,避免重复生成表头,简化逻辑。
  2. 后端生成HTML:完全绕过客户端JS,直接生成可被邮件客户端解析的完整表格。
  3. 样式修复:删除重复的.green类,用状态类代替重复ID,调整颜色适配邮件显示。
  4. 异步操作优化:将docClient.put改为Promise批量执行,确保数据更新完成后再继续流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:40:25