Skip to content

Commit 959b663

Browse files
committed
fix: 重新支持批量上传图片并修复wrapper选择器卡死问题
1 parent 1f08b0c commit 959b663

File tree

2 files changed

+70
-41
lines changed

2 files changed

+70
-41
lines changed

src/browser/page_controller.py

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -755,14 +755,11 @@ async def _robust_click_insert_assets(self, check_client_disconnected: Callable)
755755
return False
756756

757757
async def _upload_images_via_file_input(self, images: List[Dict[str, str]], check_client_disconnected: Callable) -> bool:
758-
self.logger.info(f"[{self.req_id}] 尝试逐个上传 {len(images)} 张图片...")
758+
self.logger.info(f"[{self.req_id}] 准备上传 {len(images)} 张图片...")
759759
temp_files = []
760-
uploaded_count = 0
761760

762761
try:
763762
for idx, img in enumerate(images):
764-
await self._check_disconnect(check_client_disconnected, f'上传图片 {idx+1}/{len(images)}')
765-
766763
mime = img['mime']
767764
try:
768765
data = base64.b64decode(img['data'])
@@ -777,32 +774,62 @@ async def _upload_images_via_file_input(self, images: List[Dict[str, str]], chec
777774
tf.write(data)
778775
tf.close()
779776
temp_files.append(tf.name)
777+
778+
if not temp_files:
779+
return False
780+
781+
await self._check_disconnect(check_client_disconnected, '上传图片前')
782+
menu_opened = await self._robust_click_insert_assets(check_client_disconnected)
783+
if not menu_opened:
784+
self.logger.warning(f"[{self.req_id}] 未能打开菜单,尝试直接查找 input...")
785+
786+
from config import HIDDEN_FILE_INPUT_SELECTOR
787+
file_input = self.page.locator(HIDDEN_FILE_INPUT_SELECTOR)
788+
if await file_input.count() == 0:
789+
file_input = self.page.locator('input[type="file"]').first
790+
791+
if await file_input.count() == 0:
792+
self.logger.warning(f"[{self.req_id}] 未找到文件输入框")
793+
asyncio.create_task(self._cleanup_temp_files(temp_files))
794+
return False
795+
796+
try:
797+
self.logger.info(f"[{self.req_id}] 尝试批量上传 {len(temp_files)} 张图片...")
798+
await file_input.set_input_files(temp_files)
799+
await asyncio.sleep(0.3)
800+
await self.page.keyboard.press('Escape')
801+
self.logger.info(f"[{self.req_id}] ✅ 批量上传成功 ({len(temp_files)} 张)")
802+
asyncio.create_task(self._cleanup_temp_files(temp_files))
803+
return True
804+
except Exception as batch_err:
805+
self.logger.warning(f"[{self.req_id}] 批量上传失败: {batch_err},尝试逐个上传...")
806+
807+
uploaded_count = 0
808+
for idx, tf_path in enumerate(temp_files):
809+
await self._check_disconnect(check_client_disconnected, f'上传图片 {idx+1}/{len(temp_files)}')
780810

781-
menu_opened = await self._robust_click_insert_assets(check_client_disconnected)
782-
if not menu_opened:
783-
self.logger.warning(f"[{self.req_id}] 未能打开菜单,尝试直接查找 input...")
784-
785-
from config import HIDDEN_FILE_INPUT_SELECTOR
786-
file_input = self.page.locator(HIDDEN_FILE_INPUT_SELECTOR)
787-
if await file_input.count() == 0:
788-
file_input = self.page.locator('input[type="file"]').first
789-
790-
if await file_input.count() == 0:
791-
self.logger.warning(f"[{self.req_id}] 未找到文件输入框,跳过图片 {idx+1}")
792-
continue
793-
794-
self.logger.info(f"[{self.req_id}] 上传图片 {idx+1}/{len(images)}...")
795-
await file_input.set_input_files(tf.name)
796-
uploaded_count += 1
811+
if idx > 0:
812+
menu_opened = await self._robust_click_insert_assets(check_client_disconnected)
813+
if not menu_opened:
814+
continue
815+
file_input = self.page.locator(HIDDEN_FILE_INPUT_SELECTOR)
816+
if await file_input.count() == 0:
817+
file_input = self.page.locator('input[type="file"]').first
797818

798-
await asyncio.sleep(0.2)
799-
await self.page.keyboard.press('Escape')
800-
await asyncio.sleep(0.1)
819+
try:
820+
self.logger.info(f"[{self.req_id}] 上传图片 {idx+1}/{len(temp_files)}...")
821+
await file_input.set_input_files(tf_path)
822+
uploaded_count += 1
823+
await asyncio.sleep(0.2)
824+
await self.page.keyboard.press('Escape')
825+
await asyncio.sleep(0.1)
826+
except Exception as single_err:
827+
self.logger.warning(f"[{self.req_id}] 单张上传失败 {idx+1}: {single_err}")
801828

802829
asyncio.create_task(self._cleanup_temp_files(temp_files))
803830

804831
if uploaded_count > 0:
805-
self.logger.info(f"[{self.req_id}] ✅ 成功上传 {uploaded_count}/{len(images)} 张图片")
832+
self.logger.info(f"[{self.req_id}] ✅ 逐个上传完成 {uploaded_count}/{len(temp_files)} ")
806833
return True
807834
return False
808835

@@ -902,7 +929,13 @@ async def submit_prompt(self, prompt: str, image_list: List, check_client_discon
902929
prompt_textarea_locator = self.page.locator(PROMPT_TEXTAREA_SELECTOR)
903930
else:
904931
self.logger.info(f'[{self.req_id}] 找到输入框 (匹配: {matched_selector})')
905-
autosize_wrapper_locator = self.page.locator('ms-prompt-box .text-wrapper')
932+
autosize_wrapper_selectors = ['ms-prompt-input-wrapper .text-wrapper', 'ms-prompt-box .text-wrapper', '.prompt-input-wrapper-container']
933+
autosize_wrapper_locator = None
934+
for ws in autosize_wrapper_selectors:
935+
loc = self.page.locator(ws)
936+
if await loc.count() > 0:
937+
autosize_wrapper_locator = loc
938+
break
906939
submit_button_locator, submit_matched = await get_first_visible_locator(self.page, SUBMIT_BUTTON_SELECTORS, timeout=3000)
907940
if not submit_button_locator:
908941
submit_button_locator = self.page.locator(SUBMIT_BUTTON_SELECTOR)
@@ -933,33 +966,28 @@ async def submit_prompt(self, prompt: str, image_list: List, check_client_discon
933966
self.logger.info(f"[{self.req_id}] 回退到虚拟粘贴模式...")
934967
await self._paste_images_via_event(processed_images, prompt_textarea_locator)
935968

936-
await asyncio.sleep(1)
969+
await asyncio.sleep(0.5)
937970

938-
try:
939-
self.logger.info(f"[{self.req_id}] 正在验证图片上传 (不阻塞主流程)...")
940-
await self._verify_images_uploaded(len(processed_images), check_client_disconnected)
941-
except Exception as verify_err:
942-
self.logger.warning(f"[{self.req_id}] 图片上传验证未完全通过,但继续提交文字: {verify_err}")
943-
944971
except Exception as upload_err:
945972
self.logger.error(f"[{self.req_id}] 图片上传整体流程异常: {upload_err}。继续提交文字。")
946973

947974
self.logger.info(f"[{self.req_id}] 正在填充文字内容...")
948975
await prompt_textarea_locator.evaluate('(element, text) => { element.value = text; element.dispatchEvent(new Event("input", { bubbles: true })); }', prompt)
949-
await autosize_wrapper_locator.evaluate('(element, text) => { element.setAttribute("data-value", text); }', prompt)
976+
if autosize_wrapper_locator:
977+
try:
978+
await autosize_wrapper_locator.evaluate('(element, text) => { element.setAttribute("data-value", text); }', prompt)
979+
except Exception:
980+
pass
950981

951982
await self._check_disconnect(check_client_disconnected, '输入框填充后')
952-
wait_timeout_ms_submit_enabled = 100000
983+
self.logger.info(f'[{self.req_id}] 文字填充完成,等待发送按钮...')
953984
try:
954-
await self._check_disconnect(check_client_disconnected, '等待发送按钮启用前')
955-
await expect_async(submit_button_locator).to_be_enabled(timeout=wait_timeout_ms_submit_enabled)
985+
await expect_async(submit_button_locator).to_be_enabled(timeout=15000)
956986
self.logger.info(f'[{self.req_id}] 发送按钮已启用。')
957987
except Exception as e_pw_enabled:
958-
self.logger.error(f'[{self.req_id}] 等待发送按钮启用超时或错误: {e_pw_enabled}')
959-
await save_error_snapshot(f'submit_button_enable_timeout_{self.req_id}')
960-
raise
988+
self.logger.warning(f'[{self.req_id}] 等待发送按钮启用超时: {e_pw_enabled},尝试继续提交...')
961989
await self._check_disconnect(check_client_disconnected, '发送按钮启用后')
962-
await asyncio.sleep(0.3)
990+
await asyncio.sleep(0.1)
963991
submitted_successfully = await self._try_shortcut_submit(prompt_textarea_locator, check_client_disconnected)
964992
if not submitted_successfully:
965993
self.logger.info(f'[{self.req_id}] 快捷键提交失败,尝试点击提交按钮...')

src/config/selectors.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
INSERT_BUTTON_SELECTOR = INSERT_BUTTON_SELECTORS[0]
2222

2323
UPLOAD_BUTTON_SELECTORS = [
24-
'button[role="menuitem"]:has-text("Upload a file")',
2524
'button[aria-label="Upload File"]',
25+
'button[role="menuitem"]:has-text("Upload File")',
26+
'button[role="menuitem"]:has-text("Upload a file")',
2627
]
2728
UPLOAD_BUTTON_SELECTOR = UPLOAD_BUTTON_SELECTORS[0]
2829

0 commit comments

Comments
 (0)