功能添加:可选文件类型 PDF 或 Word
This commit is contained in:
@@ -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,35 +42,38 @@ 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 os.path.exists(pdf_file):
|
if self.output_type == 'pdf':
|
||||||
os.remove(pdf_file)
|
self.progress[int].emit(101)
|
||||||
|
self.progress[str].emit("正在转换文件")
|
||||||
|
|
||||||
# https://stackoverflow.com/questions/71292585/python-docx2pdf-attributeerror-open-saveas
|
if os.path.exists(pdf_file):
|
||||||
word = client.Dispatch("Word.Application", pythoncom.CoInitialize())
|
os.remove(pdf_file)
|
||||||
try:
|
|
||||||
doc = word.Documents.Open(word_file)
|
|
||||||
doc.SaveAs(pdf_file, 17)
|
|
||||||
doc.Close()
|
|
||||||
finally:
|
|
||||||
word.Quit()
|
|
||||||
|
|
||||||
os.remove(word_file)
|
# https://stackoverflow.com/questions/71292585/python-docx2pdf-attributeerror-open-saveas
|
||||||
os.startfile(pdf_file)
|
word = client.Dispatch("Word.Application", pythoncom.CoInitialize())
|
||||||
except Exception as _:
|
try:
|
||||||
error_msg = traceback.format_exc()
|
doc = word.Documents.Open(word_file)
|
||||||
self.error.emit("😢 不好出错了", error_msg)
|
doc.SaveAs(pdf_file, 17)
|
||||||
self.progress.emit(-1)
|
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:
|
finally:
|
||||||
self.finished.emit()
|
self.finished.emit()
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user