← Back to skills
extension
Category: Productivity & OfficeAPI key requirement unconfirmed

招投标评分表自查

核对招投标评分表的抄录错误:分值合计、序号重复、评分依据漏填、占位符残留。只做加法与齐备核对,不判断分值设置是否恰当。

personAuthor: PerryLinkhubOpenAPI

招投标评分表自查

把招标文件里的评标办法/评分表变成一张表,然后核对抄录过程中的算术与齐备错误。

它回答的问题是:我把评分表从招标文件抄进工作底稿时,有没有抄错。 它不回答的问题是:分设得合不合理、会不会废标、能不能中标。


什么时候用它

  • 投标前,把招标文件评分办法整理成底稿,想知道有没有漏项、分值加不加得起来。
  • 评标时,已经打好分,想知道单项分有没有超过分值上限、合计对不对。
  • 任何时候,想确认一张评分表自身是不是自洽。

不适合:判断分值设置是否恰当、判断评标是否公平、判断是否应当否决投标、预测中标结果。 这些是评标委员会依法独立作出的判断,本工具不做,也不该做。


输入

两条路,任选其一。

A. 直接给 .docx(推荐)

node scripts/docx-text.mjs 招标文件.docx

输出是纯文本:段落一行一段,表格一行一表(| a | b |)。合并单元格会输出 ↔, 意思是"这一格与左边合并了,是占位符不是数据"——不要把它当成缺失值去补。

只认 .docx。.doc(97-2003 二进制格式)和 .wps 需要先另存为 .docx。 PDF 不支持:扫描件要 OCR,文字版 PDF 的表格结构也留不住,硬抽出来错得比不抽更多。

B. 用户直接粘贴评分表文本

粘进来的表格、或者从 PDF 里复制出来的文字都可以。这时候跳过上面的脚本,直接看下面的表结构。


表结构

输出一份 JSON(YAML 也行),形状固定:

{
  "project": "项目名称",
  "tenderNo": "招标编号",
  "method": "综合评分法",
  "rows": [
    { "序号": "1", "评审因素": "投标报价", "评审类别": "价格", "分值": "30", "评分依据": "评标基准价法,×30" }
  ]
}

| 字段 | 必填 | 说明 | |---|---|---| | 序号 | 建议 | 评分表的行号,用于定位 | | 评审因素 | 必填 | 这一行评的是什么。⚠️ 引擎不逐行校验:缺了不报错,会静默算作合格 | | 评审类别 | 建议 | 价格/技术/商务 等,原文怎么写就怎么填 | | 分值 | 必填 | 这一项的满分上限(见下面的取值规则)。⚠️ 同上,缺这一列的行会被静默忽略 | | 投标人A 投标人B 投标人C | 选填 | 实际得分。只在评标打分场景才有;投标人自查通常没有,没有就整列不填 | | 评分依据 | 建议 | 原文的评分标准/评分细则。这是核对"有没有抄全"的依据 | | 备注 | 选填 | |

完整别名表见 assets/schema.json(评审因素 也可以写 评分因素,分值 也可以写 满分)。


五条硬规则(做错了整个结果就没意义;其中一条会静默失败)

1. 子项必须拆成多行,不能压成一行

真实评分表大量出现一个单元格里塞几个子项:

| 技术分 | 60 | 技术方案 20 分;项目实施方案 20 分;售后服务方案 20 分 |

必须拆成三行,每行 分值 是子项的 20,而不是写一行 技术分 = 60。

压成一行会让所有核对全部通过——总分对得上、没有重复、没有漏填——而实际上一个子项都没查。 这是本工具最危险的一处静默失败——但不是唯一一处,见文末「已知限制」。

2. 分值 取"这一项最高能得几分"

真实文件很少给单一数字,常见三种写法,统一按上限处理:

| 原文写法 | 分值 填 | |---|---| | 3-5 分、3~5 分 | 5 | | 基准分 10 分,每缺一项扣 0.5 分 | 10 | | 优 5 分 / 良 3 分 / 一般 1 分 | 5 |

区间下限、档位中间值都不填。核对的是"上限对不对得上",取下限会让合计永远差一截。

3. 一份评分办法常常拆成好几张表,要合成一张台账

