Files
AIclinicalresearch/r-statistics-service/utils/block_helpers.R
HaHafeng 371e1c069c feat(ssa): Complete QPER architecture - Query, Planner, Execute, Reflection layers
Implement the full QPER intelligent analysis pipeline:

- Phase E+: Block-based standardization for all 7 R tools, DynamicReport renderer, Word export enhancement

- Phase Q: LLM intent parsing with dynamic Zod validation against real column names, ClarificationCard component, DataProfile is_id_like tagging

- Phase P: ConfigLoader with Zod schema validation and hot-reload API, DecisionTableService (4-dimension matching), FlowTemplateService with EPV protection, PlannedTrace audit output

- Phase R: ReflectionService with statistical slot injection, sensitivity analysis conflict rules, ConclusionReport with section reveal animation, conclusion caching API, graceful R error classification

End-to-end test: 40/40 passed across two complete analysis scenarios.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-21 18:15:53 +08:00

86 lines
2.8 KiB
R
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# utils/block_helpers.R
# Block-based 输出协议 — 构造函数
#
# 所有 R 工具通过这些函数构建 report_blocks[]
# 前端 DynamicReport.tsx 根据 block.type 统一渲染。
# 支持 4 种 Block 类型markdown / table / image / key_value
#' 构造 Markdown 文本块
#' @param content Markdown 格式文本(支持标题、列表、加粗等)
#' @param title 可选标题(前端渲染为区块标题)
#' @return block list
make_markdown_block <- function(content, title = NULL) {
block <- list(type = "markdown", content = content)
if (!is.null(title)) block$title <- title
block
}
#' 构造表格块
#' @param headers 列名字符向量,如 c("组别", "均值", "标准差")
#' @param rows 行数据列表,每行为字符向量,如 list(c("A", "5.2", "1.3"), ...)
#' @param title 可选表格标题
#' @param footnote 可选脚注(如方法说明)
#' @return block list
make_table_block <- function(headers, rows, title = NULL, footnote = NULL) {
block <- list(
type = "table",
headers = as.list(headers),
rows = lapply(rows, as.list)
)
if (!is.null(title)) block$title <- title
if (!is.null(footnote)) block$footnote <- footnote
block
}
#' 从 data.frame 构造表格块(便捷方法)
#' @param df data.frame
#' @param title 可选表格标题
#' @param footnote 可选脚注
#' @param digits 数值列保留小数位数,默认 3
#' @return block list
make_table_block_from_df <- function(df, title = NULL, footnote = NULL, digits = 3) {
headers <- colnames(df)
rows <- lapply(seq_len(nrow(df)), function(i) {
lapply(df[i, , drop = FALSE], function(val) {
if (is.numeric(val)) {
format(round(val, digits), nsmall = digits)
} else {
as.character(val)
}
})
})
make_table_block(headers, rows, title = title, footnote = footnote)
}
#' 构造图片块
#' @param base64_data 完整的 data URI如 "data:image/png;base64,..."
#' @param title 可选图片标题
#' @param alt 可选 alt 文本(无障碍 + Word 导出用)
#' @return block list
make_image_block <- function(base64_data, title = NULL, alt = NULL) {
block <- list(type = "image", data = base64_data)
if (!is.null(title)) block$title <- title
if (!is.null(alt)) block$alt <- alt
block
}
#' 构造键值对块
#' @param items 命名列表或 list(list(key=..., value=...), ...)
#' @param title 可选标题
#' @return block list
make_kv_block <- function(items, title = NULL) {
if (!is.null(names(items)) && length(names(items)) > 0 && names(items)[1] != "") {
kv_list <- lapply(names(items), function(k) {
list(key = k, value = as.character(items[[k]]))
})
} else {
kv_list <- items
}
block <- list(type = "key_value", items = kv_list)
if (!is.null(title)) block$title <- title
block
}