from pathlib import Path from zipfile import ZipFile, ZIP_DEFLATED import html OUT = Path("docs/供应监测评分卡QA质量评分机制_两页汇报_修正版.pptx") OUT.parent.mkdir(parents=True, exist_ok=True) def esc(value): return html.escape(str(value), quote=True) shape_id = 10 def next_id(): global shape_id shape_id += 1 return shape_id def text_box(x, y, cx, cy, text, size=1800, bold=False, color="1F2937"): sid = next_id() runs = [] for line in text.split("\n"): b = ' b="1"' if bold else "" runs.append( f'' f'' f'' f"{esc(line)}" ) return ( f'' f'' f'' f'' f'' f"{''.join(runs)}" ) def rect(x, y, cx, cy, fill="FFFFFF", line="D9E2F1", rounded=True): sid = next_id() prst = "roundRect" if rounded else "rect" return ( f'' f"" f'' f'' f'' f'' f"" ) def card(x, y, cx, cy, title, body, accent="2563EB"): return ( rect(x, y, cx, cy) + text_box(x + 180000, y + 130000, cx - 360000, 230000, title, 1500, True, accent) + text_box(x + 180000, y + 420000, cx - 360000, cy - 520000, body, 1120, False, "475569") ) def slide(title, subtitle, shapes): return f''' {rect(0, 0, 12192000, 760000, "1F4E79", "1F4E79", False)} {text_box(520000, 170000, 9500000, 340000, title, 2300, True, "FFFFFF")} {text_box(520000, 545000, 9800000, 200000, subtitle, 1050, False, "DBEAFE")} {shapes} ''' slide1_shapes = "" slide1_shapes += card( 520000, 1060000, 3500000, 1700000, "数据可以接入", "QA 表包含供应商、商品编码、验货日期、来货数量、抽检个数、不合格个数、大批次品和问题描述,可支撑供应商质量维度统计。", ) slide1_shapes += card( 4300000, 1060000, 3500000, 1700000, "核心计算口径", "抽检总数 = SUM(抽检/个数)\n不合格总数 = SUM(不合格/个 + 大批次品)\nQA合格率 = 合格数 / 抽检总数", "059669", ) slide1_shapes += card( 8080000, 1060000, 3500000, 1700000, "供应商匹配", "QA 表常用简称,如“顾舒家华”。系统供应商可能是公司全称。采用包含关系匹配:全称包含简称即可归属。", "7C3AED", ) slide1_shapes += rect(520000, 3200000, 11150000, 2500000) slide1_shapes += text_box(820000, 3430000, 10300000, 260000, "落地数据流", 1600, True, "1F4E79") slide1_shapes += text_box( 850000, 3920000, 10200000, 850000, "QA Excel 多月份 Sheet → 读取所有月份 → 按供应商汇总抽检/不合格 → 宽松匹配供应商评分卡 → 输出 QA合格率、质量分、不合格数", 1400, False, "334155", ) slide1_shapes += text_box( 850000, 5030000, 10200000, 450000, "无 QA 数据的供应商:QA合格率显示“暂无”,质量分按 80 分中性值处理,避免误伤。", 1250, False, "64748B", ) slide2_shapes = "" slide2_shapes += rect(520000, 1040000, 11150000, 1200000) slide2_shapes += text_box(850000, 1260000, 10200000, 280000, "综合评分新权重", 1750, True, "1F4E79") slide2_shapes += text_box( 850000, 1680000, 10200000, 360000, "综合分 = 成本分 × 30% + 交付分 × 30% + 账期分 × 15% + 质量分 × 25%", 1550, True, "2563EB", ) slide2_shapes += card(520000, 2550000, 2550000, 1900000, "页面新增字段", "质量分\nQA合格率\n不合格数\n可扩展:QA抽检数、QA来货数") slide2_shapes += card(3370000, 2550000, 2550000, 1900000, "质量预警规则", "QA抽检数 > 0\n且 QA合格率 < 95%\n则标记:质量预警", "DC2626") slide2_shapes += card(6220000, 2550000, 2550000, 1900000, "业务价值", "识别低价但质量不稳的供应商\n避免评分只被成本和交付主导\n支持整改、淘汰、谈判", "059669") slide2_shapes += card(9070000, 2550000, 2550000, 1900000, "后续建议", "将 QA Excel 入库\n建立质量检验明细表\n扩展质量趋势和问题类型分析", "7C3AED") slide2_shapes += rect(520000, 5050000, 11150000, 850000, "EFF6FF", "BFDBFE") slide2_shapes += text_box( 820000, 5290000, 10500000, 300000, "结论:QA 数据可以纳入供应监测评分卡,推荐以 QA 合格率形成质量分,并作为 25% 权重参与综合评分。", 1350, True, "1E3A8A", ) slide1 = slide("供应监测评分卡新增 QA 质量维度", "数据来源与计算逻辑", slide1_shapes) slide2 = slide("评分机制与页面落地", "新增质量分、QA合格率与质量预警", slide2_shapes) content_types = ''' ''' rels = ''' ''' pres = ''' ''' pres_rels = ''' ''' empty_rels = ''' ''' with ZipFile(OUT, "w", ZIP_DEFLATED) as z: z.writestr("[Content_Types].xml", content_types.encode("utf-8")) z.writestr("_rels/.rels", rels.encode("utf-8")) z.writestr("ppt/presentation.xml", pres.encode("utf-8")) z.writestr("ppt/_rels/presentation.xml.rels", pres_rels.encode("utf-8")) z.writestr("ppt/slides/slide1.xml", slide1.encode("utf-8")) z.writestr("ppt/slides/slide2.xml", slide2.encode("utf-8")) z.writestr("ppt/slides/_rels/slide1.xml.rels", empty_rels.encode("utf-8")) z.writestr("ppt/slides/_rels/slide2.xml.rels", empty_rels.encode("utf-8")) print(OUT.resolve())