first commit

This commit is contained in:
2025-05-16 16:15:18 +08:00
commit 6961b70a7d
11 changed files with 750 additions and 0 deletions

110
ui/main.py Normal file
View File

@@ -0,0 +1,110 @@
import os
import platform
import subprocess
import sys
from pathlib import Path
from PySide6.QtCore import QObject, QThread, Signal
from PySide6.QtWidgets import QMainWindow, QFileDialog
from module.doc import DocPaper
from module.schema import Course, Student, Question
from ui.pyui.main import Ui_MainWindow
def resource_path(relative_path: str) -> str:
if hasattr(sys, '_MEIPASS'):
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
class Worker(QObject):
progress = Signal(str)
finished = Signal()
def __init__(self, input_filepath: str, output_filepath: str, output_filename: str):
super().__init__()
self.input_filepath = input_filepath
self.output_filepath = output_filepath
self.output_filename = output_filename
def run(self):
self.progress.emit("第一步:正在读取课程信息...")
course = Course.load_from_xls(self.input_filepath)
self.progress.emit("第二步:正在读取学生信息...")
students = Student.load_from_xls(self.input_filepath)
self.progress.emit("第三步:正在读取题目信息...")
questions = Question.load_from_csv(str(Path(os.environ["APPDATA"]) / "dtg" / "questions.csv"))
d = DocPaper(self.output_filename, template_path=resource_path("template/template.docx"))
for student in students:
self.progress.emit(f"第四步:({student.no}/{len(students)})正在处理学生:{student.name},学号:{student.so}")
student.pick_question(questions)
d.add_paper(course, student)
self.progress.emit("第五步:正在保存文件...")
d.save(self.output_filepath)
self.progress.emit("第六步:文件保存成功!")
os.startfile(Path(self.output_filepath) / f"{self.output_filename}.docx")
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.setWindowTitle("答辩题目生成器")
self.select_student_list.clicked.connect(self.choose_student_list)
self.select_output_dir.clicked.connect(self.choose_output_dir)
self.edit_topics.clicked.connect(self.edit_questions)
self.start.clicked.connect(self.start_generate)
def on_button_clicked(self):
self.statusBar().showMessage("这是状态栏信息")
def choose_student_list(self):
file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "Excel 文件 (*.xlsx);")
if file_path:
self.student_list_path.setText(file_path)
input_dir_path = file_path[:file_path.rfind('/')]
default_output_filename = file_path[file_path.rfind('/') + 1:file_path.rfind('-点名册')]
self.output_path.setText(input_dir_path)
self.output_filename.setText(default_output_filename)
def choose_output_dir(self):
dir_path = QFileDialog.getExistingDirectory(self, "选择文件夹", "")
if dir_path:
self.output_path.setText(dir_path)
def edit_questions(self):
csv_path = Path(os.environ["APPDATA"]) / "dtg" / "questions.csv"
if platform.system() == "Windows":
os.startfile(csv_path.resolve())
elif platform.system() == "Darwin": # macOS
subprocess.run(["open", csv_path.resolve()])
else: # Linux
subprocess.run(["xdg-open", csv_path.resolve()])
self.update_statusbar("已打开题目文件,请在外部程序编辑后保存。")
def start_generate(self):
self.thread = QThread()
self.worker = Worker(self.student_list_path.text(), self.output_path.text(), self.output_filename.text())
self.worker.moveToThread(self.thread)
# 线程启动与信号连接
self.thread.started.connect(self.worker.run)
self.worker.progress.connect(self.update_statusbar)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.thread.finished.connect(self.thread.deleteLater)
# 启动线程
self.thread.start()
def update_statusbar(self, message):
self.statusBar().showMessage(message)

159
ui/main.ui Normal file
View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="windowModality">
<enum>Qt::WindowModality::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>200</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>200</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>学生名单</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="student_list_path"/>
</item>
<item>
<widget class="QPushButton" name="select_student_list">
<property name="text">
<string>选择</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>导出设置</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>40</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>目 录</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="output_path"/>
</item>
<item>
<widget class="QPushButton" name="select_output_dir">
<property name="text">
<string>选择</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>40</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>文件名</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="output_filename"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="edit_topics">
<property name="text">
<string>编辑题库</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="start">
<property name="text">
<string>导出</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

