先把结论甩前面:让模型输出标准 Markdown 表格,前端用 marked 解析成 HTML,再套一层轻量表格库接管排序,三步搞定。不用自己写解析器,也别用正则去硬抠管道符 |,那玩意儿写出来全是 bug。
起因是上个月做一个内部数据问答的页面。产品给我提了个需求:用户问一句"上季度各渠道转化对比",下面就吐一张表,能点表头排序。我当时第一反应------AI 返回的不就是一坨带 | 的纯文本嘛,渲染出来歪歪扭扭的,列还对不齐。
第一步:让模型乖乖吐标准表格
这步是地基。我在 system prompt 里加了一句约束,大意是"涉及多维对比时用标准 Markdown 表格,表头单独一行,分隔行用 ---"。说实话第一版它给我返回的表格时灵时不灵,偶尔会把表格塞进代码块里,或者少写分隔行。后来我把示例直接写进 prompt,稳定多了。
模型这边我没自己部署,调的是现成大模型 API,省了一堆算力的事。返回大概长这样:
erlang
| 渠道 | 访客 | 转化率 |
| --- | --- | --- |
| 抖音 | 12400 | 3.2% |
| 小红书 | 8600 | 5.1% |
第二步:marked 解析成 HTML table
别手写解析。marked 原生就支持 GFM 表格,开箱即用:
css
import { marked } from 'marked'
const html = marked.parse(aiText, { gfm: true })
// 直接吐出 <table><thead>...<tbody>... 标准结构
container.innerHTML = html
到这一步表格已经能看了,列也对齐了。但点表头没反应------它就是个死的 HTML table。
第三步:套一层排序
我没上 AG Grid 那种重型货,几百 KB 起步,杀鸡用牛刀。选了 tablesort,十几 KB,纯接管已有的 table:
javascript
import Tablesort from 'tablesort'
const table = container.querySelector('table')
new Tablesort(table)
完事。点表头就能升降序了。配图建议:../img/sortable-table.png
不过有个坑得提一嘴:tablesort 默认按字符串排,"3.2%" 和 "12400" 这种带符号/纯数字的列排出来是乱的。得给它注册一个数字解析器,把 %、逗号千分位先 replace 掉再 parseFloat。我在这儿卡了快二十分钟,一度以为库坏了。
javascript
Tablesort.extend('number', item => /\d/.test(item), (a, b) => {
const n = s => parseFloat(s.replace(/[%,]/g, '')) || 0
return n(a) - n(b)
})
顺手做的一件事
后来我嫌每次改 prompt、调返回格式、测排序,来回切代码太碎,就把这套"问答+出表"的流程整个搭成了一个小助手。用的是那种零代码就能配智能体的工具------拖几个节点、挂上知识库、把出表的提示词配进去,不写后端就跑起来了。我对它说"按转化率给我排个序看看",返回的表格前端这边接住直接就是可排序的。有点惊到,毕竟没碰一行服务端代码。
当然它也就干这点杂活,复杂的多表关联、权限那些还得自己写,别指望一个拖出来的智能体扛全场。学习曲线也不是零,光是搞清楚知识库怎么切片喂进去,我摸索了个把小时。
整套下来,前端的活其实很少:约束输出、marked 解析、套排序库、补个数字解析器。真正费劲的是让模型每次都吐干净的表格------这事儿前端兜不住,得从源头治。
(模型 API 我走的讯飞 MaaS,现成调,没自己折腾部署。)
你们渲染 AI 返回的表格都怎么处理排序的?有没有踩过比 % 这个更隐蔽的坑,评论区聊聊。