Files
people/.workbuddy/add_dimension_page.py
2026-09-14 11:25:42 +08:00

165 lines
5.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""在当前 PPT 业绩章节开头插入「科技创新类六大评审维度」总览页"""
import copy
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
F = r"E:\SynologyDrive1\project\2026-06-09 长沙市紧缺急需人才项目申报\紧缺急需-陈越-2026-9-11.pptx"
MAIN = RGBColor(0x40, 0xE0, 0xD0)
DARK = RGBColor(0x33, 0x33, 0x33)
GREY = RGBColor(0x55, 0x55, 0x55)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
TEAL = RGBColor(0x00, 0x8B, 0x8B)
FONT = "Noto Sans SC"
def set_text(shape, text, size, color, bold=False, align=PP_ALIGN.LEFT):
tf = shape.text_frame
tf.word_wrap = True
p = tf.paragraphs[0]
runs = p.runs
if runs:
runs[0].text = text
for r in runs[1:]:
r.text = ""
runs[0].font.size = Pt(size)
runs[0].font.color.rgb = color
runs[0].font.bold = bold
runs[0].font.name = FONT
else:
r = p.add_run()
r.text = text
r.font.size = Pt(size)
r.font.color.rgb = color
r.font.bold = bold
r.font.name = FONT
p.alignment = align
def card(slide, x, y, w, h, line_color=MAIN):
sh = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h))
sh.fill.solid()
sh.fill.fore_color.rgb = WHITE
sh.line.color.rgb = line_color
sh.line.width = Pt(1.25)
sh.shadow.inherit = False
try:
sh.adjustments[0] = 0.08
except Exception:
pass
sh.text_frame.text = ""
return sh
def chip(slide, x, y, w, h, text, fill=MAIN, color=WHITE, size=12):
sh = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h))
sh.fill.solid()
sh.fill.fore_color.rgb = fill
sh.line.fill.background()
sh.shadow.inherit = False
try:
sh.adjustments[0] = 0.5
except Exception:
pass
tf = sh.text_frame
tf.word_wrap = False
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p = tf.paragraphs[0]
p.alignment = PP_ALIGN.CENTER
r = p.add_run()
r.text = text
r.font.name = FONT
r.font.size = Pt(size)
r.font.bold = True
r.font.color.rgb = color
return sh
def textbox(slide, x, y, w, h, text, size=11, color=GREY, bold=False, line=1.25):
box = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = box.text_frame
tf.word_wrap = True
tf.margin_left = 0
tf.margin_right = 0
tf.margin_top = 0
tf.margin_bottom = 0
p = tf.paragraphs[0]
p.alignment = PP_ALIGN.LEFT
p.line_spacing = line
r = p.add_run()
r.text = text
r.font.name = FONT
r.font.size = Pt(size)
r.font.bold = bold
r.font.color.rgb = color
return box
def add_slide_like(prs, template, title):
new = prs.slides.add_slide(template.slide_layout)
for ph in list(new.placeholders):
ph.element.getparent().remove(ph.element)
sp_tree = new.shapes._spTree
for shp in list(template.shapes)[:2]:
sp_tree.insert_element_before(copy.deepcopy(shp.element), "p:extLst")
set_text(new.shapes[1], title, 32, DARK, bold=True)
return new
def move_slide(prs, old_index, new_index):
lst = prs.slides._sldIdLst
items = list(lst)
lst.remove(items[old_index])
lst.insert(new_index, items[old_index])
def main():
prs = Presentation(F)
tpl = prs.slides[4] # P5 两项目概览页
dims = [
("个人资质", "湖南大学应用物理学本科 · 17 年激光控制研发 · 总工程师、省工程中心副主任 · 第一/主要发明人 2 项发明专利"),
("研究方向产业契合度", "激光控制 ↔ 长沙“智能建造”产业链 · 湘江新区激光装备集群 · 高端激光控制国产替代、对标德国 ScanLab"),
("科研成果水平", "2 项省级重点攻关项目 · 多轴同步 ≤1ms · 轮廓精度 ≤0.03mm · 15μm 级高精度拼接"),
("成果转化与团队能力", "成果落地大族激光等行业龙头 · 国内最大消费级激光控制方案供应商 · 团队 117 人、年研发投入 1798 万"),
("发展潜力与平台支撑", "湖南省激光控制系统工程中心 · 国防科大技术背景 · 3D 打印市场 630 亿(2030)"),
("未来三年规划", "标准筑基 → 消费落地 → 芯片自主(EtherCAT / ESP32 / MCU+FPGA)· 开放 API/SDK · AI 就绪"),
]
s = add_slide_like(prs, tpl, "02 业绩贡献 - 科技创新类评审维度")
cw, ch = 3.77, 2.42
x0, y0 = 0.8, 1.55
for i, (name, desc) in enumerate(dims):
col, row = i % 3, i // 3
x = x0 + col * (cw + 0.2)
y = y0 + row * (ch + 0.12)
card(s, x, y, cw, ch)
chip(s, x + 0.22, y + 0.2, 0.42, 0.42, str(i + 1), fill=MAIN, size=13)
textbox(s, x + 0.78, y + 0.24, 2.8, 0.38, name, size=14, color=DARK, bold=True)
textbox(s, x + 0.24, y + 0.78, cw - 0.48, ch - 0.95, desc, size=10.5, color=GREY, line=1.3)
# 移到 index 4(原 P5 之前)
move_slide(prs, len(prs.slides._sldIdLst) - 1, 4)
prs.save(F)
print("已保存,总页数:", len(prs.slides._sldIdLst))
# 校验
prs2 = Presentation(F)
for i, sl in enumerate(prs2.slides, 1):
txt = []
for sh in sl.shapes:
if sh.has_text_frame:
t = " ".join(p.text for p in sh.text_frame.paragraphs).strip()
if t:
txt.append(t)
print(f"P{i}: " + " | ".join(txt)[:70])
if __name__ == "__main__":
main()