Skip to content

Report Plus User Guide

支持对数据进行更高级的自定义操作,数据源包含上传的文件和平台已经产生的 View,当前 创建 Report 时会同步产生相关的 View,

Report Plus 配置界面

setting

Step 1: Basic Settings

  1. Id: report plus 唯一标识,创建后无法更改
  2. Name: report plus 名称,可以更改
  3. First Tag/Second Tag: 一级标签 / 二级标签

Step 2: Source Configuration

添加文件,类型可选 View 或者 本地File 支持的数据类型包括 CSV EXCEL PARQUET PKL

Step 3: Export Options

文件导出类型,CSV/XLSX 文件导出名称 最终只能生成一个结果文件 step3 高级配置,

Customer Script

高级自定义脚本模式,需要自己编写对数据的处理,最终保存到目标目录,支持高级样式输出

Dataframe

基础自定义模式,通过对数据集的操作,无需自行输出文件,可以在下面进行导出编辑,不支持高级样式输出 首次配置时,是无法选择已有的数据集的,需要进行一次 review 可以刷新脚本中的所有df,随后既可选取进行编辑 这里是review 之后,这里会展示全部的可用数据集 export4 选择数据集后,这里是针对最终输出的 Excel 文件中的 Sheet 页,可以对 Sheet 页进行重命名 export2export1

点击左侧单Sheet 的箭头可以打开高级配置,此时可以再次选择数据集。将多个数据集纵向拼接到单Sheet 页中 export3 其中配置包括:

  1. 增加标题,
  2. 是否包含标题(默认加粗),
  3. 是否包含数据集中的 header
  4. 数据集前要保留多少行空行

!#如果选择格式为 CSV 则只能有一个 Sheet

配置介绍

record 保存之后针对 record 的操作

  1. Setting 配置 report plus
  2. Edit 跳转 jupyter 平台,编写脚本,操作选中的数据集
  3. Review 预览所有数据的加载效果(单数据集限制10000),如果是
    • Customer Script 模式,没有编辑的情况下是看不到数据集的,
    • Dataframe 模式下,在未进行配置时,会加载所有的数据集,
    • 注意:仅能预览 excel 格式的文件
  4. Download 同上,不过是加载全部(单数据集1000000)数据
  5. Delete 删除 report plus

jupyter

Edit 跳转 jupyter 之后 jupyter 中的基础概念 jupyter_base 从左到右依次

  1. 保存
  2. 添加新的 code cell
  3. 剪切
  4. 复制
  5. 粘贴
  6. 运行鼠标所在 cell 中的代码
  7. 停止内核(代码运行环境)
  8. 重启内核(代码运行环境)
  9. 重跑所有 cell 中的代码
  10. 切换 code 模式,勿动
  11. 创建 mitosheet, 会创建一个 cell 运行 mito,然后可以加载这个 cell 前的代码产生的 df

进入之后选择第一cell 运行其代码,运行效果: run_result 两种模式都不要操作 第一个 cell 的代码,在report plus 的 Setting 中源数据集 发生更改时,第一cell 中的代码会被刷新

Customer Script 模式

  1. 自行加载第一cell 中注册的 dataframe 进行处理,最后写入s3就好,写入代码模版: record
  2. 此处的环境变量在开始已经赋值,上传的 key 和 bucket 不可更改,
  3. 不建议脚本中有访问别的数据桶的数据,需额外增加权限,

Dataframe 模式

  1. 自行加载第一cell 中注册的 dataframe 进行处理,最后赋值回 dataframe 就好,此时这个dataframe会在内存中,可供后续配置选择 record
  2. 保存后需要进行一次 review 或者 download ,刷线 df_list,获取最新的可选择的 dataframe 数据集
  3. 在 setting 界面配置脚本中生成的 dataframe 数据集的拼接方式,
  4. 保存记录,即可预览或者下载,

结果文件的更新条件

  1. 上传的文件或者 view 发生更新(主要指 view info 表中的 update time)
  2. ipynb 文件发生更新, 以上两种情况满足一条时, review 和 download 时都会重新执行,生成新的结果文件,其余情况都会加载上次执行的缓存结果

邮件发送模版

