diff --git a/CHANGELOG.md b/CHANGELOG.md index e4b2608..60b0db2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ 本文件对应技能市场 **「更新日志」** Tab。 +## 1.1.21 + +- **修复登录完成检测盲区**:`_wait_for_manual_login` 现在监听 3 个信号判断「登录已完成」,任一触发即继续 + 1. URL 含 `/app/` 且稳定 2 秒(v1.1.20 旧逻辑) + 2. URL 已离开 `/login` / `/signin` / `/auth/` 等登录路径 + 3. 页面出现 sidebar 元素 `a[href$='/hr/contracts']` +- 解决「用户已经登录但脚本还在傻等」的回归:之前只判 URL 变化,cookie 已生效复用 profile 场景或 SPA 不跳 URL 的场景会卡 180 秒 + ## 1.1.20 - **登录流程重写**:第一跳改为 `https://sandbox.jc2009.com/`(根域,用户最初看到的页面),**不做任何操作**等 URL 稳定 diff --git a/SKILL.md b/SKILL.md index 1cc6f64..87ba10e 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,7 +1,7 @@ --- name: 合同到期智能预警与续聘辅助 description: "当用户说要扫描即将到期的合同、查 90/60/30 天预警名单、给某位教师生成续聘任务书、下发单位版续聘清单、从 SmartCampus HR 平台抓合同数据、解析续聘材料 PDF/Word、查看本月合同到期人员清单时,加载本技能。支持定时扫描(每日凌晨)+ 数据管理 + Agent 三入口,覆盖合同到期智能预警与续聘辅助全流程。" -version: 1.1.20 +version: 1.1.21 author: 深圳匠厂科技有限公司 metadata: openclaw: diff --git a/scripts/service/platform_collector.py b/scripts/service/platform_collector.py index 9ef35a5..f52ee76 100644 --- a/scripts/service/platform_collector.py +++ b/scripts/service/platform_collector.py @@ -168,15 +168,19 @@ def _is_logged_in(page) -> bool: def _wait_for_manual_login(page, wait_sec: int = HUMAN_WAIT_TIMEOUT) -> bool: - """手工登录 fallback(v1.1.19 重写):等用户在浏览器输完账号密码提交。 + """手工登录 fallback(v1.1.19 重写,v1.1.20 加强):等用户在浏览器完成登录。 + + 判定「登录完成」的多个信号(满足任一即视为完成): + 1. URL 含 `/app/` 且稳定 URL_STABLE_REQUIRED_S 秒(v1.1.19 旧逻辑) + 2. URL 已离开 `/login` / `/signin` / `/auth/` 等登录路径(v1.1.20 新增) + —— 即便 sandbox 未跳到 /app/,只要离开登录页就认为登录成功 + 3. 页面出现 sidebar 元素 `a[href$='/hr/contracts']`(v1.1.20 新增) + —— 说明已加载到 SPA 主页 - 与之前轮询 _is_logged_in 不同的设计: - **不做任何 goto / reload / click**,避免打断用户输入 - 每 HUMAN_PROMPT_INTERVAL 秒打印一次剩余时间(默认 15s) - - 每 HUMAN_POLL_INTERVAL 秒(默认 5s)只检查 URL,不做任何操作 - - 用户完成登录(URL 跳到 /app/...)后 **等 URL 真正稳定**,再返回 True - - 超时抛 LoginTimeoutError。 + - 每 HUMAN_POLL_INTERVAL 秒检查一次(默认 5s) + - 超时抛 LoginTimeoutError。 """ print( f"[登录] 请在浏览器中完成登录" @@ -187,12 +191,24 @@ def _wait_for_manual_login(page, wait_sec: int = HUMAN_WAIT_TIMEOUT) -> bool: last_url = page.url last_url_change_at = time.monotonic() + def _is_login_page_url(url: str) -> bool: + u = url.lower() + return ( + "/login" in u or "/signin" in u or "/auth/" in u + or u.rstrip("/").endswith("sandbox.jc2009.com") + ) + + def _sidebar_present() -> bool: + try: + return page.locator("a[href$='/hr/contracts']").count() > 0 + except Exception: + return False + while True: remaining = deadline - time.monotonic() if remaining <= 0: break - # 用户输入完提交后,URL 会从 /login 跳到 /app/... cur_url = page.url if cur_url != last_url: logger.info( @@ -201,16 +217,37 @@ def _wait_for_manual_login(page, wait_sec: int = HUMAN_WAIT_TIMEOUT) -> bool: last_url = cur_url last_url_change_at = time.monotonic() + # 信号 1:URL 跳到 /app/... 并稳定 if _is_logged_in(page): - # URL 已跳到 /app/...:等 URL 稳定 URL_STABLE_REQUIRED_S 秒再返回 stable_for = time.monotonic() - last_url_change_at if stable_for >= URL_STABLE_REQUIRED_S: - print(f"[登录] ✅ 检测到登录完成(URL={cur_url}, 稳定 {stable_for:.1f}s)") + print( + f"[登录] ✅ 检测到登录完成(URL 含 /app/,稳定 {stable_for:.1f}s)" + ) return True logger.info( - "platform_collector: 登录后 URL 还在过渡,等稳定 " + "platform_collector: URL 含 /app/ 但还在过渡,等稳定 " "(current=%s, stable_for=%.1fs)", cur_url, stable_for, ) + # 信号 2:URL 已离开登录页(即使不在 /app/,比如卡在中间过渡页也算) + elif not _is_login_page_url(cur_url): + stable_for = time.monotonic() - last_url_change_at + if stable_for >= URL_STABLE_REQUIRED_S: + print( + f"[登录] ✅ 检测到登录完成(URL 已离开登录页 → {cur_url}," + f"稳定 {stable_for:.1f}s)" + ) + return True + logger.info( + "platform_collector: URL 已离开登录页但还没稳定,等 " + "(current=%s, stable_for=%.1fs)", cur_url, stable_for, + ) + # 信号 3:sidebar 已出现 + elif _sidebar_present(): + print( + f"[登录] ✅ 检测到登录完成(sidebar 已出现,URL={cur_url})" + ) + return True else: # 还在登录页:每 HUMAN_PROMPT_INTERVAL 秒提醒用户一次 now = time.monotonic() @@ -225,6 +262,7 @@ def _wait_for_manual_login(page, wait_sec: int = HUMAN_WAIT_TIMEOUT) -> bool: raise LoginTimeoutError( f"自动登录失败,{wait_sec}s 内用户在浏览器中也未完成登录" + f"(最后 URL={page.url})" ) diff --git a/scripts/util/constants.py b/scripts/util/constants.py index a68d7c3..154bcfd 100644 --- a/scripts/util/constants.py +++ b/scripts/util/constants.py @@ -6,7 +6,7 @@ """ SKILL_SLUG = "alert-contract-expiring-hr" -SKILL_VERSION = "1.1.20" +SKILL_VERSION = "1.1.21" LOG_LOGGER_NAME = "openclaw.skill.alert_contract_expiring_hr" PLATFORM_KIT_MIN_VERSION = "1.2.11"