| name | uzoncalc-writer |
| description | 使用 uzoncalc 以编写 python 代码的方式创建工程计算书,实现公式自动计算、自动排版、自动渲染 HTML 文档等功能 |
uzoncalc-writer skill
UzonCalc 是一个基于 Python 的工程计算书生成工具。通过在 async def 函数中编写计算逻辑,UzonCalc 能自动捕获变量赋值、公式推导过程,并渲染为带目录、数学公式、表格、图表的 HTML 计算书。
在编写计算书时,应从专业高级设计工程师的角度,以工程计算算单为风格,以直接交付为目标进行编写。
最小模板示例
from uzoncalc import *
@uzon_calc()
async def sheet():
doc_title("计算书标题")
H1("示例章节")
"这是一段说明文字。"
a = 10 * unit.meter
b = 5 * unit.meter
c = a + b
if __name__ == "__main__":
ctx = run_sync(sheet)
ctx.save("output.html")
核心规则
| 规则 | 说明 |
|---|
函数必须 async def | @uzon_calc() 仅支持异步函数 |
| 字符串字面量即段落 | 函数体内裸字符串 "文本" / """多行""" 作为段落输出 |
| 变量赋值自动渲染 | x = expr 被捕获并渲染为数学公式 x = expr = 值 |
| 变量名用 camelCase | _ 被解析为下标(H_2 → H₂),避免用下划线命名变量 |
| 希腊字母自动转换 | alpha→α,Beta→Β,首字母大写得大写希腊字母 |
| 纯函数调用不会插桩输出调用过程 | 如 f(x) 不会渲染为 f(x),而是直接调用 |
可用规则文档
文档结构
用于定义文档的结构和布局。
doc_title("页眉标题")
page_size("A4")
toc("目录")
font_family("Arial")
H1("一级标题")
H2("二级标题")
H3("三级标题")
Br()
Info("提示信息")
Code("代码", "python")
P("段落")
HTML 元素
可以使用以下预定义的函数,简化 HTML 内容的生成。其中,以小写字母开头的函数会返回 HTML 结果,而以大写字母开头的函数会直接渲染到文档中。
content = div(
[
h2("截面参数"),
p("以下参数用于承载力验算。"),
span("重要", classes="text-red-600 font-bold"),
],
classes="border p-2",
)
P(content)
H1("设计依据")
P("本节列出主要设计参数。")
Div(
[
h3("材料"),
p("混凝土强度等级为 C50。"),
],
classes="bg-gray-50 p-3",
)
常用 HTML 元素如下:
| 函数 | 说明 |
|---|
h(tag, children, ...) | 通用 HTML 构造器,children 支持字符串或字符串列表 |
h1h6 / H1H6 | 标题元素,小写返回字符串,大写直接渲染 |
title / Title | 文档大标题,默认居中、加粗、大字号 |
subtitle / Subtitle | 文档副标题,默认居中、加粗 |
p / P | 段落 |
div / Div | 块级容器 |
span / Span | 行内容器 |
row / Row | 行容器,默认渲染为 div,可通过 tag 指定标签 |
br / Br | 换行,自闭合元素 |
img / Img | 图片,支持 alt、width、height |
input / Input | 输入元素,当前主要用于生成带 value 的 HTML 输入标签 |
code / Code | 代码块,language 会生成 language-python 等高亮类名 |
info / Info | 蓝色提示框 |
laTex / LaTex | 原始 LaTeX 内容标签 |
plot / Plot | Matplotlib 图像或 PNG 二进制内容转为内嵌 base64 图片 |
属性与样式使用 classes 和 props():
P("控制性参数", props=props(id="control-params"))
Div("验算通过", classes="text-green-700 font-bold")
P(
"带自定义属性的段落",
props=props(
id="note-1",
classes="text-sm",
styles={"color": "#444", "margin-top": "8px"},
data_value="section-note",
aria_label="说明段落",
),
)
Div(
"最终使用 text-blue-700",
classes="text-blue-700",
props=props(classes="text-red-700"),
)
复杂内容建议先用小写函数组合,再用大写函数渲染:
parameterPanel = div(
[
h3("几何参数"),
p(f"梁高:{beamHeight}"),
p(f"梁宽:{beamWidth}"),
info("单位统一采用 SI 制。"),
],
classes="my-3 p-3 border",
)
P(parameterPanel)
插入图片、代码、LaTeX 与 Matplotlib 图:
Img("assets/section.png", alt="截面示意图", width=480)
Code(
"""
stress = force / area
""",
language="python",
)
LaTex(r"\sigma = \frac{N}{A}")
import matplotlib.pyplot as plt
hide()
fig, ax = plt.subplots()
ax.plot([0, 1, 2], [0, 1, 4])
show()
Plot(fig, width=520)
注意:
- HTML 内容不会自动转义
children,用户输入或外部文本应先自行清洗后再拼入 HTML。
children 列表会按顺序直接拼接,适合嵌套由 p()、div()、span() 等返回的 HTML 片段。
img() 会额外包一层居中容器;设置 alt 时会在图片下方显示说明文字。
Plot() 支持 Matplotlib savefig 对象,也支持 PNG 二进制数据;普通文件路径图片使用 Img()。
变量与公式
变量名参考 linux 风格缩写,变量名不宜过长。
force = 100 * unit.newton
area = 2 * unit.meter**2
stress = force / area
alias("rhoWater", "ρ_水")
rhoWater = 1000 * unit.kilogram / unit.meter**3
alias("rhoWater", None)
f"应力为 {stress}。"
enable_fstring_equation()
f"应力为 {stress}。"
disable_fstring_equation()
f"面积 = {(A := 3 * unit.meter**2)}"
单位
from uzoncalc import unit
l = 5 * unit.meter
f = 100 * unit.newton
p = f / (l * l)
v = l.to(unit.centimeter)
控制渲染
hide()
def helper(): ...
show()
inline()
x = 1; y = 2
endInline()
enable_substitution()
disable_substitution()
表格
Table(
headers=[
[
th("构件", rowspan=2),
th("材料", rowspan=2),
th("弹性模量 (MPa)", colspan=2),
],
["Ec", "Es"],
],
rows=[
["盖梁", "C60", 36000, 34500],
["墩柱", "C50", 34500, 32500],
],
title="材料参数",
)
Table(
headers=["项目", "数值", "备注"],
rows=[
Tr(
[
Td("梁高", classes="font-bold"),
1.8 * unit.meter,
Td("控制参数", classes="text-red-600"),
],
classes="bg-yellow-50",
),
Tr(["混凝土等级", "C50", None]),
],
)
Table(
headers=["名称", "值"],
rows=[Td("宽度", classes="font-bold"), 2.5 * unit.meter],
)
图表
生成图表的过程不需要显示过程,若图表复杂,在单独的函数中定义。
静态图首先使用 svg 方式,交互式图表使用 echarts 方式。
配色
进行图表配色时,优先选择以下配色方案:
- primary: #7367f0;
- secondary: #42b883;
- dark-page: #e0e0e0;
- positive: #42b883;
- negative: #ff7a7a;
- info: #65a0bb;
echarts 图表
通过 echarts 生成交互式图表, 在使用中,若对 echarts 中的参数不确定,读取 https://echarts.apache.org/zh/option.html 读取文档
from uzoncalc.extension.echarts import use_echarts, EChart, Javascript
EChart({
"xAxis": {"type": "category", "data": ["Mon", "Tue", "Wed"]},
"yAxis": {"type": "value"},
"series": [{"type": "bar", "data": [120, 200, 150]}],
})
EChart({...}, use_gl=True)
svg
对于一般图示,建议使用 svg.py, 示例如下:
import svg
canvas = svg.SVG(
width=60,
height=60,
elements=[
svg.Circle(
cx=30, cy=30, r=20,
stroke="red",
fill="white",
stroke_width=5,
),
],
)
P(canvas)
Matplotlib 图表
也可以使用 Matplotlib 生成静态图表
import matplotlib.pyplot as plt
hide()
def make_fig():
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
return plt
show()
Plot(make_fig())
UI 输入(交互模式)
from uzoncalc import UI, Field, FieldType
inputs = await UI(
"结构参数",
[
Field("width", "宽度", FieldType.number, value=10),
Field("height", "高度", FieldType.number, value=5),
Field("mat", "材料", FieldType.selectOne, options=["C30", "C40", "C50"]),
],
)
width = inputs.width * unit.meter
FieldType 可选值:text、number、selectOne、selectMany、boolean、textarea
Excel 集成
from uzoncalc.extension.excel import get_excel_table
P(get_excel_table(
excel_path="examples/calc.xlsx",
values={
"Sheet1!A2": 6,
"Sheet1!B2": 10,
},
range="Sheet1!A1:C3",
))
保存文档
save("output/result.html")
ctx = run_sync(sheet)
ctx.save("output/result.html")
生成的 HTML 可用浏览器打印为 PDF,或用 pandoc 转为 Word。
运行方式
if __name__ == "__main__":
ctx = run_sync(sheet)
ctx.save("output.html")
ctx1 = run_sync(sheet1)
ctx2 = run_sync(sheet2)
ctx1.save("out1.html")
ctx2.save("out2.html")
注意要点
- 函数体内所有顶层赋值语句均被拦截渲染,若不希望某段代码渲染,用
hide() / show() 包裹
- 除
@uzon_calc() 函数外,其他函数均不被渲染
- 变量名中的
_ 渲染为下标,命名时应使用 camelCase
- 数组下标
arr[0, 1] 自动渲染为下标形式
@uzon_calc() 函数支持相互嵌套调用,内层函数的内容合并到当前上下文
- 单位计算依赖 pint,量纲不匹配时会抛出错误
编写要点
- 规范中涉及的公式,应在
@uzon_calc() 函数中编写,不要单独封装,其它函数不会渲染