import time import os from framework.core.base_page import BasePage from framework.core.logger import get_logger logger = get_logger("FileManagerPage") class FileManagerPage(BasePage): """文件管理页面 POM - 纯原子操作层""" MENU_TEXT = "数据管理" def __init__(self, page): self.page = page def navigate_to(self): """进入页面""" logger.info("正在切换到数据管理页面...") self.smart_click(self.MENU_TEXT) # 等待页面核心元素出现,确保切换完成 try: self.page.wait_for_selector(".p-datatable, button:has-text('新建文件夹')", timeout=5000) except: pass time.sleep(2) def create_folder(self, name): """原子:创建文件夹""" logger.info(f"📁 新建文件夹: {name}") self.smart_click("新建文件夹") self.page.fill("#folderName", name) self.smart_click("确定", role="button") time.sleep(1) def enter_folder(self, name): """原子:双击进入文件夹""" logger.info(f"📂 进入文件夹: {name}") self.page.click(f"text='{name}'") time.sleep(1) def upload_files(self, file_paths): """原子:触发上传并选择文件""" if isinstance(file_paths, str): file_paths = [file_paths] logger.info(f"📤 准备上传文件: {file_paths}") self.smart_click("上传") time.sleep(0.5) self.page.set_input_files("input[type='file']", file_paths) def cancel_upload(self, slow_mode=True): """原子:在上传中途取消""" logger.info("⏹️ 尝试取消上传任务") if slow_mode: time.sleep(1) try: # 缩短超时时间,取消操作不应阻塞太久 self.smart_click("取消上传", timeout=1500) except: # 兜底:尝试点关闭图标或按 ESC try: self.page.evaluate("document.querySelector('button.p-dialog-header-close')?.click()") self.page.keyboard.press("Escape") except: pass time.sleep(1) def wait_for_success(self, count=1): """原子:等待上传进度条跑完""" logger.info(f"⏳ 等待进度达成 ({count})...") start = time.time() while time.time() - start < 300: content = self.page.evaluate("() => document.querySelector('.p-dialog')?.innerText || ''") if ("成功" in content and str(count) in content) or f"{count}/{count}" in content: break time.sleep(2) time.sleep(2) self.page.evaluate("document.querySelector('button.p-dialog-header-close')?.click()") time.sleep(1) def rename_item(self, old_name, new_name): """原子:执行行内重命名""" logger.info(f"✏️ 重命名: {old_name} -> {new_name}") self.page.evaluate(f"""() => {{ const row = Array.from(document.querySelectorAll('tr')).find(r => r.innerText.includes('{old_name}')); row?.querySelector('button[aria-label="重命名"], .p-button-text')?.click(); }}""") time.sleep(0.5) self.page.fill("input[placeholder*='名称']", new_name) # 强力点击确定 (支持文本、类名、角色) self.smart_click("确定", role="button") time.sleep(1) def delete_item(self, name): """原子:执行行内删除""" logger.info(f"🗑️ 删除: {name}") self.page.evaluate(f"""() => {{ const row = Array.from(document.querySelectorAll('tr')).find(r => r.innerText.includes('{name}')); if (!row) return; const delBtn = row.querySelector('button[aria-label="删除"]') || Array.from(row.querySelectorAll('button')).find(b => b.innerText.includes('删除')); delBtn?.click(); }}""") time.sleep(1) # 等待弹窗动画完成 # 针对确认框的多种可能属性进行强力点击 try: self.smart_click("确定", role="button", timeout=3000) except: # 兜底:直接寻找 PrimeVue 或 通用确认框的“接受”按钮类 self.page.evaluate("""() => { const ok = document.querySelector('.p-confirm-dialog-accept, .p-dialog-footer button:last-child, .btn-primary'); if (ok) ok.click(); }""") time.sleep(1) def back_to_root(self): """原子:通过面包屑返回""" logger.info("🔙 返回根目录") self.smart_click("数据管理", timeout=2000) time.sleep(1)