# 修改人:Ld 修改时间:2026-08-12 14:53:07; 生成生产计划组件补充需求方案 Word 文档。 from docx import Document from docx.enum.section import WD_SECTION from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT, 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 Cm, Inches, Pt, RGBColor OUT = r"D:\景耀\JY1.0\docs\生产计划组件补充需求方案.docx" def set_cell_shading(cell, fill): 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_text(cell, text, bold=False, color=None): cell.text = "" p = cell.paragraphs[0] p.paragraph_format.space_after = Pt(0) run = p.add_run(text) run.bold = bold run.font.name = "Microsoft YaHei" run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") run.font.size = Pt(9.5) if color: run.font.color.rgb = RGBColor.from_string(color) cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER def set_table_width(table, widths_cm): table.autofit = False table.alignment = WD_TABLE_ALIGNMENT.CENTER for row in table.rows: for idx, width in enumerate(widths_cm): row.cells[idx].width = Cm(width) def add_table(doc, headers, rows, widths_cm): table = doc.add_table(rows=1, cols=len(headers)) table.style = "Table Grid" set_table_width(table, widths_cm) for idx, header in enumerate(headers): set_cell_text(table.rows[0].cells[idx], header, bold=True, color="0B2545") set_cell_shading(table.rows[0].cells[idx], "F2F4F7") for row in rows: cells = table.add_row().cells for idx, value in enumerate(row): set_cell_text(cells[idx], str(value)) doc.add_paragraph() return table def add_flow(doc, title, steps): doc.add_heading(title, level=3) table = doc.add_table(rows=1, cols=len(steps)) table.style = "Table Grid" table.alignment = WD_TABLE_ALIGNMENT.CENTER width = 16.0 / len(steps) set_table_width(table, [width] * len(steps)) for idx, step in enumerate(steps): cell = table.rows[0].cells[idx] set_cell_text(cell, step, bold=True) set_cell_shading(cell, "E8EEF5" if idx % 2 == 0 else "F4F6F9") p = doc.add_paragraph() p.paragraph_format.space_after = Pt(4) def add_bullet(doc, text): p = doc.add_paragraph(style="List Bullet") p.paragraph_format.space_after = Pt(3) run = p.add_run(text) run.font.name = "Microsoft YaHei" run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") run.font.size = Pt(10.5) def add_para(doc, text, bold_prefix=None): p = doc.add_paragraph() p.paragraph_format.space_after = Pt(6) if bold_prefix and text.startswith(bold_prefix): run = p.add_run(bold_prefix) run.bold = True run.font.name = "Microsoft YaHei" run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") run.font.size = Pt(10.5) text = text[len(bold_prefix):] run = p.add_run(text) run.font.name = "Microsoft YaHei" run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") run.font.size = Pt(10.5) def build(): doc = Document() section = doc.sections[0] section.top_margin = Inches(0.85) section.bottom_margin = Inches(0.85) section.left_margin = Inches(0.85) section.right_margin = Inches(0.85) styles = doc.styles normal = styles["Normal"] normal.font.name = "Microsoft YaHei" normal._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") normal.font.size = Pt(10.5) normal.paragraph_format.line_spacing = 1.1 normal.paragraph_format.space_after = Pt(6) for style_name, size, color, before, after in [ ("Heading 1", 16, "2E74B5", 16, 8), ("Heading 2", 13, "2E74B5", 12, 6), ("Heading 3", 12, "1F4D78", 8, 4), ]: style = styles[style_name] style.font.name = "Microsoft YaHei" style._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") style.font.size = Pt(size) style.font.bold = True style.font.color.rgb = RGBColor.from_string(color) style.paragraph_format.space_before = Pt(before) style.paragraph_format.space_after = Pt(after) title = doc.add_paragraph() title.alignment = WD_ALIGN_PARAGRAPH.CENTER title.paragraph_format.space_after = Pt(8) run = title.add_run("生产计划组件补充需求方案") run.bold = True run.font.name = "Microsoft YaHei" run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") run.font.size = Pt(22) run.font.color.rgb = RGBColor.from_string("0B2545") subtitle = doc.add_paragraph() subtitle.alignment = WD_ALIGN_PARAGRAPH.CENTER subtitle.paragraph_format.space_after = Pt(14) run = subtitle.add_run("周计划、设备小时级计划、销售合同计划、设备门牌看板") run.font.name = "Microsoft YaHei" run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") run.font.size = Pt(11) run.font.color.rgb = RGBColor.from_string("555555") add_para(doc, "本次先做方案,不修改业务页面和数据库过程。围绕生产计划组件的四项补充需求,建议拆成三个前端能力和一组后端数据源。") for item in [ "生产计划支持“周计划”显示。", "点击设备查看后续工作时,模块时间显示到“小时/分钟”。", "在生产任务计划之外,增加“销售合同计划”视角。", "增加类似医院诊室门口屏幕的“设备当前生产/下一项生产”直观展示。", ]: add_bullet(doc, item) doc.add_heading("一、总体设计", level=1) add_para(doc, "建议新增一个“计划看板”入口,保留现有生产计划表格页作为明细查询和导出页面,在其上扩展三种视图。") add_table( doc, ["视图", "主要用途", "展示粒度", "用户动作"], [ ["月计划", "复用现有生产计划表格", "月", "查询、导出、打开可视化"], ["周计划", "查看本周投产、派工、交付压力", "周、天", "周次切换、按天筛选、查看明细"], ["设备门牌看板", "现场快速查看每台设备当前和下一项", "设备、当前任务、下一任务", "自动刷新、点击设备查看后续队列"], ["销售合同计划", "从合同交付节点倒推生产风险", "合同、订单、产品、计划节点", "查看合同进度、跳转生产计划/订单进度"], ], [3.0, 5.0, 3.8, 4.2], ) doc.add_heading("二、功能方案", level=1) doc.add_heading("2.1 周计划显示", level=2) add_para(doc, "现有生产计划页面已经按月份查询,建议周计划不新增单独页面,先在当前生产计划页面增加“视图模式”。") for item in [ "月计划:保持现有表格。", "周计划:按选中月份自动生成第 1 周到第 5/6 周。", "周计划筛选规则:按投产时间或精工期限两种口径切换,默认按投产时间。", "顶部显示本周计划数、生产中、已完成、逾期风险、完成率。", "中部按周一到周日分列,每列列出订单/零件卡片;底部保留明细表格,便于导出。", ]: add_bullet(doc, item) add_para(doc, "最小改造方案:继续调用现有 `车间生产管理_生产计划_查询数据`,前端按日期过滤并分组。") add_para(doc, "推荐方案:后端过程增加开始时间、结束时间参数,由 SQL Server 过滤,减少月份数据量过大时的前端压力。") doc.add_heading("2.2 设备后续工作时间显示到小时", level=2) add_para(doc, "现有生产计划页面点击设备后,会打开设备后续已派工任务弹窗,样式接近 APS 时间轴。建议增强为小时级展示。") for item in [ "显示字段从日期改为 yyyy-MM-dd HH:mm。", "时间轴横向粒度由“天”增强为“天 + 小时刻度”。", "任务卡片显示订单号/合同号、零件名称、图号、工序、操作者、设备、分配时间、预计完成时间、开始加工时间、完成时间。", "如果没有预计完成时间,则按分配时间 + 计划工时/设备能力计算临时结束时间,并标记为“估算”。", ]: add_bullet(doc, item) doc.add_heading("2.3 销售合同计划", level=2) add_para(doc, "销售合同计划不建议等同于生产任务计划。它应从“合同交付承诺”看“生产是否支撑交付”,核心不是设备排产,而是合同节点和生产状态对齐。") add_para(doc, "建议层级:销售合同 -> 订单 -> 产品/部件 -> 生产计划 -> 工艺/派工/完工。") add_table( doc, ["字段", "来源", "用途"], [ ["合同编号", "PDM_项目名称或合同信息相关视图", "合同主键展示"], ["客户/收货人", "客户关系或订单关联客户", "识别交付对象"], ["合同签订日期", "合同信息", "计划起点"], ["交货日期/精工期限", "订单或生产计划", "风险判断"], ["订单编号", "PDM_订单信息_视图、合同管理_订单信息_基础表", "关联生产"], ["产品名称", "PDM 产品/组件视图", "合同产品范围"], ["计划数量", "生产计划视图", "生产负荷"], ["完成率", "生产计划或工艺完工统计", "进度展示"], ["当前工序/设备", "工艺计划、派工数据", "当前进展"], ["风险状态", "计算字段", "正常、临期、逾期、无生产计划"], ], [3.0, 6.5, 6.5], ) add_table( doc, ["状态", "判断"], [ ["正常", "精工期限未到,生产进度匹配"], ["临期", "距交付日期小于等于 7 天且未完成"], ["逾期", "当前日期超过交付日期且未完成"], ["无计划", "合同/订单已存在但没有生产计划"], ["已完成", "生产计划全部完成"], ], [3.0, 13.0], ) doc.add_heading("2.4 设备门牌看板", level=2) add_para(doc, "“医院诊室门口样式”建议做成现场大屏/看板页面,不放在复杂表格里。页面以设备为单位,每台设备一张门牌卡,重点展示“正在生产什么、下一项生产什么”。") add_table( doc, ["模块", "展示内容"], [ ["设备抬头", "设备名称 / 工位号 / 状态灯"], ["正在生产", "订单号、零件名称、图号、工序、操作者、已用时/计划工时"], ["下一项", "订单号、零件名称、图号、工序、计划开始时间"], ["辅助信息", "后续队列数、更新时间、异常状态"], ], [3.0, 13.0], ) for item in [ "设备状态颜色复用现有设备监控状态:运行、等待、关机、报警、断网。", "当前任务优先取 MES 实时加工/工位零件接口。", "下一项任务取该设备未完成、未开始或已派工未加工的最早任务。", "看板自动刷新,建议 30 秒一次。", "点击卡片进入设备后续工作 APS 弹窗。", ]: add_bullet(doc, item) doc.add_heading("三、流程图", level=1) add_flow(doc, "3.1 周计划查询流程", ["进入生产计划", "选择月份", "生成周次", "选择周次/口径", "查询数据", "按日期过滤", "分组展示", "导出周计划"]) add_flow(doc, "3.2 设备后续工作流程", ["点击设备", "传入设备/工位", "查询后续派工", "补齐时间字段", "格式化到小时", "分组", "渲染 APS 轴"]) add_flow(doc, "3.3 销售合同计划流程", ["销售合同", "关联订单", "关联产品", "关联生产计划", "关联工艺派工", "计算风险", "合同计划看板", "跳转明细"]) add_flow(doc, "3.4 设备门牌看板流程", ["设备清单", "实时状态", "当前加工", "后续任务", "合并门牌数据", "当前任务", "下一任务", "自动刷新"]) doc.add_heading("四、数据源设计", level=1) doc.add_heading("4.1 已有前端页面和接口", level=2) add_table( doc, ["功能", "文件/接口", "说明"], [ ["生产计划", "src/views/SeikoWorkshop/ProductionPlan/index.vue", "当前生产计划主页面"], ["生产任务查询", "src/views/SeikoWorkshop/ProductionTaskQuery/index.vue", "生产任务、工艺、派工入口"], ["设备监控", "src/views/SeikoWorkshop/EquipmentMonitoringNew/index.vue;src/views/DeviceManagement/EquipmentStatusMonitoring/index.vue", "设备实时状态和设备跳转"], ["合同查询", "src/views/SalesManagement/ContractSearch/index.vue;src/views/SalesManagement/ContractSearchNew/index.vue", "销售合同信息"], ["订单进度", "src/views/SalesManagement/OrderProgress/index.vue", "销售订单进度展示"], ], [3.0, 8.0, 5.0], ) doc.add_heading("4.2 已有后端过程/视图", level=2) add_table( doc, ["数据用途", "已识别数据源"], [ ["生产计划主数据", "车间生产管理_生产计划_查询数据"], ["生产计划视图", "车间生产管理_生产计划_视图_新"], ["生产任务查询", "精工车间_生成任务_查询数据"], ["订单下拉", "生产任务查询_订单信息_列表_查询数据"], ["订单产品", "订单信息_产品信息_查询数据"], ["零件追溯工序", "车间生产管理工艺_追溯加工_查询工序"], ["设备当前零件", "MES_机加工MES_工位零件图号查询_设备监控"], ["设备待加工队列", "MES_机加工MES_待加工零件_查询_设备监控"], ["设备状态", "MES_机加工MES_设备数据采集_工位状态_查询_新;MES_机加工MES_设备状态查询_初始化"], ["合同/项目", "PDM_项目名称_全部_查询数据;合同信息管理_合同信息_查询_分页"], ["订单基础关联", "合同管理_订单信息_基础表;PDM_订单信息_视图"], ], [4.0, 12.0], ) doc.add_heading("4.3 建议新增后端接口", level=2) add_table( doc, ["接口", "name", "核心返回字段"], [ ["周计划查询", "车间生产管理_生产计划_周计划_查询数据", "周次、日期、状态、合同编号、订单号、投产时间、精工期限、完成率、当前设备、OP010~OP110"], ["设备小时级任务", "车间生产管理_设备后续任务_小时计划_查询数据", "设备名称、工位号、订单号、合同编号、工序、操作者、分配时间、开始加工、预计完成、完成时间、计划工时M"], ["销售合同计划", "销售管理_销售合同计划_查询数据", "合同编号、客户、交付日期、订单号、产品名称、计划数量、完成率、当前工序、当前设备、风险状态"], ["设备门牌看板", "车间生产管理_设备门牌看板_查询数据", "设备状态、当前任务、下一任务、后续队列数、更新时间"], ], [3.0, 6.0, 7.0], ) doc.add_heading("五、实施顺序", level=1) for item in [ "先做设备后续任务时间显示到小时,只改显示和查询字段,风险最低。", "做周计划前端视图,先复用月计划数据过滤,确认业务口径。", "做设备门牌看板,先复用设备监控和待加工队列接口,后续再合并成单接口。", "做销售合同计划,需要合同、订单、生产计划多源联查,建议最后做。", ]: add_bullet(doc, item) doc.add_heading("六、验收口径", level=1) add_table( doc, ["需求", "验收方式"], [ ["周计划", "选择月份和周次后,只显示该周对应计划;周一到周日分组正确"], ["设备后续小时", "点击设备后,分配时间、开始加工、预计完成、完成时间显示到小时分钟"], ["销售合同计划", "能按合同看到关联订单、生产完成率、风险状态,并能跳转明细"], ["设备门牌看板", "每台设备清楚显示当前任务、下一项任务、状态颜色和更新时间"], ], [4.0, 12.0], ) doc.add_heading("七、注意事项", level=1) for item in [ "周计划必须确认日期口径:按投产时间、精工期限,还是两者都支持。", "销售合同计划需要统一合同编号来源,优先使用已补充的关联合同编号,其次再使用订单备注/MK 关联逻辑。", "设备门牌看板若用于现场大屏,建议单独配置自动刷新间隔,避免频繁查询影响 MES 采集接口。", "所有新增接口仍按项目规范 POST 到 MESCommonBase.ashx,携带 UserID 和 ModularID。", ]: add_bullet(doc, item) doc.add_paragraph() p = doc.add_paragraph() p.alignment = WD_ALIGN_PARAGRAPH.RIGHT run = p.add_run("修改人:Ld 修改时间:2026-08-12 14:24:23;") run.font.name = "Microsoft YaHei" run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei") run.font.size = Pt(9) run.font.color.rgb = RGBColor.from_string("555555") doc.save(OUT) if __name__ == "__main__": build()