1
1
mirror of https://github.com/KenanZhu/AutoLibrary.git synced 2026-06-18 07:23:03 +08:00

Compare commits

...

10 Commits

Author SHA1 Message Date
KenanZhu f13d983124 fix(AutoLib): correct config key from 'run/mode' to 'mode/run_mode'
Update dictionary key retrieval to use the correct
key 'mode/run_mode' instead of the outdated 'run/mode'.

This aligns the code with the recent configuration changes.
2025-11-07 22:58:43 +08:00
KenanZhu 30db2fbf9a chore(LibChecker): add new LibOperator: LibChecker.py
We introduce a new LibOperator which is used to check
if a given user date is available for reserve or check-in.

This is ready for the upcoming feature: 'Auto Check-In'.
2025-11-07 22:48:46 +08:00
KenanZhu 11bcd77208 chore(*, .gitignore): rename some folders, correct expressions in their readme.md files, and update the .gitignore 2025-11-07 13:40:04 +08:00
KenanZhu 833e5576da docs(readme): update the mistaken suffix of readme.md 2025-11-07 12:35:01 +08:00
KenanZhu efa211761d refactor(AutoLib): optimize run mode handling for extensibility
Refactor run mode processing logic to improve
adaptability for new operations.

Introduce a dedicated "passed" status to
distinguish passed users instead of classifying
them as failed.
2025-11-06 23:30:08 +08:00
KenanZhu 269eed1cac fix(LibReserve): remove spare wait in reserve operate and checking reserve list 2025-11-06 22:44:18 +08:00
KenanZhu 99975ebeee docs(manual.html): complete the user manual 2025-11-06 22:43:43 +08:00
KenanZhu a8789ad743 fix(LibReserve): fix the failure to select nearest reserve time when the max time difference is 0
The previous implementation only considered the case when more than one nearest time exists,
so we introduced the prefer_early flag to decide which one to be selected.But the comparsion
mistakenly omitted the edge case when the difference is 0.
2025-11-06 20:07:43 +08:00
KenanZhu bf106ea234 fix(AutoLib): fix the missed user counter while running the task 2025-11-06 20:07:43 +08:00
KenanZhu c67a7e3773 fix(gui.ALConfigWidget): allow earlier selection of next day and fix dialog title on config load
previous time that you can select the next day is 19:00, this may be
tensive, because the time rested to modify the reserve date is limited.
So in current commit, we change this into 18:00.
2025-11-06 20:07:43 +08:00
21 changed files with 673 additions and 288 deletions
+17 -14
View File
@@ -1,14 +1,17 @@
**/build
**/dist
**/models/*.onnx
**/driver/*.exe
**/.git
**/.vscode
**/.stfolder
**/.stignore
**/gui/AutoLibraryResources.py
**/__pycache__
**/gui/AutoLibraryResource.py
**/gui/Ui_ALMainWindow.py
**/gui/Ui_ALConfigWidget.py
**/gui/translators/qtbase_zh_CN.qm
.vscode/
.stfolder
.stignore
__pycache__/
build/
dist/
model/*.onnx
driver/*.exe
gui/configs/*.json
gui/translators/qtbase_zh_CN.qm
gui/AutoLibraryResources.py
gui/AutoLibraryResource.py
gui/Ui_ALMainWindow.py
gui/Ui_ALConfigWidget.py
Main.spec
+42 -27
View File
@@ -145,9 +145,10 @@ class AutoLib(MsgBase):
username: str,
password: str,
reserve_info: dict,
) -> bool:
) -> int:
success = False
# result : 0 - success, 1 - failed, 2 - passed
result = 1
# login
if not self.__lib_login.login(
@@ -156,31 +157,36 @@ class AutoLib(MsgBase):
self.__system_config_reader.get("login/max_attempt", 5),
self.__system_config_reader.get("login/auto_captcha", True),
):
return False
run_mode = self.__system_config_reader.get("run/mode", 1)
run_mode = {
"auto_reserve": run_mode&0x1,
"auto_checkin": run_mode&0x2,
"auto_renewal": run_mode&0x4,
}
# reserve or checkin or renewal
return 1
"""
Here, we collect the run mode from the config file.
"""
if self.__lib_reserve.canReserve(reserve_info.get("date")) and run_mode["auto_reserve"]:
if self.__lib_reserve.reserve(reserve_info):
self._showTrace(f"用户 {username} 预约成功 !")
success = True
run_mode = self.__system_config_reader.get("mode/run_mode", 0)
run_mode = {
"auto_reserve": run_mode&0x1,
"auto_checkin": run_mode&0x2,
"auto_renewal": run_mode&0x4,
}
# reserve
if run_mode["auto_reserve"]:
if self.__lib_reserve.canReserve(reserve_info.get("date")):
if self.__lib_reserve.reserve(reserve_info):
self._showTrace(f"用户 {username} 预约成功 !")
result = 0
else:
self._showTrace(f"用户 {username} 预约失败 !")
result = 1
else:
self._showTrace(f"用户 {username} 预约失败 !")
success = False
result = 2
# logout
if not self.__lib_logout.logout(
username,
):
# if logout is failed, we must make sure the host to be reloaded
# otherwise, the next login may fail
self.__driver.get(self.__system_config_reader.get("library/host_url"))
return False
return success
return 1
return result
def run(
@@ -197,24 +203,33 @@ class AutoLib(MsgBase):
if not self.__initDriverUrl():
return
user_counter = {"current": 0, "success": 0, "failed": 0}
user_counter = {"current": 0, "success": 0, "failed": 0, "passed": 0}
users = self.__users_config_reader.get("users")
self._showTrace(f"共发现 {len(users)} 个用户, "\
f"用户配置文件路径: {self.__users_config_reader.configPath()}")
self._showTrace(
f"共发现 {len(users)} 个用户, "\
f"用户配置文件路径: {self.__users_config_reader.configPath()}"
)
for user in users:
self._showTrace(f"正在处理第 {user_counter["current"]}/{len(users)} 个用户: {user['username']}......")
if self.__run(
user_counter["current"] += 1
self._showTrace(
f"正在处理第 {user_counter["current"]}/{len(users)} 个用户: {user['username']}......"
)
r = self.__run(
username=user["username"],
password=user["password"],
reserve_info=user["reserve_info"],
):
)
if r == 0:
user_counter["success"] += 1
else:
elif r == 1:
user_counter["failed"] += 1
elif r == 2:
user_counter["passed"] += 1
self._showTrace(f"处理完成, 共计 {user_counter["current"]} 个用户, "\
f"成功 {user_counter["success"]} 个用户, "\
f"失败 {user_counter["failed"]} 个用户")
f"失败 {user_counter["failed"]} 个用户, "\
f"跳过 {user_counter["passed"]} 个用户"
)
return
+207
View File
@@ -0,0 +1,207 @@
# -*- coding: utf-8 -*-
"""
Copyright (c) 2025 KenanZhu.
All rights reserved.
This software is provided "as is", without any warranty of any kind.
You may use, modify, and distribute this file under the terms of the MIT License.
See the LICENSE file for details.
"""
import re
import time
import queue
from datetime import datetime, timedelta
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from LibOperator import LibOperator
class LibChecker(LibOperator):
def __init__(
self,
input_queue: queue.Queue,
output_queue: queue.Queue,
driver
):
super().__init__(input_queue, output_queue)
self.__driver = driver
def _waitResponseLoad(
self
) -> bool:
pass
def __navigateToReserveRecordPage(
self
) -> bool:
try:
WebDriverWait(self.__driver, 5).until(
EC.element_to_be_clickable((By.XPATH, "//a[@href='/history?type=SEAT']"))
).click()
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.CLASS_NAME, "myReserveList"))
)
except:
self._showTrace("加载预约记录页面失败 !")
return False
return True
def __getReserveRecord(
self,
wanted_date: str,
wanted_status: str
) -> dict:
if wanted_date is None:
self._showTrace("日期未指定, 无法检查当前预约状态")
return None
self._showTrace(f"正在检查用户在日期 {wanted_date} 是否有预约状态为 {wanted_status} 的预约记录......")
date_obj = datetime.strptime(wanted_date, "%Y-%m-%d").date()
checked_count = 0
max_check_times = 3 # we only check (3*4=)12 reservations
if not self.__navigateToReserveRecordPage():
return None
for _ in range(max_check_times):
try:
# check if there's any reservation on the date
reservations = self.__driver.find_elements(
By.CSS_SELECTOR, ".myReserveList dl"
)
except:
self._showTrace("加载预约记录失败 !")
return None
for i in range(checked_count, len(reservations) - 1): # the last one is load button
reservation = reservations[i]
try:
time_element = reservation.find_element(
By.CSS_SELECTOR, "dt"
)
info_elements = reservation.find_elements(
By.CSS_SELECTOR, "a"
)
except:
self._showTrace(f"解析第 {i + 1} 条预约记录时发生未知错误 !")
continue
is_wanted = any(wanted_status in status.text for status in info_elements)
# process time element to get the date string
time_str = time_element.text.strip()
today = datetime.now().date()
if "明天" in time_str:
target_date = today + timedelta(days=1)
date_str = target_date.strftime("%Y-%m-%d")
elif "今天" in time_str:
target_date = today
date_str = target_date.strftime("%Y-%m-%d")
elif "昨天" in time_str:
target_date = today - timedelta(days=1)
date_str = target_date.strftime("%Y-%m-%d")
else:
date_match = re.search(r'(\d{4}-\d{1,2}-\d{1,2})', time_str)
if date_match:
date_str = date_match.group(1)
else:
self._showTrace(f"无法解析第 {i + 1} 条预约记录的日期 ! 该记录的时间为 {time_str}")
continue
# reservation is later than the given date, check the next one
if datetime.strptime(date_str, "%Y-%m-%d").date() > date_obj:
continue
# reservation is earlier than the given date, can reserve
if datetime.strptime(date_str, "%Y-%m-%d").date() < date_obj:
return None
# query the wanted status
if is_wanted:
self._showTrace(f"寻找到第 {i + 1} 条预约记录, 状态为 {wanted_status}")
time_match = re.search(r"(\d{1,2}:\d{2}) -- (\d{1,2}:\d{2})", time_str)
if time_match is None:
self._showTrace(f"无法解析第 {i + 1} 条预约记录的时间 ! 该记录的时间为 {time_str}")
continue
return {
"index": i,
"date": date_str,
"time_str": time_match.group(0),
"status": wanted_status
}
checked_count = len(reservations) - 1
# load new reservations if still not sure
try:
more_btn = self.__driver.find_element(By.ID, "moreBtn")
if more_btn.is_displayed() and more_btn.is_enabled():
self.__driver.execute_script("arguments[0].scrollIntoView(true);", more_btn)
self.__driver.execute_script("arguments[0].click();", more_btn)
else:
self._showTrace("该用户无法加载更多预约记录")
break
except:
self._showTrace("加载更多预约记录失败 !")
break
return None
def canReserve(
self,
date: str
) -> bool:
# no reserved or using record in the given date
# then can reserve
if self.__getReserveRecord(date, "已预约") is None:
if self.__getReserveRecord(date, "使用中") is None:
self._showTrace(f"用户在日期 {date} 可以预约")
return True
self._showTrace(f"用户在日期 {date} 有使用中的预约, 无法预约")
self._showTrace(f"用户在日期 {date} 已存在有效预约, 无法预约")
return False
def canCheckin(
self,
date: str
) -> bool:
# have a reserved record in the given date
record = self.__getReserveRecord(date, "已预约")
if record is not None:
time_match = re.search(r"(\d{1,2}:\d{2})", record["time_str"])
if time_match:
begin_time = time_match.group(0)
begin_time = datetime.strptime(f"{date} {begin_time}", "%Y-%m-%d %H:%M")
time_diff = datetime.now() - begin_time
time_diff_seconds = time_diff.total_seconds()
# before 30 minutes, cant checkin
if time_diff_seconds < -30*60:
self._showTrace(
f"用户在日期 {date} 的预约开始时间为 {begin_time}, "
f"距离当前时间还有 {abs(time_diff_seconds)/60:.2f} 分钟, 无法签到"
)
return False
# before in 30 minutes, can checkin
elif -30*60 <= time_diff_seconds < 0:
self._showTrace(
f"用户在日期 {date} 的预约开始时间为 {begin_time}, "
f"距离当前时间还有 {abs(time_diff_seconds)/60:.2f} 分钟, 可以签到"
)
return True
# past less than 30 minutes, can checkin
elif 0 <= time_diff_seconds < 30*60:
self._showTrace(
f"用户在日期 {date} 的预约开始时间为 {begin_time}, "
f"当前时间已经 {abs(time_diff_seconds)/60:.2f} 分钟, 可以签到"
)
return True
else:
self._showTrace(f"用户在日期 {date} 的预约时间格式错误, 无法签到")
self._showTrace(f"用户在日期 {date} 有没有有效预约记录, 无法签到")
return False
+5 -8
View File
@@ -403,9 +403,9 @@ class LibReserve(LibOperator):
if abs_diff < best_time_diff or (
abs_diff == best_time_diff and (
# prefer earlier time
(prefer_earlier and actual_diff < 0) or
(prefer_earlier and actual_diff <= 0) or
# prefer later time
(not prefer_earlier and actual_diff > 0)
(not prefer_earlier and actual_diff >= 0)
)
):
best_time_diff = abs_diff
@@ -508,9 +508,6 @@ class LibReserve(LibOperator):
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.CLASS_NAME, "myReserveList"))
)
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".myReserveList dl"))
)
except:
self._showTrace("加载预约记录页面失败 !")
return False
@@ -600,7 +597,7 @@ class LibReserve(LibOperator):
WebDriverWait(self.__driver, 5).until(
EC.element_to_be_clickable((By.XPATH, "//a[@href='/map']"))
).click()
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.ID, "seatLayout"))
)
except:
@@ -615,7 +612,7 @@ class LibReserve(LibOperator):
return False
# room find
try:
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.element_to_be_clickable((By.ID, "findRoom"))
).click()
except:
@@ -638,7 +635,7 @@ class LibReserve(LibOperator):
pass
else:
try:
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.element_to_be_clickable((By.ID, "reserveBtn"))
).click()
submit_reserve = True
Binary file not shown.

After

Width:  |  Height:  |  Size: 785 KiB

+351 -234
View File
@@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="./AutoLibrary.ico" type="image/x-icon">
<title>AutoLibrary 操作手册</title>
<style>
* {
@@ -46,31 +47,25 @@
height: 100vh;
overflow-y: auto;
}
.sidebar-header {
padding-bottom: 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
margin-bottom: 1.5rem;
transition: all 0.2s ease;
}
.sidebar-header:hover {
color: white;
}
.sidebar h1 {
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
.sidebar-nav {
list-style: none;
}
.sidebar-nav li {
margin-bottom: 0.5rem;
}
.sidebar-nav a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
@@ -79,7 +74,6 @@
border-radius: 5px;
transition: all 0.2s ease;
}
.sidebar-nav a:hover,
.sidebar-nav a.active {
background: rgba(255, 255, 255, 0.1);
@@ -112,14 +106,6 @@
margin: 1.5rem 0 1rem;
}
.intro-box {
background: #e3f2fd;
border-left: 4px solid var(--secondary);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 0 5px 5px 0;
}
.step-container {
counter-reset: step-counter;
}
@@ -149,7 +135,6 @@
flex-shrink: 0;
font-size: 1.1rem;
}
.step-number::before {
content: counter(step-counter);
}
@@ -157,27 +142,56 @@
.step-content {
flex: 1;
}
.step-image {
background: #e9ecef;
border-radius: 5px;
height: 180px;
display: flex;
align-items: center;
justify-content: center;
color: var(--gray);
margin: 1rem 0;
font-style: italic;
.step-content ol {
padding-left: 1em;
}
.step-content ul {
padding-left: 1em;
}
.step-content li {
line-height: 1.5;
}
.note {
.step-image {
background: #f0f0f0;
border-radius: 5px;
padding: 15px;
margin: 1rem 0;
display: inline-block;
text-align: center;
border: 1px solid #ddd;
max-width: 100%;
box-sizing: border-box;
}
.step-image img {
max-width: 60%;
height: auto;
border-radius: 3px;
display: block;
margin: 0 auto;
}
.intro-box {
background: #e3f2fd;
border-left: 4px solid var(--secondary);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 0 5px 5px 0;
}
.info {
background: #e3f2fd;
border-left: 4px solid #0783ff;
padding: 1rem;
margin: 1rem 0;
border-radius: 0 5px 5px 0;
}
.important {
background: #fff3cd;
border-left: 4px solid #ffc107;
padding: 1rem;
margin: 1rem 0;
border-radius: 0 5px 5px 0;
}
.warning {
background: #f8d7da;
border-left: 4px solid #dc3545;
@@ -185,6 +199,14 @@
margin: 1rem 0;
border-radius: 0 5px 5px 0;
}
.highlight {
background: #e3f2fd;
color: #3498db;
padding: 3px 6px;
border-radius: 3px;
font-size: 0.9rem;
font-family: 'Consolas', monospace;
}
.code-block {
background: #2d2d2d;
@@ -195,18 +217,18 @@
margin: 1rem 0;
font-family: 'Consolas', monospace;
white-space: pre-wrap;
border-radius: 0 5px 5px 0;
border-radius: 15px 15px 5px 5px;
font-size: 0.9rem;
overflow-x: auto;
line-height: 1.4;
}
.code-block .key { color: #2b997f; }
.code-block .string { color: #9acf65; }
.code-block .number { color: #3dd942; }
.code-block .boolean { color: #24e9ff; }
.code-block .null { color: #ff79c6; }
.code-block .property { color: #8be9fd; }
.code-block .punctuation { color: #f8f8f2; }
.code-block .bool { color: #569CD6; }
.code-block .string { color: #CE9178; }
.code-block .number { color: #B5CEA8; }
.code-block .boolean { color: #569CD6; }
.code-block .null { color: #569CD6; }
.code-block .property { color: #9CDCFE; }
.code-block .punctuation { color: #D4D4D4; }
.feature-grid {
display: grid;
@@ -214,7 +236,6 @@
gap: 1.5rem;
margin-top: 1.5rem;
}
.feature-card {
background: white;
border: 1px solid var(--border);
@@ -222,25 +243,34 @@
padding: 1.5rem;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.feature-icon {
font-size: 2rem;
color: var(--secondary);
margin-bottom: 1rem;
}
.config-tabs {
display: flex;
margin-bottom: 1rem;
border-bottom: 1px solid var(--border);
.download-section {
text-align: center;
padding: 2rem;
background: var(--light);
border-radius: 8px;
margin-top: 2rem;
}
.config-tab {
.tabs-container {
margin-top: 0.5rem;
margin-bottom: 1rem;
}
.tab-buttons {
display: flex;
margin-bottom: 0;
border-bottom: 1px solid var(--border);
}
.tab-button {
padding: 0.8rem 1.5rem;
cursor: pointer;
border: none;
@@ -250,34 +280,36 @@
border-bottom: 3px solid transparent;
transition: all 0.3s ease;
}
.config-tab.active {
.tab-button.active {
color: var(--secondary);
border-bottom: 3px solid var(--secondary);
}
.tab-content {
background: white;
border-radius: 0 5px 5px 5px;
padding: 1.5rem;
border: 1px solid var(--border);
border-top: none;
min-height: 300px;
display: flex;
align-items: center;
justify-content: center;
}
.tab-pane {
display: none;
width: 100%;
}
.tab-pane.active {
display: block;
display: flex;
flex-direction: column;
/* align-items: center;
justify-content: center; */
}
.download-section {
text-align: center;
padding: 2rem;
background: var(--light);
border-radius: 8px;
margin-top: 2rem;
.tab-pane img {
max-width: 60%;
max-height: 60%;
border-radius: 5px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
}
.btn {
@@ -292,7 +324,6 @@
border: none;
cursor: pointer;
}
.btn:hover {
background: #2980b9;
transform: translateY(-2px);
@@ -304,7 +335,6 @@
border-radius: 5px;
overflow: hidden;
}
.faq-question {
padding: 1rem 1.5rem;
background: var(--light);
@@ -314,23 +344,22 @@
justify-content: space-between;
align-items: center;
}
.faq-answer {
padding: 1rem 1.5rem;
background: rgb(220, 220, 220);
display: none;
}
.faq-item.active .faq-answer {
display: block;
}
.browser-drivers {
display: flex;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
justify-content: space-between;
gap: 1.5rem;
margin: 1.5rem 0;
}
.browser-card {
flex: 1;
background: white;
@@ -340,12 +369,10 @@
text-align: center;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.browser-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.browser-logo {
width: 80px;
height: 80px;
@@ -356,17 +383,14 @@
border-radius: 8px;
overflow: hidden;
}
.browser-logo img {
max-width: 100%;
max-height: 100%;
}
.browser-card h4 {
margin-bottom: 1rem;
color: var(--primary);
}
.browser-card .btn {
margin-top: 1rem;
}
@@ -397,15 +421,13 @@
<aside class="sidebar">
<div class="sidebar-header">
<h1>AutoLibrary</h1>
<p>操作手册 v0.01</p>
<p>操作手册 alpha-v0.03</p>
</div>
<ul class="sidebar-nav">
<li><a href="#intro" class="active">工具简介</a></li>
<li><a href="#preparation">准备工作</a></li>
<li><a href="#usage">使用步骤</a></li>
<li><a href="#configuration">配置说明</a></li>
<li><a href="#features">功能详解</a></li>
<li><a href="#interface">用户界面</a></li>
<li><a href="#features">功能介绍</a></li>
<li><a href="#troubleshooting">故障排除</a></li>
<li><a href="#faq">常见问题</a></li>
<li><a href="#download">下载安装</a></li>
@@ -413,7 +435,8 @@
</aside>
<main class="content">
<section id="name" class="section">
<section id="name" class="section" style="display: flex; align-items: center; gap: 10px;">
<img src="./AutoLibrary.ico" alt="AutoLibrary" style="width: 80px; height: 80px;">
<h1>AutoLibrary</h1>
</section>
@@ -424,7 +447,7 @@
<div class="intro-box">
<p>AutoLibrary 是一款专为北京建筑大学图书馆设计的自动化工具,旨在帮助学生简化图书馆座位操作流程,节省宝贵时间。</p>
</div>
<p>本工具模拟人工操作,通过简单的界面交互使用。</p>
<p>本工具模拟人工操作,通过简单的界面配置并交互使用。</p>
<h3>工具特点</h3>
<ul>
@@ -475,11 +498,8 @@
</div>
</div>
<div class="note">
<strong>注意</strong> 浏览器驱动版本必须与您的浏览器版本兼容,否则工具无法正常工作。
</div>
<div class="step-image">
浏览器驱动下载页面截图区域
<div class="info">
<strong>提示</strong> 浏览器驱动版本必须与您的浏览器版本兼容,否则工具无法正常工作。
</div>
</div>
</div>
@@ -488,9 +508,11 @@
<div class="step-number"></div>
<div class="step-content">
<h3>确认驱动路径</h3>
<p>下载驱动后,将浏览器驱动程序的路径(如'C:\Users\Administrator\Downloads\msedgedriver.exe')输入到AutoLibrary配置界面中。</p>
<p>下载驱动后,将浏览器驱动程序的路径通过配置窗口加载到AutoLibrary中。</p>
<p>例如:<span class="highlight">C:\Users\Administrator\Downloads\msedgedriver.exe</span></p>
<div class="step-image">
驱动文件放置位置截图区域
<img src="./配置窗口-系统配置-浏览器路径选择.png" alt="浏览器驱动路径示意图">
</div>
</div>
</div>
@@ -503,13 +525,13 @@
<div class="step">
<div class="step-number"></div>
<div class="step-content">
<h3>编辑配置文件</h3>
<p>使用文本编辑器(如记事本、Visual Studio Code等)打开config.json和users.json文件,按照您的需求修改参数</p>
<div class="warning">
<strong>重要</strong> 请勿使用Microsoft Word等富文本编辑器,这可能导致文件格式错误
<h3>启动工具</h3>
<p>双击运行AutoLibrary.exe文件,工具将启动主界面</p>
<div class="info">
<strong>提示</strong>软件首次启动,未初始化配置文件,直接运行脚本会提示失败
</div>
<div class="step-image">
配置文件编辑截图区域
<img src="./运行主界面.png" alt="运行主界面">
</div>
</div>
</div>
@@ -517,10 +539,180 @@
<div class="step">
<div class="step-number"></div>
<div class="step-content">
<h3>运行工具</h3>
<p>双击运行main.exe文件,工具将自动开始预约流程。</p>
<div class="step-image">
工具运行界面截图区域
<h3>配置工具</h3>
<p>对于不同用户的需求,你可以使用两种不同的方式来配置工具</p>
<p>1. 使用界面配置:点击主界面窗口右上角的配置按钮,打开配置窗口。</p>
<div id="use-ui" class="tabs-container">
<div class="tab-buttons">
<button class="tab-button active" data-tab="user-config">用户配置</button>
<button class="tab-button" data-tab="system-config">系统配置</button>
<button class="tab-button" data-tab="other-config">其它</button>
</div>
<div class="tab-content">
<div id="user-config" class="tab-pane active">
<div class="step-image">
<img src="./配置窗口-用户配置.png" alt="配置窗口-用户配置">
</div>
<div class="info">
<strong>提示:</strong>初次运行软件时,用户配置默认为空,需要手动添加。
</div>
<h4>用户列表</h4>
<p>用户列表显示当前配置文件中的所有用户,你可以添加、删除用户。选中用户项以进行详细的配置。</p>
<h4>用户信息</h4>
<ol>
<p><i>-学号:</i>用户的学号。</p>
<p><i>-密码:</i>用户的密码,用户默认密码为000000。</p>
</ol>
<h4>预约信息</h4>
<ol>
<p><i>-日期(YYYY-MM-DD):</i>座位预约日期,默认显示当前日期,无法更改(图书馆19:00-23:00可以预约第二天座位,软件将在18:00-23:00允许用户选择第二天的日期)。</p>
<p><i>-地点:</i>预约座位的地点,默认值为“图书馆”。</p>
<p><i>-楼层:</i>预约座位的楼层,默认值为“二层”。</p>
<p><i>-区域:</i>预约座位的区域,默认值为“二层内环”。</p>
<p><i>-座位号:</i>预约座位的座位号。</p>
<p><i>-开始时间(HH:mm):</i>预约座位的开始时间,默认值为当前时间,可选时间范围为7:30-23:30。</p>
<p><i>-结束时间(HH:mm):</i>预约座位的结束时间,默认值为当前时间加上两个小时,可选时间范围与开始时间相同。</p>
<p><i>-最大时间偏差(分钟):</i>选择的开始/结束时间不可用时,会按照该时间偏差范围寻找最近的可用时间。选择0则表示严格按照选择的时间预约,可选范围为0-120分钟。</p>
<p><i>-优先选择最早/晚:</i>当预约时间列表中存在多个相距最近的可用时间时,选择最早(开始时间)/最晚(结束时间)的时间,不勾选将会按照脚本默认行为选择。</p>
<p><i>-期望时长(小时):</i>预约座位的期望时长,默认值为“2小时”,可选范围为0-8小时。</p>
<p><i>-优先满足期望时长:</i>勾选此项,会优先满足预约时长限制,当座位紧张时可能会导致预约失败。</p>
</ol>
</div>
<div id="system-config" class="tab-pane">
<div class="step-image">
<img src="./配置窗口-系统配置.png" alt="配置窗口-系统配置">
</div>
<h4>图书馆设置</h4>
<p>这里主要包含了关于图书馆的访问网址设置,不需要更改。</p>
<h4>浏览器设置</h4>
<p>主要包含浏览器类别选择(当前支持Edge Chromium和Mozilla Firefox),浏览器驱动路径选择以及无头模式设置。</p>
<ol>
<p><i>-浏览器类别:</i>选择您使用的浏览器类别(Edge Chromium或Mozilla Firefox)。</p>
<p><i>-浏览器驱动路径:</i>点击浏览按钮选择对应浏览器类型和版本的浏览器驱动程序的路径。</p>
<p><i>-无头模式:</i>如果您不希望看到浏览器窗口自动操作,可将无头模式设置为true。</p>
</ol>
<h4>登录设置</h4>
<ol>
<p><i>-自动识别验证码:</i>默认勾选。</p>
<p><i>-登录尝试次数:</i>设置登录尝试的最大次数,默认值为3次。</p>
</ol>
<h4>运行模式</h4>
<ol>
<p><i>-自动预约:</i>脚本按照配置中起始时间和预期时长进行预约,用户如果当天存在有效预约,将自动跳过预约步骤。</p>
<p><i>-自动签到:</i>如果用户在脚本启动时满足图书馆预约条件,将自动签到,如果用户当天无有效预约或不在可签到时间内,则自动跳过。</p>
<p><i>-自动续约:</i>如果用户在脚本启动时满足图书馆预约条件,将自动续约,如果用户当天无有效预约或不在可续约时间内,则自动跳过。</p>
</ol>
</div>
<div id="other-config" class="tab-pane">
<div class="step-image">
<img src="./配置窗口-其它.png" alt="配置窗口-其它">
</div>
<h4>当前配置:</h4>
<p>这里主要显示脚本当前使用的系统配置文件和用户配置文件的路径。你可以使用右侧浏览按钮选择新的配置文件路径。</p>
<h4>导出配置:</h4>
<p>选择导出配置文件的目标路径和文件名,点击‘导出配置文件’按钮,将当前的配置项导出。</p>
</div>
</div>
</div>
<p>2. 使用配置文件:在脚本可执行文件的根目录创建系统配置文件system.json和用户配置文件users.json。</p>
<div id="use-file" class="tabs-container">
<div class="tab-buttons">
<div class="tab-button active" data-tab="system.config">系统配置文件</div>
<div class="tab-button" data-tab="users.config">用户配置文件</div>
</div>
<div class="tab-content">
<div id="system.config" class="tab-pane active">
<p>system.json文件控制工具的基本运行参数:</p>
<div class="code-block">
{
<span class="property">"library"</span>: {
<span class="property">"host_url"</span>: <span class="string">"http://10.1.20.7"</span>,
<span class="property">"login_url"</span>: <span class="string">"/login"</span>
},
<span class="property">"mode"</span>: {
<span class="property">"run_mode"</span>: <span class="number">1</span>
},
<span class="property">"login"</span>: {
<span class="property">"auto_captcha"</span>: <span class="bool">true</span>,
<span class="property">"max_attempt"</span>: <span class="number">3</span>
},
<span class="property">"web_driver"</span>: {
<span class="property">"driver_type"</span>: <span class="string">"edge"</span>,
<span class="property">"driver_path"</span>: <span class="string">"msedgedriver.exe"</span>,
<span class="property">"headless"</span>: <span class="bool">false</span>
}
}
</div>
<h4>参数说明</h4>
<ol>
<p><strong>library/host_url</strong>: 图书馆主机URL,无需更改。</p>
<p><strong>library/login_url</strong>: 登录页面URL,无需更改。</p>
<p><strong>mode/run_mode</strong>: 运行模式,可组合使用(+1:自动预约/+2:自动签到/+4:自动续约)</p>
<p><strong>login/auto_captcha</strong>: 自动验证码识别,建议保持true</p>
<p><strong>login/max_attempt</strong>: 登录尝试次数,默认3次</p>
<p><strong>web_driver/driver_type</strong>: 浏览器类型(edge/chrome/firefox</p>
<p><strong>web_driver/driver_path</strong>: 驱动文件路径</p>
<p><strong>web_driver/headless</strong>: 无头模式,默认false运行时显示浏览器窗口</p>
</ol>
</div>
<div id="users.config" class="tab-pane">
<p>users.json文件控制用户的预约和签到参数:</p>
<div class="code-block">
{
<span class="property">"users"</span>: [
{
<span class="property">"username"</span>: <span class="string">"您的学号"</span>,
<span class="property">"password"</span>: <span class="string">"您的密码"</span>,
<span class="property">"reserve_info"</span>: {
<span class="property">"date"</span>: <span class="string">"2025-10-30"</span>,
<span class="property">"place"</span>: <span class="string">"1"</span>,
<span class="property">"floor"</span>: <span class="string">"4"</span>,
<span class="property">"room"</span>: <span class="string">"5"</span>,
<span class="property">"begin_time"</span>: {
<span class="property">"time"</span>: <span class="string">"09:30"</span>,
<span class="property">"max_diff"</span>: <span class="number">30</span>,
<span class="property">"prefer_early"</span>: <span class="bool">true</span>
},
<span class="property">"end_time"</span>: {
<span class="property">"time"</span>: <span class="string">"21:23"</span>,
<span class="property">"max_diff"</span>: <span class="number">30</span>,
<span class="property">"prefer_early"</span>: <span class="bool">false</span>
},
<span class="property">"seat_id"</span>: <span class="string">"31A"</span>,
<span class="property">"expect_duration"</span>: <span class="number">6</span>
<span class="property">"satisfy_duration"</span>: <span class="bool">true</span>
}
},
/* 可以添加多个上述的配置块,每个用户预约信息独立配置 */
]
}
</div>
<h4>参数说明</h4>
<ol>
<p><strong>username</strong>: 学号</p>
<p><strong>password</strong>: 密码</p>
<p><strong>reserve_info/date</strong>: 预约日期(格式:YYYY-MM-DD</p>
<p><strong>reserve_info/place</strong>: 图书馆或者字符“1”</p>
<p><strong>reserve_info/floor</strong>: 预约楼层(“2”:二层,“3”:三层,“4”:四层,“5”:五层)</p>
<p><strong>reserve_info/room</strong>: 预约房间()</p>
<p><strong>reserve_info/seat_id</strong>: 座位编号(例如:“12A/12a/012A/012a”)</p>
<p><strong>reserve_info/begin_time</strong>: 预约开始时间(格式:HH:mm</p>
<p><strong>reserve_info/begin_time/max_diff</strong>: 最大时间差(分钟)</p>
<p><strong>reserve_info/begin_time/prefer_early</strong>: 是否优先预约较早时间(默认true)</p>
<p><strong>reserve_info/end_time</strong>: 预约结束时间(格式:HH:mm</p>
<p><strong>reserve_info/end_time/max_diff</strong>: 最大时间差(分钟)</p>
<p><strong>reserve_info/end_time/prefer_early</strong>: 是否优先预约较早时间(默认true)</p>
<p><strong>reserve_info/expect_duration</strong>: 期望使用时长(小时)</p>
<p><strong>reserve_info/satisfy_duration</strong>: 是否满足期望时长(默认true</p>
</ol>
<div class="info">
<strong>提示:</strong> 可以添加多个用户,工具会按顺序处理每个用户的预约请求。
</div>
</div>
</div>
</div>
</div>
</div>
@@ -529,9 +721,10 @@
<div class="step-number"></div>
<div class="step-content">
<h3>监控运行状态</h3>
<p>如果headless模式设置为false,您将看到浏览器窗口自动操作。请勿手动干预浏览器窗口</p>
<p>如果系统设置中没有勾选浏览器无头模式运行,工具会在运行过程中打开浏览器窗口,显示自动运行过程</p>
<p>除此之外,你还可以通过软件的运行日志输出区域查看详细的运行状态和错误信息。</p>
<div class="step-image">
浏览器自动操作截图区域
<img src="./监控运行状态-运行图.png" alt="监控运行状态">
</div>
</div>
</div>
@@ -539,139 +732,54 @@
<div class="step">
<div class="step-number"></div>
<div class="step-content">
<h3>查看结果</h3>
<p>工具运行完成后,查看生成的日志文件确认预约结果</p>
<h3>查看运行结果</h3>
<p>软件运行结束后日志会显示本次运行结果:“处理完成, 共计 n 个用户, 成功 n 个用户, 失败 m 个用户”</p>
<div class="step-image">
运行日志截图区域
<img src="./监控运行状态-运行结果.png" alt="查看运行结果">
</div>
</div>
</div>
</div>
</section>
<section id="configuration" class="section">
<h2>配置说明</h2>
<p>AutoLibrary通过两个配置文件来控制工具行为:config.json(工具设置)和users.json(用户信息)。</p>
<div class="config-tabs">
<button class="config-tab active" data-tab="config-tab">config.json</button>
<button class="config-tab" data-tab="users-tab">users.json</button>
</div>
<div class="tab-content">
<div id="config-tab" class="tab-pane active">
<h3>工具配置文件</h3>
<p>config.json文件控制工具的基本运行参数:</p>
<div class="code-block">
{
<span class="property">"library"</span>: {
<span class="property">"lib_host_url"</span>: <span class="string">"http://10.1.20.7"</span>,
<span class="property">"lib_login_url"</span>: <span class="string">"/login"</span>
},
<span class="property">"mode"</span>: {
<span class="property">"run_mode"</span>: <span class="number">1</span>
},
<span class="property">"login"</span>: {
<span class="property">"auto_captcha"</span>: <span class="key">true</span>,
<span class="property">"login_attempt"</span>: <span class="number">3</span>
},
<span class="property">"web_driver"</span>: {
<span class="property">"driver_type"</span>: <span class="string">"edge"</span>,
<span class="property">"driver_path"</span>: <span class="string">"msedgedriver.exe"</span>,
<span class="property">"headless"</span>: <span class="key">false</span>
}
}
</div>
<h4>参数说明</h4>
<ul>
<li><strong>run_mode</strong>: 运行模式,可组合使用(1+4+8=13)</li>
<li><strong>auto_captcha</strong>: 自动验证码识别,建议保持true</li>
<li><strong>login_attempt</strong>: 登录尝试次数,默认3次</li>
<li><strong>driver_type</strong>: 浏览器类型(edge/chrome/firefox</li>
<li><strong>driver_path</strong>: 驱动文件路径</li>
<li><strong>headless</strong>: 无头模式,false会显示浏览器窗口</li>
</ul>
</div>
<div id="users-tab" class="tab-pane">
<h3>用户配置文件</h3>
<p>users.json文件包含用户账号和预约信息:</p>
<div class="code-block">
{
<span class="property">"users"</span>: [
{
<span class="property">"username"</span>: <span class="string">"您的学号"</span>,
<span class="property">"password"</span>: <span class="string">"您的密码"</span>,
<span class="property">"reserve_info"</span>: {
<span class="property">"date"</span>: <span class="string">"2025-10-30"</span>,
<span class="property">"start_time"</span>: <span class="string">"09:30"</span>,
<span class="property">"end_time"</span>: <span class="string">"17:00"</span>,
<span class="property">"place"</span>: <span class="string">"1"</span>,
<span class="property">"floor"</span>: <span class="string">"4"</span>,
<span class="property">"room"</span>: <span class="string">"5"</span>,
<span class="property">"seat_id"</span>: <span class="string">"31A"</span>,
<span class="property">"expect_duration"</span>: <span class="number">6</span>
}
}
]
}
</div>
<h4>参数说明</h4>
<ul>
<li><strong>username</strong>: 学号</li>
<li><strong>password</strong>: 密码</li>
<li><strong>date</strong>: 预约日期(格式:YYYY-MM-DD</li>
<li><strong>start_time/end_time</strong>: 预约时间段</li>
<li><strong>place/floor/room</strong>: 图书馆位置信息</li>
<li><strong>seat_id</strong>: 座位编号(重要)</li>
<li><strong>expect_duration</strong>: 期望使用时长(小时)</li>
</ul>
<div class="note">
<strong>提示:</strong> 可以添加多个用户,工具会按顺序处理每个用户的预约请求。
</div>
</div>
</div>
</section>
<section id="features" class="section">
<h2>功能详解</h2>
<h2>功能介绍</h2>
<div class="feature-grid">
<div class="feature-card">
<div class="feature-icon"></div>
<h3>自动预约(模式 +1</h3>
<p>当您当前没有有效预约时,工具会自动为您预约指定座位。</p>
<div class="note">
<h3>自动预约</h3>
<p>如果用户当前没有有效预约时,工具会自动为您预约指定座位。</p>
<div class="info">
<strong>适用场景:</strong> 提前预约第二天的座位
</div>
</div>
<div class="feature-card">
<div class="feature-icon"></div>
<h3>自动签到(模式 +4</h3>
<p>如果已有预约,且在可签到时间范围内,工具会自动完成签到。</p>
<div class="note">
<strong>适用场景:</strong> 避免因忘记签到而失去座位
<h3>自动签到</h3>
<p>如果用户当前已有预约,且在可签到时间范围(开始时间的前后30分钟)内,工具会自动完成签到。</p>
<div class="info">
<strong>适用场景:</strong> 因忘记签到而导致失约,影响正常使用
</div>
</div>
<div class="feature-card">
<div class="feature-icon">🔄</div>
<h3>自动续约(模式 +8</h3>
<p>当您正在使用座位且到达可续约时间,工具会自动延长使用时间。</p>
<div class="note">
<strong>适用场景:</strong> 需要长时间使用座位的情况
<h3>自动续约</h3>
<p>如果用户当前正在使用座位且到达可续约时间(结束时间前的120分钟),工具会自动延长使用时间。</p>
<div class="info">
<strong>适用场景:</strong> 需要长时间使用座位
</div>
</div>
</div>
<h3>模式组合使用</h3>
<p>运行模式可以组合使用,只需将对应模式的数值相加</p>
<p>运行模式可以组合使用,只需在配置窗口中勾选对应模式即可</p>
<ul>
<li>自动预约 + 自动签到 + 自动续约 = 13(推荐)</li>
<li>自动预约 = 1</li>
<li>自动预约 + 自动签到 = 5</li>
<li>
<ol><strong>自动预约 + 自动签到 + 自动续约(推荐)</strong></ol>
<ol>自动预约</ol>
<ol>自动预约 + 自动签到</ol>
</ul>
</section>
@@ -680,13 +788,13 @@
<h3>常见问题及解决方法</h3>
<div class="faq-item">
<div class="faq-question">工具启动时报错"无法找到驱动"</div>
<div class="faq-question">工具启动时报错"无法找到驱动/Unable to obtain driver"等类似报错信息</div>
<div class="faq-answer">
<p>这是因为浏览器驱动未正确安装或版本不匹配。</p>
<p>这是大概率是因为浏览器驱动未正确安装或版本不匹配。</p>
<ul>
<li>检查驱动文件是否放置在正确位置</li>
<li>确认驱动版本与浏览器版本完全匹配</li>
<li>尝试重新下载并安装驱动</li>
<ol>1检查驱动文件是否放置在正确位置</ol>
<ol>2确认驱动版本与浏览器版本完全匹配,例如:Chrome浏览器需要对应版本的chromedriver.exe,切勿混用</ol>
<ol>3尝试重新下载并安装驱动</ol>
</ul>
</div>
</div>
@@ -694,11 +802,11 @@
<div class="faq-item">
<div class="faq-question">登录失败,提示账号密码错误</div>
<div class="faq-answer">
<p>请检查users.json文件中的账号密码是否正确。</p>
<p>请检查配置界面中的账号密码是否正确。</p>
<ul>
<li>确认学号和密码无误</li>
<li>检查是否有特殊字符需要转义</li>
<li>尝试手动登录图书馆系统确认账号可用</li>
<ol>1确认学号和密码无误</ol>
<ol>2检查是否有不支持的特殊字符需要转义</ol>
<ol>3尝试手动登录图书馆系统确认账号可用</ol>
</ul>
</div>
</div>
@@ -708,9 +816,8 @@
<div class="faq-answer">
<p>目标座位可能已被他人预约或不在可预约时间。</p>
<ul>
<li>确认座位编号是否正确</li>
<li>检查预约时间是否符合图书馆规定</li>
<li>尝试预约其他座位或调整预约时间</li>
<ol>1确认座位编号是否正确,是否在该楼层指定区域</ol>
<ol>2,尝试预约其它座位或调整预约时间,例如调整允许的开始或结束时间的最大偏差,位置紧张情况下可以让脚本根据允许的时间范围选择最佳起始时间</ol>
</ul>
</div>
</div>
@@ -729,7 +836,10 @@
<div class="faq-item">
<div class="faq-question">可以同时预约多个座位吗?</div>
<div class="faq-answer">
<p>根据图书馆规定,每个账号同一时间段只能预约一个座位。但您可以在users.json中添加多个账号,工具会依次处理每个账号的预约请求。</p>
<p>根据图书馆规定,每个账号同一时间段只能预约一个座位。但您可以在配置界面中添加多个账号,工具会依次处理每个账号的预约请求。</p>
<div class="important">
<p><strong>重要:</strong>本工具软件旨在简化并辅助用户正常使用时的图书馆服务流程,请勿滥用影响他人及图书馆正常运行。</p>
</div>
</div>
</div>
@@ -745,21 +855,20 @@
<h2>下载安装</h2>
<div class="download-section">
<h3>获取AutoLibrary</h3>
<p>点击下方按钮下载最新版本的AutoLibrary工具包:</p>
<a href="#" class="btn">下载 AutoLibrary v0.01</a>
<div class="note" style="margin-top: 1.5rem;">
<p>文件大小:约15MB</p>
<p>点击下方按钮下载最新版本的AutoLibrary压缩包:</p>
<a href="#" class="btn">下载 AutoLibrary alpha-v0.03</a>
<div class="info" style="margin-top: 1.5rem;">
<p>文件大小:约98MB</p>
<p>系统要求:Windows 10/11,支持Edge/Chrome/Firefox浏览器</p>
</div>
</div>
<h3>安装步骤</h3>
<ol>
<li>下载压缩包并解压到任意文件夹</li>
<li>根据您使用的浏览器下载对应版本的驱动</li>
<li>将驱动文件放置到工具文件夹中</li>
<li>按照本手册说明编辑配置文件</li>
<li>双击main.exe运行工具</li>
<ol>下载压缩包并解压到任意文件夹</ol>
<ol>根据您使用的浏览器下载对应版本的驱动</ol>
<ol>按照本手册说明配置账号密码等参数</ol>
<ol>点击启动脚本,即可开始自动预约和使用座位</ol>
</ol>
</section>
</main>
@@ -788,20 +897,28 @@
});
});
document.querySelectorAll('.config-tab').forEach(tab => {
tab.addEventListener('click', function() {
const tabId = this.getAttribute('data-tab');
document.querySelectorAll('.tabs-container').forEach(container => {
const tabButtons = container.querySelectorAll('.tab-button');
const tabPanes = container.querySelectorAll('.tab-pane');
document.querySelectorAll('.config-tab').forEach(t => {
t.classList.remove('active');
tabButtons.forEach(button => {
button.addEventListener('click', function() {
const containerButtons = this.closest('.tabs-container').querySelectorAll('.tab-button');
const containerPanes = this.closest('.tabs-container').querySelectorAll('.tab-pane');
containerButtons.forEach(btn => {
btn.classList.remove('active');
});
this.classList.add('active');
const tabId = this.getAttribute('data-tab');
containerPanes.forEach(pane => {
pane.classList.remove('active');
});
document.getElementById(tabId).classList.add('active');
});
this.classList.add('active');
document.querySelectorAll('.tab-pane').forEach(pane => {
pane.classList.remove('active');
});
document.getElementById(tabId).classList.add('active');
});
});
@@ -817,8 +934,8 @@
const observerOptions = {
root: null,
rootMargin: '0px 0px -50% 0px',
threshold: 0.2
rootMargin: '-45% 0px -45% 0px',
threshold: 0
};
const observer = new IntersectionObserver((entries) => {
Binary file not shown.

After

Width:  |  Height:  |  Size: 852 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

+1 -1
View File
@@ -1 +1 @@
This folder is used to store the browser driver by selenium.
This folder is used to store the browser driver using by selenium.
+2 -2
View File
@@ -268,7 +268,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.DateEdit.setDate(QDate.currentDate())
self.DateEdit.setMinimumDate(QDate.currentDate())
self.DateEdit.setMaximumDate(QDate.currentDate())
if QTime.currentTime() > QTime(19, 0, 0) and QTime.currentTime() < QTime(23, 0, 0):
if QTime.currentTime() > QTime(18, 0, 0) and QTime.currentTime() < QTime(23, 0, 0):
self.DateEdit.setMaximumDate(QDate.currentDate().addDays(1))
self.BeginTimeEdit.setTime(QTime.currentTime())
self.PreferEarlyBeginTimeCheckBox.setChecked(False)
@@ -479,7 +479,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if not config_path:
config_path = QFileDialog.getOpenFileName(
self,
"选择配置文件 - AutoLibrary",
"从现有配置文件中加载 - AutoLibrary",
f"{QDir.toNativeSeparators(QDir.currentPath())}",
"JSON 文件 (*.json);;所有文件 (*)"
)[0]
+40 -1
View File
@@ -560,6 +560,9 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;勾选此项,如果有多个与目标&lt;span style=&quot; font-weight:700; font-style:italic;&quot;&gt;开始时间&lt;/span&gt;相近的可选时间,选择时间最早项&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>优先选择最早</string>
</property>
@@ -601,6 +604,9 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;期望的&lt;span style=&quot; font-weight:700; font-style:italic;&quot;&gt;结束时间&lt;/span&gt;不可用时,按照该偏差范围寻找最近可选时间&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>120</number>
</property>
@@ -691,6 +697,9 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;期望的&lt;span style=&quot; font-weight:700; font-style:italic;&quot;&gt;开始时间&lt;/span&gt;不可用时,按照该偏差范围寻找最近可选时间&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>120</number>
</property>
@@ -710,6 +719,9 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;勾选此项,如果有多个与目标&lt;span style=&quot; font-weight:700; font-style:italic;&quot;&gt;结束时间&lt;/span&gt;相近的可选时间,选择时间最晚项&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>优先选择最晚</string>
</property>
@@ -789,6 +801,9 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;期望的预约时长,脚本会尽量满足&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<double>8.000000000000000</double>
</property>
@@ -869,6 +884,9 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;勾选此项,会优先满足预约时长限制,当座位紧张时可能会导致&lt;span style=&quot; font-weight:700; font-style:italic;&quot;&gt;预约失败&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>优先满足时长要求</string>
</property>
@@ -1046,6 +1064,12 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;脚本运行使用的浏览器类型&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="currentText">
<string>edge</string>
</property>
@@ -1113,6 +1137,12 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;详情请参阅根目录中的 manual.html&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
@@ -1150,6 +1180,12 @@
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;运行时不显示浏览器&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>无头模式</string>
</property>
@@ -1237,6 +1273,9 @@
<height>25</height>
</size>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;无需更改&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>主机URL</string>
</property>
@@ -1758,7 +1797,7 @@
</size>
</property>
<property name="text">
<string>载配置</string>
<string>载配置</string>
</property>
</widget>
</item>
+6
View File
@@ -127,6 +127,12 @@
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;开始运行自动脚本&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(10, 170, 10);
font: 12pt &quot;Microsoft YaHei UI&quot;;
+1
View File
@@ -0,0 +1 @@
this folder is used to store the config files.
+1
View File
@@ -0,0 +1 @@
This folder is used to store the model using by ddddocr.
-1
View File
@@ -1 +0,0 @@
This folder is used to store the models by ddddocr.
View File