diff --git a/module/worker.py b/module/worker.py index 6afc531..7f51033 100644 --- a/module/worker.py +++ b/module/worker.py @@ -4,6 +4,7 @@ import traceback import pythoncom from PySide6.QtCore import QObject, Signal from win32com import client +from typing import Literal from module.achievement.doc import DocxWriter from module.achievement.excel import ExcelReader @@ -13,7 +14,7 @@ from utils.function import resource_path class DTGWorker(QObject): - progress = Signal(int) + progress = Signal((int,), (str,)) finished = Signal() error = Signal(str, str) @@ -22,13 +23,15 @@ class DTGWorker(QObject): input_student_filepath: str, input_question_filepath: str, output_filepath: str, - output_filename: str + output_filename: str, + output_type: Literal['pdf', 'word'] = 'pdf' ): super().__init__() self.input_filepath = input_student_filepath self.input_question_filepath = input_question_filepath self.output_filepath = output_filepath self.output_filename = output_filename + self.output_type = output_type def run(self): try: @@ -39,35 +42,38 @@ class DTGWorker(QObject): d = DocPaper(self.output_filename, template_path=resource_path("template/template.docx")) for index, student in enumerate(students): if (p := int((index + 1) / len(students) * 100)) != 100: - self.progress.emit(p) - else: - self.progress.emit(99) + self.progress[int].emit(p) student.pick_question(questions) d.add_paper(course, student) d.save(self.output_filepath) - self.progress.emit(100) word_file = self.output_filepath + "/" + self.output_filename + ".docx" pdf_file = self.output_filepath + "/" + self.output_filename + ".pdf" - if os.path.exists(pdf_file): - os.remove(pdf_file) + if self.output_type == 'pdf': + self.progress[int].emit(101) + self.progress[str].emit("正在转换文件") - # https://stackoverflow.com/questions/71292585/python-docx2pdf-attributeerror-open-saveas - word = client.Dispatch("Word.Application", pythoncom.CoInitialize()) - try: - doc = word.Documents.Open(word_file) - doc.SaveAs(pdf_file, 17) - doc.Close() - finally: - word.Quit() + if os.path.exists(pdf_file): + os.remove(pdf_file) - os.remove(word_file) - os.startfile(pdf_file) - except Exception as _: - error_msg = traceback.format_exc() - self.error.emit("😢 不好出错了", error_msg) - self.progress.emit(-1) + # https://stackoverflow.com/questions/71292585/python-docx2pdf-attributeerror-open-saveas + word = client.Dispatch("Word.Application", pythoncom.CoInitialize()) + try: + doc = word.Documents.Open(word_file) + doc.SaveAs(pdf_file, 17) + doc.Close() + os.remove(word_file) + os.startfile(pdf_file) + except Exception as e: + raise Exception("PDF转换失败,但Word文档已生成") from e + finally: + 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: self.finished.emit() diff --git a/ui/pyui/defense_ui.py b/ui/pyui/defense_ui.py index 1e2142b..5bf74f4 100644 --- a/ui/pyui/defense_ui.py +++ b/ui/pyui/defense_ui.py @@ -2,9 +2,9 @@ from functools import wraps from typing import Literal, Callable 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, \ - LineEdit + LineEdit, RadioButton from module.worker import DTGWorker from ui.components.infobar import ProgressInfoBar @@ -61,7 +61,17 @@ class ExportSettingsCard(GroupHeaderCardWidget): self.chooseExportDirectoryButton = PushButton("选择") self.exportFileNameLineEdit = LineEdit() 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.hintLabel = BodyLabel("点击开始按钮以开始生成 👉") self.chooseExportDirectoryButton.setFixedWidth(120) @@ -85,7 +95,8 @@ class ExportSettingsCard(GroupHeaderCardWidget): self.chooseExportDirectoryButton) self.fnGroup = self.addGroup(FluentIcon.DOCUMENT, "导出文件名", "输入导出文件的名称", self.exportFileNameLineEdit) - self.fnGroup.setSeparatorVisible(True) + self.exportFormatGroup = self.addGroup(FluentIcon.DOCUMENT, "导出文件格式", "选择导出文件的格式", self.radioWidget) + self.exportFormatGroup.setSeparatorVisible(True) self.vBoxLayout.addLayout(self.bottomLayout) @@ -148,12 +159,12 @@ class DefenseWidget(Widget): self.pib.set_title('请稍后') def set_pb_value(self, value: int) -> None: - self.pib.set_progress(value) - if value == 100: - self.pib.set_progress(101) - self.pib.set_title('正在转换文件') - elif value == -1: + if value == -1: 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): @wraps(func) @@ -204,7 +215,8 @@ class DefenseWidget(Widget): self.input_student_filepath, self.input_question_filepath, self.output_filepath, - self.output_filename + self.output_filename, + self.exportCard.radioGroup.checkedButton().text().lower() ) self.worker.moveToThread(self.thread) @@ -214,7 +226,8 @@ class DefenseWidget(Widget): # 线程启动与信号连接 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.finished.connect(self.thread.quit)