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

Compare commits

...

4 Commits

Author SHA1 Message Date
KenanZhu 9f17474c1b fix(gui): optimize the config files' status management 2025-11-22 14:27:40 +08:00
KenanZhu 04d66346dc fix(ALConfigWidget): optimize the config window usage
add date calendar popup so that user can select
the date more easily
fix some file dialog title display issue
default max diff time change to 30 minutes
2025-11-22 14:23:35 +08:00
KenanZhu f858295af1 refactor(LibChecker): refactor the code of LibChecker to make it more readable and maintainable 2025-11-22 14:16:38 +08:00
KenanZhu cd6c899388 fix(*): optimize the operators' performance when invoking webdriver
we consume the wait time of webdriver and its
implicit wait time
2025-11-22 14:13:23 +08:00
8 changed files with 293 additions and 187 deletions
+5 -3
View File
@@ -91,7 +91,7 @@ class AutoLib(MsgBase):
self.__driver = webdriver.Firefox(service=service, options=edge_options)
case _:
raise Exception(f"不支持的浏览器驱动类型: {self.__driver_type}")
self.__driver.implicitly_wait(10)
self.__driver.implicitly_wait(1)
self.__driver.execute_script(
"Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
)
@@ -122,7 +122,7 @@ class AutoLib(MsgBase):
# wait for page load
try:
WebDriverWait(self.__driver, 5).until( # title contains "首页"
WebDriverWait(self.__driver, 2).until( # title contains "首页"
EC.title_contains("首页")
)
WebDriverWait(self.__driver, 2).until( # username field presence
@@ -147,7 +147,9 @@ class AutoLib(MsgBase):
self,
) -> bool:
self.__driver.get(self.__system_config_reader.get("library/host_url"))
url = self.__system_config_reader.get("library/host_url")
url += self.__system_config_reader.get("library/login_url")
self.__driver.get(url)
if not self.__waitResponseLoad():
return False
return True
+137 -93
View File
@@ -44,9 +44,9 @@ class LibChecker(LibOperator):
seconds: float
) -> str:
hours = int(seconds // 3600)
minutes = int(seconds % 3600 // 60)
seconds = int(seconds % 60)
hours = int(seconds//3600)
minutes = int(seconds%3600//60)
seconds = int(seconds%60)
return f"{hours}{minutes}{seconds}"
@@ -55,7 +55,7 @@ class LibChecker(LibOperator):
) -> bool:
try:
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.element_to_be_clickable((By.XPATH, "//a[@href='/history?type=SEAT']"))
).click()
WebDriverWait(self.__driver, 2).until(
@@ -67,6 +67,44 @@ class LibChecker(LibOperator):
return True
def __decodeReserveTime(
self,
time_element
) -> dict:
time_str = time_element.text.strip()
today = datetime.now().date()
if "明天" in time_str:
target_date = today + timedelta(days=1)
date = target_date.strftime("%Y-%m-%d")
elif "今天" in time_str:
target_date = today
date = target_date.strftime("%Y-%m-%d")
elif "昨天" in time_str:
target_date = today - timedelta(days=1)
date = 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 = date_match.group(1)
else:
date = ""
time_match = re.search(r"(\d{1,2}:\d{2}) -- (\d{1,2}:\d{2})", time_str)
if time_match:
begin_time = time_match.group(1)
end_time = time_match.group(2)
else:
begin_time = ""
end_time = ""
return {
"date": date,
"time": {
"begin": begin_time,
"end": end_time
}
}
def __decodeReserveInfo(
self,
info_elements
@@ -108,42 +146,80 @@ class LibChecker(LibOperator):
By.CSS_SELECTOR, "a"
)
except:
return None
# 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:
date_str = ""
time_match = re.search(r"(\d{1,2}:\d{2}) -- (\d{1,2}:\d{2})", time_str)
if time_match:
begin_time = time_match.group(1)
end_time = time_match.group(2)
else:
time_str = ""
return {
"date": "",
"time": {"begin": "", "end": ""},
"info": {"location": "", "status": ""}
}
time = self.__decodeReserveTime(time_element)
info = self.__decodeReserveInfo(info_elements)
return {
"date": date_str,
"time": {
"begin": begin_time,
"end": end_time,
},
"date": time["date"],
"time": time["time"],
"info": info
}
def __decodeReserveRecords(
self,
reservations
) -> list:
records = []
for reservation in reservations:
record = self.__decodeReserveRecord(reservation)
if record["date"] == "":
record = None
if record["time"] == {"begin": "", "end": ""}:
record = None
records.append(record)
return records
def __loadReserveRecords(
self
) -> list:
try:
# check if there's any reservation on the date
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".myReserveList > dl"))
)
reservations = self.__driver.find_elements(
By.CSS_SELECTOR, ".myReserveList > dl:not(#moreBlock)"
)
return reservations
except:
self._showTrace("加载预约记录失败 !")
return None
def __showMoreReserveRecords(
self
) -> bool:
# load new reservations if still not sure
try:
WebDriverWait(self.__driver, 0.1).until(
EC.element_to_be_clickable((By.ID, "moreBtn"))
)
except:
# the reservation is the last one
return False
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)
return True
else:
self._showTrace("用户无法加载更多预约记录")
return False
except:
self._showTrace("加载更多预约记录失败 !")
return False
def __getReserveRecord(
self,
wanted_date: str,
@@ -154,7 +230,6 @@ class LibChecker(LibOperator):
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 = 6 # we only check (4*(6-1)=)20 reservations, the last time cant be checked
@@ -162,59 +237,30 @@ class LibChecker(LibOperator):
if not self.__navigateToReserveRecordPage():
return None
for _ in range(max_check_times):
try:
# check if there's any reservation on the date
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".myReserveList > dl"))
)
reservations = self.__driver.find_elements(
By.CSS_SELECTOR, ".myReserveList > dl:not(#moreBlock)"
)
except:
self._showTrace("加载预约记录失败 !")
reservations = self.__loadReserveRecords()
if reservations is None:
return None
for i in range(checked_count, len(reservations)): # the last one is load button
reservation = reservations[i]
record = self.__decodeReserveRecord(reservation)
records = self.__decodeReserveRecords(reservations[checked_count:])
for record in records:
checked_count += 1
if record is None:
continue
record_date = record["date"]
record_time = record["time"]
status = record["info"]["status"]
location = record["info"]["location"]
if record_date == "" or record_time == {"begin": "", "end": ""}:
# record date is later than the given date, check the next one
if datetime.strptime(record["date"], "%Y-%m-%d").date() >\
datetime.strptime(wanted_date, "%Y-%m-%d").date():
continue
is_wanted = (status == wanted_status)
# reservation is later than the given date, check the next one
if datetime.strptime(record_date, "%Y-%m-%d").date() > date_obj:
continue
# reservation is earlier than the given date, can reserve
if datetime.strptime(record_date, "%Y-%m-%d").date() < date_obj:
# record date is earlier than the given date, so there is no wanted record
if datetime.strptime(record["date"], "%Y-%m-%d").date() <\
datetime.strptime(wanted_date, "%Y-%m-%d").date():
return None
# query the wanted status
if is_wanted:
if record["info"]["status"] == wanted_status:
self._showTrace(
f"寻找到用户第 {i + 1} 条状态为 {wanted_status} 的预约记录, "
f"详细信息: {record_date} {record_time['begin']} - {record_time['end']} {location}"
f"寻找到用户第 {checked_count} 条状态为 {wanted_status} 的预约记录, "
f"详细信息: {record["date"]} "
f"{record["time"]["begin"]} - {record["time"]["end"]} {record["info"]["location"]}"
)
return {
"index": i,
"date": record_date,
"time": record_time,
"status": wanted_status
}
checked_count = len(reservations)
# 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("加载更多预约记录失败 !")
return record
if not self.__showMoreReserveRecords():
break
return None
@@ -252,21 +298,21 @@ class LibChecker(LibOperator):
if time_diff_seconds < -30*60:
self._showTrace(
f"用户在 {date} 的预约开始时间为 {begin_time}, "
f"距离当前时间还有 {self.__formatDiffTime(abs(time_diff_seconds))}, 无法签到"
f"当前距离预约开始时间还有 {self.__formatDiffTime(abs(time_diff_seconds))}, 无法签到"
)
return False
# before in 30 minutes, can checkin
elif -30*60 <= time_diff_seconds < 0:
self._showTrace(
f"用户在 {date} 的预约开始时间为 {begin_time}, "
f"距离当前时间还有 {self.__formatDiffTime(abs(time_diff_seconds))}, 可以签到"
f"当前距离预约开始时间还有 {self.__formatDiffTime(abs(time_diff_seconds))}, 可以签到"
)
return True
# past less than 30 minutes, can checkin
elif 0 <= time_diff_seconds < 30*60:
elif 0 <= time_diff_seconds < 30*60 - 5: # spare 5 seconds for the checkin process
self._showTrace(
f"用户在 {date} 的预约开始时间为 {begin_time}, "
f"当前时间已经 {self.__formatDiffTime(abs(time_diff_seconds))}, 可以签到"
f"当前距离预约开始时间已经过去 {self.__formatDiffTime(abs(time_diff_seconds))}, 可以签到"
)
return True
self._showTrace(f"用户在 {date} 没有有效预约记录, 无法签到")
@@ -286,17 +332,15 @@ class LibChecker(LibOperator):
time_diff = end_time - datetime.now()
time_diff_seconds = time_diff.total_seconds()
# a using record is definitely after the begin time
trace_msg = (
f"用户在 {date} 的预约结束时间为 {end_time}, "
f"当前距离预约结束时间还有 {self.__formatDiffTime(abs(time_diff_seconds))}"
)
if abs(time_diff_seconds) < 120*60:
self._showTrace(
f"用户在 {date} 的预约结束时间为 {end_time}, "
f"距离当前时间还有 {self.__formatDiffTime(abs(time_diff_seconds))}, 可以续约"
)
self._showTrace(f"{trace_msg}, 可以续约")
return True
else:
self._showTrace(
f"用户在 {date} 的预约结束时间为 {end_time}, "
f"距离当前时间还有 {self.__formatDiffTime(abs(time_diff_seconds))}, 无法续约"
)
self._showTrace(f"{trace_msg}, 无法续约")
return False
self._showTrace(f"用户在 {date} 没有有效预约记录, 无法续约")
return False
+1 -1
View File
@@ -38,7 +38,7 @@ class LibCheckin(LibOperator):
) -> bool:
try:
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.CLASS_NAME, "ui_dialog"))
)
WebDriverWait(self.__driver, 2).until(
+3 -3
View File
@@ -41,13 +41,13 @@ class LibLogin(LibOperator):
# wait to verify login success
try:
WebDriverWait(self.__driver, 5).until( # title contains "自选座位 :: 座位预约系统"
WebDriverWait(self.__driver, 2).until( # title contains "自选座位 :: 座位预约系统"
EC.title_contains("自选座位 :: 座位预约系统")
)
WebDriverWait(self.__driver, 3).until( # search button presence
WebDriverWait(self.__driver, 2).until( # search button presence
EC.presence_of_element_located((By.ID, "search"))
)
WebDriverWait(self.__driver, 3).until( # select content presence
WebDriverWait(self.__driver, 2).until( # select content presence
EC.presence_of_element_located((By.CLASS_NAME, "selectContent"))
)
return True
+26 -7
View File
@@ -55,13 +55,13 @@ class LibReserve(LibOperator):
) -> bool:
try:
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.CLASS_NAME, "layoutSeat"))
)
title_elements = []
# reserve failed without title elements, so we need to try
try:
WebDriverWait(self.__driver, 1).until(
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".layoutSeat dt"))
)
title_elements = self.__driver.find_elements(
@@ -309,12 +309,12 @@ class LibReserve(LibOperator):
try:
# click the trigger element
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.element_to_be_clickable(trigger_locator)
).click()
if option_locator:
# select the option element if specified
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.element_to_be_clickable(option_locator)
).click()
self._showTrace(success_msg)
@@ -386,9 +386,16 @@ class LibReserve(LibOperator):
try:
# wait fot seat layout element to load
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.presence_of_element_located((By.ID, "seatLayout"))
)
WebDriverWait(self.__driver, 2).until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "li[id^='seat_']"))
)
except:
self._showTrace(f"座位加载失败 !")
return False
try:
all_seats = self.__driver.find_elements(
By.CSS_SELECTOR, "li[id^='seat_']"
)
@@ -397,7 +404,7 @@ class LibReserve(LibOperator):
if not seat_id_upper == seat.text.lstrip('0'):
continue
seat_link = seat.find_element(By.TAG_NAME, "a")
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.element_to_be_clickable(seat_link)
)
seat_link.click()
@@ -419,6 +426,15 @@ class LibReserve(LibOperator):
prefer_earlier: bool = True
) -> int:
try:
WebDriverWait(self.__driver, 2).until(
EC.presence_of_all_elements_located(
(By.CSS_SELECTOR, f"#{time_id} ul li a")
)
)
except:
self._showTrace(f"{time_type} 选择失败 ! : 当前未查询到可用时间")
return -1
try:
all_time_opts = self.__driver.find_elements(
By.CSS_SELECTOR,
@@ -429,6 +445,9 @@ class LibReserve(LibOperator):
best_actual_diff = None
best_time_opt = None
if not all_time_opts:
self._showTrace(f"{time_type} 选择失败 ! : 当前未查询到可用时间")
return -1
for time_opt in all_time_opts:
time_attr = time_opt.get_attribute("time")
if time_attr == "now":
@@ -544,7 +563,7 @@ class LibReserve(LibOperator):
return False
# map page
try:
WebDriverWait(self.__driver, 5).until(
WebDriverWait(self.__driver, 2).until(
EC.element_to_be_clickable((By.XPATH, "//a[@href='/map']"))
).click()
WebDriverWait(self.__driver, 2).until(
+101 -73
View File
@@ -32,27 +32,24 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self,
parent = None,
config_paths = {
"system":
f"{QDir.toNativeSeparators(QFileInfo(sys.executable).absoluteDir().absoluteFilePath("system.json"))}",
"users":
f"{QDir.toNativeSeparators(QFileInfo(sys.executable).absoluteDir().absoluteFilePath("users.json"))}",
"system": "",
"users": ""
}
):
super().__init__(parent)
self.setupUi(self)
self.connectSignals()
self.modifyUi()
self.__config_paths = config_paths
self.__system_config_data = self.loadSystemConfig(self.__config_paths["system"])
self.__users_config_data = self.loadUsersConfig(self.__config_paths["users"])
if not self.__system_config_data:
self.initlizeDefaultConfig("system")
if not self.__users_config_data:
self.initlizeDefaultConfig("users")
self.initlizeConfigToWidget("system", self.__system_config_data)
self.initlizeConfigToWidget("users", self.__users_config_data)
self.__config_data = {"system": {}, "users": {}}
self.__seat_map_widget = None
self.modifyUi()
self.connectSignals()
self.initlizeFloorRoomMap()
self.initlizeDefaultConfigPaths()
if not self.initlizeConfigs():
self.close()
def modifyUi(
@@ -129,42 +126,16 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
def initlizeDefaultConfigPaths(
self
) -> dict:
):
script_path = sys.executable
script_dir = QFileInfo(script_path).absoluteDir()
return {
self.__default_config_paths = {
"users": QDir.toNativeSeparators(script_dir.absoluteFilePath("users.json")),
"system": QDir.toNativeSeparators(script_dir.absoluteFilePath("system.json"))
}
def initlizeDefaultConfig(
self,
which: str
):
default_config_paths = self.initlizeDefaultConfigPaths()
if which == "system":
self.__system_config_data = self.defaultSystemConfig()
self.__config_paths["system"] = default_config_paths["system"]
self.saveSystemConfig(self.__config_paths["system"], self.__system_config_data)
elif which == "users":
self.__users_config_data = self.defaultUsersConfig()
self.__config_paths["users"] = default_config_paths["users"]
self.saveUsersConfig(self.__config_paths["users"], self.__users_config_data)
if which == "system":
file_type = "系统配置文件"
elif which == "users":
file_type = "用户配置文件"
QMessageBox.information(
self,
"提示 - AutoLibrary",
f"{file_type}已初始化, \n"\
f" 文件路径: {self.__config_paths[which]}"
)
def initlizeConfigToWidget(
self,
which: str,
@@ -180,6 +151,63 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.CurrentUserConfigEdit.setText(self.__config_paths["users"])
def initlizeConfig(
self,
which: str
) -> bool:
msg = ""
is_success = True
if which == "system":
system_config_path = self.__config_paths[which]
if not os.path.exists(system_config_path):
self.__config_data[which] = self.defaultSystemConfig()
self.__config_paths[which] = self.__default_config_paths[which]
if self.saveSystemConfig(self.__config_paths[which], self.__config_data[which]):
msg += f"系统配置文件已初始化, 文件路径: \n{self.__config_paths[which]}\n"
else:
is_success = False
else:
self.__config_data[which] = self.loadSystemConfig(system_config_path)
if self.__config_data[which] is None:
is_success = False
elif which == "users":
users_config_path = self.__config_paths[which]
if not os.path.exists(users_config_path):
self.__config_data[which] = self.defaultUsersConfig()
self.__config_paths[which] = self.__default_config_paths[which]
if self.saveUsersConfig(self.__config_paths[which], self.__config_data[which]):
msg += f"用户配置文件已初始化, 文件路径: \n{self.__config_paths[which]}\n"
else:
is_success = False
else:
self.__config_data[which] = self.loadUsersConfig(users_config_path)
if self.__config_data[which] is None:
is_success = False
if msg:
QMessageBox.information(
self,
"提示 - AutoLibrary",
f"配置文件初始化完成: \n{msg}"
)
return is_success
def initlizeConfigs(
self
) -> bool:
is_success = True
for which in ["system", "users"]:
if not self.__config_paths[which]:
self.__config_paths[which] = self.__default_config_paths[which]
if not self.initlizeConfig(which):
is_success = False
break
self.initlizeConfigToWidget(which, self.__config_data[which])
return is_success
def defaultSystemConfig(
self
) -> dict:
@@ -261,21 +289,18 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.UsernameEdit.setText("")
self.PasswordEdit.setText("")
self.UserListWidget.setSortingEnabled(True)
self.PasswordEdit.setEchoMode(QLineEdit.Password)
self.PasswordEdit.setEchoMode(QLineEdit.EchoMode.Password)
self.ShowPasswordCheckBox.setChecked(False)
self.FloorComboBox.setCurrentIndex(1) # use for the '__init__' to effect the signal
self.FloorComboBox.setCurrentIndex(0)
self.onFloorComboBoxCurrentIndexChanged()
self.DateEdit.setDate(QDate.currentDate())
self.DateEdit.setMinimumDate(QDate.currentDate())
self.DateEdit.setMaximumDate(QDate.currentDate())
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)
self.MaxBeginTimeDiffSpinBox.setValue(10)
self.MaxBeginTimeDiffSpinBox.setValue(30)
self.EndTimeEdit.setTime(QTime.currentTime().addSecs(120*60))
self.PreferLateEndTimeCheckBox.setChecked(False)
self.MaxEndTimeDiffSpinBox.setValue(10)
self.MaxEndTimeDiffSpinBox.setValue(30)
self.ExpectDurationSpinBox.setValue(self.BeginTimeEdit.time().secsTo(self.EndTimeEdit.time())/3600)
self.SatisfyDurationCheckBox.setChecked(False)
@@ -451,21 +476,21 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
) -> bool:
if users_config_path:
self.__users_config_data = self.defaultUsersConfig()
self.__config_data["users"] = self.defaultUsersConfig()
for index in range(self.UserListWidget.count()):
user_config = self.collectUserConfigFromUserListWidget(index)
if user_config:
self.__users_config_data["users"].append(user_config)
self.__config_data["users"]["users"].append(user_config)
if not self.saveUsersConfig(
users_config_path,
self.__users_config_data
self.__config_data["users"]
):
return False
if system_config_path:
self.__system_config_data = self.collectSystemConfigFromWidget()
self.__config_data["system"] = self.collectSystemConfigFromWidget()
if not self.saveSystemConfig(
system_config_path,
self.__system_config_data
self.__config_data["system"]
):
return False
return True
@@ -489,12 +514,12 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
system_config = self.loadSystemConfig(config_path)
users_config = self.loadUsersConfig(config_path)
if system_config is not None:
self.__system_config_data.update(system_config)
self.setSystemConfigToWidget(self.__system_config_data)
self.__config_data["system"].update(system_config)
self.setSystemConfigToWidget(self.__config_data["system"])
return True
if users_config is not None:
self.__users_config_data.update(users_config)
self.fillUsersList(self.__users_config_data)
self.__config_data["users"].update(users_config)
self.fillUsersList(self.__config_data["users"])
return True
except:
return False
@@ -528,12 +553,12 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
"seat_id": "",
"begin_time": {
"time": f"{QTime.currentTime().toString("hh:mm")}",
"max_diff": 0,
"max_diff": 30,
"prefer_early": False
},
"end_time": {
"time": f"{QTime.currentTime().addSecs(2*3600).toString("hh:mm")}",
"max_diff": 0,
"max_diff": 30,
"prefer_early": True
},
"expect_duration": 2.0,
@@ -621,7 +646,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
browser_driver_path = QFileDialog.getOpenFileName(
self,
"选择浏览器驱动 - AutoLibrary",
self.CurrentSystemConfigEdit.text(),
self.BrowseBrowserDriverEdit.text(),
"可执行文件 (*.exe);;所有文件 (*)"
)[0]
if browser_driver_path:
@@ -700,19 +725,22 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
users_config_path = self.ExportUserConfigEdit.text()
if system_config_path:
if self.saveConfigs(
system_config_path,
users_config_path=""
system_config_path, ""
):
msg += f"系统配置文件已导出到: \n'{system_config_path}'\n"
else:
msg += f"系统配置文件导出失败: \n'{system_config_path}'\n"
if users_config_path:
if self.saveConfigs(
"", users_config_path
):
msg += f"用户配置文件已导出到: \n'{users_config_path}'\n"
else:
msg += f"用户配置文件导出失败: \n'{users_config_path}'\n"
if msg:
QMessageBox.information(
self,
"信息 - AutoLibrary",
"提示 - AutoLibrary",
msg
)
@@ -748,21 +776,21 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
exist_files.append(users_config_path)
reply = QMessageBox.information(
self,
"信息 - AutoLibrary",
"提示 - AutoLibrary",
f"文件夹中已存在以下文件, 是否覆盖 ?\n{chr(10).join(exist_files)}",
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No
)
if reply == QMessageBox.No:
return
self.__system_config_data = self.defaultSystemConfig()
self.__users_config_data = self.defaultUsersConfig()
self.__config_data["system"] = self.defaultSystemConfig()
self.__config_data["users"] = self.defaultUsersConfig()
self.__config_paths = {
"system": system_config_path,
"users": users_config_path
}
self.initlizeConfigToWidget("system", self.__system_config_data)
self.initlizeConfigToWidget("users", self.__users_config_data)
self.initlizeConfigToWidget("system", self.__config_data["system"])
self.initlizeConfigToWidget("users", self.__config_data["users"])
@Slot()
def onConfirmButtonClicked(
@@ -770,16 +798,16 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
):
if self.UserListWidget.currentItem() is not None:
user = self.collectUserConfigFromUserInfoWidget()
if user:
self.UserListWidget.currentItem().setData(Qt.UserRole, user)
user_config = self.collectUserConfigFromUserInfoWidget()
if user_config:
self.UserListWidget.currentItem().setData(Qt.UserRole, user_config)
if self.saveConfigs(
self.__config_paths["system"],
self.__config_paths["users"]
):
QMessageBox.information(
self,
"信息 - AutoLibrary",
"提示 - AutoLibrary",
"配置文件保存成功 !\n"
f"系统配置文件路径: \n{self.__config_paths['system']}\n"\
f"用户配置文件路径: \n{self.__config_paths['users']}"
+17 -2
View File
@@ -448,11 +448,14 @@
</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>
<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="maximum">
<double>8.000000000000000</double>
</property>
<property name="stepType">
<enum>QAbstractSpinBox::StepType::AdaptiveDecimalStepType</enum>
</property>
</widget>
</item>
<item row="11" column="4">
@@ -620,6 +623,9 @@
<height>25</height>
</size>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
<property name="date">
<date>
<year>2025</year>
@@ -752,6 +758,9 @@
<property name="maximum">
<number>120</number>
</property>
<property name="stepType">
<enum>QAbstractSpinBox::StepType::AdaptiveDecimalStepType</enum>
</property>
</widget>
</item>
<item row="2" column="1">
@@ -842,6 +851,9 @@
<property name="maximum">
<number>120</number>
</property>
<property name="stepType">
<enum>QAbstractSpinBox::StepType::AdaptiveDecimalStepType</enum>
</property>
</widget>
</item>
<item row="3" column="4">
@@ -911,6 +923,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="text">
<string/>
</property>
@@ -1164,7 +1179,7 @@
</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>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;详情请参阅 &lt;a href=&quot;https://www.autolibrary.cv/docs/manual_lists.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#69fcff;&quot;&gt;用户手册&lt;/span&gt;&lt;/a&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>
+3 -5
View File
@@ -13,7 +13,7 @@ import time
import queue
from PySide6.QtCore import (
Qt, Signal, Slot, QDir, QFileInfo, QTimer, QThread
Qt, Signal, Slot, QTimer, QThread
)
from PySide6.QtWidgets import (
QMainWindow, QMenu
@@ -130,10 +130,8 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
self.__input_queue = queue.Queue()
self.__output_queue = queue.Queue()
self.__config_paths = {
"system":
f"{QDir.toNativeSeparators(QFileInfo(sys.executable).absoluteDir().absoluteFilePath("system.json"))}",
"users":
f"{QDir.toNativeSeparators(QFileInfo(sys.executable).absoluteDir().absoluteFilePath("users.json"))}",
"system": "",
"users": "",
}
self.__alConfigWidget = None
self.__auto_lib_thread = None