真实招标文件的评分办法经常是三到五张独立的表,每张表前面各有一行"评审因素 / 分值 / 评分标准"表头:

| 评审因素 | 分值 | 评分标准 |      ← 表一:价格分 + 技术分
| 评审因素 | 分值 | 评分标准 |      ← 表二:扣分制项目
| 评审因素 | 分值 | 评分标准 |      ← 表三:商务分

必须合并成一张台账,只写一套表头,行按出现顺序连续编号。

这一条不做的后果很具体:只抽表一会得到"合计 45,与总分 100 相差 55"——这是你抽漏了,不是文档错了。 工具会如实报这个差异,用户却会以为自己的表有问题。

4. 整行合并且没有分值的是分节标题,不是评分项

评分表里常见这样的行:

| 服务部分 | ↔ | ↔ |

一整行合并、没有分值、文字是"服务部分""商务部分""技术部分"这类——它是分节标题, 用来把下面的行分组。不要把它当成一行评分项写进台账——写了不会拉低合计(空分值那行会被静默忽略), 但会在报告里留一条无意义的 TM-005,并掩盖你真正缺的行。

如果它自带合计(如"技术部分(31分)"),把合计记进心里用于交叉核对,但不要作为一行。

5. 抄不到就留空,不要补

原文没写分值、或者那一格是图片、或者写着"详见附件",就把 分值 留空,不要估算、不要填 0。 注意:留空的项不会被单独指出来。 它的 分值 不参与合计,报告也不会有一条「这一行缺分值」—— 你不会知道它被漏掉了。它的 评分依据 若为空或有占位符,仍会被 TM-005 / TM-007 抓到, 但那两条说的是别的问题,不是「你忘了填分值」。所以宁可先删掉整行,也不要留一个空分值。

同理:评分依据 抄原文,不要改写、不要概括成"按方案优劣打分"。


跑之前先数一遍

抽完表、跑核对之前,做这个检查——它比后面所有核对都重要:

  1. 文档里出现了几个"评审因素 / 分值 / 评分标准"表头?→ 记为 N
  2. 你的台账里有没有 N 张表的所有行?
  3. 文档里有几句"合计 100 分""技术部分 31 分"?把它们加起来对不对?

如果 合计不符 这一条命中,先回头找有没有漏掉的表,再考虑是不是数字抄错。 真实文件里"漏一张表"比"抄错一个数字"常见得多,而报出来的症状一模一样。

怎么跑

# 1. 如果给的是 .docx,先把正文取出来
node scripts/docx-text.mjs 招标文件.docx > 正文.txt

# 2. 照着上面的表结构写出 score-table.json

# 3. 核对。--total 传招标文件写明的总分
node scripts/check.mjs score-table.json --total 100

--total 强烈建议传。 招标文件里通常有一句"评标总分为 100 分"。 不传,最有用的一条(分值合计是否等于总分)会被跳过,报告变成"什么也没查到"。 分制不是 100 的(120 分制、分项加权)就按实际数字传。

其他用法:

node scripts/check.mjs score-table.json --total 100 --json   # 原始报告
node scripts/check.mjs --schema                              # 打印字段别名表
cat score-table.json | node scripts/check.mjs - --total 100  # 从标准输入读

退出码:0 没发现问题,1 有问题,2 表结构被拒(字段名不对/不是合法 JSON)。

没有 npm 依赖,不需要 npm install。 只需要 Node ≥ 18。


报告怎么读

七种检查,按命中时的措辞看:

| 规则 | 查什么 | 命中说明 | |---|---|---| | TM-001 | 有没有写项目名与评标办法 | 表头缺栏 | | TM-002 | 单项得分有没有超过分值上限 | 只在填了 投标人A 时执行 | | TM-003 | 分值合计等于总分吗 | 需要 --total | | TM-004 | 得分合计等于汇总栏吗 | ⚠️ 当前版本永不执行:它需要配置该投标人的合计目标,而工具没有提供这个入口 | | TM-005 | 评分依据有没有漏填 | 该行没抄评分标准 | | TM-006 | 序号有没有重复 | 抄重了一行 | | TM-007 | 有没有残留 【】、XXX、待填、TBD、示例 等占位符 | 模板没改完。⚠️ 裸的 XX 分 识别不到 |

