You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
4.1 KiB

"""
积分管理组件
"""
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QTableWidget, QTableWidgetItem,
QHeaderView, QFileDialog, QMessageBox, QGroupBox)
from PyQt5.QtCore import Qt
from frontend.utils.api_client import APIClient
class ScoreManagementWidget(QWidget):
"""积分管理界面"""
def __init__(self, api_client: APIClient, parent=None):
super().__init__(parent)
self.api_client = api_client
self.init_ui()
self.load_statistics()
def init_ui(self):
"""初始化界面"""
layout = QVBoxLayout()
# 标题
title = QLabel("积分管理")
title.setStyleSheet("font-size: 18px; font-weight: bold; margin: 10px;")
layout.addWidget(title)
# 统计信息
stats_group = QGroupBox("统计信息")
stats_layout = QVBoxLayout()
self.stats_label = QLabel("加载中...")
self.stats_label.setStyleSheet("font-size: 14px; padding: 10px;")
stats_layout.addWidget(self.stats_label)
stats_group.setLayout(stats_layout)
layout.addWidget(stats_group)
# 按钮栏
button_layout = QHBoxLayout()
self.export_btn = QPushButton("导出积分详单")
self.export_btn.clicked.connect(self.export_scores)
button_layout.addWidget(self.export_btn)
self.refresh_btn = QPushButton("刷新")
self.refresh_btn.clicked.connect(self.load_statistics)
button_layout.addWidget(self.refresh_btn)
button_layout.addStretch()
layout.addLayout(button_layout)
# 排名表格
ranking_group = QGroupBox("积分排名")
ranking_layout = QVBoxLayout()
self.ranking_table = QTableWidget()
self.ranking_table.setColumnCount(6)
self.ranking_table.setHorizontalHeaderLabels(["排名", "学号", "姓名", "专业", "总积分", "随机点名次数"])
self.ranking_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
ranking_layout.addWidget(self.ranking_table)
ranking_group.setLayout(ranking_layout)
layout.addWidget(ranking_group)
self.setLayout(layout)
def load_statistics(self):
"""加载统计信息和排名"""
try:
# 加载统计信息
stats = self.api_client.get_statistics()
stats_text = (f"总学生数: {stats['total_students']} | "
f"总点名次数: {stats['total_rollcall_count']} | "
f"平均积分: {stats['avg_score']:.2f} | "
f"最高积分: {stats['max_score']:.2f} | "
f"最低积分: {stats['min_score']:.2f}")
self.stats_label.setText(stats_text)
# 加载排名
ranking_data = self.api_client.get_ranking(top_n=50)
rankings = ranking_data['rankings']
self.ranking_table.setRowCount(len(rankings))
for row, item in enumerate(rankings):
self.ranking_table.setItem(row, 0, QTableWidgetItem(str(item['rank'])))
self.ranking_table.setItem(row, 1, QTableWidgetItem(item['student_id']))
self.ranking_table.setItem(row, 2, QTableWidgetItem(item['name']))
self.ranking_table.setItem(row, 3, QTableWidgetItem(item.get('major', '')))
self.ranking_table.setItem(row, 4, QTableWidgetItem(f"{item['total_score']:.2f}"))
self.ranking_table.setItem(row, 5, QTableWidgetItem(str(item['random_rollcall_count'])))
except Exception as e:
QMessageBox.critical(self, "错误", f"加载数据失败: {str(e)}")
def export_scores(self):
"""导出积分详单"""
file_path, _ = QFileDialog.getSaveFileName(self, "保存积分详单", "积分详单.xlsx", "Excel Files (*.xlsx)")
if not file_path:
return
try:
self.api_client.export_scores(file_path)
QMessageBox.information(self, "成功", f"积分详单已导出到: {file_path}")
except Exception as e:
QMessageBox.critical(self, "错误", f"导出失败: {str(e)}")