109 lines
4.0 KiB
Python
109 lines
4.0 KiB
Python
import math
|
||
import os
|
||
import traceback
|
||
from typing import Literal
|
||
|
||
import pythoncom
|
||
from PySide6.QtCore import QObject, Signal
|
||
from win32com import client
|
||
|
||
from module.achievement.doc import DocxWriter
|
||
from module.achievement.excel import ExcelReader
|
||
from module.defense.doc import DocPaper
|
||
from module.schema import Course, Student, Question
|
||
from utils.function import resource_path
|
||
|
||
|
||
class DTGWorker(QObject):
|
||
progress = Signal((int,), (str,))
|
||
finished = Signal()
|
||
error = Signal(str, str)
|
||
|
||
def __init__(
|
||
self,
|
||
input_student_filepath: str,
|
||
input_question_filepath: str,
|
||
output_filepath: 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:
|
||
course = Course.load_from_xls(self.input_filepath)
|
||
students = Student.load_from_xls(self.input_filepath)
|
||
questions = Question.load_from_xls(self.input_question_filepath)
|
||
|
||
max_question_count = math.ceil(len(students) * 3 / len(questions))
|
||
|
||
d = DocPaper(self.output_filename, resource_path("template/template-defense-paper-paper.docx"))
|
||
for index, student in enumerate(students):
|
||
if (p := int((index + 1) / len(students) * 100)) != 100:
|
||
self.progress[int].emit(p)
|
||
student.pick_question(questions, max_count=max_question_count)
|
||
d.add_paper(course, student)
|
||
d.save(self.output_filepath)
|
||
|
||
word_file = self.output_filepath + "/" + self.output_filename + ".docx"
|
||
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):
|
||
os.remove(pdf_file)
|
||
pythoncom.CoInitialize()
|
||
# https://stackoverflow.com/questions/71292585/python-docx2pdf-attributeerror-open-saveas
|
||
word = client.Dispatch("Word.Application")
|
||
doc = word.Documents.Open(word_file)
|
||
try:
|
||
doc.SaveAs(pdf_file, 17)
|
||
doc.Close()
|
||
os.remove(word_file)
|
||
os.startfile(pdf_file)
|
||
except Exception as e:
|
||
doc.Close()
|
||
os.startfile(word_file)
|
||
raise Exception("PDF转换失败,但Word文档已生成,已打开Word文档") from e
|
||
finally:
|
||
word.Quit()
|
||
elif self.output_type == 'word':
|
||
os.startfile(word_file)
|
||
except Exception:
|
||
self.error.emit("😢 不好出错了", traceback.format_exc())
|
||
self.progress[int].emit(-1)
|
||
finally:
|
||
self.finished.emit()
|
||
|
||
|
||
class ARGWorker(QObject):
|
||
finished = Signal()
|
||
error = Signal(str, str)
|
||
info = Signal(str, str)
|
||
|
||
def __init__(self, input_filepath: str, output_filepath: str, output_filename: str, disable_cc: bool = False):
|
||
super().__init__()
|
||
self.input_filepath = input_filepath
|
||
self.output_filepath = output_filepath
|
||
self.output_filename = output_filename
|
||
self.disable_compatibility_check = disable_cc
|
||
|
||
def run(self):
|
||
try:
|
||
excel = ExcelReader(self.input_filepath, self.disable_compatibility_check, self.info.emit)
|
||
excel.run()
|
||
|
||
doc = DocxWriter(self.output_filepath, self.output_filename, excel, self.info.emit)
|
||
doc.write()
|
||
except Exception as e:
|
||
self.error.emit("😢 不好出错了", str(e))
|
||
finally:
|
||
self.finished.emit()
|