140
ui/pyui/main.py Normal file
View File

@@ -0,0 +1,140 @@
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'main.ui'
##
## Created by: Qt User Interface Compiler version 6.9.0
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMainWindow, QPushButton,
QSizePolicy, QSpacerItem, QStatusBar, QWidget)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.setWindowModality(Qt.WindowModality.ApplicationModal)
MainWindow.resize(500, 200)
MainWindow.setMinimumSize(QSize(500, 200))
MainWindow.setMaximumSize(QSize(500, 200))
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout_2 = QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.horizontalLayout_3 = QHBoxLayout()
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.label = QLabel(self.centralwidget)
self.label.setObjectName(u"label")
self.horizontalLayout_3.addWidget(self.label)
self.student_list_path = QLineEdit(self.centralwidget)
self.student_list_path.setObjectName(u"student_list_path")
self.horizontalLayout_3.addWidget(self.student_list_path)
self.select_student_list = QPushButton(self.centralwidget)
self.select_student_list.setObjectName(u"select_student_list")
self.horizontalLayout_3.addWidget(self.select_student_list)
self.gridLayout_2.addLayout(self.horizontalLayout_3, 0, 0, 1, 1)
self.groupBox = QGroupBox(self.centralwidget)
self.groupBox.setObjectName(u"groupBox")
self.gridLayout = QGridLayout(self.groupBox)
self.gridLayout.setObjectName(u"gridLayout")
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.label_2 = QLabel(self.groupBox)
self.label_2.setObjectName(u"label_2")
self.label_2.setMinimumSize(QSize(40, 0))
self.label_2.setMaximumSize(QSize(40, 16777215))
self.horizontalLayout.addWidget(self.label_2)
self.output_path = QLineEdit(self.groupBox)
self.output_path.setObjectName(u"output_path")
self.horizontalLayout.addWidget(self.output_path)
self.select_output_dir = QPushButton(self.groupBox)
self.select_output_dir.setObjectName(u"select_output_dir")
self.horizontalLayout.addWidget(self.select_output_dir)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
self.horizontalLayout_2 = QHBoxLayout()
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.label_3 = QLabel(self.groupBox)
self.label_3.setObjectName(u"label_3")
self.label_3.setMinimumSize(QSize(40, 0))
self.label_3.setMaximumSize(QSize(40, 16777215))
self.horizontalLayout_2.addWidget(self.label_3)
self.output_filename = QLineEdit(self.groupBox)
self.output_filename.setObjectName(u"output_filename")
self.horizontalLayout_2.addWidget(self.output_filename)
self.gridLayout.addLayout(self.horizontalLayout_2, 1, 0, 1, 1)
self.gridLayout_2.addWidget(self.groupBox, 1, 0, 1, 1)
self.horizontalLayout_4 = QHBoxLayout()
self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_4.addItem(self.horizontalSpacer)
self.edit_topics = QPushButton(self.centralwidget)
self.edit_topics.setObjectName(u"edit_topics")
self.horizontalLayout_4.addWidget(self.edit_topics)
self.start = QPushButton(self.centralwidget)
self.start.setObjectName(u"start")
self.horizontalLayout_4.addWidget(self.start)
self.gridLayout_2.addLayout(self.horizontalLayout_4, 2, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
self.label.setText(QCoreApplication.translate("MainWindow", u"\u5b66\u751f\u540d\u5355", None))
self.select_student_list.setText(QCoreApplication.translate("MainWindow", u"\u9009\u62e9", None))
self.groupBox.setTitle(QCoreApplication.translate("MainWindow", u"\u5bfc\u51fa\u8bbe\u7f6e", None))
self.label_2.setText(QCoreApplication.translate("MainWindow", u"\u76ee \u5f55", None))
self.select_output_dir.setText(QCoreApplication.translate("MainWindow", u"\u9009\u62e9", None))
self.label_3.setText(QCoreApplication.translate("MainWindow", u"\u6587\u4ef6\u540d", None))
self.edit_topics.setText(QCoreApplication.translate("MainWindow", u"\u7f16\u8f91\u9898\u5e93", None))
self.start.setText(QCoreApplication.translate("MainWindow", u"\u5bfc\u51fa", None))
# retranslateUi