Skip to content

Commit c990858

Browse files
committed
一堆优化
1 parent d80cfad commit c990858

7 files changed

Lines changed: 771 additions & 759 deletions

File tree

CHANGELOG/v2.2.0/CHANGELOG.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ v2.0 - Koharu(小鸟游星野) release 3
99

1010
## 💡 功能优化
1111

12-
- 优化 **动画流畅性**新增控件复用减少重绘开销
12+
- 优化 **闪抽动画日志**减少不必要的日志输出
1313
- 优化 **动画性能**,新增数据缓存减少频繁IO操作
1414
- 优化 **通知渠道选择**,新增ClassIsland使用提示
1515
- 优化 **浮窗点击识别**,减少误识别为拖动
1616
- 优化 **安全验证逻辑**,统一使用项目验证系统
1717
- 优化 **软件退出**,解决退出缓慢问题
1818
- 优化 **URL 注册**,无需管理员权限即可完成
1919
- 优化 **TEMP 清理**,仅清理 TEMP 文件夹
20-
- 优化 **日志记录**,描述错误问题
2120
- 优化 **历史记录表格**,未设置性别/小组则隐藏对应列
2221
- 优化 **音乐播放延迟**,减少文件读取和音频流初始化开销
2322

@@ -29,9 +28,6 @@ v2.0 - Koharu(小鸟游星野) release 3
2928
- 修复 **重启功能**,解决无法重启异常
3029
- 修复 **URL 注册**,修复注册失败问题
3130
- 修复 **收纳浮窗无焦点**,修复无焦点模式未生效
32-
- 修复 **自动播放动画**,修复次数不准确导致的卡顿问题
33-
- 修复 **手动停止动画**,修复动画闪几下后停止的问题
34-
- 修复 **浮窗通知闪烁**,修复更新标签时导致的闪烁问题
3531
- 修复 **ClassIsland通知渠道显示时长**,修复时间未生效问题
3632

3733
## 🔧 其它变更

app/common/display/result_display.py

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -699,14 +699,57 @@ def update_grid_labels(result_grid, new_labels, cached_labels):
699699
new_item = new_layout.itemAt(j)
700700