参数描述说明
recipient收件人必填
cc抄送选填
subject邮件主题选填
body_text/body_html邮件内容二选一,同时存在时 body_html 生效
sender发件人支持:bi.report@item.com(不传参数时默认),bi.no-reply@item.com

返回值

Graph API 邮件发送 Lambda 调用说明

概述

本 Lambda 函数用于通过 Microsoft Graph API 发送邮件,支持文本和 HTML 格式,提供统一的响应结构和完善的错误处理机制。

请求参数

邮件发送模版

参数类型描述说明
recipientstring收件人邮箱地址必填(当 cc 不为空时);支持单个邮箱地址,多邮箱','分割
ccstring抄送邮箱地址选填;支持多个邮箱,用逗号或分号分隔
subjectstring邮件主题选填;默认值为 "No Subject"
body_textstring纯文本邮件内容body_html 二选一
body_htmlstringHTML 格式邮件内容body_text 二选一;同时存在时 body_html 优先生效
senderstring发件人邮箱地址选填;支持:
bi.report@item.com(默认)
bi.no-reply@item.com

参数校验规则

  1. recipientcc 至少需要提供一个
  2. cc 不为空时,recipient 必填
  3. body_textbody_html 至少需要提供一个

请求示例

json
{
  "recipient": "user@example.com",
  "cc": "manager@example.com;team@example.com",
  "subject": "月度报表",
  "body_html": "<html><body><h1>报表内容</h1><p>详细数据...</p></body></html>",
  "sender": "bi.report@item.com"
}

返回值

响应结构

所有响应均遵循统一的 JSON 结构:

json
{
  "success": "boolean",
  "code": "integer",
  "message": "string",
  "data": "object",
  "request_id": "string",
  "timestamp": "string"
}

响应字段说明

字段类型描述
successboolean请求是否成功执行
codeintegerHTTP 状态码(见下方状态码说明)
messagestring响应消息描述
dataobject返回的数据对象(内容根据状态不同而变化)
request_idstringAWS Lambda 请求 ID,用于追踪和调试
timestampstring响应时间戳(ISO 8601 格式,UTC 时区)

状态码说明

状态码含义说明
200成功邮件发送成功
400参数错误请求参数不符合要求
401认证错误Graph API 认证失败
500服务器错误Lambda 内部错误或 Graph API 调用失败

响应示例

成功响应 (200)

json
{
  "success": true,
  "code": 200,
  "message": "邮件发送成功",
  "data": {
    "message_id": "AAMkAGI2T...",
    "recipient": "user@example.com",
    "cc": "manager@example.com",
    "subject": "月度报表",
    "sender": "bi.report@item.com",
    "timestamp": "2026-01-14T10:30:45.123Z"
  },
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "timestamp": "2026-01-14T10:30:45.123Z"
}

参数错误响应 (400)

场景 1:recipient 和 cc 都为空

json
{
  "success": false,
  "code": 400,
  "message": "参数错误:recipient 和 cc 至少需要一个",
  "data": {
    "invalid_parameters": ["recipient", "cc"],
    "validation": "recipient 和 cc 不能同时为空"
  },
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "timestamp": "2026-01-14T10:30:45.123Z"
}

场景 2:cc 不为空但 recipient 为空

json
{
  "success": false,
  "code": 400,
  "message": "参数错误:当 cc 不为空时,必须提供 recipient",
  "data": {
    "invalid_parameters": ["recipient"],
    "validation": "recipient is required when cc is provided"
  },
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "timestamp": "2026-01-14T10:30:45.123Z"
}

认证错误响应 (401)

json
{
  "success": false,
  "code": 401,
  "message": "认证失败: Token expired",
  "data": {
    "error_type": "authentication_error",
    "sender": "bi.report@item.com"
  },
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "timestamp": "2026-01-14T10:30:45.123Z"
}

Graph API 发送失败响应 (500)

json
{
  "success": false,
  "code": 500,
  "message": "Graph API 发送失败: Request timeout",
  "data": {
    "error_type": "graph_api_error",
    "recipient": "user@example.com",
    "cc": "manager@example.com",
    "subject": "月度报表",
    "sender": "bi.report@item.com",
    "error_notification_sent": true,
    "retry_suggested": true
  },
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "timestamp": "2026-01-14T10:30:45.123Z"
}

