Skip to content

Commit

Permalink
fix(module): 修复无响应的bug,优化UI效果 (#9)
Browse files Browse the repository at this point in the history
* add(module): add skipper module

* fix(module): move skip task out to skipper module

* fix(docs): remove an entry of FAQ

* fix(module): add function description

* fix(module): add progress bar

* fix(module): get code formatted

* fix(module): change constant source

* fix(module): remove unused imports
  • Loading branch information
RX-105 authored May 1, 2022
1 parent 460ca4b commit 8dc28ba
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 23 deletions.
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@
这是因为重庆高校在线课程平台服务器的管控策略。短时间跳过太多任务,你可能会遭到网站临时屏蔽。屏蔽不会持续太久,不到一分钟就会解除。
但为了保证所有任务都能成功跳过,程序设置跳过每个任务之间都会间隔一段时间,具体是30秒。

- 跳过的过程中按钮没有反应?

为了防止反复多次跳过任务,执行任务期间,程序会阻止按钮的点击,直到任务完成。
如果程序进入无响应状态,跳过任务仍然在进行,请不要尝试关闭程序。

## Special Thanks

<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" alt="JetBrains Logo (Main) logo." width="168">
87 changes: 69 additions & 18 deletions ui/dashboardRoot.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
from ttkbootstrap.constants import SUCCESS
from ttkbootstrap.constants import OUTLINE
from ttkbootstrap.constants import INFO
from ttkbootstrap.constants import STRIPED
from ttkbootstrap.constants import DISABLED
from ttkbootstrap.constants import NORMAL
from ttkbootstrap.dialogs import Messagebox
from ttkbootstrap.dialogs import MessageDialog
from ttkbootstrap.icons import Icon
from time import sleep

from ui.skipper import skipper


class dashboardRoot(ttk.Window):
Expand Down Expand Up @@ -104,13 +108,15 @@ def setupDashboardFrame(self) -> None:
self.courseFrame = ttk.Frame(self.contentWrapperFrame)
self.lessonFrame = ttk.Frame(self.contentWrapperFrame)
self.actionFrame = ttk.Frame(self.root)
self.progressFrame = ttk.Frame(self.root)

# 放置所有框架
self.welcomeFrame.pack()
self.contentWrapperFrame.pack()
self.courseFrame.pack(side=LEFT)
self.lessonFrame.pack(side=LEFT)
self.actionFrame.pack()
self.progressFrame.pack(fill=X, expand=YES, pady=(20, 0))

# 设置顶部状态提示语
self.labelWelcome = ttk.Label(
Expand Down Expand Up @@ -177,6 +183,15 @@ def setupDashboardFrame(self) -> None:
self.buttonSelectAll.pack(side=LEFT, padx=(400, 0), pady=(20, 0))
self.buttonProceed.pack(side=LEFT, padx=(50, 0), pady=(20, 0))

# 设置进度条
self.progressBar = ttk.Progressbar(
master=self.progressFrame,
orient=tkinter.HORIZONTAL,
value=0,
bootstyle=(SUCCESS, STRIPED),
)
self.progressBar.pack(fill=X, padx=(30, 30), expand=YES)

def login(self) -> None:
"""登录"""
username = self.varUsername.get()
Expand Down Expand Up @@ -269,26 +284,62 @@ def selectAll(self, e: tkinter.Event) -> None:
item[0] = "☑"
self.treeLesson.item(i, values=item)

def proceedTaskAfter(self, skipper: skipper) -> None:
# 利用标志位检查完成情况
if skipper.getState():
# 执行完成
self.progressBar["value"] = 100
Messagebox.show_info(
f"跳过完成。\n成功跳过{skipper.success}个任务,失败{skipper.fail}个。", "提示"
)
# 恢复按钮到可点击状态
self.buttonSelectAll["state"] = NORMAL
self.buttonProceed["state"] = NORMAL
# 清空列表
for i in self.treeLesson.get_children():
self.treeLesson.delete(i)
self.displayLessonsById()
else:
# 未完成则需要继续回调
self.after(self.skipInterval, self.proceedTaskAfter, skipper)

def incrementProgressBar(self, args: list) -> None:
"""传递参数列表中,间隔时间为列表元素1,执行次数为元素2"""
countDown = args[1]
if not countDown == 0:
self.progressBar["value"] += 0.1
args[1] -= 1
self.progressBar.after(
int(args[0]), self.incrementProgressBar, args
)

def proceedTask(self, e: tkinter.Event) -> None:
successCount = 0
failCount = 0
sectionList = list()
argList = list()
skipThread = None
# 检查完成的间隔时间
self.skipInterval = 1000 + 500
# 预计任务全部完成需要的时间
self.skipDuration = 500
# 获取勾选的任务sectionID
for i in self.treeLesson.get_children():
item = self.treeLesson.item(i)["values"]
if item[0] == "☑":
sectionList.append(str(item[3]))
for i in sectionList:
result = self.core.skip_section(i)
if result["code"] == 200:
successCount += 1
else:
failCount += 1
if len(sectionList) != 1:
sleep(31)
Messagebox.show_info(
f"跳过完成。\n成功跳过{successCount}个任务,失败{failCount}个。", "提示"
)
# 清空列表
for i in self.treeLesson.get_children():
self.treeLesson.delete(i)
self.displayLessonsById()
# 默认检查间隔是1秒。如果任务数量大于1,就改为31秒
# 额外增加了500ms,防止出现检查的时候当前的单个任务差一点就完成的情况
if len(sectionList) != 1:
self.skipInterval = 31000 + 500
self.skipDuration = (31000 + 1000) * len(sectionList)
skipThread = skipper(core=self.core, sectionList=sectionList)
skipThread.start()
# 关闭按钮,防止任务执行过程中再次点击
self.buttonSelectAll["state"] = DISABLED
self.buttonProceed["state"] = DISABLED
# 开启回调,检查任务执行情况
self.after(self.skipInterval, self.proceedTaskAfter, skipThread)
print(self.skipDuration)
argList = [int(self.skipDuration / 1000), 1000]
# 开始进度条之前需要先清空
self.progressBar["value"] = 0
self.progressBar.after(0, self.incrementProgressBar, argList)
46 changes: 46 additions & 0 deletions ui/skipper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
from src.core import Core

import threading
from time import sleep


class skipper(threading.Thread):
"""用于执行跳过课程任务的线程类"""

def __init__(self, core: Core, sectionList: list) -> None:
"""参数说明:
*core* 功能内核对象,来自src.core
*sectionList* 包含课程ID的字符串列表
"""
threading.Thread.__init__(self)
self.core = core
self.sectionList = sectionList
self.success = 0
self.fail = 0
self.state = False

def run(self) -> None:
print("skip thread started")
self.skip(self.sectionList)

def skip(self, sectionList: list) -> None:
print("skip task started")
for i in sectionList:
result = self.core.skip_section(i)
if result["code"] == 200:
self.success += 1
else:
self.fail += 1
# 对于任务列表长度为1的情况就没有必要sleep这么久了,只有长度超过1的才要分别sleep 31秒
if len(sectionList) != 1:
sleep(31)
# 跳出循环说明任务执行完成,修改状态标志位为True
self.state = True

def getState(self) -> bool:
"""返回True说明任务执行完成,False为未完成"""
return self.state

0 comments on commit 8dc28ba

Please sign in to comment.