功能添加:可选文件类型 PDF 或 Word

This commit is contained in:
2025-06-03 23:49:17 +08:00
parent 92f32202f1
commit 5e73571705
2 changed files with 51 additions and 32 deletions

View File

@@ -4,6 +4,7 @@ import traceback
import pythoncom import pythoncom
from PySide6.QtCore import QObject, Signal from PySide6.QtCore import QObject, Signal
from win32com import client from win32com import client
from typing import Literal
from module.achievement.doc import DocxWriter from module.achievement.doc import DocxWriter
from module.achievement.excel import ExcelReader from module.achievement.excel import ExcelReader
@@ -13,7 +14,7 @@ from utils.function import resource_path
class DTGWorker(QObject): class DTGWorker(QObject):
progress = Signal(int) progress = Signal((int,), (str,))
finished = Signal() finished = Signal()
error = Signal(str, str) error = Signal(str, str)
@@ -22,13 +23,15 @@ class DTGWorker(QObject):
input_student_filepath: str, input_student_filepath: str,
input_question_filepath: str, input_question_filepath: str,
output_filepath: str, output_filepath: str,
output_filename: str output_filename: str,
output_type: Literal['pdf', 'word'] = 'pdf'
): ):
super().__init__() super().__init__()
self.input_filepath = input_student_filepath self.input_filepath = input_student_filepath
self.input_question_filepath = input_question_filepath self.input_question_filepath = input_question_filepath
self.output_filepath = output_filepath self.output_filepath = output_filepath
self.output_filename = output_filename self.output_filename = output_filename
self.output_type = output_type
def run(self): def run(self):
try: try:
@@ -39,17 +42,18 @@ class DTGWorker(QObject):
d = DocPaper(self.output_filename, template_path=resource_path("template/template.docx")) d = DocPaper(self.output_filename, template_path=resource_path("template/template.docx"))
for index, student in enumerate(students): for index, student in enumerate(students):
if (p := int((index + 1) / len(students) * 100)) != 100: if (p := int((index + 1) / len(students) * 100)) != 100:
self.progress.emit(p) self.progress[int].emit(p)
else:
self.progress.emit(99)
student.pick_question(questions) student.pick_question(questions)
d.add_paper(course, student) d.add_paper(course, student)
d.save(self.output_filepath) d.save(self.output_filepath)
self.progress.emit(100)
word_file = self.output_filepath + "/" + self.output_filename + ".docx" word_file = self.output_filepath + "/" + self.output_filename + ".docx"
pdf_file = self.output_filepath + "/" + self.output_filename + ".pdf" pdf_file = self.output_filepath + "/" + self.output_filename + ".pdf"
if self.output_type == 'pdf':
self.progress[int].emit(101)
self.progress[str].emit("正在转换文件")
if os.path.exists(pdf_file): if os.path.exists(pdf_file):
os.remove(pdf_file) os.remove(pdf_file)
@@ -59,15 +63,17 @@ class DTGWorker(QObject):
doc = word.Documents.Open(word_file) doc = word.Documents.Open(word_file)
doc.SaveAs(pdf_file, 17) doc.SaveAs(pdf_file, 17)
doc.Close() doc.Close()
finally:
word.Quit()
os.remove(word_file) os.remove(word_file)
os.startfile(pdf_file) os.startfile(pdf_file)
except Exception as _: except Exception as e:
error_msg = traceback.format_exc() raise Exception("PDF转换失败但Word文档已生成") from e
self.error.emit("😢 不好出错了", error_msg) finally:
self.progress.emit(-1) word.Quit()
elif self.output_type == 'word':
os.startfile(word_file)
except Exception as e:
self.error.emit("😢 不好出错了", e)
self.progress[int].emit(-1)
finally: finally:
self.finished.emit() self.finished.emit()

View File

