diff --git a/CHANGELOG.md b/CHANGELOG.md index c3a47a5..d514c55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ 本文件对应技能市场 **「更新日志」** Tab。 +## 1.1.23 + +- **修复登录后跳 /app/home 的流程**: + - `_wait_for_url_stable` 支持 tuple targets(任一匹配即稳定) + - 登录后等 URL 稳定到 `/app/` 或 `/select`(sandbox 中间页) + - 显式 `goto SPA_HOME_URL` (/app/home) → 等 sidebar link 出现 → click `合同到期续聘` + - 删掉重复的 # 4 块(之前手抖复制粘贴的 bug) + ## 1.1.22 - **登录流程接入 sandbox 自动登录**:root 登录页(https://sandbox.jc2009.com/)的 #jc-user / #jc-pass 默认有 demo/123456 预填 diff --git a/SKILL.md b/SKILL.md index 8cbb078..21e6992 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,7 +1,7 @@ --- name: 合同到期智能预警与续聘辅助 description: "当用户说要扫描即将到期的合同、查 90/60/30 天预警名单、给某位教师生成续聘任务书、下发单位版续聘清单、从 SmartCampus HR 平台抓合同数据、解析续聘材料 PDF/Word、查看本月合同到期人员清单时,加载本技能。支持定时扫描(每日凌晨)+ 数据管理 + Agent 三入口,覆盖合同到期智能预警与续聘辅助全流程。" -version: 1.1.22 +version: 1.1.23 author: 深圳匠厂科技有限公司 metadata: openclaw: diff --git a/scripts/service/platform_collector.py b/scripts/service/platform_collector.py index c788526..78d9e18 100644 --- a/scripts/service/platform_collector.py +++ b/scripts/service/platform_collector.py @@ -167,6 +167,16 @@ def _is_logged_in(page) -> bool: ) +def _is_spa_routed(page) -> bool: + """v1.1.22:检测 sandbox SPA 是否已路由到 SPA 页面(含 /select /app/)。""" + url_lower = page.url.lower() + return ( + ("/app/" in url_lower or "/select" in url_lower) + and "/login" not in url_lower + and "/signin" not in url_lower + ) + + def _try_auto_sign_in(page, wait_input_sec: int = 2) -> bool: """v1.1.21:检测登录页 demo/123456 是否已预填,有则自动点 Sign in。 @@ -386,16 +396,23 @@ def _wait_for_manual_login(page, wait_sec: int = HUMAN_WAIT_TIMEOUT) -> bool: def _wait_for_url_stable( - page, target_substr: str, max_wait_sec: int = 30, + page, target_substr: str | tuple[str, ...], max_wait_sec: int = 30, ) -> bool: """v1.1.19:等 URL 含 target_substr,且连续 URL_STABLE_REQUIRED_S 秒不变。 + v1.1.22:target_substr 支持 tuple(任一匹配即视为稳定)。 + 用于「已登录态直接跳到目标页面」后等待 SPA 路由稳定。 **不做任何 goto / reload**,只 listen URL 变化。 Returns: - True = URL 已稳定到目标;False = 超时。 + True = URL 已稳定到任一目标;False = 超时。 """ + if isinstance(target_substr, str): + targets = (target_substr,) + else: + targets = target_substr + deadline = time.monotonic() + max_wait_sec last_url = page.url last_url_change_at = time.monotonic() @@ -410,7 +427,8 @@ def _wait_for_url_stable( last_url = cur_url last_url_change_at = time.monotonic() - if target_substr in cur_url.lower(): + cur_lower = cur_url.lower() + if any(t.lower() in cur_lower for t in targets): stable_for = time.monotonic() - last_url_change_at if stable_for >= URL_STABLE_REQUIRED_S: return True @@ -653,32 +671,39 @@ def collect_all( f"(请用 --show-browser 重试)" ) - # 4. 登录完成 → 等 URL 真正稳定到 /app/(最多 30s,**不做任何操作**) - # 之前 retry loop 会强制 goto home / fill login,**打断用户刚登录态**。 - if not _wait_for_url_stable(page, "/app/", max_wait_sec=30): + # 4. 登录完成 → 等 URL 真正稳定到 /app/ 或 /select(最多 30s,**不做任何操作**) + # v1.1.22:sandbox 登录后会先跳 /select,再自动跳 /app/home, + # 所以两个 URL 都算"SPA 已路由" + if not _wait_for_url_stable(page, ("/app/", "/select"), max_wait_sec=30): logger.warning( - "platform_collector: 登录后 30s 内 URL 未稳定到 /app/(当前 URL=%s)", + "platform_collector: 登录后 30s 内 URL 未稳定到 /app/或 /select(当前 URL=%s)", page.url, ) # 不强行 reload —— 让用户决定是否手工刷新 - # 5. 登录完成 → 等 URL 真正稳定到 /app/(最多 30s,**不做任何操作**) - # 之前 retry loop 会强制 goto home / fill login,**打断用户刚登录态**。 - if not _wait_for_url_stable(page, "/app/", max_wait_sec=30): - logger.warning( - "platform_collector: 登录后 30s 内 URL 未稳定到 /app/(当前 URL=%s)", - page.url, + # 5. v1.1.22:显式跳到 SPA_HOME_URL(/app/home),等侧边栏 link 出现 + # 避免 sandbox 在 /select 中间页时直接找 sidebar link 找不到 + if "/app/home" not in page.url.lower(): + logger.info( + "platform_collector: 当前 URL=%s,跳到 SPA_HOME_URL=%s", + page.url, SPA_HOME_URL, ) - # 不强行 reload —— 让用户决定是否手工刷新 + _goto(page, SPA_HOME_URL) + page.wait_for_timeout(SPA_HYDRATION_MS) + # 等 URL 稳定到 /app/home(最多 15s,**不做任何操作**) + if not _wait_for_url_stable(page, "/app/home", max_wait_sec=15): + logger.warning( + "platform_collector: 15s 内未稳定到 /app/home(当前 URL=%s)", + page.url, + ) - # 5. 等 SPA 渲染 + click 侧边栏 hr/contracts(SPA 路由,避免 goto 触发整页 reload 丢 session) + # 6. 等 SPA 渲染 + click 侧边栏 hr/contracts(SPA 路由,避免 goto 触发整页 reload 丢 session) try: # dump SPA home 一次(用于调试 selector) page.wait_for_timeout(POST_LOGIN_SETTLE_MS) _dump_page(page, download_dir.parent / "spa_home_dump.html", "SPA home") # 等 SPA 真正加载完(侧边栏 link 出现,最长 SIDEBAR_LINK_TIMEOUT_MS) - # 修复:之前 15s 太短,sandbox mock 加载慢时直接 fallback 到 pushState → 表格加载不出来 try: page.wait_for_selector( "a[href$='/hr/contracts']", diff --git a/scripts/util/constants.py b/scripts/util/constants.py index 78bb7bf..094c618 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.22" +SKILL_VERSION = "1.1.23" LOG_LOGGER_NAME = "openclaw.skill.alert_contract_expiring_hr" PLATFORM_KIT_MIN_VERSION = "1.2.11"