Files
JITToolBox/ui/pyui/picker_ui.py
2025-06-25 23:18:32 +08:00

249 lines
9.1 KiB
Python

from PySide6.QtCore import Qt, Signal, QTimer
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QStackedWidget, QGridLayout, QFileDialog
from qfluentwidgets import GroupHeaderCardWidget, PushButton, FluentIcon, PrimaryPushButton, IconWidget, BodyLabel, \
SegmentedWidget, SpinBox, LargeTitleLabel, DisplayLabel, SubtitleLabel
from module.picker.schema import PickerExcel, PickerStudent
from ui.components.widget import RollingTextWidget
from ui import MAIN_THEME_COLOR
from ui.components.widget import Widget
from ui.components.window import MyWindow
class PSMMain(MyWindow):
finishSignal = Signal()
def __init__(self, student: PickerStudent, parent=None):
super().__init__(parent)
self.student = student
self.grade_edit = SpinBox(self)
self.init_layout()
def init_layout(self):
main_layout = QVBoxLayout()
hLayout = QHBoxLayout()
name_layout = QVBoxLayout()
date_layout = QVBoxLayout()
hLayout.addStretch()
hLayout.addLayout(name_layout)
hLayout.addLayout(date_layout)
hLayout.addStretch()
hLayout.setSpacing(20)
so = LargeTitleLabel(f"{self.student.so}", self)
so.setAlignment(Qt.AlignCenter)
sname = DisplayLabel(
f"{self.student.name[0] + ' ' + self.student.name[1] if len(self.student.name) == 2 else self.student.name}",
self)
sname.setAlignment(Qt.AlignCenter)
name_layout.addWidget(so)
name_layout.addWidget(sname)
self.grade_edit.setFixedWidth(260)
self.grade_edit.setRange(0, 100)
grade_layout = QHBoxLayout()
grade_layout.setContentsMargins(0, 0, 0, 48)
grade_layout.setSpacing(20)
submit_button = PrimaryPushButton("确定", self)
cancel_button = PushButton("重置", self)
submit_button.clicked.connect(self.close_modal)
cancel_button.clicked.connect(lambda: self.grade_edit.clear())
submit_button.setFixedWidth(120)
cancel_button.setFixedWidth(120)
grade_layout.addWidget(submit_button)
grade_layout.addWidget(cancel_button)
date_layout.addWidget(self.grade_edit)
date_layout.addLayout(grade_layout)
main_layout.addStretch()
main_layout.addLayout(hLayout)
main_layout.addStretch()
# 快速打分
quick_grade_layout = QVBoxLayout()
quick_grade_layout.setContentsMargins(0, 0, 0, 0)
quick_grade_layout.setSpacing(20)
quick_grade_title = SubtitleLabel("快速打分", self)
quick_grade_title.setAlignment(Qt.AlignCenter)
quick_grade_layout.addWidget(quick_grade_title)
grid_wrapper_layout = QHBoxLayout()
grid_layout = QGridLayout()
buttons = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
for i, num in enumerate(buttons):
row = i // 3
col = i % 3
btn = PushButton(str(num))
btn.setFixedSize(80, 80)
# 使用lambda绑定事件
btn.clicked.connect(lambda _, n=num: self.grade_edit.setValue(n))
grid_layout.addWidget(btn, row, col)
grid_wrapper_layout.addStretch()
grid_wrapper_layout.addLayout(grid_layout)
grid_wrapper_layout.addStretch()
quick_grade_layout.addLayout(grid_layout)
quick_grade_layout.addLayout(grid_wrapper_layout)
main_layout.addLayout(quick_grade_layout)
self.widgetLayout.addLayout(main_layout)
def close_modal(self):
self.student.append_score(self.grade_edit.value())
self.finishSignal.emit()
self.close()
class PickStudentMode(QWidget):
errorSignal = Signal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.card = GroupHeaderCardWidget(self)
self.vbox = QVBoxLayout(self)
self.vbox.setContentsMargins(0, 0, 0, 0)
self.chooseBtn = PushButton("打开")
self.startButton = PrimaryPushButton(FluentIcon.PLAY_SOLID, "开始")
self.bottomLayout = QHBoxLayout()
self.hintIcon = IconWidget(FluentIcon.INFO.icon(color=MAIN_THEME_COLOR))
self.hintLabel = BodyLabel("点击开始按钮以开始抽签 👉")
self.spinbox = SpinBox()
self.rollingText = RollingTextWidget(self)
self.card.setTitle("输入选项")
self.chooseBtn.setFixedWidth(120)
self.startButton.setFixedWidth(120)
self.startButton.setEnabled(False)
self.spinbox.setRange(0, 6)
self.spinbox.setFixedWidth(120)
self.spinbox.setEnabled(False)
self.hintIcon.setFixedSize(16, 16)
self.hintIcon.autoFillBackground()
self.bottomLayout.setSpacing(10)
self.bottomLayout.setContentsMargins(24, 15, 24, 20)
self.bottomLayout.addWidget(self.hintIcon, 0, Qt.AlignLeft)
self.bottomLayout.addWidget(self.hintLabel, 0, Qt.AlignLeft)
self.bottomLayout.addStretch(1)
self.bottomLayout.addWidget(self.startButton, 0, Qt.AlignRight)
self.bottomLayout.setAlignment(Qt.AlignVCenter)
self.group = self.card.addGroup(FluentIcon.DOCUMENT, "提问名单", "选择提问名单", self.chooseBtn)
self.spinGroup = self.card.addGroup(FluentIcon.SETTING, "提问次数", "设置提问的最大次数", self.spinbox)
self.spinGroup.setSeparatorVisible(True)
self.card.vBoxLayout.addLayout(self.bottomLayout)
self.vbox.addWidget(self.card)
self.vbox.addWidget(self.rollingText)
self.vbox.addStretch(1)
# ==============================
self.chooseBtn.clicked.connect(self.choose_file)
self.spinbox.valueChanged.connect(lambda: PickerExcel.save_total_time(value=self.spinbox.value()))
self.startButton.clicked.connect(self.start_rolling)
self.rollingText.finishSignal.connect(self.finish_rolling)
# ==============================
self.filepath = ""
self.students = []
def choose_file(self):
file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "Excel 文件 (*.xlsm);")
if file_path:
self.group.setContent("已选择文件:" + file_path)
self.filepath = file_path
self.startButton.setEnabled(True)
self.init_spinbox_value()
def init_spinbox_value(self):
if not self.filepath:
return
try:
PickerExcel.open(self.filepath)
self.spinbox.setValue(PickerExcel.read_total_time())
self.spinbox.setEnabled(True)
except Exception as e:
self.errorSignal.emit(str(e))
self.spinbox.setEnabled(False)
self.startButton.setEnabled(False)
def start_rolling(self):
self.students = PickerExcel.read_student()
self.rollingText.set_items(self.students)
self.rollingText.start_rolling()
self.startButton.setEnabled(False)
def finish_rolling(self):
stu = PickerStudent.pick(self.students)
if not (stu.so and stu.name):
self.errorSignal.emit("学生信息读取失败")
self.rollingText.label.setText(stu.name)
timer = QTimer(self)
timer.setSingleShot(True)
timer.timeout.connect(lambda: self.show_screen(stu))
timer.timeout.connect(lambda: self.startButton.setEnabled(True))
timer.start(1000)
def show_screen(self, stu: PickerStudent):
screen = PSMMain(stu)
screen.finishSignal.connect(lambda: PickerExcel.write_back(stu))
screen.finishSignal.connect(lambda: self.rollingText.label.clear())
class PickQuestionMode(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
lable = DisplayLabel('🚧', self)
lable.setAlignment(Qt.AlignCenter)
self.layout = QHBoxLayout(self)
self.layout.addStretch()
self.layout.addWidget(lable)
self.layout.addStretch()
class PickerWidget(Widget):
errorSignal = Signal(str, str)
def __init__(self, key: str, parent=None):
super().__init__(key, parent)
self.vbox = QVBoxLayout(self)
self.menu = SegmentedWidget(self)
self.stack = QStackedWidget(self)
self.psm = PickStudentMode(self)
self.pqm = PickQuestionMode(self)
self.add_sub_interface(self.psm, "pickStudentMode", "选人模式")
self.add_sub_interface(self.pqm, "pickQuestionMode", "选题模式")
self.menu.setCurrentItem("pickStudentMode")
self.vbox.addWidget(self.menu)
self.vbox.addWidget(self.stack)
self.vbox.addStretch(1)
# ===========================
self.stack.currentChanged.connect(self.on_stack_index_changed)
self.psm.errorSignal.connect(lambda n: self.errorSignal.emit("😢 不好出错了", n))
def add_sub_interface(self, widget: QWidget, obj_name: str, text: str):
widget.setObjectName(obj_name)
self.stack.addWidget(widget)
self.menu.addItem(routeKey=obj_name, text=text, onClick=lambda: self.stack.setCurrentWidget(widget))
def on_stack_index_changed(self, index: int):
widget = self.stack.widget(index)
self.stack.setCurrentWidget(widget)