chore: auto release commit (2026-09-14 18:37:22)
All checks were successful
技能自动化发布 / release (push) Successful in 11s
All checks were successful
技能自动化发布 / release (push) Successful in 11s
This commit is contained in:
@@ -2,6 +2,15 @@
|
||||
|
||||
本文件对应技能市场 **「更新日志」** Tab。
|
||||
|
||||
## 1.1.11
|
||||
|
||||
- **RPA 自动登录 selector 修复(用户反馈驱动)**
|
||||
- **`_fill_spa_login` selector 改用 sandbox 实际 ID**:之前用 `input[autocomplete="username"]` 但 sandbox SPA 登录页 input 是 `type="tel"` + 无 autocomplete,导致 selector 永远 miss、自动 fill 100% 失败
|
||||
- 改为按优先级 fallback 三组 selector:`#jc-user` → `input[type="tel"]` → `input[autocomplete="username"]`(密码同样:`#jc-pass` → `input[type="password"]` → `input[autocomplete="current-password"]`)
|
||||
- 按钮 selector 同样按优先级:`button:has-text("登录")` → `button[type="submit"]:has-text("Sign in")` → `button[type="submit"]`
|
||||
- **SPA_HOME 探针二次等待**:sandbox SPA 有时首次访问跳中间过渡页(如 /select),等几秒看 URL 是否稳定到 /app/,避免误判未登录
|
||||
- **意外发现**:sandbox 服务端今天已恢复,demo/123456 凭据可重新自动登录通过(之前 9-14 探测失败应该是服务端临时故障),本版本同时修复了 selector 和兜底
|
||||
|
||||
## 1.1.10
|
||||
|
||||
- **RPA 已登录态检测优化(profile cookie 复用零打扰)**
|
||||
|
||||
2
SKILL.md
2
SKILL.md
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: 合同到期智能预警与续聘辅助
|
||||
description: "每日凌晨扫描全校教职工合同电子台账,对距离到期日 90/60/30 天的合同分级预警,并自动生成《续聘准备任务书》和《本月合同到期人员清单》。"
|
||||
version: 1.1.10
|
||||
version: 1.1.11
|
||||
author: 深圳匠厂科技有限公司
|
||||
metadata:
|
||||
openclaw:
|
||||
|
||||
@@ -235,6 +235,10 @@ def _fill_spa_login(page, settle_ms: int = SPA_LOGIN_SETTLE_MS) -> bool:
|
||||
v1.1.10 关键修复:**先检测 _is_logged_in,已登录态直接 return True 不再 fill**。
|
||||
之前没这个检查,profile 复用时会被强制 demo fill 破坏 session。
|
||||
|
||||
v1.1.11 关键修复:**sandbox SPA 登录 input 实际是 `type="tel"` + 无 autocomplete**,
|
||||
之前 selector `input[autocomplete="username"]` 永远找不到,自动 fill 100% 失败。
|
||||
改用 sandbox 实际 selector `#jc-user` / `#jc-pass`(来自 root 登录页)+ `button[type="submit"]`。
|
||||
|
||||
修复要点(v1.1.5/v1.1.6 登录时间太短导致采集不到数据):
|
||||
- 默认 settle_ms = SPA_LOGIN_SETTLE_MS(4000ms),给 SPA 异步渲染 + token 写入 cookie 时间
|
||||
- 等 username input 的 timeout = SPA_LOGIN_INPUT_TIMEOUT_MS(20s)
|
||||
@@ -251,24 +255,43 @@ def _fill_spa_login(page, settle_ms: int = SPA_LOGIN_SETTLE_MS) -> bool:
|
||||
url_lower = page.url.lower()
|
||||
if "/login" not in url_lower and "/signin" not in url_lower and "/auth/" not in url_lower:
|
||||
return False
|
||||
# v1.1.11:sandbox SPA 登录页 input 是 #jc-user / #jc-pass(与 root 登录页同 ID)
|
||||
# 等输入框出现(带超时,避免 sandbox mock 慢启动卡死)
|
||||
try:
|
||||
page.wait_for_selector(
|
||||
'input[autocomplete="username"]',
|
||||
'#jc-user, input[type="tel"], input[autocomplete="username"]',
|
||||
timeout=SPA_LOGIN_INPUT_TIMEOUT_MS,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning("SPA login input 未出现: %s;当前 URL=%s", e, page.url)
|
||||
return False
|
||||
spa_user = page.locator('input[autocomplete="username"]').first
|
||||
if spa_user.count() == 0:
|
||||
logger.warning("SPA login input count=0")
|
||||
# v1.1.11:按优先级选 selector —— sandbox 实际用 #jc-user
|
||||
user_sel = None
|
||||
for sel in ('#jc-user', 'input[type="tel"]', 'input[autocomplete="username"]'):
|
||||
loc = page.locator(sel).first
|
||||
if loc.count() > 0:
|
||||
user_sel = sel
|
||||
break
|
||||
if not user_sel:
|
||||
logger.warning("SPA login input selector 全 miss(#jc-user / type=tel / autocomplete=username)")
|
||||
return False
|
||||
spa_user.fill("demo")
|
||||
page.locator('input[autocomplete="current-password"]').first.fill("123456")
|
||||
page.locator(user_sel).first.fill("demo")
|
||||
# 密码 selector 同样按优先级
|
||||
pass_sel = None
|
||||
for sel in ('#jc-pass', 'input[type="password"]', 'input[autocomplete="current-password"]'):
|
||||
loc = page.locator(sel).first
|
||||
if loc.count() > 0:
|
||||
pass_sel = sel
|
||||
break
|
||||
if not pass_sel:
|
||||
logger.warning("SPA password input selector 全 miss")
|
||||
return False
|
||||
page.locator(pass_sel).first.fill("123456")
|
||||
page.locator(
|
||||
'button:has-text("登录"), button[type="submit"]:has-text("Sign in")'
|
||||
'button:has-text("登录"), button[type="submit"]:has-text("Sign in"), '
|
||||
'button[type="submit"]'
|
||||
).first.click()
|
||||
logger.info("platform_collector: sandbox SPA 自动登录...")
|
||||
logger.info("platform_collector: sandbox SPA 自动登录 (user_sel=%s pass_sel=%s)", user_sel, pass_sel)
|
||||
page.wait_for_timeout(settle_ms)
|
||||
try:
|
||||
page.wait_for_url(
|
||||
@@ -361,18 +384,26 @@ def collect_all(
|
||||
# 所有 wait_for_selector 默认 30s,调试时不直观)
|
||||
page.set_default_timeout(DEFAULT_PAGE_TIMEOUT_MS)
|
||||
|
||||
# 1. v1.1.10:先用**最小侵入**方式检测已登录态 —— 直接 goto SPA_HOME
|
||||
# 1. v1.1.11:先用**最小侵入**方式检测已登录态 —— 直接 goto SPA_HOME_URL
|
||||
# (不要先跳 ROOT_URL + 自动 fill,会破坏已登录态)
|
||||
# 已登录态:SPA_HOME 直接落到 /app/home → _is_logged_in=True → 全跳过
|
||||
# 未登录态:SPA_HOME 被踢回 /login → _is_logged_in=False → 走登录分支
|
||||
# v1.1.11 改进:探针结果 + 二次等待 + cookie 检测,三重判断避免误判
|
||||
logger.info(
|
||||
"platform_collector: 检测登录态,goto SPA_HOME 先探 (当前 URL=%s)",
|
||||
page.url,
|
||||
)
|
||||
_goto(page, SPA_HOME_URL)
|
||||
# v1.1.10:等 sandbox SPA 异步验证 cookie(之前 POST_LOGIN_SETTLE_MS=2s 不够,
|
||||
# 探针误判未登录,触发不必要的 fallback 手工登录)
|
||||
# v1.1.11:等 sandbox SPA 异步验证 cookie(POST_LOGIN_SETTLE_MS → SPA_HYDRATION_MS)
|
||||
page.wait_for_timeout(SPA_HYDRATION_MS)
|
||||
# v1.1.11:二次等待 —— sandbox SPA 有时首次访问会先跳一个中间过渡页
|
||||
# (如 /select),等几秒看 URL 是否稳定到 /app/
|
||||
first_url = page.url
|
||||
page.wait_for_timeout(SPA_HOME_RETRY_DELAY_MS)
|
||||
second_url = page.url
|
||||
if first_url != second_url:
|
||||
logger.info(
|
||||
"platform_collector: 探针 URL 过渡 %s → %s,等稳定", first_url, second_url,
|
||||
)
|
||||
page.wait_for_timeout(SPA_HOME_RETRY_DELAY_MS)
|
||||
|
||||
if _is_logged_in(page):
|
||||
logger.info(
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"""
|
||||
|
||||
SKILL_SLUG = "alert-contract-expiring-hr"
|
||||
SKILL_VERSION = "1.1.10"
|
||||
SKILL_VERSION = "1.1.11"
|
||||
LOG_LOGGER_NAME = "openclaw.skill.alert_contract_expiring_hr"
|
||||
PLATFORM_KIT_MIN_VERSION = "1.2.11"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user