返回文章列表

竞价项目报价链路:多次提交、加密存储与截止后解密

竞价系统不是公开拍卖,核心流程是发布竞价项目、供应商下载文件、加密提交报价、截止后统一解密、自动排序和顺位中标。这个流程里最容易出错的是多次报价的覆盖关系、截止边界和加密解密时点。

业务状态机

项目状态需要明确,不能只靠“开始时间和结束时间”推断。建议用显式状态记录项目从发布到定标的完整生命周期。

常见状态包括草稿、已发布、报价中、已截止、解密中、已排序、已定标和流标。每个状态流转都需要记录操作人和时间,方便追查问题。

多次报价

供应商在截止前可以反复上传报价,系统要保证“最后一次提交有效”。这里有两个容易出错的地方:

  • 旧请求不能覆盖新请求,需要给每次提交生成版本号。
  • 同一个供应商不能同时出现多个有效报价,切换有效报价必须保证原子性。
BEGIN;

UPDATE quote
SET is_current = 0
WHERE project_id = ?
  AND supplier_id = ?
  AND is_current = 1;

INSERT INTO quote (project_id, supplier_id, version_no, content, is_current)
VALUES (?, ?, ?, ?, 1);

COMMIT;

加密提交

报价提交后应立即加密保存,业务展示和后续处理都基于密文。明文不应该长期停留在数据库或文件系统中,避免截止前通过内部查询或日志泄露。

加密需要在提交入口完成,而不是等后台任务再处理。这样即使文件上传和报价保存分属不同模块,也不会出现明文落库的窗口。

截止一致性

截止时间必须以服务端时间为准。用户请求可能因为网络延迟晚到,但系统不能因此把报价写入已截止的项目。

提交报价时需要在同一个事务里检查项目状态和截止时间。状态不是“报价中”或时间已过,直接拒绝,不能只依赖前端按钮禁用。

截止后解密

截止后由后台任务统一解密报价和文件。解密过程要保证幂等,同一批项目重复触发不会重复解密或产生重复记录。

解密失败不能直接跳过,需要重试、告警并进入人工处理队列。只有解密完成的报价才允许参与排序,未解密完成的项目不能提前生成结果。

自动排序与顺位中标

解密完成后,系统按业务规则自动排序,生成顺位中标结果。排序规则要配置化,结果要留痕。

中标结果不能通过直接改数据库实现,必须通过明确的定标操作触发,避免业务人员绕过流程修改最终结果。

这个系统的难点不是流量,而是报价覆盖、截止边界、加密解密时点和结果可追溯。先把这四条链路做严,业务才不会在关键时刻出问题。