#!/usr/bin/env python3 """生成 U24-L2 转段剧本 Excel""" import openpyxl from openpyxl.styles import Font, Alignment, PatternFill, Border, Side wb = openpyxl.Workbook() ws = wb.active ws.title = "U24-L2_转" headers = ["类型", "剧情描述", "角色名", "编剧台词"] header_font = Font(bold=True, size=11) header_fill = PatternFill(start_color="D9E1F2", end_color="D9E1F2", fill_type="solid") thin_border = Border( left=Side(style="thin"), right=Side(style="thin"), top=Side(style="thin"), bottom=Side(style="thin"), ) for col, h in enumerate(headers, 1): cell = ws.cell(row=1, column=col, value=h) cell.font = header_font cell.fill = header_fill cell.alignment = Alignment(horizontal="center", vertical="center") cell.border = thin_border ws.column_dimensions["A"].width = 16 ws.column_dimensions["B"].width = 60 ws.column_dimensions["C"].width = 16 ws.column_dimensions["D"].width = 50 # ⚠️ 对话互动仅首行标"中互动",User行类型留空 rows = [ # === #0: 看火 === ["TL", "【场景】Tom的厨房\n【角色】User、Mama Green、Sue、Jay、Lin", "", ""], ["", "Jay和Lin站在灶台前,盯着火焰,一动不动。表情异常严肃,如临大敌。", "", ""], ["", "【emoji】Jay云朵气泡", "Jay", "She said to watch the fire."], ["", "", "Lin", "There must be a deeper meaning."], ["", "两人对视,郑重地点头。火焰在锅里跳跃,他们继续凝视——眼睛都不眨。", "", ""], # === #1: 看傻了 === ["TL", "Sue和User在远处洗番茄,瞥见两人僵硬的背影。", "", ""], ["", "【emoji】Sue问号", "Sue", "What are they doing?"], ["", "【镜头】Jay和Lin背影——纹丝不动,如两尊石像。", "", ""], ["", "镜头切到油锅:油面开始冒细烟。两人浑然不觉。", "", ""], ["", "Lin掏出一支筷子在火焰上方比划,仿佛在测量某种未知能量。", "", ""], ["", "烟雾越来越浓,弥漫整个厨房。User和Sue开始咳嗽。", "", ""], # === #2: 着火 === ["TL", "【emoji】Sue惊讶", "Sue", "The fire!"], ["", "", "Sue", "It's **really** dangerous!"], ["", "Sue抓住User的胳膊,指向灶台旁挂着的锅盖。", "", ""], ["", "", "Sue", "The lid! Quick!"], ["中互动", "", "Sue", "Say it loud!"], ["", "", "User", "Use the lid!"], # === #3: Green灭火 + 吐槽 === ["TL", "Mama Green冲进厨房,一把抓起锅盖——", "", ""], ["", "啪!精准地盖住火焰。烟雾渐渐散去。", "", ""], ["", "她转头看着缩在角落的Jay和Lin,两人灰头土脸,头顶还飘着细烟。", "", ""], ["", "【emoji】Mama Green生气", "Mama Green", "The **kids** are calmer and braver than you!"], ["", "Mama Green指了指User和Sue。", "", ""], ["", "【emoji】Jay流汗", "", ""], ["", "【emoji】Lin流汗", "", ""], ["", "Jay和Lin缩着脖子,一声不敢吭。", "", ""], # === #4: Tony带人冲入 === ["TL", "【音效】急促的脚步声。", "", ""], ["", "Tony推开门,Ben、May、Vicky跟在后面。", "", ""], ["", "【emoji】Tony惊讶", "Tony", "What happened?!"], ["", "Ben、May、Vicky看着满屋烟雾,目瞪口呆。", "", ""], ["", "", "May", "The **kitchen** is full of smoke!"], ["", "Sue站出来,拍拍User的肩膀。", "", ""], ["", "", "Sue", "You tell them everything!"], # === #5: 核心互动·写作 === ["核心互动-写作", "【插入图】厨房场景大图:灶台、油锅(已盖上盖)、Jay和Lin缩在角落灰头土脸、Mama Green双手叉腰、Sue和User站在一旁。" "\n请User在下方句子中填入正确的单词,补全事件描述。", "", ""], ["", "第1处 — 第一句填空:\"Smoke in the ___.\"\n" "配图提示:厨房冒烟的镜头特写。待拼写单词:**kitchen**", "", ""], ["", "第2处 — 第二句填空:\"It was ___ dangerous.\"\n" "配图提示:火焰在锅中跳跃的特写。待拼写单词:**really**", "", ""], ["", "第3处 — 第三句填空:\"A ___ helped!\"\n" "配图提示:Sue和User一起指向锅盖。待拼写单词:**kid**", "", ""], # === #6: 认错 + kid #3 === ["TL", "Ben拿起抹布擦台面,May和Vicky捡起地上的碎蛋壳,User和Sue也在帮忙。", "", ""], ["", "Jay和Lin站在一旁,低着头。众人收拾的画面在他们面前展开。", "", ""], ["", "【emoji】Jay黑线", "Jay", "...Kids can do **many** things."], ["", "【emoji】Lin黑线", "Lin", "More than us."], ["", "Mama Green拍了拍手上的灰,嘴角微扬,转头看着User。", "", ""], ["", "", "Mama Green", "Who helped me today?"], ["中互动", "", "Sue", "Go on."], ["", "", "User", "A **kid** can help!"], # === #7: 收尾·合段钩子 === ["TL", "厨房终于恢复整洁。Mama Green重新起锅,火焰稳定。", "", ""], ["", "大家围在灶台前,汉堡的香味开始飘散。", "", ""], ["", "突然——【音效】啪的一声,灯灭了。厨房陷入一片黑暗。", "", ""], ["", "黑暗中传来一声闷响,有人撞到了身后的矮柜。", "", ""], ["", "矮柜移开了一条缝——一道微弱的光从柜子后面漏出来。", "", ""], ["", "【插入图】矮柜后微光", "", ""], ["", "【emoji】User感叹号", "", ""], ] wrap = Alignment(wrap_text=True, vertical="top") for i, row_data in enumerate(rows): for j, val in enumerate(row_data): cell = ws.cell(row=i + 2, column=j + 1, value=val) cell.alignment = wrap cell.border = thin_border if j == 0 and val: cell.alignment = Alignment(horizontal="center", vertical="top") if "中互动" in val: cell.font = Font(bold=True, color="0070C0") elif "核心互动" in val: cell.font = Font(bold=True, color="C00000") elif val == "TL": cell.font = Font(bold=True, color="404040") # 统计 stat_row = len(rows) + 3 ws.cell(row=stat_row, column=1, value="统计").font = Font(bold=True, size=12) tl_count = sum(1 for r in rows if r[0] == "TL") mid_count = sum(1 for r in rows if r[0] == "中互动") core_count = sum(1 for r in rows if r[0].startswith("核心互动")) ws.cell(row=stat_row + 1, column=1, value="总行数").font = Font(bold=True) ws.cell(row=stat_row + 1, column=2, value=len(rows)) ws.cell(row=stat_row + 2, column=1, value="TL").font = Font(bold=True) ws.cell(row=stat_row + 2, column=2, value=tl_count) ws.cell(row=stat_row + 3, column=1, value="中互动").font = Font(bold=True) ws.cell(row=stat_row + 3, column=2, value=mid_count) ws.cell(row=stat_row + 4, column=1, value="核心互动").font = Font(bold=True) ws.cell(row=stat_row + 4, column=2, value=core_count) # 知识点 ws.cell(row=stat_row + 6, column=1, value="知识点覆盖").font = Font(bold=True, size=12) kps = [ ["kitchen", "May输入 \"The kitchen is full of smoke!\" + 核心互动写作"], ["kid(s)", "#3 kid #3 中互动输出 \"A kid can help!\" + 核心互动写作"], ["many", "Jay输入 \"Kids can do many things.\""], ["really", "Sue输入 \"It's really dangerous!\" + 核心互动写作"], ["There are many...", "核心互动可覆盖(写作填空可关联此句型)"], ["It's really...", "Sue回归 \"It's really dangerous!\""], ] for i, kp in enumerate(kps): for j, val in enumerate(kp): ws.cell(row=stat_row + 7 + i, column=j + 1, value=val) out = "/root/.openclaw/workspace-xiaobian/output/U24-L2_转_剧本.xlsx" wb.save(out) print(f"✅ {out}") print(f" 总行数: {len(rows)} TL: {tl_count} 中互动: {mid_count} 核心互动: {core_count}")