@@ -2,9 +2,9 @@ from functools import wraps
from typing import Literal, Callable from typing import Literal, Callable
from PySide6.QtCore import Qt, Signal, QThread from PySide6.QtCore import Qt, Signal, QThread
from PySide6.QtWidgets import QHBoxLayout, QVBoxLayout, QFileDialog from PySide6.QtWidgets import QHBoxLayout, QVBoxLayout, QFileDialog, QButtonGroup, QWidget
from qfluentwidgets import GroupHeaderCardWidget, PushButton, IconWidget, BodyLabel, PrimaryPushButton, FluentIcon, \ from qfluentwidgets import GroupHeaderCardWidget, PushButton, IconWidget, BodyLabel, PrimaryPushButton, FluentIcon, \
LineEdit LineEdit, RadioButton
from module.worker import DTGWorker from module.worker import DTGWorker
from ui.components.infobar import ProgressInfoBar from ui.components.infobar import ProgressInfoBar
@@ -61,7 +61,17 @@ class ExportSettingsCard(GroupHeaderCardWidget):
self.chooseExportDirectoryButton = PushButton("选择") self.chooseExportDirectoryButton = PushButton("选择")
self.exportFileNameLineEdit = LineEdit() self.exportFileNameLineEdit = LineEdit()
self.startButton = PrimaryPushButton(FluentIcon.PLAY_SOLID, "开始") self.startButton = PrimaryPushButton(FluentIcon.PLAY_SOLID, "开始")
self.pdfRadio = RadioButton("PDF")
self.wordRadio = RadioButton("Word")
self.radioWidget = QWidget(self)
self.radioHbox = QHBoxLayout(self.radioWidget)
self.radioGroup = QButtonGroup(self.radioWidget)
self.radioGroup.addButton(self.pdfRadio)
self.radioGroup.addButton(self.wordRadio)
self.radioHbox.addWidget(self.pdfRadio)
self.radioHbox.addWidget(self.wordRadio)
self.pdfRadio.setChecked(True)
self.hintIcon = IconWidget(FluentIcon.INFO.icon(color=MAIN_THEME_COLOR)) self.hintIcon = IconWidget(FluentIcon.INFO.icon(color=MAIN_THEME_COLOR))
self.hintLabel = BodyLabel("点击开始按钮以开始生成 👉") self.hintLabel = BodyLabel("点击开始按钮以开始生成 👉")
self.chooseExportDirectoryButton.setFixedWidth(120) self.chooseExportDirectoryButton.setFixedWidth(120)
@@ -85,7 +95,8 @@ class ExportSettingsCard(GroupHeaderCardWidget):
self.chooseExportDirectoryButton) self.chooseExportDirectoryButton)
self.fnGroup = self.addGroup(FluentIcon.DOCUMENT, "导出文件名", "输入导出文件的名称", self.fnGroup = self.addGroup(FluentIcon.DOCUMENT, "导出文件名", "输入导出文件的名称",
self.exportFileNameLineEdit) self.exportFileNameLineEdit)
self.fnGroup.setSeparatorVisible(True) self.exportFormatGroup = self.addGroup(FluentIcon.DOCUMENT, "导出文件格式", "选择导出文件的格式", self.radioWidget)
self.exportFormatGroup.setSeparatorVisible(True)
self.vBoxLayout.addLayout(self.bottomLayout) self.vBoxLayout.addLayout(self.bottomLayout)
@@ -148,12 +159,12 @@ class DefenseWidget(Widget):
self.pib.set_title('请稍后') self.pib.set_title('请稍后')
def set_pb_value(self, value: int) -> None: def set_pb_value(self, value: int) -> None:
self.pib.set_progress(value) if value == -1:
if value == 100:
self.pib.set_progress(101)
self.pib.set_title('正在转换文件')
elif value == -1:
self.successFlag = False self.successFlag = False
self.pib.set_progress(value)
def set_pb_msg(self, value: str) -> None:
self.pib.set_title(value)
def enable_start_check(func: Callable): def enable_start_check(func: Callable):
@wraps(func) @wraps(func)
@@ -204,7 +215,8 @@ class DefenseWidget(Widget):
self.input_student_filepath, self.input_student_filepath,
self.input_question_filepath, self.input_question_filepath,
self.output_filepath, self.output_filepath,
self.output_filename self.output_filename,
self.exportCard.radioGroup.checkedButton().text().lower()
) )
self.worker.moveToThread(self.thread) self.worker.moveToThread(self.thread)
@@ -214,7 +226,8 @@ class DefenseWidget(Widget):
# 线程启动与信号连接 # 线程启动与信号连接
self.thread.started.connect(self.worker.run) self.thread.started.connect(self.worker.run)
self.worker.progress.connect(self.set_pb_value) self.worker.progress[int].connect(self.set_pb_value)
self.worker.progress[str].connect(self.set_pb_msg)
self.worker.error.connect(self.show_error) self.worker.error.connect(self.show_error)
self.worker.finished.connect(self.thread.quit) self.worker.finished.connect(self.thread.quit)