feat: 新增按钮状态检测与等待完成逻辑

This commit is contained in:
knowen
2026-03-13 22:59:11 +08:00
parent f609656d5f
commit 27565c0314
3 changed files with 85 additions and 18 deletions

View File

@@ -21,22 +21,38 @@ description: 通过 Gemini 官网gemini.google.com执行问答与生图操
## 标准执行流程 ## 标准执行流程
### 按钮状态机
Gemini 页面的操作按钮(`.send-button-container` 内)通过 `aria-label` 反映当前状态:
| aria-label | 状态 | 含义 |
|---|---|---|
| 麦克风 | `idle` | 输入框为空,空闲中 |
| 发送 / Send | `ready` | 输入框有内容,可发送 |
| 停止 / Stop | `loading` | 已发送,正在生成回答 |
可通过 `GeminiOps.getStatus()` 获取当前状态,通过 `GeminiOps.waitForComplete()` 轮询等待生成完毕。
### A. 文本问答 ### A. 文本问答
1. 打开 `https://gemini.google.com` 1. 打开 `https://gemini.google.com`
2. 校验登录态(头像/输入框可见)。 2. 校验登录态(头像/输入框可见)。
3. 选择最强可用模型(优先 Gemini 3.1 Pro 3. 新建会话:`click('newChatBtn')`,确保干净上下文
4. 将用户问题原样输入并发送 4. 选择最强可用模型(优先 Gemini 3.1 Pro
5. 等待完整输出,提炼后回传(必要时附原文要点) 5. 将用户问题原样输入并发送
6. 调用 `waitForComplete()` 等待状态从 `loading` 变回 `idle`
7. 等待完整输出,提炼后回传(必要时附原文要点)。
### B. 生图流程 ### B. 生图流程
1. 打开 Gemini 页面并确认登录。 1. 打开 Gemini 页面并确认登录。
2. 选择最强可用模型(优先 Gemini 3.1 Pro 2. 新建会话:`click('newChatBtn')`,确保干净上下文
3. 将用户提示词原样输入 3. 选择最强可用模型(优先 Gemini 3.1 Pro
4. 发送后立即通知用户:正在绘图中 4. 将用户提示词原样输入
6. 结果出现后: 5. 发送后立即通知用户:正在绘图中。
6. 调用 `waitForComplete()` 等待生成完毕(生图默认超时 120s
7. 结果出现后:
- 优先用"下载原图"按钮获取原图。 - 优先用"下载原图"按钮获取原图。
- 若无下载按钮或失败,可对图片右键另存(通常是标清图)。 - 若无下载按钮或失败,可对图片右键另存(通常是标清图)。
7. 把图片返回用户;若有多张,按顺序全部回传。 8. 把图片返回用户;若有多张,按顺序全部回传。
## 失败回退 ## 失败回退

View File

@@ -16,15 +16,27 @@
若切换失败,保留默认并告知用户。 若切换失败,保留默认并告知用户。
## 3) 生图结果获取 ## 3) 按钮状态检测
`.send-button-container` 内的按钮通过 `aria-label` 区分三种状态:
- **空闲idle**aria-label 为麦克风相关,按钮 disabled输入框为空。
- **可发送ready**aria-label 为"发送"/"Send",输入框有内容。
- **生成中loading**aria-label 为"停止"/"Stop"Gemini 正在输出。
使用方式:
- `GeminiOps.getStatus()` → 返回 `{status: 'idle'|'ready'|'loading', label, disabled}`
- `GeminiOps.waitForComplete(timeout, interval)` → 返回 Promise状态脱离 `loading` 后 resolve
## 4) 生图结果获取
优先顺序: 优先顺序:
1. 图片右上角下载原图 1. 图片右上角"下载原图"
2. 右键另存为(标清) 2. 右键另存为(标清)
下载到本地后再通过渠道回传。 下载到本地后再通过渠道回传。
## 4) 用户提示文案(建议) ## 5) 用户提示文案(建议)
- 开始生图: - 开始生图:
- `已收到,正在用 Gemini 给你绘图中 🎨` - `已收到,正在用 Gemini 给你绘图中 🎨`

View File

@@ -6,10 +6,15 @@
'[contenteditable="true"][data-placeholder*="Gemini"]', '[contenteditable="true"][data-placeholder*="Gemini"]',
'div[contenteditable="true"][role="textbox"]' 'div[contenteditable="true"][role="textbox"]'
], ],
sendBtn: [ actionBtn: [
'button[aria-label*="发送"]', '.send-button-container button.send-button',
'button[aria-label*="Send"]', '.send-button-container button'
'button:has-text("发送")' ],
newChatBtn: [
'[data-test-id="new-chat-button"] a',
'[data-test-id="new-chat-button"]',
'a[aria-label="发起新对话"]',
'a[aria-label*="new chat" i]'
], ],
modelBtn: [ modelBtn: [
'button:has-text("Gemini")', 'button:has-text("Gemini")',
@@ -66,13 +71,47 @@
return {ok:true}; return {ok:true};
} }
function getStatus(){
const btn=find('actionBtn');
if(!btn) return {status:'unknown',error:'btn_not_found'};
const label=(btn.getAttribute('aria-label')||'').trim();
const disabled=btn.getAttribute('aria-disabled')==='true';
if(/停止|Stop/i.test(label)) return {status:'loading',label};
if(/发送|Send|Submit/i.test(label)) return {status:'ready',label,disabled};
return {status:'idle',label,disabled};
}
function waitForComplete(timeout,interval){
timeout=timeout||120000;
interval=interval||2000;
return new Promise(function(resolve){
var elapsed=0;
var timer=setInterval(function(){
elapsed+=interval;
var s=getStatus();
if(s.status!=='loading'){
clearInterval(timer);
resolve({ok:true,status:s.status,elapsed});
return;
}
if(elapsed>=timeout){
clearInterval(timer);
resolve({ok:false,status:'timeout',elapsed});
}
},interval);
});
}
function probe(){ function probe(){
var s=getStatus();
return { return {
promptInput: !!find('promptInput'), promptInput: !!find('promptInput'),
sendBtn: !!find('sendBtn'), actionBtn: !!find('actionBtn'),
modelBtn: !!find('modelBtn') newChatBtn: !!find('newChatBtn'),
modelBtn: !!find('modelBtn'),
status: s.status
}; };
} }
window.GeminiOps = {probe, click, fillPrompt, selectors:S, version:'0.1.0'}; window.GeminiOps = {probe, click, fillPrompt, getStatus, waitForComplete, selectors:S, version:'0.3.0'};
})(); })();