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

Step 1: Basic Settings
- Id: report plus 唯一标识,创建后无法更改
- Name: report plus 名称,可以更改
- First Tag/Second Tag: 一级标签 / 二级标签
Step 2: Source Configuration
添加文件,类型可选 View 或者 本地File 支持的数据类型包括 CSV EXCEL PARQUET PKL
Step 3: Export Options
文件导出类型,CSV/XLSX 文件导出名称 最终只能生成一个结果文件
高级配置,
Customer Script
高级自定义脚本模式,需要自己编写对数据的处理,最终保存到目标目录,支持高级样式输出
Dataframe
基础自定义模式,通过对数据集的操作,无需自行输出文件,可以在下面进行导出编辑,不支持高级样式输出 首次配置时,是无法选择已有的数据集的,需要进行一次 review 可以刷新脚本中的所有df,随后既可选取进行编辑 这里是review 之后,这里会展示全部的可用数据集
选择数据集后,这里是针对最终输出的 Excel 文件中的 Sheet 页,可以对 Sheet 页进行重命名 

点击左侧单Sheet 的箭头可以打开高级配置,此时可以再次选择数据集。将多个数据集纵向拼接到单Sheet 页中
其中配置包括:
- 增加标题,
- 是否包含标题(默认加粗),
- 是否包含数据集中的 header
- 数据集前要保留多少行空行
!#如果选择格式为 CSV 则只能有一个 Sheet
配置介绍
保存之后针对 record 的操作
- Setting 配置 report plus
- Edit 跳转 jupyter 平台,编写脚本,操作选中的数据集
- Review 预览所有数据的加载效果(单数据集限制10000),如果是
- Customer Script 模式,没有编辑的情况下是看不到数据集的,
- Dataframe 模式下,在未进行配置时,会加载所有的数据集,
- 注意:仅能预览 excel 格式的文件
- Download 同上,不过是加载全部(单数据集1000000)数据
- Delete 删除 report plus
jupyter
Edit 跳转 jupyter 之后 jupyter 中的基础概念
从左到右依次
- 保存
- 添加新的 code cell
- 剪切
- 复制
- 粘贴
- 运行鼠标所在 cell 中的代码
- 停止内核(代码运行环境)
- 重启内核(代码运行环境)
- 重跑所有 cell 中的代码
- 切换 code 模式,勿动
- 创建 mitosheet, 会创建一个 cell 运行 mito,然后可以加载这个 cell 前的代码产生的 df
进入之后选择第一cell 运行其代码,运行效果:
两种模式都不要操作 第一个 cell 的代码,在report plus 的 Setting 中源数据集 发生更改时,第一cell 中的代码会被刷新
Customer Script 模式
- 自行加载第一cell 中注册的 dataframe 进行处理,最后写入s3就好,写入代码模版:

- 此处的环境变量在开始已经赋值,上传的 key 和 bucket 不可更改,
- 不建议脚本中有访问别的数据桶的数据,需额外增加权限,
Dataframe 模式
- 自行加载第一cell 中注册的 dataframe 进行处理,最后赋值回 dataframe 就好,此时这个dataframe会在内存中,可供后续配置选择

- 保存后需要进行一次 review 或者 download ,刷线 df_list,获取最新的可选择的 dataframe 数据集
- 在 setting 界面配置脚本中生成的 dataframe 数据集的拼接方式,
- 保存记录,即可预览或者下载,
结果文件的更新条件
- 上传的文件或者 view 发生更新(主要指 view info 表中的 update time)
- 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 格式,提供统一的响应结构和完善的错误处理机制。
请求参数
邮件发送模版
| 参数 | 类型 | 描述 | 说明 |
|---|---|---|---|
recipient | string | 收件人邮箱地址 | 必填(当 cc 不为空时);支持单个邮箱地址,多邮箱','分割 |
cc | string | 抄送邮箱地址 | 选填;支持多个邮箱,用逗号或分号分隔 |
subject | string | 邮件主题 | 选填;默认值为 "No Subject" |
body_text | string | 纯文本邮件内容 | 与 body_html 二选一 |
body_html | string | HTML 格式邮件内容 | 与 body_text 二选一;同时存在时 body_html 优先生效 |
sender | string | 发件人邮箱地址 | 选填;支持: • bi.report@item.com(默认)• bi.no-reply@item.com |
参数校验规则
recipient和cc至少需要提供一个- 当
cc不为空时,recipient必填 body_text和body_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"
}响应字段说明
| 字段 | 类型 | 描述 |
|---|---|---|
success | boolean | 请求是否成功执行 |
code | integer | HTTP 状态码(见下方状态码说明) |
message | string | 响应消息描述 |
data | object | 返回的数据对象(内容根据状态不同而变化) |
request_id | string | AWS Lambda 请求 ID,用于追踪和调试 |
timestamp | string | 响应时间戳(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 发送失败时,系统会自动发送错误通知邮件到配置的管理员邮箱,包含以下信息:
- 原始收件人
- 邮件主题
- 错误详情
- 失败时间戳
注意事项
- 认证机制:Lambda 函数会自动管理 Graph API 的 access_token,包括过期检测和自动刷新
- 发件人限制:仅支持预配置的发件人邮箱地址
- 邮件格式:优先使用
body_html,如果未提供则使用body_text - 请求追踪:使用返回的
request_id可在 CloudWatch Logs 中查找详细日志 - 时区:所有时间戳均为 UTC 时区,格式为 ISO 8601
- 发送调用:谨慎将邮件发送放到循环中使用,一旦循环异常触发,段时间发送量太大时,邮箱有封禁的风险,多封邮件发送时应增加调用间隔
监控和日志
CloudWatch Logs
Lambda 函数会记录以下关键日志:
[ERROR]前缀:Graph API 发送失败或内部错误[INFO]前缀:正常执行流程(如需启用)
常见问题
Q: 如何判断邮件是否发送成功?
A: 检查响应中的 success 字段为 true 且 code 为 200。
Q: 发送失败后是否需要手动重试?
A: 如果出现 graph 相关错误,会自动通知 管理员,
Q: 如何添加新的发件人邮箱?
A: 需要在 Lambda 函数的配置中添加新的 Graph API 认证信息,并更新代码中的发件人白名单。
Q: 支持发送附件吗?
A: 当前版本不支持附件,如有需求请联系开发团队。
版本历史
- v1.0 (2026-01-14): 初始版本,支持基本邮件发送功能