diff --git a/mateclaw-ui/src/views/Triggers.vue b/mateclaw-ui/src/views/Triggers.vue index b933065a..def2276c 100644 --- a/mateclaw-ui/src/views/Triggers.vue +++ b/mateclaw-ui/src/views/Triggers.vue @@ -68,8 +68,10 @@ cron channel_message - webhook + content_match + agent_lifecycle workflow_completion + webhook {{ t('triggers.fields.patternJson') }} diff --git a/outputs/北京公交票务评估/__pycache__/build_svg_diagrams.cpython-312.pyc b/outputs/北京公交票务评估/__pycache__/build_svg_diagrams.cpython-312.pyc deleted file mode 100644 index 59ec067d..00000000 Binary files a/outputs/北京公交票务评估/__pycache__/build_svg_diagrams.cpython-312.pyc and /dev/null differ diff --git a/outputs/北京公交票务评估/__pycache__/build_vibe_design_doc.cpython-312.pyc b/outputs/北京公交票务评估/__pycache__/build_vibe_design_doc.cpython-312.pyc deleted file mode 100644 index 02667347..00000000 Binary files a/outputs/北京公交票务评估/__pycache__/build_vibe_design_doc.cpython-312.pyc and /dev/null differ diff --git a/outputs/北京公交票务评估/__pycache__/insert_diagrams_into_doc.cpython-312.pyc b/outputs/北京公交票务评估/__pycache__/insert_diagrams_into_doc.cpython-312.pyc deleted file mode 100644 index 95c476b1..00000000 Binary files a/outputs/北京公交票务评估/__pycache__/insert_diagrams_into_doc.cpython-312.pyc and /dev/null differ diff --git a/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx b/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx deleted file mode 100644 index b2f10dca..00000000 Binary files a/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx and /dev/null differ diff --git a/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单.docx b/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单.docx deleted file mode 100644 index d82b903a..00000000 Binary files a/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单.docx and /dev/null differ diff --git a/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-详细设计与Codex实施方案.docx b/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-详细设计与Codex实施方案.docx deleted file mode 100644 index 735abe2d..00000000 Binary files a/outputs/北京公交票务评估/_archive/北京公交集团票务综合管理平台系统升级-详细设计与Codex实施方案.docx and /dev/null differ diff --git a/outputs/北京公交票务评估/build_design_doc.py b/outputs/北京公交票务评估/build_design_doc.py deleted file mode 100644 index 63a60fe2..00000000 --- a/outputs/北京公交票务评估/build_design_doc.py +++ /dev/null @@ -1,367 +0,0 @@ -from __future__ import annotations - -from datetime import date -from pathlib import Path -from typing import Iterable - -from docx import Document -from docx.enum.section import WD_SECTION -from docx.enum.table import WD_ALIGN_VERTICAL, WD_TABLE_ALIGNMENT -from docx.enum.text import WD_ALIGN_PARAGRAPH -from docx.oxml import OxmlElement -from docx.oxml.ns import qn -from docx.shared import Inches, Pt, RGBColor - - -OUT = Path("/Users/mate/Codes/mate/mateclaw/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-详细设计与Codex实施方案.docx") - -BLUE = RGBColor(46, 116, 181) -DARK_BLUE = RGBColor(31, 77, 120) -INK = RGBColor(11, 37, 69) -MUTED = RGBColor(96, 108, 122) -LIGHT = "F2F4F7" -LIGHT_BLUE = "E8EEF5" -CALLOUT = "F4F6F9" - - -def set_cell_shading(cell, fill: str) -> None: - tc_pr = cell._tc.get_or_add_tcPr() - shd = tc_pr.find(qn("w:shd")) - if shd is None: - shd = OxmlElement("w:shd") - tc_pr.append(shd) - shd.set(qn("w:fill"), fill) - - -def set_cell_margins(cell, top=80, start=120, bottom=80, end=120) -> None: - tc = cell._tc - tc_pr = tc.get_or_add_tcPr() - tc_mar = tc_pr.first_child_found_in("w:tcMar") - if tc_mar is None: - tc_mar = OxmlElement("w:tcMar") - tc_pr.append(tc_mar) - for m, v in [("top", top), ("start", start), ("bottom", bottom), ("end", end)]: - node = tc_mar.find(qn(f"w:{m}")) - if node is None: - node = OxmlElement(f"w:{m}") - tc_mar.append(node) - node.set(qn("w:w"), str(v)) - node.set(qn("w:type"), "dxa") - - -def set_table_width(table, widths: list[float]) -> None: - table.autofit = False - table.alignment = WD_TABLE_ALIGNMENT.CENTER - for row in table.rows: - for idx, cell in enumerate(row.cells): - cell.width = Inches(widths[idx]) - set_cell_margins(cell) - cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER - - -def set_run_font(run, size=None, bold=None, color=None, name="Calibri"): - run.font.name = name - run._element.rPr.rFonts.set(qn("w:ascii"), name) - run._element.rPr.rFonts.set(qn("w:hAnsi"), name) - run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") - if size is not None: - run.font.size = Pt(size) - if bold is not None: - run.bold = bold - if color is not None: - run.font.color.rgb = color - - -def add_para(doc: Document, text: str = "", style: str | None = None, bold=False, color=None, size=None, align=None): - p = doc.add_paragraph(style=style) - if align is not None: - p.alignment = align - p.paragraph_format.space_after = Pt(6) - p.paragraph_format.line_spacing = 1.1 - if text: - r = p.add_run(text) - set_run_font(r, size=size, bold=bold, color=color) - return p - - -def add_bullets(doc: Document, items: Iterable[str]) -> None: - for item in items: - p = doc.add_paragraph(style="List Bullet") - p.paragraph_format.space_after = Pt(4) - p.paragraph_format.line_spacing = 1.167 - r = p.add_run(item) - set_run_font(r, size=10.5) - - -def add_numbered(doc: Document, items: Iterable[str]) -> None: - for item in items: - p = doc.add_paragraph(style="List Number") - p.paragraph_format.space_after = Pt(4) - p.paragraph_format.line_spacing = 1.167 - r = p.add_run(item) - set_run_font(r, size=10.5) - - -def add_heading(doc: Document, text: str, level: int): - p = doc.add_heading(text, level=level) - if level == 1: - p.paragraph_format.space_before = Pt(16) - p.paragraph_format.space_after = Pt(8) - elif level == 2: - p.paragraph_format.space_before = Pt(12) - p.paragraph_format.space_after = Pt(6) - else: - p.paragraph_format.space_before = Pt(8) - p.paragraph_format.space_after = Pt(4) - for r in p.runs: - set_run_font(r, size={1: 16, 2: 13, 3: 12}.get(level, 11), bold=True, color=BLUE if level < 3 else DARK_BLUE) - return p - - -def add_table(doc: Document, headers: list[str], rows: list[list[str]], widths: list[float], header_fill=LIGHT) -> None: - table = doc.add_table(rows=1, cols=len(headers)) - table.style = "Table Grid" - hdr = table.rows[0].cells - for i, h in enumerate(headers): - hdr[i].text = h - set_cell_shading(hdr[i], header_fill) - set_cell_margins(hdr[i]) - for p in hdr[i].paragraphs: - p.paragraph_format.space_after = Pt(0) - for r in p.runs: - set_run_font(r, size=9.5, bold=True, color=INK) - for row in rows: - cells = table.add_row().cells - for i, value in enumerate(row): - cells[i].text = value - set_cell_margins(cells[i]) - for p in cells[i].paragraphs: - p.paragraph_format.space_after = Pt(0) - p.paragraph_format.line_spacing = 1.08 - for r in p.runs: - set_run_font(r, size=9) - set_table_width(table, widths) - doc.add_paragraph() - - -def add_callout(doc: Document, title: str, body: str) -> None: - table = doc.add_table(rows=1, cols=1) - table.style = "Table Grid" - cell = table.cell(0, 0) - set_cell_shading(cell, CALLOUT) - set_cell_margins(cell, top=120, bottom=120, start=160, end=160) - p = cell.paragraphs[0] - p.paragraph_format.space_after = Pt(4) - r = p.add_run(title) - set_run_font(r, size=10.5, bold=True, color=DARK_BLUE) - p2 = cell.add_paragraph() - p2.paragraph_format.space_after = Pt(0) - r2 = p2.add_run(body) - set_run_font(r2, size=10) - set_table_width(table, [6.5]) - doc.add_paragraph() - - -def configure_document(doc: Document) -> None: - section = doc.sections[0] - section.top_margin = Inches(1) - section.bottom_margin = Inches(1) - section.left_margin = Inches(1) - section.right_margin = Inches(1) - section.header_distance = Inches(0.492) - section.footer_distance = Inches(0.492) - - styles = doc.styles - normal = styles["Normal"] - normal.font.name = "Calibri" - normal._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") - normal.font.size = Pt(11) - normal.paragraph_format.space_after = Pt(6) - normal.paragraph_format.line_spacing = 1.1 - - for name, size, color in [("Heading 1", 16, BLUE), ("Heading 2", 13, BLUE), ("Heading 3", 12, DARK_BLUE)]: - st = styles[name] - st.font.name = "Calibri" - st._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") - st.font.size = Pt(size) - st.font.color.rgb = color - st.font.bold = True - - header = section.header.paragraphs[0] - header.text = "北京公交集团票务综合管理平台系统升级 | 详细设计与 Codex 实施方案" - header.alignment = WD_ALIGN_PARAGRAPH.LEFT - for r in header.runs: - set_run_font(r, size=9, color=MUTED) - - footer = section.footer.paragraphs[0] - footer.alignment = WD_ALIGN_PARAGRAPH.RIGHT - footer.text = "内部评估文件" - for r in footer.runs: - set_run_font(r, size=9, color=MUTED) - - -def build() -> None: - doc = Document() - configure_document(doc) - - add_para(doc, "技术方案", bold=True, color=MUTED, size=11) - title = doc.add_paragraph() - title.paragraph_format.space_after = Pt(4) - r = title.add_run("北京公交集团票务综合管理平台系统升级") - set_run_font(r, size=24, bold=True, color=INK) - subtitle = doc.add_paragraph() - subtitle.paragraph_format.space_after = Pt(16) - r = subtitle.add_run("详细设计与 Codex 协作实施方案") - set_run_font(r, size=15, color=MUTED) - - meta = [ - ["文档用途", "用于项目立项、报价拆分、研发实施和 Codex 协作开发规划"], - ["编制日期", date.today().isoformat()], - ["需求来源", "《北京公交集团票务综合管理平台系统升级-需求分析说明书(初稿0506)》"], - ["版本", "V1.0"], - ] - add_table(doc, ["字段", "内容"], meta, [1.3, 5.2], header_fill=LIGHT_BLUE) - - add_callout( - doc, - "总体判断", - "本项目属于存量核心业务系统重构升级,重点不是页面生成,而是票据库存流水、票单结算、报表口径、数据权限、历史数据迁移和国产化适配。Codex 可显著提升需求整理、重复代码生成、测试补齐和文档产出效率,但架构边界、业务规则确认和上线割接仍需人工主导。", - ) - - add_heading(doc, "1. 项目范围与建设目标", 1) - add_para(doc, "本次建设目标是在继承现有生产系统主要能力的基础上,完成业务流程重构、国产化数据库迁移、权限和数据范围治理、报表整合、接口标准化和运维能力提升。系统面向集团、分公司和票务室多级用户,覆盖有人售票、无人售票、票库、票柜、票袋、票单、充值卡、特殊业务和统计报表等票务经营管理场景。") - add_bullets(doc, [ - "完整保留并优化核心票务业务闭环:印制、调拨、核销、配票、结算、退票、库存查询和流水追溯。", - "整合同类报表,按集团、分公司、票务室三级数据权限展示统计结果。", - "完成 Oracle 历史数据到达梦数据库的迁移、校验和兼容适配。", - "预留并分阶段实现与 IC 卡系统、数据湖、二维码系统、票款清分系统、电子签章系统的对接。", - "建立可审计、可测试、可持续迭代的工程体系,支持 Codex 辅助开发和自动化校验。", - ]) - - add_heading(doc, "2. 总体技术架构", 1) - add_table(doc, ["层级", "建议技术", "设计说明"], [ - ["前端展示层", "Vue 3 + TypeScript + Vite + Element Plus", "承载菜单导航、列表查询、业务表单、报表展示、打印和导入导出入口。"], - ["后端服务层", "Java 17 + Spring Boot 3 + MyBatis-Plus", "实现业务编排、事务控制、权限校验、库存流水、报表聚合和接口服务。"], - ["数据存储层", "达梦 DM8 + Redis + OBS/MinIO", "达梦作为主业务库,Redis 用于会话/缓存/短期任务状态,文件对象存储用于模板、导入文件和导出文件。"], - ["集成层", "REST/OpenAPI + 批量文件导入 + 定时任务", "对外提供标准接口;对无网络银行清分场景保留线下 Excel/CSV 导入;定时同步基础信息和报表数据。"], - ["运维层", "Nginx + 应用服务 + 日志审计 + 监控告警", "满足国产化部署、日志追溯、性能监控和上线回滚要求。"], - ], [1.15, 1.75, 3.6], header_fill=LIGHT_BLUE) - - add_heading(doc, "3. 系统模块设计", 1) - modules = [ - ["基础信息", "票务室、线路、票价、车辆、司售、普票类型、充值类型、机具、多样化运营类型、IC 卡类型", "以 CRUD 和同步查询为主,需统一数据权限和停用机制。"], - ["票库管理", "印制、调拨、核销、调账、票库库存、票库出入库查询", "核心在审批状态、库存流水、票号段合法性和跨公司调拨。"], - ["票柜管理", "票柜库存、入库、出库、配票申请、票务室调票", "承接票库到票务室的库存流转,需要单张/批量调票能力。"], - ["票单管理", "票袋、票单配票、票单结算、票单查询、票袋调票、重新结算、票号查询", "项目最复杂模块,需要严格状态机和结算口径。"], - ["无人售与特殊业务", "异物、大额币、残币、无人售线路结算、多样化收入、特殊票", "重点是异常状态、待销毁/领取/入账流程和批量导入。"], - ["退票管理", "票袋退票、票柜退票", "支持连续退票和单张退票,必须回写库存和流水。"], - ["充值管理", "IC 卡库存、入库、出库、网点库存、售出、充值收入", "需要处理网点维度库存、售出导入和收入记录。"], - ["统计报表", "集团、分公司、票务室多级报表、趋势图、Excel 导出", "需先冻结报表口径,避免开发完成后重复返工。"], - ["系统管理", "用户、角色、权限、菜单、阈值、日志", "为全系统提供认证、授权、数据范围和审计能力。"], - ] - add_table(doc, ["模块", "主要功能", "设计重点"], modules, [1.25, 2.9, 2.35]) - - add_heading(doc, "4. 核心业务状态与流水设计", 1) - add_para(doc, "票据类业务必须采用“当前库存 + 流水台账 + 状态机”的组合模型。只存库存余额无法满足审计、调账、退票、票号查询和异常追溯要求。") - add_table(doc, ["业务对象", "关键状态", "关键校验"], [ - ["印制申请", "待审核、不同意、待确认、完成", "待审核/不同意可修改;完成后生成票库入库流水。"], - ["调拨申请", "待审核、不同意、待确认、完成", "校验调出库存、调入公司、票号段不重叠。"], - ["核销申请", "待审核、完成、驳回", "核销后票号段不可再配出,保留原因和审批记录。"], - ["配票申请", "待处理、已配票、退回、完成", "票柜库存扣减,票袋或票单库存增加。"], - ["票单结算", "已配票、已结算、重新结算中、已更正", "销售张数和金额由剩余票号段反推,保留旧结算记录。"], - ["退票", "申请、确认、完成、驳回", "退票票号不能已核销、不能重复退票,完成后回写对应库存。"], - ], [1.3, 2.1, 3.1]) - - add_heading(doc, "5. 数据模型设计原则", 1) - add_bullets(doc, [ - "基础主数据表:组织、分公司、票务室、线路、车辆、司售、票价、票种、充值类型、机具等。", - "库存余额表:按库存主体、票种、票价、票组、起止号、状态聚合当前可用数量。", - "库存流水表:记录每一次入库、出库、调拨、退票、核销、调账、配票、结算的来源单据和操作人。", - "业务单据表:每类申请、审核、确认、结算均独立建单,避免把审批状态混入库存余额。", - "报表宽表/汇总表:对日结、月结、趋势报表建立可重算的汇总层,减少实时聚合压力。", - "审计表:记录登录、菜单访问、增删改、导入导出、审批、结账等关键操作。", - ]) - - add_heading(doc, "6. 权限与数据范围设计", 1) - add_table(doc, ["角色", "功能权限", "数据范围"], [ - ["集团管理员", "最高权限,可维护菜单、角色、用户和全局参数", "全集团数据,可分配集团/分公司/票务室数据权限。"], - ["集团操作员", "按角色授权使用业务功能", "可查看被授权的分公司和票务室数据。"], - ["分公司管理员", "维护本分公司及下属票务室用户和权限", "默认本分公司数据,可细分到票务室。"], - ["分公司操作员", "使用分公司层面业务和报表功能", "本分公司及授权票务室数据。"], - ["票务室操作员", "操作票柜、票袋、票单、结算等票务室业务", "仅本票务室数据。"], - ], [1.25, 2.55, 2.7], header_fill=LIGHT_BLUE) - add_callout(doc, "权限实现建议", "权限必须拆成菜单权限、按钮权限、数据范围权限和字段/导出权限。所有查询接口必须统一经过数据范围拦截器,避免前端隐藏菜单但后端接口越权。") - - add_heading(doc, "7. 接口与集成设计", 1) - add_table(doc, ["系统/对象", "对接方式", "一期处理建议"], [ - ["IC 卡系统", "接口同步或定时任务", "优先同步线路、车辆、司售、IC 卡基础信息;接口不稳定时保留手动导入兜底。"], - ["数据湖/二维码系统", "标准 REST/API 或数据推送", "先定义统一数据服务接口、鉴权、频率、字段口径;具体联调作为独立里程碑。"], - ["银行清分清点系统", "线下 Excel/CSV 导入", "按银行无网环境处理,建立模板、校验、导入日志和失败明细下载。"], - ["票款清分/胆款系统", "批量同步或接口推送", "以票务系统生成的清分日报为主数据源,明确对账字段。"], - ["电子签章系统", "第三方接口", "建议一期预留签章对象、签章状态和附件字段,实际签章联调单独报价/排期。"], - ], [1.55, 1.55, 3.4]) - - add_heading(doc, "8. 数据迁移方案", 1) - add_numbered(doc, [ - "盘点 Oracle 现有 79 张表、序列、视图、函数、触发器和历史附件,建立字段映射表。", - "完成达梦库结构设计,明确字段类型、索引、主键、唯一约束和历史兼容字段。", - "开发迁移脚本,先迁移基础主数据,再迁移库存、单据、结算、报表历史数据。", - "执行数据清洗:重复票号、缺失组织、异常状态、金额不平、非法日期等问题生成清洗报告。", - "进行三轮迁移演练:开发环境、测试环境、准生产环境,每轮输出数量核对和金额核对报告。", - "上线割接时冻结旧系统写入,完成增量迁移、业务抽样验证和回滚预案确认。", - ]) - - add_heading(doc, "9. Codex 协作开发流程", 1) - add_table(doc, ["阶段", "Codex 可承担工作", "人工控制点"], [ - ["需求结构化", "从 Word/Excel 提取功能项、生成需求池、补充初版验收点", "业务人员确认字段、流程、报表口径和删除/保留范围。"], - ["设计阶段", "生成表结构草案、接口草案、状态机草案、测试场景清单", "架构师确认边界、事务、权限模型和关键业务规则。"], - ["编码阶段", "生成 CRUD、Service、Mapper、Controller、前端页面、导入导出、测试用例", "开发负责人审查代码风格、事务完整性和异常处理。"], - ["测试阶段", "补接口测试、构造 Mock 数据、生成回归脚本、修复构建问题", "测试负责人确认场景覆盖和真实业务数据抽样。"], - ["交付阶段", "生成部署文档、接口文档、用户手册和变更说明", "项目组确认上线窗口、培训材料、应急预案。"], - ], [1.2, 2.8, 2.5], header_fill=LIGHT_BLUE) - - add_heading(doc, "10. 实施计划", 1) - add_table(doc, ["阶段", "周期", "主要产出"], [ - ["阶段 0:需求深化", "3-5 周", "最终需求清单、原型、报表口径、接口清单、迁移清单。"], - ["阶段 1:平台底座", "4-6 周", "登录、权限、菜单、日志、字典、导入导出、消息中心。"], - ["阶段 2:基础与库存", "8-10 周", "基础资料、票库、票柜、库存流水、审批流程。"], - ["阶段 3:票单核心", "8-12 周", "票袋、配票、结算、重新结算、票号查询、退票。"], - ["阶段 4:扩展业务与报表", "8-10 周", "无人售、充值、特殊业务、集团/分公司/票务室报表。"], - ["阶段 5:迁移联调与上线", "8-10 周", "数据迁移、接口联调、UAT、性能测试、安全整改、上线割接。"], - ], [1.55, 1.15, 3.8]) - - add_heading(doc, "11. 测试与验收策略", 1) - add_bullets(doc, [ - "单元测试:覆盖票号段计算、金额计算、库存扣减、状态流转、权限过滤等纯业务逻辑。", - "接口测试:覆盖所有新增、修改、删除、审核、确认、结账、导入导出接口。", - "场景测试:按印制到配票、配票到结算、结算到报表、退票回库等业务闭环执行。", - "数据迁移测试:按表数量、记录数、金额合计、票号段覆盖、异常数据清单进行核对。", - "权限测试:集团、分公司、票务室分别验证菜单、按钮、数据、导出范围。", - "性能测试:以峰值 150 在线用户为基准,重点压测报表查询、导入、结账和库存查询。", - ]) - - add_heading(doc, "12. 风险与控制措施", 1) - add_table(doc, ["风险", "影响", "控制措施"], [ - ["报表口径未冻结", "开发完成后反复返工", "每张报表先签字确认指标、维度、过滤条件和样例数据。"], - ["历史数据质量差", "迁移延期、上线后账不平", "提前做数据体检,问题数据单独出清洗规则和责任确认。"], - ["接口资料不完整", "联调延期", "接口作为独立里程碑,未提供资料的内容不阻塞核心业务开发。"], - ["票据状态规则遗漏", "库存错误、审计风险", "核心单据全部状态机化,关键状态变更必须有流水和测试用例。"], - ["Codex 生成代码缺少业务约束", "隐藏缺陷", "Codex 只产出初稿,核心业务必须人工 review 和场景测试。"], - ["国产化兼容问题", "部署和性能不稳定", "早期引入达梦、国产 OS、中间件环境,不到上线前再适配。"], - ], [1.65, 1.8, 3.05]) - - add_heading(doc, "13. 结论建议", 1) - add_para(doc, "建议采用“核心闭环优先、接口分阶段、报表先定口径、迁移提前演练”的实施策略。Codex 应作为研发加速工具嵌入需求整理、代码生成、测试补齐和文档交付过程,但不能替代架构决策、业务确认和验收责任。") - add_bullets(doc, [ - "一期优先交付票务核心闭环:基础信息、票库、票柜、票袋、票单、退票、无人售、充值、报表、权限和迁移。", - "电子签章、复杂实时接口、等保/密评配合建议单独列项,降低一期范围失控风险。", - "开发组织建议按 10-12 人、8-10 个月主计划推进,使用 Codex 后可将重复开发和文档测试工作压缩 30%-50%。", - "正式实施前应先输出功能清单 Excel、原型稿、数据库初设和迁移体检报告,作为报价和排期基线。", - ]) - - doc.save(OUT) - print(OUT) - - -if __name__ == "__main__": - build() diff --git a/outputs/北京公交票务评估/build_svg_diagrams.py b/outputs/北京公交票务评估/build_svg_diagrams.py deleted file mode 100644 index 0688a725..00000000 --- a/outputs/北京公交票务评估/build_svg_diagrams.py +++ /dev/null @@ -1,340 +0,0 @@ -from pathlib import Path - -OUT = Path("/Users/mate/Codes/mate/mateclaw/outputs/北京公交票务评估/svg设计图") -OUT.mkdir(parents=True, exist_ok=True) - -COLORS = { - "red": "#D71920", - "wall_red": "#B63A2E", - "gray": "#6F7378", - "dark": "#1F2933", - "light": "#F5F7FA", - "line": "#D8DEE6", - "blue": "#2E86C1", - "green": "#3FA45B", - "yellow": "#F2C94C", - "ink": "#0B2545", -} - - -def write(name: str, body: str) -> None: - (OUT / name).write_text(body, encoding="utf-8") - - -def header(title: str, subtitle: str, width=1440, height=960) -> str: - return f''' - - - - - - - - - - - - - - - - {title} - {subtitle} -''' - - -def footer() -> str: - return f''' - 北京公交集团票务综合管理平台系统升级 | SDD(Spec-Driven Development,规范驱动开发)实施方案配套设计图 - - - -''' - - -def card(x, y, w, h, title, lines, color="#D71920"): - parts = [f'', - f'', - f'{title}'] - yy = y + 72 - for line in lines: - parts.append(f'{line}') - yy += 26 - return "\n".join(parts) - - -architecture = header("总体技术架构图", "从用户访问、应用服务、数据存储、外部集成到运维保障的分层架构") -architecture += f''' - - 访问与用户层 - {card(88, 206, 248, 138, "集团用户", ["集团管理员 / 操作员", "全局管理、报表、审批"], COLORS['red'])} - {card(376, 206, 248, 138, "分公司用户", ["分公司管理员 / 操作员", "本公司业务、审核、统计"], COLORS['blue'])} - {card(664, 206, 248, 138, "票务室用户", ["票柜、票袋、票单", "配票、结算、退票"], COLORS['green'])} - {card(952, 206, 248, 138, "移动/内网终端", ["浏览器访问", "打印、导入、导出"], COLORS['yellow'])} - - - - - - - 应用与业务服务层 - {card(88, 466, 248, 168, "前端应用", ["Vue3 / TypeScript", "菜单导航、表单、报表", "打印与导入导出"], COLORS['red'])} - {card(376, 466, 248, 168, "网关与认证", ["统一登录认证", "菜单 / 按钮权限", "数据范围拦截"], COLORS['gray'])} - {card(664, 466, 248, 168, "业务服务", ["票库、票柜、票单", "充值、无人售、退票", "审批与状态机"], COLORS['blue'])} - {card(952, 466, 248, 168, "报表服务", ["日结、月结、趋势", "Excel 导出", "汇总表加速"], COLORS['green'])} - - - - - - - 数据、集成与运维层 - {card(88, 752, 220, 120, "达梦数据库", ["主业务库 / 主备", "库存、流水、报表"], COLORS['red'])} - {card(342, 752, 220, 120, "Redis / 缓存", ["会话、字典、短期任务", "热点查询缓存"], COLORS['gray'])} - {card(596, 752, 220, 120, "文件与对象存储", ["模板、导入文件", "导出报表、附件"], COLORS['yellow'])} - {card(850, 752, 220, 120, "外部系统集成", ["IC卡 / 数据湖 / 胆款", "银行清分线下导入"], COLORS['blue'])} - {card(1104, 752, 220, 120, "运维保障", ["日志、监控、备份", "灰度、回滚、巡检"], COLORS['green'])} -''' -architecture += footer() -write("01-总体技术架构图.svg", architecture) - - -flow = header("核心票务业务流转图", "围绕票库、票柜、票袋、票单、结算、退票和报表的主业务闭环") -flow += f''' - - {card(104, 190, 220, 126, "1. 印制入库", ["分公司发起印制申请", "集团审核", "确认后进入票库"], COLORS['red'])} - {card(384, 190, 220, 126, "2. 票库管理", ["票号段入库", "库存余额与流水", "调拨 / 核销 / 调账"], COLORS['gray'])} - {card(664, 190, 220, 126, "3. 配票申请", ["票务室申请", "分公司确认", "票库到票柜"], COLORS['blue'])} - {card(944, 190, 220, 126, "4. 票柜库存", ["票务室库存", "入库 / 出库查询", "票务室调票"], COLORS['green'])} - - - - - - {card(104, 400, 220, 126, "5. 票袋管理", ["绑定线路、售票员", "更换线路", "票袋库存归属"], COLORS['green'])} - {card(384, 400, 220, 126, "6. 票单配票", ["加载票袋数据", "录入起号止号", "票柜出库到票袋"], COLORS['red'])} - {card(664, 400, 220, 126, "7. 票单结算", ["录入剩余票号", "自动计算张数金额", "生成结算记录"], COLORS['blue'])} - {card(944, 400, 220, 126, "8. 票单查询", ["配票单 / 结算单", "打印、导出", "重新结算入口"], COLORS['gray'])} - - - - - - - {card(104, 610, 220, 126, "9. 退票处理", ["票袋退票", "票柜退票", "库存回写"], COLORS['wall_red'])} - {card(384, 610, 220, 126, "10. 无人售/充值", ["无人售线路结算", "IC卡库存与收入", "导入与异常处理"], COLORS['yellow'])} - {card(664, 610, 220, 126, "11. 报表汇总", ["日结、月结", "收入、清分、趋势", "三级数据权限"], COLORS['blue'])} - {card(944, 610, 220, 126, "12. 审计追溯", ["库存流水", "操作日志", "票号查询"], COLORS['gray'])} - - - - - - 异常更正 / 重新结算 -''' -flow += footer() -write("02-核心票务业务流转图.svg", flow) - - -deployment = header("部署与可运维性架构图", "面向国产化环境的部署、监控、备份、回滚和运维交接设计") -deployment += f''' - - 网络与访问区 - {card(104, 214, 230, 116, "用户浏览器", ["集团 / 分公司 / 票务室", "内网访问、统一认证"], COLORS['red'])} - {card(394, 214, 230, 116, "Nginx / 网关", ["HTTPS 终止", "反向代理、限流"], COLORS['gray'])} - {card(684, 214, 230, 116, "应用服务 A", ["业务 API", "前端静态资源"], COLORS['blue'])} - {card(974, 214, 230, 116, "应用双节点预留", ["建议位 / 二期可选", "原需求为 1 台业务主机"], COLORS['gray'])} - - - - - 数据与文件区 - {card(104, 426, 230, 128, "达梦主库", ["业务数据写入", "库存与单据主数据"], COLORS['red'])} - {card(394, 426, 230, 128, "达梦备库", ["主备同步", "故障切换准备"], COLORS['gray'])} - {card(684, 426, 230, 128, "Redis", ["会话、缓存", "任务状态、热点字典"], COLORS['green'])} - {card(974, 426, 230, 128, "对象存储", ["模板、导入文件", "导出报表、附件"], COLORS['yellow'])} - - Oracle - 旧库 - 迁移演练 - 回滚备份 - - - - - - 运维保障区 - {card(104, 648, 216, 124, "日志中心", ["业务日志、接口日志", "登录与操作审计"], COLORS['gray'])} - {card(360, 648, 216, 124, "监控告警", ["存活、慢SQL、磁盘", "异常率、任务失败"], COLORS['red'])} - {card(616, 648, 216, 124, "备份恢复", ["数据库全量/增量", "文件备份、恢复演练"], COLORS['green'])} - {card(872, 648, 216, 124, "CI/CD", ["构建、测试、制品", "部署、版本标记"], COLORS['blue'])} - {card(1128, 648, 216, 124, "回滚预案", ["旧版本保留", "割接窗口、冒烟检查"], COLORS['wall_red'])} - - - -''' -deployment += footer() -write("03-部署与可运维性架构图.svg", deployment) - - -permissions = header("权限与数据范围设计图", "菜单权限、按钮权限、接口权限、数据权限和导出权限的统一控制") -permissions += f''' - - {card(96, 198, 240, 134, "集团管理员", ["配置菜单、角色、用户", "分配分公司数据范围", "查看全集团数据"], COLORS['red'])} - {card(396, 198, 240, 134, "集团操作员", ["按角色使用功能", "查看授权公司数据", "集团级报表"], COLORS['gray'])} - {card(696, 198, 240, 134, "分公司管理员", ["维护本公司用户", "配置票务室权限", "本公司业务管理"], COLORS['blue'])} - {card(996, 198, 240, 134, "票务室操作员", ["票柜、票袋、票单", "结算、退票、导出", "仅本票务室数据"], COLORS['green'])} - - - 统一权限拦截层 - 菜单权限 → 按钮权限 → 接口权限 → 数据范围权限 → 导出/打印权限 - - - - - - {card(116, 604, 230, 126, "组织维度", ["集团", "分公司", "票务室 / 车队 / 线路"], COLORS['red'])} - {card(386, 604, 230, 126, "业务维度", ["票库 / 票柜 / 票袋", "充值网点", "无人售线路"], COLORS['blue'])} - {card(656, 604, 230, 126, "数据维度", ["单据、库存、流水", "报表汇总", "历史迁移数据"], COLORS['green'])} - {card(926, 604, 230, 126, "审计维度", ["登录日志", "操作日志", "导入导出日志"], COLORS['gray'])} - - - -''' -permissions += footer() -write("04-权限与数据范围设计图.svg", permissions) - - -delivery = header("SDD 协同交付流程图", "把大系统拆成可验证的小任务,形成需求、编码、测试、评审、交付闭环") -delivery += f''' - - {card(102, 202, 230, 128, "1. 需求卡片化", ["按页面/动作拆分", "角色、输入、输出", "验收标准"], COLORS['red'])} - {card(382, 202, 230, 128, "2. 领域建模", ["状态机、票号段", "库存流水、报表口径", "人工确认"], COLORS['gray'])} - {card(662, 202, 230, 128, "3. 任务生成", ["表结构、接口", "页面、测试", "小批量执行"], COLORS['blue'])} - {card(942, 202, 230, 128, "4. 编码实现", ["前后端协同", "导入导出", "权限与日志"], COLORS['green'])} - - - - - {card(102, 470, 230, 128, "8. 模块验收", ["业务演示", "样例数据核对", "问题闭环"], COLORS['wall_red'])} - {card(382, 470, 230, 128, "7. 人工评审", ["核心规则 review", "安全与权限检查", "SQL 与事务检查"], COLORS['gray'])} - {card(662, 470, 230, 128, "6. 自动化测试", ["单元 / 接口", "场景 / 回归", "构建检查"], COLORS['blue'])} - {card(942, 470, 230, 128, "5. 本地自测", ["页面联调", "异常分支", "导入导出校验"], COLORS['green'])} - - - - - - - 交付原则 - 小任务、强测试、人工把关、持续演示;常规功能提效,核心规则不省评审。 - -''' -delivery += footer() -write("05-SDD协同交付流程图.svg", delivery) - - -lake = header("数据湖与外部系统对接架构图", "明确票务系统向数据湖、二维码、胆款、IC卡和银行清分场景的数据供给边界") -lake += f''' - - 票务系统数据源 - {card(104, 222, 222, 124, "业务库", ["单据、库存、流水", "结算、退票、充值"], COLORS['red'])} - {card(370, 222, 222, 124, "报表汇总库", ["日结、月结、趋势", "集团 / 分公司 / 票务室"], COLORS['blue'])} - {card(636, 222, 222, 124, "文件与附件", ["导入文件", "导出报表、签章文件"], COLORS['yellow'])} - - 数据服务与交换层 - {card(104, 458, 222, 136, "数据目录", ["数据集清单", "字段字典", "版本管理"], COLORS['gray'])} - {card(370, 458, 222, 136, "接口服务", ["REST / 批量文件", "鉴权、限流、加密"], COLORS['red'])} - {card(636, 458, 222, 136, "同步任务", ["全量 / 增量", "重试、补偿、对账"], COLORS['green'])} - {card(902, 458, 222, 136, "接口审计", ["调用日志", "失败告警", "手工补传"], COLORS['blue'])} - - - - - - - - - 外部消费与对接对象 - {card(104, 700, 188, 116, "数据湖", ["统一取数", "数据质量校验"], COLORS['red'])} - {card(326, 700, 188, 116, "二维码系统", ["是否保留供数", "历史数据确认"], COLORS['gray'])} - {card(548, 700, 188, 116, "胆款系统", ["清分日报同步", "对账与补偿"], COLORS['blue'])} - {card(770, 700, 188, 116, "IC卡系统", ["主数据同步", "增量补偿"], COLORS['green'])} - {card(992, 700, 168, 116, "银行清分", ["线下文件导入", "异常明细"], COLORS['yellow'])} - {card(1190, 700, 150, 116, "电子签章", ["状态预留", "签章归档"], COLORS['wall_red'])} - - - - - - - -''' -lake += footer() -write("06-数据湖与外部系统对接架构图.svg", lake) - - -map_svg = header("系统功能地图", "按集团、分公司、票务室三级用户视角展示业务入口和能力分布") -map_svg += f''' - - 集团视角 - {card(104, 220, 210, 116, "集团管理", ["用户、权限、菜单", "阈值、日志、配置"], COLORS['red'])} - {card(344, 220, 210, 116, "集团审批", ["印制、调拨、核销", "调账审核"], COLORS['gray'])} - {card(584, 220, 210, 116, "集团报表", ["存售、收入、清分", "趋势、月报"], COLORS['blue'])} - {card(824, 220, 210, 116, "数据服务", ["数据湖、二维码", "接口审计"], COLORS['green'])} - - 分公司视角 - {card(104, 444, 210, 116, "基础资料", ["票务室、线路", "车辆、司售、票价"], COLORS['blue'])} - {card(344, 444, 210, 116, "票库票柜", ["印制、调拨、核销", "配票申请、调票"], COLORS['red'])} - {card(584, 444, 210, 116, "充值与特殊", ["IC卡库存、售出", "异物、大额币、残币"], COLORS['yellow'])} - {card(824, 444, 210, 116, "分公司报表", ["日报、月报", "收入核对、导出"], COLORS['green'])} - - 票务室视角 - {card(104, 668, 210, 116, "票柜库存", ["入库、出库", "库存查询"], COLORS['green'])} - {card(344, 668, 210, 116, "票袋票单", ["票袋、配票", "结算、重新结算"], COLORS['red'])} - {card(584, 668, 210, 116, "退票打印", ["票袋/票柜退票", "配票单、结算单"], COLORS['gray'])} - {card(824, 668, 210, 116, "票务室报表", ["日结、存售", "交班、银行登记"], COLORS['blue'])} - - - - 共用能力 - 消息中心 - 阈值预警 - Excel 导入导出 - 打印模板 - 操作审计 - 数据权限 - 外部接口 - 备份恢复 - - - -''' -map_svg += footer() -write("07-系统功能地图.svg", map_svg) - -index = "\n".join([ - "# SVG 设计图清单", - "", - "- 01-总体技术架构图.svg", - "- 02-核心票务业务流转图.svg", - "- 03-部署与可运维性架构图.svg", - "- 04-权限与数据范围设计图.svg", - "- 05-SDD协同交付流程图.svg", - "- 06-数据湖与外部系统对接架构图.svg", - "- 07-系统功能地图.svg", -]) -(OUT / "README.md").write_text(index, encoding="utf-8") -print(OUT) diff --git a/outputs/北京公交票务评估/build_vibe_design_doc.py b/outputs/北京公交票务评估/build_vibe_design_doc.py deleted file mode 100644 index 86d1f70b..00000000 --- a/outputs/北京公交票务评估/build_vibe_design_doc.py +++ /dev/null @@ -1,883 +0,0 @@ -from __future__ import annotations - -from collections import defaultdict -from datetime import date -from pathlib import Path -from re import sub -from typing import Iterable - -from docx import Document -from docx.enum.section import WD_ORIENT, WD_SECTION -from docx.enum.table import WD_ALIGN_VERTICAL, WD_TABLE_ALIGNMENT -from docx.enum.text import WD_ALIGN_PARAGRAPH -from docx.oxml import OxmlElement -from docx.oxml.ns import qn -from docx.shared import Inches, Pt, RGBColor - - -SOURCE = Path("/Users/mate/Docs/Work/北京公交集团票务综合管理平台系统升级-需求分析说明书(初稿0506).docx") -OUT = Path("/Users/mate/Codes/mate/mateclaw/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单.docx") - -BLUE = RGBColor(46, 116, 181) -DARK_BLUE = RGBColor(31, 77, 120) -INK = RGBColor(11, 37, 69) -MUTED = RGBColor(96, 108, 122) -LIGHT = "F2F4F7" -LIGHT_BLUE = "E8EEF5" -CALLOUT = "F4F6F9" - - -def clean(text: str) -> str: - text = text.replace("\u200c", "").replace("\u200b", "").replace("\ufeff", "") - text = sub(r"\s+", " ", text).strip() - return text - - -def module_name(text: str) -> str: - text = clean(text) - text = sub(r"^[\d.、\s]+", "", text) - return text.strip(" ") - - -def set_run_font(run, size=None, bold=None, color=None, name="Calibri"): - run.font.name = name - run._element.rPr.rFonts.set(qn("w:ascii"), name) - run._element.rPr.rFonts.set(qn("w:hAnsi"), name) - run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") - if size is not None: - run.font.size = Pt(size) - if bold is not None: - run.bold = bold - if color is not None: - run.font.color.rgb = color - - -def shade(cell, fill: str): - tc_pr = cell._tc.get_or_add_tcPr() - shd = tc_pr.find(qn("w:shd")) - if shd is None: - shd = OxmlElement("w:shd") - tc_pr.append(shd) - shd.set(qn("w:fill"), fill) - - -def margins(cell, top=80, start=120, bottom=80, end=120): - tc_pr = cell._tc.get_or_add_tcPr() - tc_mar = tc_pr.first_child_found_in("w:tcMar") - if tc_mar is None: - tc_mar = OxmlElement("w:tcMar") - tc_pr.append(tc_mar) - for key, val in [("top", top), ("start", start), ("bottom", bottom), ("end", end)]: - node = tc_mar.find(qn(f"w:{key}")) - if node is None: - node = OxmlElement(f"w:{key}") - tc_mar.append(node) - node.set(qn("w:w"), str(val)) - node.set(qn("w:type"), "dxa") - - -def table_width(table, widths: list[float]): - table.autofit = False - table.alignment = WD_TABLE_ALIGNMENT.CENTER - for row in table.rows: - for idx, cell in enumerate(row.cells): - cell.width = Inches(widths[idx]) - cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER - margins(cell) - - -def add_para(doc, text="", bold=False, color=None, size=10.5, align=None): - p = doc.add_paragraph() - p.paragraph_format.space_after = Pt(6) - p.paragraph_format.line_spacing = 1.12 - if align is not None: - p.alignment = align - if text: - r = p.add_run(text) - set_run_font(r, size=size, bold=bold, color=color) - return p - - -def heading(doc, text, level): - p = doc.add_heading(text, level=level) - p.paragraph_format.space_before = Pt(16 if level == 1 else 10) - p.paragraph_format.space_after = Pt(8 if level == 1 else 5) - for r in p.runs: - set_run_font(r, size={1: 16, 2: 13, 3: 12}.get(level, 11), bold=True, color=BLUE if level < 3 else DARK_BLUE) - - -def bullets(doc, items: Iterable[str]): - for item in items: - p = doc.add_paragraph(style="List Bullet") - p.paragraph_format.space_after = Pt(3) - p.paragraph_format.line_spacing = 1.12 - r = p.add_run(item) - set_run_font(r, size=10) - - -def numbered(doc, items: Iterable[str]): - for item in items: - p = doc.add_paragraph(style="List Number") - p.paragraph_format.space_after = Pt(3) - p.paragraph_format.line_spacing = 1.12 - r = p.add_run(item) - set_run_font(r, size=10) - - -def add_table(doc, headers: list[str], rows: list[list[str]], widths: list[float], fill=LIGHT, font_size=8.8): - table = doc.add_table(rows=1, cols=len(headers)) - table.style = "Table Grid" - for i, h in enumerate(headers): - c = table.rows[0].cells[i] - c.text = h - shade(c, fill) - margins(c) - for p in c.paragraphs: - p.paragraph_format.space_after = Pt(0) - for r in p.runs: - set_run_font(r, size=font_size, bold=True, color=INK) - for row in rows: - cells = table.add_row().cells - for i, value in enumerate(row): - cells[i].text = str(value) - margins(cells[i]) - for p in cells[i].paragraphs: - p.paragraph_format.space_after = Pt(0) - p.paragraph_format.line_spacing = 1.02 - for r in p.runs: - set_run_font(r, size=font_size) - table_width(table, widths) - doc.add_paragraph() - - -def callout(doc, title, body): - table = doc.add_table(rows=1, cols=1) - table.style = "Table Grid" - cell = table.cell(0, 0) - shade(cell, CALLOUT) - margins(cell, top=120, bottom=120, start=160, end=160) - p = cell.paragraphs[0] - p.paragraph_format.space_after = Pt(4) - r = p.add_run(title) - set_run_font(r, size=10.5, bold=True, color=DARK_BLUE) - p2 = cell.add_paragraph() - p2.paragraph_format.space_after = Pt(0) - r2 = p2.add_run(body) - set_run_font(r2, size=10) - table_width(table, [6.5]) - doc.add_paragraph() - - -def configure(doc: Document): - section = doc.sections[0] - section.top_margin = Inches(0.85) - section.bottom_margin = Inches(0.85) - section.left_margin = Inches(0.9) - section.right_margin = Inches(0.9) - section.header_distance = Inches(0.45) - section.footer_distance = Inches(0.45) - styles = doc.styles - normal = styles["Normal"] - normal.font.name = "Calibri" - normal._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") - normal.font.size = Pt(10.5) - normal.paragraph_format.space_after = Pt(6) - normal.paragraph_format.line_spacing = 1.12 - for style_name, size, color in [("Heading 1", 16, BLUE), ("Heading 2", 13, BLUE), ("Heading 3", 12, DARK_BLUE)]: - st = styles[style_name] - st.font.name = "Calibri" - st._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") - st.font.size = Pt(size) - st.font.bold = True - st.font.color.rgb = color - header = section.header.paragraphs[0] - header.text = "北京公交集团票务综合管理平台系统升级 | SDD 实施与工作量评估" - for r in header.runs: - set_run_font(r, size=8.5, color=MUTED) - footer = section.footer.paragraphs[0] - footer.text = "内部评估文件" - footer.alignment = WD_ALIGN_PARAGRAPH.RIGHT - for r in footer.runs: - set_run_font(r, size=8.5, color=MUTED) - - -def extract_items(): - doc = Document(SOURCE) - table = doc.tables[38] - items = [] - current = "" - for row in table.rows[1:]: - cells = [clean(c.text) for c in row.cells[:5]] - mod, page, func, change, note = cells - if mod: - current = module_name(mod) - if not page: - continue - items.append({ - "module": current, - "page": page, - "function": func, - "change": change, - "note": note, - }) - return items - - -DELETE_OR_MERGE_PAGES = {"模版下载", "票单打印", "包专管理", "无人售管理(车辆)"} -GROUP_COMPANY_REPORTS = { - "配出统计", - "存售日报表", - "普票收入日报表", - "票款清分日报", - "IC卡充值日报表", - "IC卡充值走势报表", - "收入走势报表", - "大额币走势报表", - "残币入账走势报表", - "分公司票务管理月报表", -} - - -def normalize_requirement_items(items): - normalized = [] - for item in items: - item = dict(item) - if item["page"] in DELETE_OR_MERGE_PAGES: - item["change"] = "删除/整合" - item["note"] = f"{item['note']} 原需求标注删除或合并,按菜单下线/能力整合处理。".strip() - if item["module"] == "统计报表(分公司)" and item["page"] in GROUP_COMPANY_REPORTS: - continue - if item["module"] == "统计报表(集团)" and item["page"] in GROUP_COMPANY_REPORTS: - item["module"] = "统计报表(集团/分公司整合)" - item["note"] = f"{item['note']} 集团/分公司同名报表合并建设,按数据权限切换展示范围。".strip() - normalized.append(item) - return normalized - - -def add_external_and_pending_items(items): - additions = [ - { - "module": "外部系统对接", - "page": "公交集团数据湖标准数据接口", - "function": "统一数据接口、数据格式、传输频率、安全保障、数据加密", - "change": "待补充接口文档、数据范围、推拉模式、频率和鉴权要求", - "note": "需求文档 3.3.1 明确用于数据湖获取票务系统数据。", - }, - { - "module": "外部系统对接", - "page": "二维码系统数据接口", - "function": "统一标准数据接口、二维码相关历史/统计数据供给", - "change": "需求文档中现有二维码报表拟删除,但对外接口仍需确认是否保留数据输出", - "note": "需确认二维码普票进出站、售检统计是否仅删除页面,还是同步取消数据服务。", - }, - { - "module": "外部系统对接", - "page": "银行清分清点系统线下对接", - "function": "线下报表传递、手动导入、清分日报入库", - "change": "银行无网环境运行,需通过文件模板、导入校验和人工确认完成", - "note": "涉及无人售票与票款清分,需失败明细、重复导入控制和导入日志。", - }, - { - "module": "外部系统对接", - "page": "票款清分/胆款系统同步", - "function": "票务系统导入数据后同步胆款系统,涉及票款清分日报", - "change": "拓展部分待明确,需确认同步字段、触发时点、失败重试和对账机制", - "note": "建议作为独立联调里程碑,未提供接口前只做适配层和模拟接口。", - }, - { - "module": "外部系统对接", - "page": "IC卡/一卡通系统数据对接", - "function": "线路、车辆、司售、IC卡类型、充值相关数据同步", - "change": "需确认接口方式、同步频率、主数据归属、异常补偿", - "note": "需求文档多处说明线路、车辆、司售信息来自 IC 卡系统接口同步。", - }, - { - "module": "外部系统对接", - "page": "电子签章系统预留/对接", - "function": "特殊业务在线签字确认、签章状态、签章文件归档", - "change": "根据业务后续评估再升级", - "note": "一期建议预留字段和附件能力;正式联调、CA/签章授权另列。", - }, - { - "module": "待定事项", - "page": "安全性与合规要求确认", - "function": "安全策略、审计要求、加密要求、等保/密评/信创测评配合", - "change": "需求文档标注待集团补充确认", - "note": "会影响部署架构、日志留存、账号策略、接口加密和报价边界。", - }, - { - "module": "待定事项", - "page": "调账管理业务场景确认", - "function": "调账申请、审核、库存/金额调整、差异流水", - "change": "具体业务场景待明确", - "note": "需明确可调对象、审批层级、是否影响历史报表和会计口径。", - }, - { - "module": "待定事项", - "page": "特殊票管理业务场景确认", - "function": "特殊票新增、修改、删除、领取、核销或结算关系", - "change": "具体业务场景待明确", - "note": "需确认是否进入库存流水、是否纳入收入和报表。", - }, - { - "module": "待定事项", - "page": "无人售票自动对账与数据清洗", - "function": "无人售票清分数据自动对账、异常识别、数据清洗", - "change": "文档提出新增能力,但规则和数据来源需补充", - "note": "需确认银行文件格式、对账容差、异常处理流程和人工复核机制。", - }, - { - "module": "专项工作", - "page": "数据迁移与上线割接", - "function": "Oracle 到达梦迁移、三轮迁移演练、增量割接、抽样核验、回滚预案", - "change": "专项工作量,不并入普通功能页面", - "note": "原需求明确 79 张表、序列、视图、函数、约 200GB 历史数据和 10 年存储。", - }, - { - "module": "专项工作", - "page": "培训与运维交接", - "function": "管理员培训、业务培训、报表核对培训、运维培训、用户手册和培训课件", - "change": "专项工作量", - "note": "建议至少上线前集中培训和上线后复盘培训两轮。", - }, - { - "module": "平台底座专项", - "page": "消息中心与审批待办", - "function": "阈值预警、申请/审核消息、未读已读、弹窗提醒、待办跳转", - "change": "原需求明确消息中心和阈值预警", - "note": "作为平台底座能力单列,不混入单个业务模块。", - }, - { - "module": "平台底座专项", - "page": "打印模板与浏览器打印", - "function": "配票单、结算单、打印模板、纸张规格、浏览器打印兼容", - "change": "票单打印菜单删除,但打印能力保留", - "note": "打印能力整合至配票、结算、查询入口。", - }, - { - "module": "平台底座专项", - "page": "Excel异步导出中心", - "function": "大数据量导出、异步任务、下载中心、导出权限、水印/字段控制", - "change": "报表和查询列表共用能力", - "note": "避免大文件导出阻塞浏览器请求。", - }, - ] - return items + additions - - -def classify(item): - text = f"{item['module']} {item['page']} {item['function']} {item['change']} {item['note']}" - if item["module"] == "专项工作": - if "数据迁移" in text: - return "专项工作", 50, 80, "三轮迁移演练、数据治理、增量割接和回滚验证不可省略。" - if "培训" in text: - return "专项工作", 15, 25, "培训材料、分角色培训和上线后复盘需单列交付。" - if item["module"] == "平台底座专项": - if "消息" in text: - return "平台能力", 8, 14, "消息中心、待办提醒和阈值预警属于跨模块底座能力。" - if "打印" in text: - return "平台能力", 8, 14, "打印菜单删除不代表打印能力删除,需统一模板和兼容性验证。" - if "导出" in text: - return "平台能力", 8, 14, "大数据量导出需异步任务、权限控制和下载中心。" - if item["module"] == "外部系统对接": - if "数据湖" in text: - return "外部对接", 18, 35, "需确认数据范围、接口协议、鉴权加密、传输频率、推拉模式和验收样例。" - if "胆款" in text or "清分" in text: - return "外部对接", 15, 32, "需确认字段口径、文件/接口格式、重试补偿、对账机制和失败处理。" - if "IC卡" in text or "一卡通" in text: - return "外部对接", 18, 36, "需确认主数据归属、同步频率、增量机制、异常补偿和历史数据映射。" - if "电子签章" in text: - return "外部对接", 8, 20, "一期建议预留签章对象、签章状态和附件归档;正式联调视接口材料另估。" - return "外部对接", 12, 28, "需以接口文档、联调环境、样例数据和验收规则为准。" - if item["module"] == "待定事项": - if "无人售票自动对账" in text: - return "待定补充", 12, 24, "自动对账规则未冻结,需按银行清分护栏预留分析、校验和复核工时。" - if "调账管理" in text: - return "待定补充", 8, 24, "调账业务会影响库存、金额、报表和审计追溯,需高于普通待定事项估算。" - return "待定补充", 6, 24, "当前需求材料不足,需业务或集团侧补充确认后才能冻结范围。" - if "可删除" in text or "删除" in item["page"] or "删除" in item["change"]: - return "拟删除/整合", 0, 1, "确认下线、菜单隐藏、历史数据保留和跳转清理。" - if any(k in text for k in ["结算", "重新结算", "配票", "调票", "调账", "退票", "库存", "入库", "出库", "核销", "调拨", "印制", "票号"]): - lo, hi = 8, 18 - if any(k in text for k in ["票单结算", "重新结算", "票袋调票", "票柜退票", "票袋退票"]): - lo, hi = 14, 26 - return "核心业务", lo, hi, "需要状态机、库存流水、票号段校验、事务一致性和回归测试。" - if any(k in item["module"] for k in ["统计报表"]) or "报表" in text or "统计" in text: - return "报表统计", 6, 14, "需确认统计口径、权限范围、导出格式和历史数据性能。" - if "导入" in text or "上传" in text or "下载" in text: - return "导入导出", 5, 10, "需模板、字段校验、失败明细、导入日志和重复处理。" - if any(k in item["module"] for k in ["系统管理"]) or any(k in item["page"] for k in ["用户", "权限", "菜单", "日志", "阈值"]): - return "平台能力", 6, 14, "需统一认证授权、按钮权限、数据范围和审计记录。" - if any(k in text for k in ["查询、新建、修改、删除", "添加、编辑、删除", "添加、编辑", "新增", "管理"]): - return "常规功能", 4, 8, "以列表、表单、校验、权限按钮和操作日志为主。" - return "查询维护", 3, 6, "以查询、筛选、详情、导出或基础维护为主。" - - -def build_rows(items): - rows = [] - for idx, item in enumerate(items, start=1): - kind, lo, hi, detail = classify(item) - vibe_lo = round(lo * 0.32, 1) - vibe_hi = round(hi * 0.40, 1) - vibe_lo, vibe_hi = apply_protection_floor(item, kind, vibe_lo, vibe_hi) - vibe_display = build_vibe_display(item, vibe_lo, vibe_hi) - dev = build_dev_scope(item, kind) - rows.append({ - **item, - "idx": idx, - "kind": kind, - "lo": lo, - "hi": hi, - "vibe_lo": vibe_lo, - "vibe_hi": vibe_hi, - "vibe_display": vibe_display, - "dev": dev, - "detail": detail, - }) - return rows - - -def build_vibe_display(item, vibe_lo, vibe_hi): - text = f"{item['module']} {item['page']} {item['function']} {item['change']} {item['note']}" - if "二维码系统数据接口" in text: - return "0-1 / 12-18" - return f"{vibe_lo}-{vibe_hi}" - - -def apply_protection_floor(item, kind, vibe_lo, vibe_hi): - text = f"{item['module']} {item['page']} {item['function']} {item['change']} {item['note']}" - if kind == "拟删除/整合": - return 0, 1 - if item["module"] == "专项工作" and "数据迁移" in text: - return 30, 55 - if item["module"] == "专项工作" and "培训" in text: - return 10, 18 - if any(k in text for k in ["票单结算", "票单重新结算", "重新结算", "月终结算", "票袋退票", "票柜退票", "票袋调票", "调账"]): - vibe_lo = max(vibe_lo, 8) - vibe_hi = max(vibe_hi, 12) - if any(k in text for k in ["数据湖", "IC卡/一卡通", "IC 卡/一卡通"]): - vibe_lo = max(vibe_lo, 15) - vibe_hi = max(vibe_hi, 20) - if "胆款系统" in text: - vibe_lo = max(vibe_lo, 15) - vibe_hi = max(vibe_hi, 18) - if "二维码系统数据接口" in text: - vibe_lo = max(vibe_lo, 12) - vibe_hi = max(vibe_hi, 18) - if any(k in text for k in ["银行清分", "自动对账"]): - vibe_lo = max(vibe_lo, 12) - vibe_hi = max(vibe_hi, 18) - if any(k in text for k in ["票款实交银行登记", "票务室交班对账"]): - vibe_lo = max(vibe_lo, 6) - vibe_hi = max(vibe_hi, 12) - if "配票应急导入" in text: - vibe_lo = max(vibe_lo, 6) - vibe_hi = max(vibe_hi, 10) - if kind == "报表统计": - vibe_lo = max(vibe_lo, 4) - vibe_hi = max(vibe_hi, 8) - if vibe_hi < vibe_lo: - vibe_hi = vibe_lo - return round(vibe_lo, 1), round(vibe_hi, 1) - - -def build_dev_scope(item, kind): - page = item["page"] - if kind == "拟删除/整合": - return f"确认 {page} 下线或合并路径,处理菜单、权限、历史查询入口和数据保留。" - if kind == "核心业务": - return f"建设 {page} 的单据、审批/确认、库存流水、票号段校验、查询导出和异常回滚。" - if kind == "报表统计": - return f"建设 {page} 查询、统计聚合、权限过滤、Excel 导出、必要趋势展示和口径校验。" - if kind == "导入导出": - return f"建设 {page} 模板下载、文件上传、字段校验、入库处理、失败明细和导入日志。" - if kind == "平台能力": - return f"建设 {page} 的配置管理、权限控制、审计记录、查询筛选和维护页面。" - return f"建设 {page} 的列表查询、详情、新增/编辑/停用或删除、权限按钮、日志和导出能力。" - - -def module_summary(rows): - result = [] - grouped = defaultdict(list) - for row in rows: - grouped[row["module"]].append(row) - for mod, vals in grouped.items(): - lo = sum(v["lo"] for v in vals) - hi = sum(v["hi"] for v in vals) - vlo = sum(v["vibe_lo"] for v in vals) - vhi = sum(v["vibe_hi"] for v in vals) - focus = module_focus(mod) - if mod == "外部系统对接": - focus = "含数据湖、二维码、银行清分、胆款、IC 卡、电子签章 6 项。二维码若业务下线,模块协同后下调至 60-84 人日;若仍需对外供数,维持 72-102 人日。开工前第 1 周以集团业务部书面冻结结果为准。" - result.append([mod, str(len(vals)), f"{lo}-{hi}", f"{round(vlo)}-{round(vhi)}", focus]) - report_vals = [] - for mod, vals in grouped.items(): - if "统计报表" in mod: - report_vals.extend(vals) - if report_vals: - lo = sum(v["lo"] for v in report_vals) - hi = sum(v["hi"] for v in report_vals) - vlo = sum(v["vibe_lo"] for v in report_vals) - vhi = sum(v["vibe_hi"] for v in report_vals) - deleted = sum(1 for v in report_vals if v["kind"] == "拟删除/整合") - actual = len(report_vals) - deleted - result.append([ - "报表合计(含整合/集团/分公司/票务室)", - f"{len(report_vals)}", - f"{lo}-{hi}", - f"{round(vlo)}-{round(vhi)}", - f"报表实际开发 {actual} 项,拟删除/整合 {deleted} 项,便于报价沟通。", - ]) - return result - - -def module_focus(mod): - if "专项工作" in mod: - return "数据迁移、上线割接、培训和运维交接专项,不应混入普通功能项。" - if "平台底座专项" in mod: - return "消息中心、打印模板、异步导出等跨模块共用能力。" - if "外部系统" in mod: - return "数据湖、二维码、银行清分、胆款、IC卡、电子签章等接口联调。" - if "待定事项" in mod: - return "需求边界未冻结,需补材料后确定开发、测试和报价口径。" - if "票单" in mod: - return "票袋、配票、结算、重新结算、票号追溯,是核心复杂域。" - if "票柜" in mod or "票库" in mod or "申请" in mod or "审核" in mod: - return "围绕库存流转、审批状态和票号段控制。" - if "统计报表" in mod: - return "以口径确认、聚合性能、导出格式和权限过滤为重点。" - if "系统" in mod: - return "全局权限、菜单、日志、阈值,是平台底座。" - if "基础" in mod: - return "主数据维护和外部同步,是后续业务依赖。" - return "按业务场景完成查询、维护、导入导出和日志审计。" - - -def make_landscape(doc): - section = doc.add_section(WD_SECTION.NEW_PAGE) - section.orientation = WD_ORIENT.LANDSCAPE - section.page_width, section.page_height = section.page_height, section.page_width - section.top_margin = Inches(0.6) - section.bottom_margin = Inches(0.6) - section.left_margin = Inches(0.55) - section.right_margin = Inches(0.55) - section.header_distance = Inches(0.35) - section.footer_distance = Inches(0.35) - return section - - -def build(): - items = add_external_and_pending_items(normalize_requirement_items(extract_items())) - rows = build_rows(items) - normal_lo = sum(r["lo"] for r in rows) - normal_hi = sum(r["hi"] for r in rows) - vibe_lo = round(sum(r["vibe_lo"] for r in rows)) - vibe_hi = round(sum(r["vibe_hi"] for r in rows)) - - doc = Document() - configure(doc) - - add_para(doc, "项目实施方案", bold=True, color=MUTED, size=11) - p = doc.add_paragraph() - r = p.add_run("北京公交集团票务综合管理平台系统升级") - set_run_font(r, size=23, bold=True, color=INK) - p.paragraph_format.space_after = Pt(4) - p = doc.add_paragraph() - r = p.add_run("SDD 实施方案与工作量清单") - set_run_font(r, size=15, color=MUTED) - p.paragraph_format.space_after = Pt(14) - add_table(doc, ["字段", "内容"], [ - ["文档用途", "用于项目立项、排期、报价拆分、研发组织和验收范围确认"], - ["文档版本", "v1.0"], - ["编制日期", date.today().isoformat()], - ["编制人", "项目经理 / 解决方案团队"], - ["审核人", "架构师 / 技术负责人"], - ["变更记录", "v0.9 初稿;v1.0 修订工作量护栏、删除项口径、外部接口区间、报表整合、部署运维披露、目标环境矩阵和 SDD 术语展开"], - ["需求来源", "北京公交集团票务综合管理平台系统升级需求分析说明书(初稿0506)"], - ["估算口径", "包含需求深化、设计、开发、自测、联调、迁移、测试配合和上线支持"], - ], [1.35, 5.15], fill=LIGHT_BLUE, font_size=9) - - callout(doc, "简要结论", f"本项目按当前修订口径约 {len(rows)} 个工作条目,正常工作量约 {normal_lo}-{normal_hi} 人日。SDD 对常规页面、脚手架、测试样例、文档和部分接口适配按 60% 以上提效目标组织;但核心业务、外部对接、报表口径、数据迁移和上线割接设置最低保护工时,因此全口径协同后工作量约 {vibe_lo}-{vibe_hi} 人日。该口径要求需求冻结、接口材料同步到位、自动化测试和人工评审强约束。") - - heading(doc, "一、简要评估", 1) - add_table(doc, ["项目", "建议口径"], [ - ["功能规模", f"{len(rows)} 个功能项,覆盖原需求 14 个一级模块,并补充外部系统对接、数据湖接口和待定事项工作量。"], - ["传统开发团队", "10-12 人,8-10 个月完成;包含产品、前端、后端、数据迁移、测试、实施。"], - ["SDD 激进团队", "8-10 人,4-5 个月完成;前提是需求冻结、接口材料及时、测试自动化、代码评审、业务验收和并行联调节奏全部到位。"], - ["SDD 稳妥团队", "8-10 人,5-6 个月完成;适用于接口材料存在补充、报表口径需要多轮确认、迁移数据质量需要治理的情况。"], - ["外部条件受阻场景", "6 个月以上;适用于数据湖、IC卡、胆款、电子签章等接口资料或联调环境延期,或安全合规要求后置补充。"], - ["核心难点", "票号段连续性、库存流水、票单结算、报表口径、数据权限、历史数据迁移、数据湖/外部系统对接、国产化适配。"], - ["报价建议", "完整建设建议按 450-650 万区间,稳妥报价点 520-580 万;效率提升主要压缩周期和重复劳动,不等于按同等比例降低报价;电子签章、等保测评、第三方授权另列。"], - ], [1.4, 5.1], fill=LIGHT_BLUE, font_size=9) - - heading(doc, "二、模块工作量简表", 1) - add_table(doc, ["模块", "功能项数", "正常人日", "协同后人日", "重点说明"], module_summary(rows), [1.25, 0.65, 0.85, 0.9, 2.85], fill=LIGHT) - - heading(doc, "三、SDD 实施方式", 1) - add_para(doc, "本方案中的 SDD(Spec-Driven Development,规范驱动开发)不是直接让工具一次性生成完整系统,而是把需求、设计、编码、测试、文档拆成小批量可验证任务。每个功能都按照“需求卡片 → 数据结构 → 接口 → 页面 → 测试 → 评审 → 合并”的节奏推进。本文 SDD 一律指本节定义的开发方法论,与软件工程语境中作为交付物的 Software Design Description(软件设计说明书)不同。") - numbered(doc, [ - "需求卡片化:每个页面或业务动作形成独立任务,明确角色、数据范围、输入输出、状态和验收标准。", - "先底座后业务:先完成认证、菜单、权限、字典、日志、导入导出、文件存储等平台能力。", - "核心域手工建模:票据库存、票号段、结算、退票、调账等领域模型由架构师和业务人员先确认,再进入编码。", - "批量生成常规代码:常规列表、表单、接口、DTO、Mapper、权限按钮、导入模板可以批量生成并统一 review。", - "测试前置:每个核心业务先写状态流转和金额/张数计算测试,避免只实现页面不验证账务逻辑。", - "小步交付:每个模块独立演示、独立验收、独立回归,不把问题积压到总体验收阶段。", - ]) - heading(doc, "3.1 可压缩与不可压缩工作", 2) - add_table(doc, ["类别", "可压缩内容", "不可压缩/低压缩内容", "管理要求"], [ - ["常规 CRUD 与页面", "列表、表单、详情、权限按钮、DTO、Mapper、基础接口、前端页面可批量生成。", "业务字段确认、页面原型确认、用户体验验收。", "适合按 60% 以上提效估算。"], - ["核心票据业务", "单据骨架、状态枚举、接口样板、测试样例可提效。", "票号连续性、库存流水、结算口径、退票回写、调账规则。", "设置最低保护工时,必须人工评审。"], - ["报表统计", "查询页面、导出模板、聚合 SQL 初稿可提效。", "指标口径、历史数据比对、金额/张数验收、旧系统样例核对。", "口径确认和验收时间不按编码效率压缩。"], - ["外部系统对接", "适配层、Mock 服务、接口日志、重试框架可提效。", "接口文档等待、网络开通、联调排期、外部系统问题定位。", "拆分内部开发工时和外部等待周期。"], - ["数据迁移", "映射脚本、校验脚本、异常报告生成可提效。", "历史脏数据处理、业务确认、割接窗口、抽样核验。", "至少三轮演练,不压缩关键验证。"], - ["部署运维", "部署脚本、巡检脚本、监控配置模板可提效。", "生产网络、安全审查、备份恢复演练、回滚演练。", "纳入上线准入条件。"], - ], [1.0, 1.8, 2.05, 1.65], fill=LIGHT_BLUE, font_size=8) - heading(doc, "3.2 核心工作最低保护工时", 2) - add_table(doc, ["工作类型", "最低保护工时建议", "原因"], [ - ["票单结算、重新结算", "单项不低于 8-12 人日", "涉及金额、张数、票号段、重新结算和历史追溯,不能只按页面复杂度估算。"], - ["退票、调票、调账", "单项不低于 8-12 人日", "会影响库存回写、流水一致性和报表口径。"], - ["数据湖、IC 卡接口", "单接口不低于 15-20 人日", "需字段确认、鉴权、安全、日志、联调、失败补偿和验收样例。"], - ["胆款接口", "单接口不低于 15-18 人日", "以清分日报同步、补偿、对账为主,按中等接口复杂度预留。"], - ["银行清分导入/自动对账", "不低于 12-18 人日", "需文件模板、重复导入控制、异常明细、人工复核和对账规则。"], - ["核心报表", "单张不低于 4-8 人日", "报表开发本身可提效,但口径和数据核对需要保留时间。"], - ["数据迁移与割接", "专项不低于 50-80 人日", "迁移脚本、三轮演练、异常治理、割接和回滚不可省略。"], - ], [1.7, 1.2, 3.6], fill=LIGHT) - add_para(doc, "下表给出 SDD 协同后的实施护栏,适用于详细功能项清单。它不是传统正常工作量,而是协同开发后仍需保留的区间口径;数据迁移一行的 30-55 人日为协同后专项口径,与上一表传统 50-80 人日并存不冲突。", size=9.5) - add_table(doc, ["工作类别", "协同后人日护栏", "适用功能项", "说明"], [ - ["票单结算/重新结算", "8-12 人日", "票单结算、票单重新结算", "按保护工时修正表 19,不再直接套用统一压缩系数。"], - ["退票/调票/调账", "8-12 人日", "票袋退票、票柜退票、票袋调票、调账管理", "涉及库存回写、流水一致性和报表回写。"], - ["数据湖/IC 卡接口", "15-20 人日", "数据湖、IC 卡/一卡通", "含字段确认、鉴权、安全、日志、联调和失败补偿。"], - ["胆款接口", "15-18 人日", "票款清分/胆款", "以清分日报同步、补偿、对账为主,按中等接口复杂度预留。"], - ["银行清分/自动对账", "12-18 人日", "银行清分清点、无人售票自动对账", "含文件模板、重复导入控制、异常明细和人工复核。"], - ["核心报表", "4-8 人日", "日结、月结、清分、收入、趋势等核心报表", "报表口径和旧系统样例核对不按编码效率压缩。"], - ["数据迁移与割接", "30-55 人日", "Oracle 到达梦迁移、三轮演练、增量割接", "协同可提效脚本和报告生成,但数据治理和演练需保留周期。"], - ], [1.4, 1.05, 2.0, 2.05], fill=LIGHT_BLUE, font_size=8) - - heading(doc, "四、实施步骤简表", 1) - add_table(doc, ["阶段", "周期", "主要工作", "交付物"], [ - ["0. 需求冻结与切片", "1.5-2 周", "需求清单、业务流程、角色权限、报表口径、接口范围、迁移对象确认;同步拆成可并行任务卡。", "需求矩阵、原型、报表口径表、接口清单、迁移清单、任务切片清单。"], - ["1. 平台底座", "2.5-3 周", "登录、用户、角色、菜单、数据权限、日志、字典、阈值、消息、文件导入导出。", "可登录可授权的基础系统。"], - ["2. 基础与库存", "4-5 周", "基础资料、票库、票柜、审批、库存余额和流水。", "库存闭环 MVP。"], - ["3. 票单核心", "5-6 周", "票袋、配票、结算、重新结算、退票、票号查询。", "票务室核心业务闭环。"], - ["4. 扩展业务与报表", "4-5 周", "无人售、充值、特殊业务、集团/分公司/票务室报表。", "完整业务与统计能力。"], - ["5. 迁移联调上线", "4-6 周", "数据迁移、接口联调、UAT、性能、安全整改、上线演练。", "生产上线版本与运维交接材料。"], - ], [0.9, 0.8, 3.05, 1.75], fill=LIGHT) - add_callout = callout - add_callout(doc, "周期口径说明", "上表阶段存在并行关系,不应简单相加。平台底座完成 60%-70% 后,基础信息、库存、报表模板、接口 Mock、迁移脚本可并行推进。若甲方接口材料、报表口径、历史样例数据无法同步提供,周期应切换到 5-6 个月或 6 个月以上口径。") - - heading(doc, "五、关键设计细节", 1) - heading(doc, "5.1 库存与票号设计", 2) - bullets(doc, [ - "采用“库存余额表 + 库存流水表 + 业务单据表”三层模型,不以单一库存字段承载全部业务历史。", - "票号段字段统一包含票价、票种、票组、起号、止号、张数、状态、库存主体、来源单据。", - "所有出入库动作必须写流水,流水记录来源、目标、数量、金额、操作人、操作时间和业务原因。", - "连续票号段需校验重叠、断号、越界、已核销、已退票、已结算等状态。", - "重新结算不得覆盖原记录,应形成更正单据和差异流水,保证历史可追溯。", - ]) - heading(doc, "5.2 权限与数据范围", 2) - bullets(doc, [ - "权限拆分为菜单权限、按钮权限、接口权限、数据范围权限和导出权限。", - "集团管理员可分配全局权限;集团操作员按授权查看部分分公司;分公司角色默认本分公司;票务室角色只看本票务室。", - "后端查询必须统一注入数据范围条件,不能只依赖前端隐藏菜单。", - "导出、打印、报表接口必须复用同一套数据权限规则。", - ]) - heading(doc, "5.3 报表设计", 2) - bullets(doc, [ - "每张报表上线前先确认指标定义、筛选条件、统计维度、取数来源、金额精度、导出格式。", - "集团和分公司同类报表尽量合并,用数据权限和维度字段控制展示结果。", - "高频报表建立日汇总/月汇总表,避免每次查询实时扫大量流水。", - "报表验收必须使用旧系统样例数据做金额和张数比对。", - ]) - heading(doc, "5.3.1 消息中心、阈值预警与打印模板", 3) - add_table(doc, ["能力", "设计内容", "待确认事项"], [ - ["消息中心", "统一承载阈值预警、申请待审核、审核结果、导入失败、接口失败、结账提醒等站内消息。支持未读/已读、弹窗提醒、按角色过滤。", "是否需要短信、企业微信、邮件等外部通知;提醒频率和免打扰规则。"], - ["阈值预警", "阈值管理配置指标、阈值类型、适用组织、提醒对象;达到阈值时进入消息中心并在用户打开系统时提醒。", "具体阈值指标、计算频率、是否需要定时任务预计算。"], - ["审批待办", "印制、调拨、核销、调账、退票、销毁等流程统一生成待办消息,支持跳转到对应单据。", "各流程审批层级和超时提醒规则。"], - ["打印模板", "票单配票、票单结算、票单查询整合配票单/结算单打印;票单打印菜单删除但打印能力保留。", "纸张规格、打印机环境、页眉页脚、签字栏、是否套打。"], - ["Excel 导出", "报表、库存、流水、查询列表提供导出;大数据量导出采用异步任务和下载中心。", "导出字段、文件格式、最大导出量、是否水印。"], - ], [1.0, 3.45, 2.05], fill=LIGHT_BLUE, font_size=8) - heading(doc, "5.4 数据迁移", 2) - bullets(doc, [ - "迁移对象包括 Oracle 表、序列、视图、函数、历史业务数据和必要附件。", - "先做数据体检,输出重复票号、缺失组织、异常状态、金额不平、非法日期等问题清单。", - "至少执行三轮迁移演练:开发、测试、准生产,每轮生成记录数、金额、票号覆盖和异常清单。", - "上线割接需要冻结旧系统写入、执行增量迁移、业务抽样核验,并保留回滚方案。", - ]) - heading(doc, "5.5 数据湖与外部系统对接", 2) - add_para(doc, "重新审查需求文档后,外部系统对接不能只作为技术预留处理。数据湖、二维码系统、银行清分、票款清分/胆款系统、IC 卡系统、电子签章均会影响接口设计、数据模型、测试样例、部署网络和验收边界。") - add_table(doc, ["对接对象", "需求依据", "设计内容", "工作量建议", "待确认事项"], [ - ["公交集团数据湖", "3.3.1 要求对外提供统一标准数据接口,用于数据湖获取票务系统数据。", "建设数据服务接口、字段字典、鉴权加密、调用日志、频率控制、失败重试、样例数据。", "18-35 人日", "数据范围、推送/拉取模式、接口协议、传输频率、加密算法、验收样例。"], - ["二维码系统", "3.3.1 与数据湖并列;附录中二维码报表页面拟删除。", "确认页面删除后是否仍需保留二维码相关数据服务;如保留,需建立接口或数据集。", "12-28 人日", "页面删除是否等于业务下线;历史二维码数据是否迁移;是否还要对外供数。"], - ["银行清分清点系统", "3.3.2 明确银行无网环境,通过线下报表、手动导入方式对接。", "设计导入模板、字段校验、重复导入控制、失败明细、导入日志、人工确认流程。", "15-32 人日", "银行文件格式、清分日报字段、异常处理、是否需要自动对账。"], - ["票款清分/胆款系统", "3.3.3 由票务系统导入数据后同步胆款系统,拓展部分待明确。", "设计清分日报同步接口、对账字段、同步状态、失败重试、补偿任务和接口日志。", "15-32 人日", "同步方向、字段口径、触发时点、接口环境、失败重传和对账责任。"], - ["IC 卡/一卡通系统", "3.3.4;线路、车辆、司售等基础信息来自 IC 卡系统同步。", "建设主数据同步、增量更新、异常补偿、数据映射、同步日志和人工修正入口。", "18-36 人日", "接口文档、同步频率、主数据归属、历史数据映射、异常数据处理。"], - ["电子签章系统", "功能需求中说明根据业务后续评估再升级,特殊业务提供在线签字确认。", "一期预留签章对象、签章状态、附件归档和业务钩子;正式接口联调可单列。", "8-20 人日", "签章厂商、CA/证书、签章流程、法律效力、附件存储、费用授权。"], - ], [1.05, 1.35, 1.75, 0.75, 1.6], fill=LIGHT_BLUE, font_size=7.8) - heading(doc, "5.5.1 数据湖接口细化设计", 3) - add_table(doc, ["设计项", "建议方案", "需要确认"], [ - ["数据目录", "建立票务主数据、库存流水、单据审批、票单结算、充值收入、无人售清分、报表汇总等数据集目录。", "数据湖实际需要哪些主题域,是否需要历史全量数据。"], - ["同步模式", "支持全量初始化 + 增量同步;增量可按更新时间、业务流水号或同步批次号识别。", "数据湖是主动拉取还是票务系统主动推送。"], - ["接口形态", "优先 REST/OpenAPI;大批量历史数据可采用文件交换或定时批量导出。", "接口协议、网络通道、文件格式、字符集和压缩方式。"], - ["安全与加密", "接口鉴权、签名、时间戳、防重放、传输加密、敏感字段脱敏、调用白名单。", "集团安全要求、密钥管理方式、是否要求国密算法。"], - ["数据质量", "提供记录数、金额合计、张数合计、批次状态、失败明细和重传机制。", "数据湖验收规则、质量阈值、错误处理责任边界。"], - ["版本管理", "字段字典和接口版本化,新增字段向后兼容,重大变更需变更单。", "数据湖侧是否有统一接口规范和版本发布流程。"], - ["审计监控", "记录调用方、接口、时间、参数摘要、返回状态、耗时、错误信息和重试次数。", "日志留存周期、审计字段、告警推送方式。"], - ], [1.1, 3.25, 2.15], fill=LIGHT) - heading(doc, "5.6 待定事项与范围冻结", 2) - add_table(doc, ["待定事项", "需求文档表述", "影响", "冻结前处理建议"], [ - ["第三方对接模块", "待提供具体接口材料。", "影响接口工作量、排期、联调环境和报价边界。", "把接口文档、样例数据、联调账号、验收规则作为开工前置条件。"], - ["安全性要求", "待集团补充确认。", "影响账号策略、日志留存、接口加密、部署网络和等保/密评。", "形成安全需求清单,明确是否含等保、密评、信创测评配合。"], - ["调账管理", "具体业务场景待明确。", "影响库存、金额、报表和审计追溯。", "明确可调对象、审批层级、是否影响历史报表、是否需要会计凭证。"], - ["特殊票管理", "具体业务场景待明确。", "影响是否纳入库存流水、收入统计和报表。", "明确特殊票类型、领取/核销/结算流程和数据口径。"], - ["无人售票自动对账", "功能范围中提出新增无人售票自动对账、数据清洗。", "影响银行清分导入、异常处理和对账算法。", "明确银行文件格式、对账口径、容差规则、人工复核流程。"], - ["电子签章", "后续根据业务评估再升级。", "影响特殊业务闭环和第三方费用。", "一期只做预留还是完整接入需在合同中明确。"], - ], [1.2, 1.75, 1.65, 1.9], fill=LIGHT, font_size=8) - heading(doc, "5.6.1 范围边界与报价口径", 3) - add_table(doc, ["事项", "建议纳入一期", "建议单列/待确认", "原因"], [ - ["数据湖接口", "接口框架、字段字典、调用日志、Mock 联调、已确认数据集。", "数据湖侧未确认的数据集、特殊加密、历史全量大批量交换。", "数据范围和集团安全规范会直接影响工作量。"], - ["二维码系统", "保留必要数据接口占位和历史数据确认。", "若页面删除后仍要求完整二维码统计供数,应单列确认。", "需求中页面拟删除,但 3.3.1 仍提到二维码系统。"], - ["电子签章", "签章状态、附件字段、业务钩子、归档能力预留。", "完整电子签章厂商联调、CA 授权、法律效力流程。", "需求明确后续评估再升级。"], - ["等保/密评/信创测评", "基础安全设计、日志审计、国产化适配。", "正式测评整改、测评材料、第三方平台对接。", "需求中安全性待集团补充确认。"], - ["调账/特殊票", "基础单据与菜单预留。", "完整业务规则、报表影响、会计口径调整。", "原文标注具体业务场景待明确。"], - ["无人售自动对账", "导入、清分日报、异常记录基础能力。", "自动对账算法、容差规则、异常闭环和清洗策略。", "原文提出新增能力但规则未展开。"], - ], [1.05, 2.0, 2.0, 1.45], fill=LIGHT_BLUE, font_size=8) - add_table(doc, ["序号", "冻结对象", "冻结物", "责任方", "截止节点", "未冻结后果"], [ - ["1", "二维码业务边界", "业务下线/仅删菜单/仍需对外供数三选一书面确认", "集团业务部", "第 1 周", "进入稳妥计划"], - ["2", "调账管理业务场景", "可调对象、审批层级、是否影响历史报表、是否需会计凭证", "集团财务/业务", "第 2 周", "单列变更"], - ["3", "特殊票管理业务场景", "特殊票类型、领取/核销/结算流程", "集团业务", "第 2 周", "单列变更"], - ["4", "银行清分文件格式", "字段、分隔符、字符集、对账容差", "银行/集团清算", "第 3 周", "银行清分项延后"], - ["5", "安全合规等级", "等保二级/三级、是否含密评/信创测评", "集团信息安全", "第 4 周", "安全整改后置或单列"], - ["6", "电子签章范围", "一期预留/一期完整接入 + CA 厂商", "集团法务/业务", "第 8 周", "一期仅做预留"], - ["7", "数据湖数据集与协议", "主题域、推/拉、加密算法、验收样例", "数据湖团队", "第 4 周", "数据湖仅交付框架"], - ["8", "IC 卡同步主数据归属", "线路/车辆/司售数据源、增量字段", "一卡通公司", "第 4 周", "协同人日上调"], - ["9", "报表口径样例", "集团/分公司/票务室各类报表旧系统样例数据", "集团业务", "第 6 周", "报表验收延后"], - ["10", "达梦双套许可", "生产主备 + 开发测试主备", "集团采购", "第 6 周", "联调延期 1-2 周或本地用 H2/MySQL 临时联调"], - ], [0.35, 1.05, 2.0, 1.0, 0.75, 1.35], fill=LIGHT, font_size=7.5) - - heading(doc, "六、部署与可运维性设计", 1) - add_para(doc, "本项目属于票务核心管理系统,部署和运维能力应在一期同步设计,不能等到开发完成后补。运维设计目标是:可部署、可监控、可审计、可备份、可恢复、可灰度、可回滚。") - heading(doc, "6.0 基础资源与容量规划", 2) - add_table(doc, ["资源项", "原始需求口径", "设计建议"], [ - ["用户规模", "总量 >200 名,峰值 150 名在线。", "按 150 在线用户进行压力测试,报表、导入、结账等高负载场景单独压测。"], - ["服务器资源", "3 台服务器:2 台数据库服务器,1 台应用服务器;总计 24vCPU、96G 内存。", "基础方案按 1 台应用主机交付;应用双节点仅作为建议位预留或二期可选,不纳入基础资源口径。"], - ["数据库", "达梦数据库 2 套:生产 1 套主备 + 开发测试 1 套主备。", "达梦许可由甲方采购或在合同中单列;SQL 兼容性需前置验证,重点关注 Oracle 迁移函数、序列、视图和报表 SQL。"], - ["历史数据", "Oracle 历史数据约 200GB,涉及 79 张表、序列、视图、函数等。", "先做数据体检和迁移映射,历史数据全量迁移后再做增量割接。"], - ["对象存储", "10 年存储需求约 800-1000G OBS。", "导入文件、导出报表、签章附件、迁移中间文件需制定生命周期和归档策略。"], - ["网络资源", "业务应用、数据库、数据中心服务器、线网中心内网需互通;涉及 192.168.99.x、10.129.87.x 和外网映射。", "上线前完成网络连通性、端口、白名单、接口访问、文件交换路径和外网 NAT 映射确认。"], - ], [1.0, 2.25, 3.25], fill=LIGHT_BLUE, font_size=8) - callout(doc, "资源与许可边界", "基础部署严格对齐原始需求 3 台服务器口径。应用双节点、双活容灾、第三方运维平台对接、OBS 异地副本属于建议项或二期可选。达梦数据库授权、国产服务器与操作系统、国产中间件与浏览器、电子签章 CA 与硬件介质、等保/密评/信创测评费用,由甲方采购或在合同中单列。") - add_table(doc, ["运维领域", "设计要求", "工作量建议"], [ - ["环境规划", "至少规划开发、测试、预生产、生产四类环境;生产采用应用服务与数据库分离部署,数据库主备。", "12-18 人日"], - ["国产化适配", "适配达梦数据库、国产服务器操作系统、国产中间件或 Nginx/应用服务部署要求,提前验证驱动和 SQL 兼容性。", "20-35 人日"], - ["配置管理", "数据库连接、文件存储、外部接口、导入目录、日志级别、任务开关全部配置化,避免写死在代码中。", "8-12 人日"], - ["CI/CD", "建立构建、单元测试、打包、制品归档、部署脚本流程;生产部署需支持版本标记和回滚。", "15-25 人日"], - ["日志审计", "区分业务操作日志、登录日志、接口日志、导入导出日志、系统错误日志;关键单据状态变化必须可追溯。", "15-25 人日"], - ["监控告警", "监控应用存活、接口耗时、数据库连接池、慢 SQL、磁盘空间、导入任务、定时任务和异常错误率。", "15-25 人日"], - ["备份恢复", "数据库全量/增量备份,导入文件和导出附件备份,定期恢复演练,形成恢复时间目标。", "12-20 人日"], - ["上线回滚", "上线前冻结窗口、迁移脚本、冒烟检查、业务抽样、失败回滚、旧系统只读策略均需预案。", "15-25 人日"], - ["运维交接", "提供部署手册、配置手册、巡检手册、常见问题、数据恢复手册和接口联调手册。", "10-18 人日"], - ["外部接口运维", "对数据湖、IC卡、胆款、银行清分导入等接口建立调用日志、失败告警、重试补偿和手工补传工具。", "20-35 人日"], - ], [1.15, 4.2, 1.15], fill=LIGHT_BLUE) - heading(doc, "6.1 运维验收指标建议", 2) - add_table(doc, ["指标", "建议值/要求", "说明"], [ - ["RPO", "核心业务数据建议 ≤ 15 分钟;最终以甲方灾备要求和上线前验证为准。", "通过达梦主备同步和定时归档备份兜底;如要求 RPO ≤ 5 分钟需开启同步复制并单独验收。"], - ["RTO", "普通故障 2 小时内恢复;重大故障按应急预案切换或回滚。", "需在上线前完成恢复演练和回滚演练。"], - ["日志留存", "操作日志、登录日志、接口日志建议不少于 180 天;审计类日志可按集团要求延长。", "满足操作追溯、接口追踪和安全审计。"], - ["接口重试", "外部接口失败建议自动重试 3 次,仍失败进入补偿队列并告警。", "适用于数据湖、IC 卡、胆款等接口。"], - ["导入失败处理", "导入失败必须生成失败明细,可下载、可修正、可重新导入。", "适用于银行清分、无人售、残币、充值等文件导入场景。"], - ["慢 SQL 阈值", "建议 2 秒以上记录慢 SQL,5 秒以上告警或进入优化清单。", "重点关注报表查询、库存查询和迁移后 SQL。"], - ["备份恢复演练", "上线前至少 1 次,正式运行后建议每季度 1 次。", "演练结果纳入运维交接材料。"], - ["生产配置管理", "密钥、数据库连接、接口地址、文件路径、任务开关全部外置配置。", "避免生产环境硬编码和手工改包。"], - ], [1.0, 2.45, 3.05], fill=LIGHT) - heading(doc, "6.2 性能、可靠性与兼容性验收", 2) - add_table(doc, ["验收项", "建议指标", "说明"], [ - ["在线用户", "按峰值 150 在线用户设计压测场景。", "覆盖登录、列表查询、库存查询、票单结算、报表查询。"], - ["普通查询", "常规列表查询建议 2 秒内返回。", "大数据量查询需分页、索引和权限过滤优化。"], - ["报表查询", "常用日报/月报建议 5-10 秒内返回;复杂历史报表可异步生成。", "高频报表建议使用汇总表或预计算。"], - ["Excel 导出", "大文件导出使用异步任务,完成后下载,避免浏览器长时间等待。", "需限制单次最大导出量和导出权限。"], - ["文件导入", "导入任务异步执行,失败明细可下载,可修正后重导。", "适用于银行清分、无人售、残币、充值等模板。"], - ["可靠性", "关键业务异常必须事务回滚,不产生半库存、半流水状态。", "票据库存、结算、退票、调账为重点。"], - ["浏览器兼容", "优先支持 Chrome、Edge 及甲方内网指定国产浏览器。", "打印、上传、下载需在目标浏览器验证。"], - ["打印兼容", "配票单、结算单需验证纸张、页边距、分页和打印机兼容。", "票单打印菜单删除,但打印能力保留到查询/结算入口。"], - ], [1.05, 2.25, 3.2], fill=LIGHT) - add_table(doc, ["压测场景", "建议并发/数据量", "通过判据", "工具建议"], [ - ["登录与菜单加载", "150 在线用户,分批登录", "登录成功率稳定,菜单加载无明显超时", "JMeter/Locust 或甲方指定工具"], - ["库存查询", "50 并发,按分公司/票务室/票号段查询", "常规查询 2 秒内,大查询分页返回", "JMeter/Locust"], - ["票单结算", "20 并发,含票号段计算和保存", "事务一致,无半库存/半流水状态", "接口压测 + 场景脚本"], - ["报表查询", "20 并发,日报/月报/清分报表", "常用报表 5-10 秒内,复杂报表异步生成", "接口压测"], - ["Excel 导出", "10 并发,大数据量导出", "进入异步任务,不阻塞浏览器请求", "接口压测 + 文件校验"], - ["文件导入", "5 并发,银行清分/残币/充值模板", "失败明细准确,可修正后重导", "批量导入脚本"], - ], [1.1, 1.4, 2.55, 1.45], fill=LIGHT_BLUE, font_size=8) - add_para(doc, "压测完成后需执行数据一致性核验脚本,至少校验:库存余额等于流水汇总、票号段数量等于起号至止号枚举数量、单据金额等于明细金额汇总。核验结果应纳入性能测试报告。", size=9.5) - heading(doc, "6.3 交付物、培训与运维交接", 2) - add_table(doc, ["交付类别", "交付物", "说明"], [ - ["需求与设计", "需求矩阵、功能清单、原型、数据库设计、接口设计、报表口径表。", "作为验收范围和变更管理基线。"], - ["开发交付", "源代码、构建脚本、部署包、数据库脚本、迁移脚本、导入模板、打印模板。", "版本需可追溯,生产发布包需归档。"], - ["测试交付", "测试用例、接口测试报告、性能测试报告、UAT 问题清单、回归测试报告。", "重点覆盖库存流水、结算、权限、报表、迁移。"], - ["数据迁移", "迁移方案、字段映射、迁移脚本、数据体检报告、迁移核对报告、割接记录。", "至少三轮迁移演练后上线。"], - ["运维文档", "部署手册、配置手册、巡检手册、备份恢复手册、接口补偿手册、应急回滚预案。", "交付给甲方运维团队。"], - ["用户材料", "用户操作手册、管理员手册、培训课件、常见问题清单。", "按集团、分公司、票务室角色分别组织培训。"], - ["培训安排", "管理员培训、业务操作培训、报表核对培训、运维培训。", "建议至少 2 轮:上线前集中培训,上线后问题复盘培训。"], - ], [1.05, 2.65, 2.8], fill=LIGHT_BLUE, font_size=8) - heading(doc, "6.4 目标环境矩阵", 2) - add_table(doc, ["维度", "必测项", "选测项", "备注"], [ - ["浏览器", "Chrome 100+、Edge 100+", "奇安信浏览器、UOS 浏览器、360 安全浏览器", "甲方信创浏览器需提供具体版本。"], - ["操作系统", "Windows 10/11", "统信 UOS、麒麟 V10", "服务端和客户端分别声明。"], - ["打印机", "1 款激光 + 1 款针打(甲方提供型号)", "热敏打印机(如有)", "票务打印多用针打,纸张需现场调试。"], - ["屏幕", "1920×1080 桌面", "1366×768 笔记本、4K 屏", "UI 适配最小宽度建议 1366。"], - ["网络", "内网 100M/1G", "跨区域内网带宽 ≥ 50M", "报表和导出场景按 50M 估算。"], - ], [0.85, 1.55, 1.75, 2.35], fill=LIGHT, font_size=8) - callout(doc, "部署工作量口径", "部署与运维建设建议单独预留 140-235 人日,其中外部接口运维、失败补偿和告警监控需纳入一期。如果甲方要求等保测评、密评配合、信创测评、双活容灾或第三方运维平台对接,应另行增加专项工作量和报价。") - - heading(doc, "七、详细功能项清单", 1) - add_para(doc, "以下清单按需求文档附录逐项展开。正常人日为完整开发、自测、联调配合口径;协同后人日为采用 SDD 方式后的执行估算,不包含甲方等待、接口资料延迟和重大需求变更。") - make_landscape(doc) - heading(doc, "详细功能项与工作量估算", 1) - detail_rows = [] - for r in rows: - detail_rows.append([ - r["idx"], - r["module"], - r["page"], - r["kind"], - r["function"] or "按页面说明", - r["dev"], - f"{r['lo']}-{r['hi']}", - r["vibe_display"], - r["detail"], - ]) - add_table( - doc, - ["序号", "模块", "功能页面", "类型", "现有功能", "开发内容", "正常人日", "协同后", "难点/备注"], - detail_rows, - [0.35, 0.95, 1.35, 0.75, 1.25, 2.1, 0.58, 0.58, 1.6], - fill=LIGHT_BLUE, - font_size=7.2, - ) - - doc.add_section(WD_SECTION.NEW_PAGE) - heading(doc, "八、风险与边界", 1) - add_table(doc, ["风险点", "表现", "建议处理"], [ - ["需求边界不清", "文档中存在“待明确”“删除”“整合”项,容易反复变更。", "在开发前形成冻结版功能清单,变更走审批和工期调整。"], - ["接口资料缺失", "数据湖、二维码、胆款、电子签章等接口材料未完全明确。", "一期只做接口框架和已确认接口,未确认部分单独列二期。"], - ["报表口径争议", "同一报表集团/分公司/票务室口径不同,数字验收困难。", "先用旧系统样例数据签字确认,再开发。"], - ["历史数据异常", "旧系统长期运行导致脏数据和状态不一致。", "迁移前做数据体检,异常数据由业务确认处理规则。"], - ["国产化兼容风险", "达梦 SQL、数据库驱动、国产操作系统、中间件和浏览器兼容问题可能后置暴露。", "开发早期即接入达梦和目标浏览器,迁移函数、序列、视图和报表 SQL 前置验证。"], - ["网络连通延期", "云平台、数据中心、线网中心、外部接口白名单和端口开通不及时。", "把网络连通、端口、白名单和 NAT 映射列为上线前置条件。"], - ["安全合规后补", "等保、密评、信创测评要求若后置补充,会影响架构、日志、加密和部署。", "安全等级和测评范围在第 4 周前冻结,正式测评配合单列报价。"], - ["打印与浏览器兼容", "配票单、结算单在目标浏览器、打印机、纸张和页边距下可能存在偏差。", "上线前用甲方实际浏览器和打印机做专项验证。"], - ["旧系统并行窗口", "上线割接后旧系统是否只读、并行多久、如何回滚未明确。", "制定割接窗口、只读策略、增量迁移、回滚分支和抽样验收流程。"], - ["AI 生成代码质量波动", "常规代码效率高,但核心业务可能遗漏隐性规则。", "核心交易类代码必须人工 review,并要求测试覆盖状态流转和金额计算。"], - ], [1.35, 2.45, 2.7], fill=LIGHT) - - heading(doc, "九、结论", 1) - add_para(doc, f"本项目按当前修订口径共 {len(rows)} 个工作条目,已将原需求明确删除/整合的功能按 0-1 人日处理,并合并集团/分公司同名报表。传统完整实施工作量约 {normal_lo}-{normal_hi} 人日,SDD 协同后约 {vibe_lo}-{vibe_hi} 人日;核心业务、外部接口、报表口径、数据迁移和上线割接设置最低保护工时,不随 60% 提效目标等比例压缩。") - add_para(doc, "周期建议采用双口径:激进计划为 8-10 人、4-5 个月,前提是需求冻结、接口资料、历史样例数据、达梦许可和联调环境在约定节点全部到位;稳妥计划为 8-10 人、5-6 个月,适用于接口材料补充、报表口径多轮确认或迁移数据质量治理场景。任一关键前置条件未达成,应自动切换至稳妥计划或单列变更。上述协同后人日不含部署与运维建设的 140-235 人日;后者已包含在基础报价中,仅当甲方追加等保/密评/信创测评、双活容灾或第三方运维平台对接时另行增加专项报价。") - add_para(doc, "报价建议维持 450-650 万区间,稳妥报价点 520-580 万。该报价不含达梦数据库授权、国产服务器与操作系统、国产中间件、第三方电子签章、CA/硬件介质、等保/密评/信创测评、第三方运维平台和双活容灾等单列项目。效率提升主要压缩周期和重复劳动,不等于按同等比例降低项目责任、质保、联调和验收成本。") - - doc.save(OUT) - print(OUT) - - -if __name__ == "__main__": - build() diff --git a/outputs/北京公交票务评估/insert_diagrams_into_doc.py b/outputs/北京公交票务评估/insert_diagrams_into_doc.py deleted file mode 100644 index 664bc635..00000000 --- a/outputs/北京公交票务评估/insert_diagrams_into_doc.py +++ /dev/null @@ -1,72 +0,0 @@ -from pathlib import Path - -from docx import Document -from docx.enum.text import WD_ALIGN_PARAGRAPH -from docx.shared import Inches, Pt - - -SRC = Path("/Users/mate/Codes/mate/mateclaw/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单.docx") -OUT = Path("/Users/mate/Codes/mate/mateclaw/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单-含设计图.docx") -PNG = Path("/Users/mate/Codes/mate/mateclaw/outputs/北京公交票务评估/svg设计图/png预览") - - -DIAGRAMS = { - "三、SDD 实施方式": ("05-SDD协同交付流程图.png", "图 1 SDD 协同交付流程图"), - "四、实施步骤简表": ("07-系统功能地图.png", "图 2 系统功能地图"), - "五、关键设计细节": ("02-核心票务业务流转图.png", "图 3 核心票务业务流转图"), - "5.2 权限与数据范围": ("04-权限与数据范围设计图.png", "图 4 权限与数据范围设计图"), - "六、部署与可运维性设计": ("03-部署与可运维性架构图.png", "图 5 部署与可运维性架构图"), - "5.5 数据湖与外部系统对接": ("06-数据湖与外部系统对接架构图.png", "图 6 数据湖与外部系统对接架构图"), - "七、详细功能项清单": ("01-总体技术架构图.png", "图 7 总体技术架构图"), -} - - -def insert_after(paragraph, image_path: Path, caption: str, width=Inches(6.7)): - caption_p = paragraph.insert_paragraph_before("") - # Move caption and picture after the heading by inserting before next paragraph is not directly - # supported in python-docx. Use low-level insertion after heading. - pic_p = paragraph._p.addnext(paragraph._p.__class__()) - - -def add_picture_after(paragraph, image_path: Path, caption: str, width=Inches(6.7)): - doc = paragraph.part.document - p_pic = doc.add_paragraph() - p_pic.alignment = WD_ALIGN_PARAGRAPH.CENTER - run = p_pic.add_run() - run.add_picture(str(image_path), width=width) - p_pic.paragraph_format.space_before = Pt(6) - p_pic.paragraph_format.space_after = Pt(3) - - p_cap = doc.add_paragraph() - p_cap.alignment = WD_ALIGN_PARAGRAPH.CENTER - p_cap.paragraph_format.space_after = Pt(8) - r = p_cap.add_run(caption) - r.font.size = Pt(9) - r.font.name = "Microsoft YaHei" - - # Move the newly appended picture + caption immediately after the target paragraph. - paragraph._p.addnext(p_cap._p) - paragraph._p.addnext(p_pic._p) - - -def main(): - doc = Document(SRC) - inserted = 0 - for para in list(doc.paragraphs): - text = para.text.strip() - if text in DIAGRAMS: - file_name, caption = DIAGRAMS[text] - image = PNG / file_name - if not image.exists(): - raise FileNotFoundError(image) - width = Inches(8.9) if "详细功能项" in text else Inches(6.7) - add_picture_after(para, image, caption, width=width) - inserted += 1 - if inserted != len(DIAGRAMS): - raise RuntimeError(f"Inserted {inserted}, expected {len(DIAGRAMS)}") - doc.save(OUT) - print(OUT) - - -if __name__ == "__main__": - main() diff --git a/outputs/北京公交票务评估/quicklook/北京公交集团票务综合管理平台系统升级-详细设计与Codex实施方案.docx.png b/outputs/北京公交票务评估/quicklook/北京公交集团票务综合管理平台系统升级-详细设计与Codex实施方案.docx.png deleted file mode 100644 index 61becd5e..00000000 Binary files a/outputs/北京公交票务评估/quicklook/北京公交集团票务综合管理平台系统升级-详细设计与Codex实施方案.docx.png and /dev/null differ diff --git a/outputs/北京公交票务评估/quicklook含图/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx.png b/outputs/北京公交票务评估/quicklook含图/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx.png deleted file mode 100644 index 1f52a785..00000000 Binary files a/outputs/北京公交票务评估/quicklook含图/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx.png and /dev/null differ diff --git a/outputs/北京公交票务评估/quicklook最终/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx.png b/outputs/北京公交票务评估/quicklook最终/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx.png deleted file mode 100644 index 2e6f6847..00000000 Binary files a/outputs/北京公交票务评估/quicklook最终/北京公交集团票务综合管理平台系统升级-VibeCoding实施方案与工作量清单-含设计图.docx.png and /dev/null differ diff --git a/outputs/北京公交票务评估/svg设计图/01-总体技术架构图.svg b/outputs/北京公交票务评估/svg设计图/01-总体技术架构图.svg deleted file mode 100644 index f082f403..00000000 --- a/outputs/北京公交票务评估/svg设计图/01-总体技术架构图.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - 总体技术架构图 - 从用户访问、应用服务、数据存储、外部集成到运维保障的分层架构 - - - 访问与用户层 - - -集团用户 -集团管理员 / 操作员 -全局管理、报表、审批 - - -分公司用户 -分公司管理员 / 操作员 -本公司业务、审核、统计 - - -票务室用户 -票柜、票袋、票单 -配票、结算、退票 - - -移动/内网终端 -浏览器访问 -打印、导入、导出 - - - - - - - 应用与业务服务层 - - -前端应用 -Vue3 / TypeScript -菜单导航、表单、报表 -打印与导入导出 - - -网关与认证 -统一登录认证 -菜单 / 按钮权限 -数据范围拦截 - - -业务服务 -票库、票柜、票单 -充值、无人售、退票 -审批与状态机 - - -报表服务 -日结、月结、趋势 -Excel 导出 -汇总表加速 - - - - - - - 数据、集成与运维层 - - -达梦数据库 -主业务库 / 主备 -库存、流水、报表 - - -Redis / 缓存 -会话、字典、短期任务 -热点查询缓存 - - -文件与对象存储 -模板、导入文件 -导出报表、附件 - - -外部系统集成 -IC卡 / 数据湖 / 胆款 -银行清分线下导入 - - -运维保障 -日志、监控、备份 -灰度、回滚、巡检 - - 北京公交集团票务综合管理平台系统升级 | SDD(Spec-Driven Development,规范驱动开发)实施方案配套设计图 - - - diff --git a/outputs/北京公交票务评估/svg设计图/02-核心票务业务流转图.svg b/outputs/北京公交票务评估/svg设计图/02-核心票务业务流转图.svg deleted file mode 100644 index ee4dd815..00000000 --- a/outputs/北京公交票务评估/svg设计图/02-核心票务业务流转图.svg +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - 核心票务业务流转图 - 围绕票库、票柜、票袋、票单、结算、退票和报表的主业务闭环 - - - - -1. 印制入库 -分公司发起印制申请 -集团审核 -确认后进入票库 - - -2. 票库管理 -票号段入库 -库存余额与流水 -调拨 / 核销 / 调账 - - -3. 配票申请 -票务室申请 -分公司确认 -票库到票柜 - - -4. 票柜库存 -票务室库存 -入库 / 出库查询 -票务室调票 - - - - - - - -5. 票袋管理 -绑定线路、售票员 -更换线路 -票袋库存归属 - - -6. 票单配票 -加载票袋数据 -录入起号止号 -票柜出库到票袋 - - -7. 票单结算 -录入剩余票号 -自动计算张数金额 -生成结算记录 - - -8. 票单查询 -配票单 / 结算单 -打印、导出 -重新结算入口 - - - - - - - - -9. 退票处理 -票袋退票 -票柜退票 -库存回写 - - -10. 无人售/充值 -无人售线路结算 -IC卡库存与收入 -导入与异常处理 - - -11. 报表汇总 -日结、月结 -收入、清分、趋势 -三级数据权限 - - -12. 审计追溯 -库存流水 -操作日志 -票号查询 - - - - - - 异常更正 / 重新结算 - - 北京公交集团票务综合管理平台系统升级 | SDD(Spec-Driven Development,规范驱动开发)实施方案配套设计图 - - - diff --git a/outputs/北京公交票务评估/svg设计图/03-部署与可运维性架构图.svg b/outputs/北京公交票务评估/svg设计图/03-部署与可运维性架构图.svg deleted file mode 100644 index 4563361a..00000000 --- a/outputs/北京公交票务评估/svg设计图/03-部署与可运维性架构图.svg +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - - - - - - - - - - 部署与可运维性架构图 - 面向国产化环境的部署、监控、备份、回滚和运维交接设计 - - - 网络与访问区 - - -用户浏览器 -集团 / 分公司 / 票务室 -内网访问、统一认证 - - -Nginx / 网关 -HTTPS 终止 -反向代理、限流 - - -应用服务 A -业务 API -前端静态资源 - - -应用双节点预留 -建议位 / 二期可选 -原需求为 1 台业务主机 - - - - - 数据与文件区 - - -达梦主库 -业务数据写入 -库存与单据主数据 - - -达梦备库 -主备同步 -故障切换准备 - - -Redis -会话、缓存 -任务状态、热点字典 - - -对象存储 -模板、导入文件 -导出报表、附件 - - Oracle - 旧库 - 迁移演练 - 回滚备份 - - - - - - 运维保障区 - - -日志中心 -业务日志、接口日志 -登录与操作审计 - - -监控告警 -存活、慢SQL、磁盘 -异常率、任务失败 - - -备份恢复 -数据库全量/增量 -文件备份、恢复演练 - - -CI/CD -构建、测试、制品 -部署、版本标记 - - -回滚预案 -旧版本保留 -割接窗口、冒烟检查 - - - - - 北京公交集团票务综合管理平台系统升级 | SDD(Spec-Driven Development,规范驱动开发)实施方案配套设计图 - - - diff --git a/outputs/北京公交票务评估/svg设计图/04-权限与数据范围设计图.svg b/outputs/北京公交票务评估/svg设计图/04-权限与数据范围设计图.svg deleted file mode 100644 index 68a3de5d..00000000 --- a/outputs/北京公交票务评估/svg设计图/04-权限与数据范围设计图.svg +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - 权限与数据范围设计图 - 菜单权限、按钮权限、接口权限、数据权限和导出权限的统一控制 - - - - -集团管理员 -配置菜单、角色、用户 -分配分公司数据范围 -查看全集团数据 - - -集团操作员 -按角色使用功能 -查看授权公司数据 -集团级报表 - - -分公司管理员 -维护本公司用户 -配置票务室权限 -本公司业务管理 - - -票务室操作员 -票柜、票袋、票单 -结算、退票、导出 -仅本票务室数据 - - - 统一权限拦截层 - 菜单权限 → 按钮权限 → 接口权限 → 数据范围权限 → 导出/打印权限 - - - - - - - -组织维度 -集团 -分公司 -票务室 / 车队 / 线路 - - -业务维度 -票库 / 票柜 / 票袋 -充值网点 -无人售线路 - - -数据维度 -单据、库存、流水 -报表汇总 -历史迁移数据 - - -审计维度 -登录日志 -操作日志 -导入导出日志 - - - - - 北京公交集团票务综合管理平台系统升级 | SDD(Spec-Driven Development,规范驱动开发)实施方案配套设计图 - - - diff --git a/outputs/北京公交票务评估/svg设计图/05-SDD协同交付流程图.svg b/outputs/北京公交票务评估/svg设计图/05-SDD协同交付流程图.svg deleted file mode 100644 index a3186680..00000000 --- a/outputs/北京公交票务评估/svg设计图/05-SDD协同交付流程图.svg +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - SDD 协同交付流程图 - 把大系统拆成可验证的小任务,形成需求、编码、测试、评审、交付闭环 - - - - -1. 需求卡片化 -按页面/动作拆分 -角色、输入、输出 -验收标准 - - -2. 领域建模 -状态机、票号段 -库存流水、报表口径 -人工确认 - - -3. 任务生成 -表结构、接口 -页面、测试 -小批量执行 - - -4. 编码实现 -前后端协同 -导入导出 -权限与日志 - - - - - - -8. 模块验收 -业务演示 -样例数据核对 -问题闭环 - - -7. 人工评审 -核心规则 review -安全与权限检查 -SQL 与事务检查 - - -6. 自动化测试 -单元 / 接口 -场景 / 回归 -构建检查 - - -5. 本地自测 -页面联调 -异常分支 -导入导出校验 - - - - - - - 交付原则 - 小任务、强测试、人工把关、持续演示;常规功能提效,核心规则不省评审。 - - - 北京公交集团票务综合管理平台系统升级 | SDD(Spec-Driven Development,规范驱动开发)实施方案配套设计图 - - - diff --git a/outputs/北京公交票务评估/svg设计图/06-数据湖与外部系统对接架构图.svg b/outputs/北京公交票务评估/svg设计图/06-数据湖与外部系统对接架构图.svg deleted file mode 100644 index abbecb3f..00000000 --- a/outputs/北京公交票务评估/svg设计图/06-数据湖与外部系统对接架构图.svg +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - 数据湖与外部系统对接架构图 - 明确票务系统向数据湖、二维码、胆款、IC卡和银行清分场景的数据供给边界 - - - 票务系统数据源 - - -业务库 -单据、库存、流水 -结算、退票、充值 - - -报表汇总库 -日结、月结、趋势 -集团 / 分公司 / 票务室 - - -文件与附件 -导入文件 -导出报表、签章文件 - - 数据服务与交换层 - - -数据目录 -数据集清单 -字段字典 -版本管理 - - -接口服务 -REST / 批量文件 -鉴权、限流、加密 - - -同步任务 -全量 / 增量 -重试、补偿、对账 - - -接口审计 -调用日志 -失败告警 -手工补传 - - - - - - - - - 外部消费与对接对象 - - -数据湖 -统一取数 -数据质量校验 - - -二维码系统 -是否保留供数 -历史数据确认 - - -胆款系统 -清分日报同步 -对账与补偿 - - -IC卡系统 -主数据同步 -增量补偿 - - -银行清分 -线下文件导入 -异常明细 - - -电子签章 -状态预留 -签章归档 - - - - - - - - - 北京公交集团票务综合管理平台系统升级 | SDD(Spec-Driven Development,规范驱动开发)实施方案配套设计图 - - - diff --git a/outputs/北京公交票务评估/svg设计图/07-系统功能地图.svg b/outputs/北京公交票务评估/svg设计图/07-系统功能地图.svg deleted file mode 100644 index aed0b3ee..00000000 --- a/outputs/北京公交票务评估/svg设计图/07-系统功能地图.svg +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - 系统功能地图 - 按集团、分公司、票务室三级用户视角展示业务入口和能力分布 - - - 集团视角 - - -集团管理 -用户、权限、菜单 -阈值、日志、配置 - - -集团审批 -印制、调拨、核销 -调账审核 - - -集团报表 -存售、收入、清分 -趋势、月报 - - -数据服务 -数据湖、二维码 -接口审计 - - 分公司视角 - - -基础资料 -票务室、线路 -车辆、司售、票价 - - -票库票柜 -印制、调拨、核销 -配票申请、调票 - - -充值与特殊 -IC卡库存、售出 -异物、大额币、残币 - - -分公司报表 -日报、月报 -收入核对、导出 - - 票务室视角 - - -票柜库存 -入库、出库 -库存查询 - - -票袋票单 -票袋、配票 -结算、重新结算 - - -退票打印 -票袋/票柜退票 -配票单、结算单 - - -票务室报表 -日结、存售 -交班、银行登记 - - - - 共用能力 - 消息中心 - 阈值预警 - Excel 导入导出 - 打印模板 - 操作审计 - 数据权限 - 外部接口 - 备份恢复 - - - - - 北京公交集团票务综合管理平台系统升级 | SDD(Spec-Driven Development,规范驱动开发)实施方案配套设计图 - - - diff --git a/outputs/北京公交票务评估/svg设计图/README.md b/outputs/北京公交票务评估/svg设计图/README.md deleted file mode 100644 index bff0edb0..00000000 --- a/outputs/北京公交票务评估/svg设计图/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# SVG 设计图清单 - -- 01-总体技术架构图.svg -- 02-核心票务业务流转图.svg -- 03-部署与可运维性架构图.svg -- 04-权限与数据范围设计图.svg -- 05-SDD协同交付流程图.svg -- 06-数据湖与外部系统对接架构图.svg -- 07-系统功能地图.svg \ No newline at end of file diff --git a/outputs/北京公交票务评估/svg设计图/png预览/01-总体技术架构图.png b/outputs/北京公交票务评估/svg设计图/png预览/01-总体技术架构图.png deleted file mode 100644 index e9a34085..00000000 Binary files a/outputs/北京公交票务评估/svg设计图/png预览/01-总体技术架构图.png and /dev/null differ diff --git a/outputs/北京公交票务评估/svg设计图/png预览/02-核心票务业务流转图.png b/outputs/北京公交票务评估/svg设计图/png预览/02-核心票务业务流转图.png deleted file mode 100644 index 1d5c3cd4..00000000 Binary files a/outputs/北京公交票务评估/svg设计图/png预览/02-核心票务业务流转图.png and /dev/null differ diff --git a/outputs/北京公交票务评估/svg设计图/png预览/03-部署与可运维性架构图.png b/outputs/北京公交票务评估/svg设计图/png预览/03-部署与可运维性架构图.png deleted file mode 100644 index fa87f739..00000000 Binary files a/outputs/北京公交票务评估/svg设计图/png预览/03-部署与可运维性架构图.png and /dev/null differ diff --git a/outputs/北京公交票务评估/svg设计图/png预览/04-权限与数据范围设计图.png b/outputs/北京公交票务评估/svg设计图/png预览/04-权限与数据范围设计图.png deleted file mode 100644 index 0ea9741f..00000000 Binary files a/outputs/北京公交票务评估/svg设计图/png预览/04-权限与数据范围设计图.png and /dev/null differ diff --git a/outputs/北京公交票务评估/svg设计图/png预览/05-SDD协同交付流程图.png b/outputs/北京公交票务评估/svg设计图/png预览/05-SDD协同交付流程图.png deleted file mode 100644 index 9d51fd03..00000000 Binary files a/outputs/北京公交票务评估/svg设计图/png预览/05-SDD协同交付流程图.png and /dev/null differ diff --git a/outputs/北京公交票务评估/svg设计图/png预览/06-数据湖与外部系统对接架构图.png b/outputs/北京公交票务评估/svg设计图/png预览/06-数据湖与外部系统对接架构图.png deleted file mode 100644 index dbae241b..00000000 Binary files a/outputs/北京公交票务评估/svg设计图/png预览/06-数据湖与外部系统对接架构图.png and /dev/null differ diff --git a/outputs/北京公交票务评估/svg设计图/png预览/07-系统功能地图.png b/outputs/北京公交票务评估/svg设计图/png预览/07-系统功能地图.png deleted file mode 100644 index 33d417d6..00000000 Binary files a/outputs/北京公交票务评估/svg设计图/png预览/07-系统功能地图.png and /dev/null differ diff --git a/outputs/北京公交票务评估/svg设计图/quicklook/01-总体技术架构图.svg.png b/outputs/北京公交票务评估/svg设计图/quicklook/01-总体技术架构图.svg.png deleted file mode 100644 index 15fa48c5..00000000 Binary files a/outputs/北京公交票务评估/svg设计图/quicklook/01-总体技术架构图.svg.png and /dev/null differ diff --git a/outputs/北京公交票务评估/北京公交票务平台功能开发清单.xlsx b/outputs/北京公交票务评估/北京公交票务平台功能开发清单.xlsx deleted file mode 100644 index b39ae364..00000000 Binary files a/outputs/北京公交票务评估/北京公交票务平台功能开发清单.xlsx and /dev/null differ diff --git a/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单-含设计图.docx b/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单-含设计图.docx deleted file mode 100644 index 05bad298..00000000 Binary files a/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单-含设计图.docx and /dev/null differ diff --git a/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单.docx b/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单.docx deleted file mode 100644 index 144da954..00000000 Binary files a/outputs/北京公交票务评估/北京公交集团票务综合管理平台系统升级-SDD实施方案与工作量清单.docx and /dev/null differ