701701
if old_item and new_item:
702-
old_label = old_item.widget()
703-
new_label = new_item.widget()
704-
705-
if isinstance(old_label, BodyLabel) and isinstance(
706-
new_label, BodyLabel
702+
old_content = old_item.widget()
703+
new_content = new_item.widget()
704+
705+
# 如果内容是容器(带头像的情况),更新其内部组件
706+
if old_content.layout() and new_content.layout():
707+
old_inner_layout = old_content.layout()
708+
new_inner_layout = new_content.layout()
709+
710+
for k in range(
711+
min(
712+
old_inner_layout.count(),
713+
new_inner_layout.count(),
714+
)
715+
):
716+
old_inner_item = old_inner_layout.itemAt(k)
717+
new_inner_item = new_inner_layout.itemAt(k)
718+
719+
if old_inner_item and new_inner_item:
720+
old_inner_widget = old_inner_item.widget()
721+
new_inner_widget = new_inner_item.widget()
722+
723+
# 更新文本标签
724+
if isinstance(
725+
old_inner_widget, BodyLabel
726+
) and isinstance(new_inner_widget, BodyLabel):
727+
old_inner_widget.setText(
728+
new_inner_widget.text()
729+
)
730+
old_inner_widget.setStyleSheet(
731+
new_inner_widget.styleSheet()
732+
)
733+
734+
# 更新头像组件
735+
from qfluentwidgets import AvatarWidget
736+
737+
if isinstance(
738+
old_inner_widget, AvatarWidget
739+
) and isinstance(
740+
new_inner_widget, AvatarWidget
741+
):
742+
old_image = old_inner_widget.getImage()
743+
new_image = new_inner_widget.getImage()
744+
if old_image != new_image:
745+
old_inner_widget.setImage(new_image)
746+
747+
# 如果内容是直接标签(不带头像的情况)
748+
elif isinstance(old_content, BodyLabel) and isinstance(
749+
new_content, BodyLabel
707750
):
708-
old_label.setText(new_label.text())
709-
old_label.setStyleSheet(new_label.styleSheet())
751+
old_content.setText(new_content.text())
752+
old_content.setStyleSheet(new_content.styleSheet())
710753

711754
cached_labels[:] = new_labels
712755

@@ -739,7 +782,12 @@ def clear_grid(result_grid, log_debug=False):
739782

740783
@staticmethod
741784
def show_notification_if_enabled(
742-
class_name, selected_students, draw_count=1, settings=None, settings_group=None
785+
class_name,
786+
selected_students,
787+
draw_count=1,
788+
settings=None,
789+
settings_group=None,
790+
is_animating=False,
743791
):
744792
"""
745793
如果启用了通知服务,则显示抽取结果通知
@@ -749,14 +797,21 @@ def show_notification_if_enabled(
749797
selected_students: 选中的学生列表
750798
draw_count: 抽取人数
751799
settings: 通知设置参数
800+
settings_group: 设置组名称
801+
is_animating: 是否在动画过程中,如果是则不启动自动关闭定时器
752802
"""
753803
# 检查是否启用了通知服务(这个检查应该由调用方完成)
754804
from app.common.notification.notification_service import (
755805
show_roll_call_notification,
756806
)
757807

758808
show_roll_call_notification(
759-
class_name, selected_students, draw_count, settings, settings_group
809+
class_name,
810+
selected_students,
811+
draw_count,
812+
settings,
813+
settings_group,
814+
is_animating,
760815
)
761816

762817
@staticmethod

app/common/notification/notification_service.py

Lines changed: 74 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,6 @@ def __init__(self, parent=None):
158158
# 关闭动画
159159
self.hide_animation = None
160160

161-
# 缓存的标签,用于复用
162-
self.cached_student_labels = []
163-
164161
# 启动周期性置顶
165162
self._start_periodic_topmost()
166163

@@ -321,8 +318,14 @@ def update_drag_line_style(self):
321318
}}
322319
""")
323320

324-
def apply_settings(self, settings=None, settings_group=None):
325-
"""应用设置到通知窗口"""
321+
def apply_settings(self, settings=None, settings_group=None, is_animating=False):
322+
"""应用设置到通知窗口
323+
324+
Args:
325+
settings: 设置字典
326+
settings_group: 设置组名称
327+
is_animating: 是否在动画过程中,如果是则不启动自动关闭定时器
328+
"""
326329
if settings:
327330
# 使用传递的设置
328331
transparency = settings.get("transparency", 0.6)
@@ -354,8 +357,8 @@ def apply_settings(self, settings=None, settings_group=None):
354357
# 根据设置定位窗口
355358
self.position_window(settings)
356359

357-
# 设置自动关闭时间
358-
if auto_close_time > 0:
360+
# 设置自动关闭时间(仅在非动画状态下启动)
361+
if auto_close_time > 0 and not is_animating:
359362
self.auto_close_timer.stop()
360363
self.auto_close_timer.setInterval(auto_close_time * 1000) # 转换为毫秒
361364
# 初始化倒计时并启动更新定时器
@@ -786,7 +789,7 @@ def update_content(
786789
font_settings_group=None,
787790
settings_group=None,
788791
):
789-
"""更新通知窗口的内容(优化版,复用控件避免闪烁)
792+
"""更新通知窗口的内容
790793
791794
Args:
792795
student_labels: 包含学生信息的BodyLabel控件列表
@@ -809,31 +812,15 @@ def update_content(
809812
if not student_labels:
810813
return
811814

812-
min_count = min(len(student_labels), len(self.cached_student_labels))
813-
814-
for i in range(min_count):
815-
old_widget = self.cached_student_labels[i]
816-
new_widget = student_labels[i]
817-
818-
if old_widget and new_widget:
819-
old_layout = old_widget.layout()
820-
new_layout = new_widget.layout()
821-
822-
if old_layout and new_layout:
823-
for j in range(min(old_layout.count(), new_layout.count())):
824-
old_item = old_layout.itemAt(j)
825-
new_item = new_layout.itemAt(j)
826-
827-
if old_item and new_item:
828-
old_label = old_item.widget()
829-
new_label = new_item.widget()
830-
831-
if old_label and new_label:
832-
old_label.setText(new_label.text())
833-
old_label.setStyleSheet(new_label.styleSheet())
815+
# 清除所有旧控件
816+
while self.content_layout.count():
817+
item = self.content_layout.takeAt(0)
818+
widget = item.widget()
819+
if widget:
820+
widget.deleteLater()
834821

835-
for i in range(min_count, len(student_labels)):
836-
label = student_labels[i]
822+
# 添加新控件
823+
for label in student_labels:
837824
# 如果有字体设置,则应用到标签上
838825
if font_settings_group:
839826
# 检查是否使用全局字体
@@ -853,13 +840,6 @@ def update_content(
853840
)
854841
self.content_layout.addWidget(label)
855842

856-
for i in range(min_count, len(self.cached_student_labels)):
857-
widget = self.cached_student_labels[i]
858-
self.content_layout.removeWidget(widget)
859-
widget.deleteLater()
860-
861-
self.cached_student_labels = student_labels
862-
863843
# 确保颜色与当前主题同步
864844
try:
865845
self._on_theme_changed()
@@ -925,6 +905,7 @@ def send_to_classisland(
925905
settings=None,
926906
settings_group=None,
927907
fallback_on_error=True,
908+
is_animating=False,
928909
):
929910
"""发送通知到ClassIsland
930911
@@ -935,6 +916,7 @@ def send_to_classisland(
935916
settings: 通知设置参数
936917
settings_group: 设置组名称
937918
fallback_on_error: 是否在错误时回退到内置通知
919+
is_animating: 是否在动画过程中,如果是则不启动自动关闭定时器
938920
"""
939921

940922
try:
@@ -953,6 +935,7 @@ def send_to_classisland(
953935
draw_count,
954936
settings,
955937
settings_group,
938+
is_animating,
956939
)
957940
else:
958941
logger.warning("发送通知到ClassIsland失败")
@@ -962,7 +945,12 @@ def send_to_classisland(
962945
if fallback_on_error:
963946
logger.info("因错误回退到SecRandom通知服务")
964947
self._show_secrandom_notification(
965-
class_name, selected_students, draw_count, settings, settings_group
948+
class_name,
949+
selected_students,
950+
draw_count,
951+
settings,
952+
settings_group,
953+
is_animating,
966954
)
967955
else:
968956
logger.warning("发送通知到ClassIsland时出错,但不回退")
@@ -974,8 +962,18 @@ def _show_secrandom_notification(
974962
draw_count=1,
975963
settings=None,
976964
settings_group=None,
965+
is_animating=False,
977966
):
978-
"""显示SecRandom内置通知(用于回退)"""
967+
"""显示SecRandom内置通知(用于回退)
968+
969+
Args:
970+
class_name: 班级名称
971+
selected_students: 选中的学生列表 [(学号, 姓名, 是否存在), ...]
972+
draw_count: 抽取的学生数量
973+
settings: 通知设置参数
974+
settings_group: 设置组名称
975+
is_animating: 是否在动画过程中,如果是则不启动自动关闭定时器
976+
"""
979977
# 重新调用SecRandom通知服务,使用原始的show_roll_call_result逻辑
980978
if settings:
981979
font_size = settings.get("font_size", 50)
@@ -1034,10 +1032,14 @@ def _show_secrandom_notification(
10341032
if settings:
10351033
display_duration = settings.get("notification_display_duration", 5)
10361034
window.apply_settings(
1037-
{**settings, "auto_close_time": display_duration}, settings_group
1035+
{**settings, "auto_close_time": display_duration},
1036+
settings_group,
1037+
is_animating,
10381038
)
10391039
else:
1040-
window.apply_settings({"auto_close_time": 5}, settings_group) # 默认5秒
1040+
window.apply_settings(
1041+
{"auto_close_time": 5}, settings_group, is_animating
1042+
) # 默认5秒
10411043

10421044
window.update_content(
10431045
student_labels, settings, font_settings_group, settings_group
@@ -1063,6 +1065,7 @@ def show_roll_call_result(
10631065
draw_count=1,
10641066
settings=None,
10651067
settings_group=None,
1068+
is_animating=False,
10661069
):
10671070
"""在浮动通知窗口中显示点名结果
10681071
@@ -1072,6 +1075,7 @@ def show_roll_call_result(
10721075
draw_count: 抽取的学生数量
10731076
settings: 通知设置参数
10741077
settings_group: 设置组名称,默认为notification_settings
1078+
is_animating: 是否在动画过程中,如果是则不启动自动关闭定时器
10751079
"""
10761080
# 获取通知服务类型设置
10771081
notification_service_type = 0 # 默认为SecRandom通知服务
@@ -1087,7 +1091,12 @@ def show_roll_call_result(
10871091
# 如果选择了ClassIsland通知服务,则发送到ClassIsland
10881092
if notification_service_type == 1: # 1 表示 ClassIsland 通知服务
10891093
self.send_to_classisland(
1090-
class_name, selected_students, draw_count, settings, settings_group
1094+
class_name,
1095+
selected_students,
1096+
draw_count,
1097+
settings,
1098+
settings_group,
1099+
is_animating=is_animating,
10911100
)
10921101
return
10931102

@@ -1101,6 +1110,7 @@ def show_roll_call_result(
11011110
settings,
11021111
settings_group,
11031112
fallback_on_error=False,
1113+
is_animating=is_animating,
11041114
)
11051115
# 继续执行下面的内置通知逻辑,不return
11061116

@@ -1163,10 +1173,14 @@ def show_roll_call_result(
11631173
if settings:
11641174
display_duration = settings.get("notification_display_duration", 5)
11651175
window.apply_settings(
1166-
{**settings, "auto_close_time": display_duration}, settings_group
1176+
{**settings, "auto_close_time": display_duration},
1177+
settings_group,
1178+
is_animating,
11671179
)
11681180
else:
1169-
window.apply_settings({"auto_close_time": 5}, settings_group) # 默认5秒
1181+
window.apply_settings(
1182+
{"auto_close_time": 5}, settings_group, is_animating
1183+
) # 默认5秒
11701184

11711185
window.update_content(
11721186
student_labels, settings, font_settings_group, settings_group
@@ -1183,7 +1197,12 @@ def close_all_notifications(self):
11831197

11841198

11851199
def show_roll_call_notification(
1186-
class_name, selected_students, draw_count=1, settings=None, settings_group=None
1200+
class_name,
1201+
selected_students,
1202+
draw_count=1,
1203+
settings=None,
1204+
settings_group=None,
1205+
is_animating=False,
11871206
):
11881207
"""显示点名通知的便捷函数
11891208
@@ -1192,8 +1211,15 @@ def show_roll_call_notification(
11921211
selected_students: 选中的学生列表 [(学号, 姓名, 是否存在), ...]
11931212
draw_count: 抽取的学生数量
11941213
settings: 通知设置参数
1214+
settings_group: 设置组名称
1215+
is_animating: 是否在动画过程中,如果是则不启动自动关闭定时器
11951216
"""
11961217
manager = FloatingNotificationManager()
11971218
manager.show_roll_call_result(
1198-
class_name, selected_students, draw_count, settings, settings_group
1219+
class_name,
1220+
selected_students,
1221+
draw_count,
1222+
settings,
1223+
settings_group,
1224+
is_animating,
11991225
)

0 commit comments

Comments
 (0)