Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion app/Language/modules/remaining_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
"description": "带班级名称的标题",
},
"count_label": {"name": "剩余人数:{count}", "description": "剩余人数标签文本"},
"group_count_label": {"name": "剩余组数:{count}", "description": "剩余组数标签文本"},
"group_count_label": {
"name": "剩余组数:{count}",
"description": "剩余组数标签文本",
},
"no_students": {
"name": "暂无未抽取的学生",
"description": "没有剩余学生时的提示文本",
Expand Down
12 changes: 6 additions & 6 deletions app/page_building/another_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,10 @@ def create_remaining_list_window(
# 激活窗口并置于前台
window.raise_()
window.activateWindow()

# 获取页面实例并更新数据
page = None

def setup_page():
nonlocal page
page_template = window.get_page("remaining_list")
Expand All @@ -245,10 +245,10 @@ def setup_page():
group_index,
gender_index,
)

# 使用延迟调用确保内容控件已创建
QTimer.singleShot(100, setup_page)

# 创建一个回调函数,用于在页面设置完成后获取页面实例
def get_page_callback(callback):
def check_page():
Expand All @@ -258,13 +258,13 @@ def check_page():
QTimer.singleShot(50, check_page)

check_page()

return window, get_page_callback
except Exception as e:
# 如果窗口已损坏,从字典中移除并创建新窗口
logger.error(f"激活剩余名单窗口失败: {e}")
_window_instances.pop("remaining_list", None)

# 创建新窗口
title = "剩余名单"
window = SimpleWindowTemplate(title, width=800, height=600)
Expand Down
86 changes: 60 additions & 26 deletions app/page_building/page_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ def __init__(self, page_config: dict, parent: QFrame = None):

self.page_config = page_config # 页面配置字典
self.ui_created = False
self.pages = {} # 存储页面组件
self.pages = {} # 存储页面组件 (scroll areas)
self.page_infos = {} # 存储页面附加信息: display, layout, loaded
self.current_page = None # 当前页面
self.base_path = "app.view.settings.list_management" # 默认基础路径

Expand Down Expand Up @@ -222,9 +223,19 @@ def add_pages(self):
for page_name, display_name in self.page_config.items():
self.add_page(page_name, display_name)

# 如果有页面,设置第一个页面为当前页面
if self.pages:
first_page_name = next(iter(self.pages))
# 如果有页面,设置第一个页面为当前页面并仅加载第一个页面的内容
if self.page_infos:
first_page_name = next(iter(self.page_infos))
# 延迟一点点创建第一个页面的内容,避免阻塞
QTimer.singleShot(
0,
lambda n=first_page_name: self._load_page_content(
n,
self.page_infos[n]["display"],
self.page_infos[n]["scroll"],
self.page_infos[n]["layout"],
),
)
self.switch_to_page(first_page_name)

def add_page(self, page_name: str, display_name: str):
Expand Down Expand Up @@ -279,14 +290,12 @@ def add_page(self, page_name: str, display_name: str):

# 存储滑动区域引用
self.pages[page_name] = scroll_area

# 延迟加载实际页面组件
QTimer.singleShot(
0,
lambda: self._load_page_content(
page_name, display_name, scroll_area, inner_layout
),
)
self.page_infos[page_name] = {
"display": display_name,
"scroll": scroll_area,
"layout": inner_layout,
"loaded": False,
}

def _load_page_content(
self,
Expand Down Expand Up @@ -314,17 +323,26 @@ def _load_page_content(
widget = content_widget_class(self)
widget.setObjectName(page_name)

# 清除加载提示
if inner_layout.count() > 0:
item = inner_layout.itemAt(0)
if item:
inner_layout.removeItem(item)
if item.widget():
item.widget().deleteLater()
# 清除加载提示(使用安全的 takeAt 循环以避免 Qt C++ 对象提前删除问题)
try:
while inner_layout.count() > 0:
item = inner_layout.takeAt(0)
if not item:
break
w = item.widget()
if w is not None:
w.deleteLater()
except RuntimeError:
# 如果内部对象被底层 Qt 提前销毁,忽略并继续
pass

# 添加实际内容到内部布局
inner_layout.addWidget(widget)

# 标记为已加载
if page_name in self.page_infos:
self.page_infos[page_name]["loaded"] = True

elapsed = time.perf_counter() - start
logger.debug(f"加载页面组件 {page_name} 耗时: {elapsed:.3f}s")

Expand All @@ -335,13 +353,17 @@ def _load_page_content(
except (ImportError, AttributeError) as e:
print(f"无法导入页面组件 {page_name}: {e}")

# 清除加载提示
if inner_layout.count() > 0:
item = inner_layout.itemAt(0)
if item:
inner_layout.removeItem(item)
if item.widget():
item.widget().deleteLater()
# 清除加载提示(安全地移除所有子项)
try:
while inner_layout.count() > 0:
item = inner_layout.takeAt(0)
if not item:
break
w = item.widget()
if w is not None:
w.deleteLater()
except RuntimeError:
pass

# 创建错误页面
error_widget = QWidget()
Expand All @@ -362,13 +384,25 @@ def _load_page_content(
# 添加错误页面到内部布局
inner_layout.addWidget(error_widget)

# 标记为已加载(虽然是错误页面,但不再重复尝试)
if page_name in self.page_infos:
self.page_infos[page_name]["loaded"] = True

# 如果当前页面就是正在加载的页面,确保滑动区域是当前可见的
if self.current_page == page_name:
self.stacked_widget.setCurrentWidget(scroll_area)

def switch_to_page(self, page_name: str):
"""切换到指定页面"""
if page_name in self.pages:
# 按需加载:如果尚未加载该页面的实际内容,则先加载
info = self.page_infos.get(page_name)
if info and not info.get("loaded"):
# 调用加载函数(同步执行),传入存储的 inner_layout
self._load_page_content(
page_name, info["display"], info["scroll"], info["layout"]
)

self.stacked_widget.setCurrentWidget(self.pages[page_name])
self.pivot.setCurrentItem(page_name)
self.current_page = page_name
Expand Down
29 changes: 18 additions & 11 deletions app/page_building/window_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ def initWindow(self, title: str, width: int = 700, height: int = 500) -> None:
custom_font = load_custom_font()
title_font = QFont(custom_font, 9)
self.titleBar.setFont(title_font)

# 确保在设置标题栏后应用当前主题和自定义字体
self._apply_current_theme()

if self.parent_window is None:
screen = QApplication.primaryScreen().availableGeometry()
w, h = screen.width(), screen.height()
Expand All @@ -148,7 +148,7 @@ def _apply_current_theme(self) -> None:
try:
# 获取当前主题设置
current_theme = readme_settings("basic_settings", "theme")

# 根据主题设置窗口背景色
if current_theme == "DARK":
# 深色主题 - 设置深色背景
Expand All @@ -158,12 +158,17 @@ def _apply_current_theme(self) -> None:
# 自动主题 - 根据系统设置
try:
from darkdetect import isDark

if isDark():
self.setStyleSheet("background-color: #202020;")
self.default_page.setStyleSheet("background-color: transparent;")
self.default_page.setStyleSheet(
"background-color: transparent;"
)
else:
self.setStyleSheet("background-color: #ffffff;")
self.default_page.setStyleSheet("background-color: transparent;")
self.default_page.setStyleSheet(
"background-color: transparent;"
)
except:
# 如果检测失败,使用浅色主题
self.setStyleSheet("background-color: #ffffff;")
Expand All @@ -172,10 +177,10 @@ def _apply_current_theme(self) -> None:
# 浅色主题
self.setStyleSheet("background-color: #ffffff;")
self.default_page.setStyleSheet("background-color: transparent;")

# 应用标题栏自定义字体和颜色
self._set_titlebar_colors()

logger.debug(f"窗口主题已更新为: {current_theme}")
except Exception as e:
logger.error(f"应用主题时出错: {e}")
Expand All @@ -188,7 +193,7 @@ def _set_titlebar_colors(self) -> None:
try:
# 判断是否为深色主题
is_dark = is_dark_theme(qconfig)

if is_dark:
# 深色主题
title_color = "#ffffff" # 白色文字
Expand All @@ -197,7 +202,7 @@ def _set_titlebar_colors(self) -> None:
# 浅色主题
title_color = "#000000" # 黑色文字
background_color = "#ffffff"

# 设置标题栏颜色样式
titlebar_style = f"""
QWidget {{
Expand Down Expand Up @@ -228,8 +233,10 @@ def _set_titlebar_colors(self) -> None:
}}
"""
self.titleBar.setStyleSheet(titlebar_style)

logger.debug(f"标题栏颜色已设置: 文字色={title_color}, 背景色={background_color}")

logger.debug(
f"标题栏颜色已设置: 文字色={title_color}, 背景色={background_color}"
)
except Exception as e:
logger.error(f"设置标题栏颜色失败: {e}")

Expand Down
6 changes: 3 additions & 3 deletions app/tools/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ def calculate_remaining_count(
if group_index == 1: # 全部小组
# 获取所有小组列表
group_list = get_group_list(class_name)

# 计算已被排除的小组数量
excluded_count = 0
for group_name in group_list:
Expand All @@ -656,7 +656,7 @@ def calculate_remaining_count(
and drawn_counts[group_name] >= half_repeat
):
excluded_count += 1

# 计算实际剩余组数
return max(0, len(group_list) - excluded_count)
else:
Expand All @@ -672,7 +672,7 @@ def calculate_remaining_count(
if isinstance(student, dict) and "name" in student
else student
)

# 如果学生已被抽取次数达到或超过设置值,则计入排除数量
if (
student_name in drawn_counts
Expand Down
6 changes: 3 additions & 3 deletions app/tools/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ def get_group_members(class_name: str, group_name: str) -> List[Dict[str, Any]]:
"""
student_list = get_student_list(class_name)
group_members = []

for student in student_list:
if student["group"] == group_name:
group_members.append(student)

# 按ID排序
group_members.sort(key=lambda x: x["id"])
return group_members
Expand Down Expand Up @@ -366,7 +366,7 @@ def filter_students_data(
gender_index == 0 or gender == gender_filter
): # 根据性别条件过滤
groups_set.add(group)

# 对小组进行排序,按小组名称排序
# 返回格式为 (id, name, gender, group, exist),但小组模式下只需要小组名称
students_data = []
Expand Down
Loading
Loading