fix:实现园长签名页面

This commit is contained in:
2026-01-25 23:50:40 +08:00
parent 016e392524
commit 60a78ed1e3
3 changed files with 232 additions and 3 deletions

View File

@@ -1,7 +1,7 @@
from nicegui import ui
from config.config import load_config
from ui.core.state import app_state
from ui.core.task_runner import run_task
from ui.core.task_runner import run_task, select_folder
# 导入业务函数
from utils.generate_utils import (
@@ -10,7 +10,6 @@ from utils.generate_utils import (
generate_convert_pdf,
generate_report,
generate_zodiac,
generate_signature,
)
from utils.file_utils import open_folder
@@ -71,7 +70,18 @@ def create_home_page():
func_btn("📊 生成报告 (PPT)", generate_report)
func_btn("📑 格式转换 (PDF)", generate_convert_pdf)
func_btn("🐂 生肖转化 (生日)", generate_zodiac)
func_btn("💴 园长一键签名", generate_signature)
# 签名按钮
async def on_signature_click():
selected_folder = await select_folder()
if selected_folder:
ui.navigate.to(f"/signature?folder={selected_folder}")
else:
ui.notify("未选择目录", type="warning")
ui.button("💴 园长签名", on_click=on_signature_click).props(
f"outline"
).classes("w-full")
# === 下方双栏布局 ===
# 数据管理

213
ui/views/signature_page.py Normal file
View File

@@ -0,0 +1,213 @@
from nicegui import ui
import os
from config.config import load_config
from utils.file_utils import open_folder
from loguru import logger
import traceback
from pptx import Presentation
def create_signature_page(folder: str = ""):
ui.add_head_html('<link href="/assets/style.css" rel="stylesheet" />')
# 添加样式
ui.add_head_html(
"""
<style>
.file-list { max-height: 450px; overflow-y: auto; }
.file-list::-webkit-scrollbar {
width: 6px;
}
.file-list::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.file-list::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.file-list::-webkit-scrollbar-thumb:hover {
background: #a1a1a1;
}
.file-item { transition: background-color 0.2s ease; }
.file-item:hover { background-color: #f8f9fa; }
</style>
"""
)
with ui.header().classes("app-header items-center justify-between shadow-md"):
# 左侧:图标和标题
with ui.row().classes("items-center gap-2"):
ui.image("/assets/icon.ico").classes("w-8 h-8").props("fit=contain")
ui.label("尚城幼儿园成长报告助手").classes("text-xl font-bold")
# 右侧:署名 + 配置按钮
with ui.row().classes("items-center gap-4"):
ui.label("By 寒寒 | 这里的每一份评语都充满爱意").classes(
"text-xs opacity-90"
)
ui.button(icon="home", on_click=lambda: ui.navigate.to("/")).props(
"flat round color=white"
)
with ui.card().classes("w-full"):
ui.label("💴 园长签名").classes("section-title")
with ui.row().classes("w-full items-center justify-between"):
with ui.row().classes("flex-1 items-center"):
ui.label("📁 当前目录:").classes(
"text-sm text-white border bg-[#2e8b57] p-2 rounded"
)
ui.label(f"{folder}").classes("text-sm text-gray-600")
with ui.row().classes("items-center"):
ui.button(
"💴 一键签名",
on_click=lambda: sign_all_files(folder),
).props().classes()
ui.button(
"📂 打开文件夹",
on_click=lambda: open_folder(folder),
).props("outline").classes()
ui.button(
"🔄 刷新数据",
on_click=lambda: for_file_list(list_card, folder),
).props("outline").classes()
list_card = ui.card().classes("w-full p-4 gap-4")
for_file_list(list_card, folder)
# 遍历目录
def for_file_list(list_card, folder):
# 清空旧内容
list_card.clear()
files = get_signature_files(folder)
with list_card:
ui.label(f"📄 找到 {len(files)} 个 PPT 文件").classes(
"text-sm text-gray-600 mb-4"
)
# 存储选中的文件
selected_files = []
def toggle_file(file_name):
if file_name in selected_files:
selected_files.remove(file_name)
else:
selected_files.append(file_name)
# 创建可滚动的文件列表
with ui.grid(columns=2).classes("file-list"):
for ppt_file in files:
with ui.row().classes(
"w-full justify-between items-center file-item p-3 rounded mb-2"
):
with ui.row().classes("flex-1 items-center"):
ui.checkbox(
on_change=lambda e, f=ppt_file: toggle_file(f)
).classes("mr-3")
ui.label(ppt_file).classes("flex-1 text-sm")
with ui.row().classes("items-center gap-2"):
# 打开文件按钮
ui.button(
"📂 打开",
on_click=lambda f=ppt_file: open_folder(
os.path.join(folder, f)
),
).props("outline").classes("text-xs")
# 签名按钮
ui.button(
"💴 签名",
on_click=lambda f=ppt_file: (
sign_file(folder, f),
ui.notify(f"签名完成: {f}", type="positive"),
),
).props("outline").classes("text-xs")
def get_signature_files(folder: str) -> list:
"""获取目录下所有 PPT 文件"""
if not os.path.exists(folder):
return []
files = []
for filename in os.listdir(folder):
if not filename.startswith(".") and filename.endswith(".pptx"):
files.append(filename)
return sorted(files)
def sign_file(folder, file_name: str):
"""
生成园长签名(不依赖占位符,直接在指定位置添加)
:param folder: PPT 文件所在目录
:param file_name: PPT 文件名称
"""
try:
# 1. 加载配置文件
config = load_config("config.toml")
except Exception as e:
logger.error(f"配置文件获取失败: {str(e)}")
# 打印详细报错位置,方便调试
logger.error(traceback.format_exc())
try:
# 2. 等待签名文件路径
file_path = os.path.join(folder, file_name)
logger.info(f"开始生成签名,PPT文件:{file_name}")
# 加载签名图片路径
img_path = config.get("signature_image")
if not img_path or not os.path.exists(img_path):
logger.error(f"签名图片不存在: {img_path}")
logger.warning(f"⚠️ 警告: 缺少签名照片('signature'")
return
logger.info(f"签名图片存在: {img_path}")
# 从配置文件获取签名位置信息,如果没有则使用默认值
signature_left = config.get("signature_left", 2987040) # 左位置
signature_top = config.get("signature_top", 8273415) # 上位置
signature_width = config.get("signature_width", 1800000) # 宽度
signature_height = config.get("signature_height", 720000) # 高度
# 导入必要的模块
from utils.image_utils import get_corrected_image_stream
# 打开 PPT 对象
prs = Presentation(file_path)
# 获取第二张幻灯片 (索引为1)
slide = prs.slides[1]
# 获取修正后的图片流
img_stream = get_corrected_image_stream(img_path)
# 直接在指定位置添加签名图片
slide.shapes.add_picture(
img_stream,
signature_left,
signature_top,
signature_width,
signature_height,
)
# 保存修改后的 PPT
prs.save(file_path)
logger.info(f"签名完成,PPT文件:{file_name}")
except Exception as e:
logger.error(f"generate_signature 发生未知错误: {e}")
# 打印详细报错位置,方便调试
logger.error(traceback.format_exc())
return str(e)
def sign_selected_files(folder: str, files: list):
"""为选中的文件进行签名"""
total_files = len(files)
logger.info(f"开始生成签名,共 {total_files} 个文件")
for i, file_name in enumerate(files):
sign_file(folder, file_name)
logger.info(f"已为 {total_files} 个文件签名")
ui.notify(f"签名完成: {total_files} 个文件", type="positive")
def sign_all_files(folder: str):
"""为目录下所有文件进行签名"""
files = get_signature_files(folder)
if files:
sign_selected_files(folder, files)
total_files = len(files)
ui.notify(f"签名完成: {total_files} 个文件", type="positive")