"注:"开头的段落、以及 Word 文本框里的字会被读出来——里面常常写着"以下分值以评标办法为准"这类改变读法的说明。 ⚠️ 脚注(footnotes)当前不抽取:脚本只读正文。分值和评分标准若写在脚注里,你会漏项。

报告末尾的**"未执行的检查"**不是错误,是在告诉你哪几条规则因为材料不足没跑。 要把这一节原样转述给用户——它决定了这个结论能用到什么程度。

每条命中都带条款依据(《招标投标法》的对应条款原文)和"建议核对"。


转述结果时的措辞

  • 说"第 4 行缺评分依据",不说"你这条不合格"。
  • 说"分值合计 95,与总分 100 相差 5",不说"你的表错了"。
  • 说"TM-002 未执行,因为没填投标人得分",不说"全部检查通过"。
  • 不要说"这样就不会废标"。本工具连"是否应当否决投标"都不判断。
  • 不要替用户改数字。指出差异,改不改、怎么改由用户按招标文件决定。

报告自带的免责声明要一起给出,不要删。


示例

assets/example/ 下有一套完整样例:

  • tender-sample.docx — 一份带合并单元格、嵌套子表、修订痕迹的评分办法
  • score-table.json — 按上表结构抽出来的结果,子项已拆行,抄录正确
  • score-table-typo.json — 同一份文件的抄录件,含三种真实的手误:漏抄一个子项(20 写成 15)、把序号 3 抄成 2、有一行评分依据没填
  • report.md — 上面那份抄录件的核对报告
  • tender-multi-table.docx — 评分办法拆成三张表、带分节标题行、带文本框注释的那一版
  • score-table-multi-table.json — 上面这份的三张表合并成一张台账后的样子(5 行)

先用它验证环境(第一条抽文档,第二条核对干净件,第三条核对抄错件):

node scripts/docx-text.mjs assets/example/tender-sample.docx
node scripts/check.mjs assets/example/score-table.json --total 100     # 0 条,退出码 0
node scripts/check.mjs assets/example/score-table-typo.json --total 100 # 3 条,退出码 1

# 三表合并那一份:看它怎么把 3 张表、1 个分节标题行合成 5 行台账
node scripts/docx-text.mjs assets/example/tender-multi-table.docx
node scripts/check.mjs assets/example/score-table-multi-table.json --total 100

已知限制(实测确认,发布前逐条验过)

这些不是"以后会修",是当前版本的确定行为。报结果时若碰到下面任何一种,要主动向用户说明。

| # | 限制 | 后果 | |---|---|---| | 1 | 评审因素 / 分值 号称必填,引擎不逐行校验 | 一张没有评分项、没有分值的表会得到「0 条,退出码 0」 | | 2 | 分值 留空的行不参与合计,也没有规则指出「缺分值」 | 你以为查了这一行;只有它的评分依据为空/有占位符时才会被 TM-005/TM-007 间接抓到 | | 3 | TM-004 永不执行(缺合计目标入口) | 评标场景的"得分合计对不对"无法核对 | | 4 | TM-006 的定位显示的是你声明的序号,不是物理行号 | 会看到"第 2 行与第 2 行重复"这种自相矛盾的话;实际是第 3 行和第 2 行 | | 5 | TM-007 不识别裸的 XX | 模板里的 XX 分 会被当成正常内容 | | 6 | 脚注不抽取(只读正文 word/document.xml) | 写在脚注里的分值/标准会漏 | | 7 | YAML 只支持块式,且顶层不能用 flow 式 | 顶层的 {...} 或 --- 文档标记会失败;rows: [{...}] 这种内层 flow 式可以 | | 8 | 分值 直接写区间 "3-5" 会被取成 3 | 必须自己填上限 5,工具不会帮你判断 | | 9 | 报告标题和字段名是内部名(dsh-tender-matrix、basis、maxScore、seq) | 转述给用户时要换成中文说法 |

第 1、2、5、6 条都属于静默失败:工具说"0 条",但它其实没查。 所以不要用「0 条差异」当成"没问题"的同义词——先看「未执行的检查」,再对照这张表。