Lambda 内部错误响应 (500)

json
{
  "success": false,
  "code": 500,
  "message": "Lambda 内部错误: 'NoneType' object has no attribute 'get'",
  "data": {
    "error_type": "lambda_internal_error",
    "suggestion": "请检查 Lambda 函数配置和权限"
  },
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "timestamp": "2026-01-14T10:30:45.123Z"
}

调用方式

AWS SDK (Python - Boto3)

python
import boto3
import json
from datetime import datetime
核心内容:
lambda_function_name = "BI_smtp_send_email"

# 邮件参数
payload = {
    "recipient": "xxxxx1@example.com,xxxxx2@example.com", #必填
    "cc": "xxxxx1@example.com,xxxxx2@example.com",#可为空
    "subject": f"测试邮件 - {datetime.now().strftime('%Y-%m-%d %H:%M')}", #
    "body_text": "这是一封测试邮件,通过 Lambda 同步调用发送。\n\n发送时间: " + datetime.now().isoformat(),
    "body_html": """
    <html>
    <body style="font-family: Arial, sans-serif; line-height: 1.6;">
        <h2 style="color: #2c3e50;">测试邮件通知</h2>
        <p>这是一封通过 <strong>Lambda 函数</strong> 发送的测试邮件。</p>

        <div style="background-color: #f8f9fa; padding: 15px; border-left: 4px solid #3498db; margin: 20px 0;">
            <p><strong>邮件详情:</strong></p>
            <ul>
                <li><strong>收件人:</strong>user@example.com</li>
                <li><strong>抄送5:</strong>manager@example.com, supervisor@example.com</li>
                <li><strong>发送时间:</strong>{time}</li>
            </ul>
        </div>

        <p>如果这是系统邮件,请勿直接回复。</p>
        <hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
    </body>
    </html>
    """.format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S')),
    "sender": "bi.report@item.com"  # 可选,默认是 bi.report@item.com
}

# 创建 Lambda 客户端
lambda_client = boto3.client('lambda')  # 根据实际情况修改区域

print(f"正在调用 Lambda 函数: {lambda_function_name}")
print(f"请求参数: {json.dumps(payload, indent=2, ensure_ascii=False)}")

# 同步调用 Lambda
response = lambda_client.invoke(
    FunctionName=lambda_function_name,
    InvocationType='RequestResponse',  # 同步调用
    LogType='Tail',  # 返回最近的日志
    Payload=json.dumps(payload)
)

错误处理机制

错误通知

当 Graph API 发送失败时,系统会自动发送错误通知邮件到配置的管理员邮箱,包含以下信息:

  • 原始收件人
  • 邮件主题
  • 错误详情
  • 失败时间戳

注意事项

  1. 认证机制:Lambda 函数会自动管理 Graph API 的 access_token,包括过期检测和自动刷新
  2. 发件人限制:仅支持预配置的发件人邮箱地址
  3. 邮件格式:优先使用 body_html,如果未提供则使用 body_text
  4. 请求追踪:使用返回的 request_id 可在 CloudWatch Logs 中查找详细日志
  5. 时区:所有时间戳均为 UTC 时区,格式为 ISO 8601
  6. 发送调用:谨慎将邮件发送放到循环中使用,一旦循环异常触发,段时间发送量太大时,邮箱有封禁的风险,多封邮件发送时应增加调用间隔

监控和日志

CloudWatch Logs

Lambda 函数会记录以下关键日志:

  • [ERROR] 前缀:Graph API 发送失败或内部错误
  • [INFO] 前缀:正常执行流程(如需启用)

常见问题

Q: 如何判断邮件是否发送成功?

A: 检查响应中的 success 字段为 truecode200

Q: 发送失败后是否需要手动重试?

A: 如果出现 graph 相关错误,会自动通知 管理员,

Q: 如何添加新的发件人邮箱?

A: 需要在 Lambda 函数的配置中添加新的 Graph API 认证信息,并更新代码中的发件人白名单。

Q: 支持发送附件吗?

A: 当前版本不支持附件,如有需求请联系开发团队。

版本历史

  • v1.0 (2026-01-14): 初始版本,支持基本邮件发送功能