Commit 141c5999 authored by allen.wang's avatar allen.wang

fix:优化报表效果-效率

parent efff934e
...@@ -464,12 +464,12 @@ def build_shoes_filters( ...@@ -464,12 +464,12 @@ def build_shoes_filters(
return filters return filters
def build_overall_ui_filter_actions( def build_time_ui_filter_actions(
report_month: str, report_month: str,
report_year: int, report_year: int,
compare_year: int | None = None, compare_year: int | None = None,
) -> list[dict[str, Any]]: ) -> list[dict[str, Any]]:
"""Force S04 Overall to re-apply the visible time quick filters through the UI.""" """Apply the visible Month and billdate 年 quick filters through the UI."""
month_values = [ month_values = [
normalize_month_label(index) normalize_month_label(index)
for index in range(1, resolve_month_index(report_month) + 1) for index in range(1, resolve_month_index(report_month) + 1)
...@@ -491,6 +491,15 @@ def build_overall_ui_filter_actions( ...@@ -491,6 +491,15 @@ def build_overall_ui_filter_actions(
}, },
] ]
def build_overall_ui_filter_actions(
report_month: str,
report_year: int,
compare_year: int | None = None,
) -> list[dict[str, Any]]:
"""Force S04 Overall to re-apply the visible time quick filters through the UI."""
return build_time_ui_filter_actions(report_month, report_year, compare_year)
def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[str, Any]: def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[str, Any]:
"""Helper.""" """Helper."""
filters = [ filters = [
...@@ -505,13 +514,26 @@ def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[ ...@@ -505,13 +514,26 @@ def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[
report_year, report_year,
compare_year, compare_year,
) )
s05_filters = normalize_dashboard_download_filters( bags_shoes_ui_filter_actions = build_time_ui_filter_actions(
build_bags_filters(report_month, report_year, compare_year) report_month,
report_year,
compare_year,
) )
s05_filters = [
filter_spec
for filter_spec in normalize_dashboard_download_filters(
build_bags_filters(report_month, report_year, compare_year)
)
if filter_spec.get("label") == "storename"
]
# S06 intentionally mirrors the S05 Bags flow; only the Tableau page differs. # S06 intentionally mirrors the S05 Bags flow; only the Tableau page differs.
s06_filters = normalize_dashboard_download_filters( s06_filters = [
build_bags_filters(report_month, report_year, compare_year) filter_spec
) for filter_spec in normalize_dashboard_download_filters(
build_bags_filters(report_month, report_year, compare_year)
)
if filter_spec.get("label") == "storename"
]
s07_filters = normalize_dashboard_download_filters( s07_filters = normalize_dashboard_download_filters(
build_s07_filters(report_month, report_year, compare_year) build_s07_filters(report_month, report_year, compare_year)
) )
...@@ -526,7 +548,7 @@ def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[ ...@@ -526,7 +548,7 @@ def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[
"filters": filters, "filters": filters,
"capture_mode": "download_image", "capture_mode": "download_image",
"post_filter_wait_ms": INVENTORY_MONTHLY_OVERALL_POST_FILTER_WAIT_MS, "post_filter_wait_ms": INVENTORY_MONTHLY_OVERALL_POST_FILTER_WAIT_MS,
"ui_filter_mode": "snapshot", "ui_filter_mode": "script",
"ui_filter_actions": s04_ui_filter_actions, "ui_filter_actions": s04_ui_filter_actions,
"ui_filter_post_wait_ms": 8000, "ui_filter_post_wait_ms": 8000,
"ui_filter_forbidden_text_patterns": ["当前筛选器没有要可视化的数据"], "ui_filter_forbidden_text_patterns": ["当前筛选器没有要可视化的数据"],
...@@ -546,6 +568,10 @@ def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[ ...@@ -546,6 +568,10 @@ def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[
"viewport": {"width": 1280, "height": 960}, "viewport": {"width": 1280, "height": 960},
"capture_mode": "download_image", "capture_mode": "download_image",
"post_filter_wait_ms": INVENTORY_MONTHLY_DOWNLOAD_POST_FILTER_WAIT_MS, "post_filter_wait_ms": INVENTORY_MONTHLY_DOWNLOAD_POST_FILTER_WAIT_MS,
"ui_filter_mode": "script",
"ui_filter_actions": bags_shoes_ui_filter_actions,
"ui_filter_post_wait_ms": 8000,
"ui_filter_forbidden_text_patterns": ["当前筛选器没有要可视化的数据"],
"params": {}, "params": {},
"raw_screenshot_name": "inventory-s05-bags-download.png", "raw_screenshot_name": "inventory-s05-bags-download.png",
"note": "S05 bags dashboard export after applying active-sheet filters.", "note": "S05 bags dashboard export after applying active-sheet filters.",
...@@ -559,6 +585,10 @@ def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[ ...@@ -559,6 +585,10 @@ def build_specs(report_month: str, report_year: int, compare_year: int) -> dict[
"capture_mode": "download_image", "capture_mode": "download_image",
"viewport": {"width": 1280, "height": 960}, "viewport": {"width": 1280, "height": 960},
"post_filter_wait_ms": INVENTORY_MONTHLY_DOWNLOAD_POST_FILTER_WAIT_MS, "post_filter_wait_ms": INVENTORY_MONTHLY_DOWNLOAD_POST_FILTER_WAIT_MS,
"ui_filter_mode": "script",
"ui_filter_actions": bags_shoes_ui_filter_actions,
"ui_filter_post_wait_ms": 8000,
"ui_filter_forbidden_text_patterns": ["当前筛选器没有要可视化的数据"],
"params": {}, "params": {},
"raw_screenshot_name": "inventory-s06-shoes-download.png", "raw_screenshot_name": "inventory-s06-shoes-download.png",
"note": "S06 shoes dashboard export after applying active-sheet filters.", "note": "S06 shoes dashboard export after applying active-sheet filters.",
...@@ -814,6 +844,11 @@ def resolve_playwright_download_path(filename: str, download_dir: Path | None = ...@@ -814,6 +844,11 @@ def resolve_playwright_download_path(filename: str, download_dir: Path | None =
return path return path
def resolve_session_capture_path(root: Path, session: str, filename: str) -> Path:
"""Helper."""
return root / "output" / "playwright" / session / filename
def build_login_js(username: str, password: str) -> str: def build_login_js(username: str, password: str) -> str:
"""Helper.""" """Helper."""
payload = {"username": username, "password": password} payload = {"username": username, "password": password}
...@@ -2283,11 +2318,25 @@ def build_apply_quick_filters_js(spec: dict[str, Any]) -> str: ...@@ -2283,11 +2318,25 @@ def build_apply_quick_filters_js(spec: dict[str, Any]) -> str:
}}); }});
}} }}
const checkedAfter = await listCheckedRows(listbox); const checkedAfter = await listCheckedRows(listbox);
const checkedAfterLabels = [...new Set(
checkedAfter
.map((entry) => String(entry?.text || '').trim())
.filter((value) => value && value !== allFilterValue)
)];
const desiredCheckedLabels = [...new Set(
desiredValues
.map((value) => String(value || '').trim())
.filter((value) => value && value !== allFilterValue)
)];
const exactSelection =
checkedAfterLabels.length === desiredCheckedLabels.length &&
desiredCheckedLabels.every((value) => checkedAfterLabels.includes(value));
const closeMethod = await closeQuickFilter(button); const closeMethod = await closeQuickFilter(button);
const finalButtonText = await waitForButtonText(button, expectedButtonText, Number(spec.close_wait_ms || 15000)); const finalButtonText = await waitForButtonText(button, expectedButtonText, Number(spec.close_wait_ms || 15000));
const ok = const ok =
missingValues.length === 0 && missingValues.length === 0 &&
desiredStates.every((entry) => entry.checked) && desiredStates.every((entry) => entry.checked) &&
exactSelection &&
(!expectedButtonText || finalButtonText.includes(expectedButtonText)); (!expectedButtonText || finalButtonText.includes(expectedButtonText));
return {{ return {{
ok, ok,
...@@ -2299,6 +2348,9 @@ def build_apply_quick_filters_js(spec: dict[str, Any]) -> str: ...@@ -2299,6 +2348,9 @@ def build_apply_quick_filters_js(spec: dict[str, Any]) -> str:
desiredValues, desiredValues,
checkedBefore, checkedBefore,
checkedAfter, checkedAfter,
checkedAfterLabels,
desiredCheckedLabels,
exactSelection,
desiredStates, desiredStates,
actionsTaken, actionsTaken,
missingValues, missingValues,
...@@ -2744,29 +2796,9 @@ def load_state_if_present( ...@@ -2744,29 +2796,9 @@ def load_state_if_present(
def locate_session_file(root: Path, session: str, filename: str) -> Path: def locate_session_file(root: Path, session: str, filename: str) -> Path:
"""Helper.""" """Helper."""
direct = root / "output" / "playwright" / session / filename direct = resolve_session_capture_path(root, session, filename)
if direct.exists(): if direct.exists():
return direct return direct
search_roots = [
root / "output" / "playwright",
root / "output" / "vip-report",
root,
]
matches: list[Path] = []
for search_root in search_roots:
if search_root.exists():
matches.extend(search_root.rglob(filename))
if len(matches) == 1:
return matches[0]
if matches:
latest = sorted(
{item.resolve() for item in matches},
key=lambda item: item.stat().st_mtime,
reverse=True,
)[0]
return latest
raise FileNotFoundError(f"Unable to locate {filename} under {root}.") raise FileNotFoundError(f"Unable to locate {filename} under {root}.")
...@@ -2812,17 +2844,14 @@ def wait_for_capture_file( ...@@ -2812,17 +2844,14 @@ def wait_for_capture_file(
) )
wait_deadline = time.monotonic() + effective_timeout wait_deadline = time.monotonic() + effective_timeout
local_output = workdir / filename local_output = workdir / filename
session_output = resolve_session_capture_path(workspace_root, session, filename)
while time.monotonic() < wait_deadline: while time.monotonic() < wait_deadline:
if preferred_path is not None and preferred_path.exists(): if preferred_path is not None and preferred_path.exists():
return preferred_path return preferred_path
if local_output.exists(): if local_output.exists():
return local_output return local_output
try: if session_output.exists():
located = locate_session_file(workspace_root, session, filename) return session_output
if located.exists():
return located
except FileNotFoundError:
pass
time.sleep(1) time.sleep(1)
raise FileNotFoundError(f"Unable to locate {filename} under {workspace_root}.") raise FileNotFoundError(f"Unable to locate {filename} under {workspace_root}.")
......
...@@ -338,6 +338,18 @@ def write_js(workdir: Path, name: str, content: str) -> Path: ...@@ -338,6 +338,18 @@ def write_js(workdir: Path, name: str, content: str) -> Path:
return path return path
def resolve_playwright_download_path(filename: str, workdir: Path) -> Path:
"""Helper."""
path = workdir / ".playwright-downloads" / filename
path.parent.mkdir(parents=True, exist_ok=True)
return path
def resolve_session_capture_path(root: Path, session: str, filename: str) -> Path:
"""Helper."""
return root / "output" / "playwright" / session / filename
def build_login_js(username: str, password: str) -> str: def build_login_js(username: str, password: str) -> str:
"""Helper.""" """Helper."""
payload = { payload = {
...@@ -762,27 +774,26 @@ def load_state_if_present(session: str, state_path: Path, *, cwd: Path) -> None: ...@@ -762,27 +774,26 @@ def load_state_if_present(session: str, state_path: Path, *, cwd: Path) -> None:
) )
def locate_session_file(root: Path, session: str, filename: str) -> Path: def locate_session_file(
root: Path,
session: str,
filename: str,
*,
workdir: Path | None = None,
) -> Path:
"""Helper.""" """Helper."""
direct = root / "output" / "playwright" / session / filename candidates: list[Path] = []
if direct.exists(): if workdir is not None:
return direct candidates.extend(
[
search_roots = [ resolve_playwright_download_path(filename, workdir),
root / "output" / "playwright", workdir / filename,
root / "output" / "vip-report", ]
root, )
] candidates.append(resolve_session_capture_path(root, session, filename))
matches: list[Path] = [] for candidate in candidates:
for search_root in search_roots: if candidate.exists():
if search_root.exists(): return candidate
matches.extend(search_root.rglob(filename))
if len(matches) == 1:
return matches[0]
if matches:
latest = sorted({item.resolve() for item in matches}, key=lambda item: item.stat().st_mtime, reverse=True)[0]
return latest
raise FileNotFoundError(f"Unable to locate {filename} under {root}.") raise FileNotFoundError(f"Unable to locate {filename} under {root}.")
...@@ -939,6 +950,18 @@ def capture_tableau_view( ...@@ -939,6 +950,18 @@ def capture_tableau_view(
) -> Path: ) -> Path:
"""Helper.""" """Helper."""
target_url = build_tableau_target_url(base_url, capture_spec["hash_url"]) target_url = build_tableau_target_url(base_url, capture_spec["hash_url"])
preferred_capture_path = resolve_playwright_download_path(capture_spec["raw_screenshot_name"], workdir)
legacy_session_output = resolve_session_capture_path(
workspace_root,
session,
capture_spec["raw_screenshot_name"],
)
for stale_path in (
preferred_capture_path,
workdir / capture_spec["raw_screenshot_name"],
legacy_session_output,
):
stale_path.unlink(missing_ok=True)
goto_with_retry(session, target_url, cwd=workdir) goto_with_retry(session, target_url, cwd=workdir)
run_playwright( run_playwright(
["--session", session, "resize", str(VIEWPORT["width"]), str(VIEWPORT["height"])], ["--session", session, "resize", str(VIEWPORT["width"]), str(VIEWPORT["height"])],
...@@ -963,7 +986,7 @@ def capture_tableau_view( ...@@ -963,7 +986,7 @@ def capture_tableau_view(
f"tmp-{capture_spec['capture_id']}-capture.js", f"tmp-{capture_spec['capture_id']}-capture.js",
build_export_image_js( build_export_image_js(
capture_spec["inner_frame_fragment"], capture_spec["inner_frame_fragment"],
str((workdir / capture_spec["raw_screenshot_name"]).resolve()), str(preferred_capture_path.resolve()),
viewport=VIEWPORT, viewport=VIEWPORT,
), ),
) )
...@@ -994,11 +1017,12 @@ def capture_tableau_view( ...@@ -994,11 +1017,12 @@ def capture_tableau_view(
configure_script.unlink(missing_ok=True) configure_script.unlink(missing_ok=True)
capture_script.unlink(missing_ok=True) capture_script.unlink(missing_ok=True)
local_output = workdir / capture_spec["raw_screenshot_name"] captured_path = locate_session_file(
if local_output.exists(): workspace_root,
normalize_image_size(local_output, {"width": 1400, "height": 3360}) session,
return local_output capture_spec["raw_screenshot_name"],
captured_path = locate_session_file(workspace_root, session, capture_spec["raw_screenshot_name"]) workdir=workdir,
)
normalize_image_size(captured_path, {"width": 1400, "height": 3360}) normalize_image_size(captured_path, {"width": 1400, "height": 3360})
return captured_path return captured_path
......
...@@ -488,6 +488,18 @@ def write_js(workdir: Path, name: str, content: str) -> Path: ...@@ -488,6 +488,18 @@ def write_js(workdir: Path, name: str, content: str) -> Path:
return path return path
def resolve_playwright_download_path(filename: str, workdir: Path) -> Path:
"""Helper."""
path = workdir / ".playwright-downloads" / filename
path.parent.mkdir(parents=True, exist_ok=True)
return path
def resolve_session_capture_path(root: Path, session: str, filename: str) -> Path:
"""Helper."""
return root / "output" / "playwright" / session / filename
def build_login_js(username: str, password: str) -> str: def build_login_js(username: str, password: str) -> str:
"""Helper.""" """Helper."""
payload = {"username": username, "password": password} payload = {"username": username, "password": password}
...@@ -1629,22 +1641,27 @@ def load_state_if_present(session: str, state_path: Path, *, cwd: Path) -> None: ...@@ -1629,22 +1641,27 @@ def load_state_if_present(session: str, state_path: Path, *, cwd: Path) -> None:
run_playwright(["--session", session, "state-load", str(state_path)], cwd=cwd, timeout=60) run_playwright(["--session", session, "state-load", str(state_path)], cwd=cwd, timeout=60)
def locate_session_file(root: Path, session: str, filename: str) -> Path: def locate_session_file(
root: Path,
session: str,
filename: str,
*,
workdir: Path | None = None,
) -> Path:
"""Helper.""" """Helper."""
direct = root / "output" / "playwright" / session / filename candidates: list[Path] = []
if direct.exists(): if workdir is not None:
return direct candidates.extend(
[
search_roots = [root / "output" / "playwright", root / "output" / "vip-report", root] resolve_playwright_download_path(filename, workdir),
matches: list[Path] = [] workdir / filename,
for search_root in search_roots: ]
if search_root.exists(): )
matches.extend(search_root.rglob(filename)) candidates.append(resolve_session_capture_path(root, session, filename))
for candidate in candidates:
if not matches: if candidate.exists():
raise FileNotFoundError(f"Unable to locate {filename} under {root}.") return candidate
raise FileNotFoundError(f"Unable to locate {filename} under {root}.")
return sorted({item.resolve() for item in matches}, key=lambda item: item.stat().st_mtime, reverse=True)[0]
def crop_image(source: Path, target: Path, crop: dict[str, int], *, resize_to: dict[str, int] | None = None) -> None: def crop_image(source: Path, target: Path, crop: dict[str, int], *, resize_to: dict[str, int] | None = None) -> None:
...@@ -1673,6 +1690,18 @@ def capture_tableau_view( ...@@ -1673,6 +1690,18 @@ def capture_tableau_view(
) -> Path: ) -> Path:
"""Helper.""" """Helper."""
target_url = f"{base_url}{capture_spec['hash_url']}" target_url = f"{base_url}{capture_spec['hash_url']}"
preferred_capture_path = resolve_playwright_download_path(capture_spec["raw_screenshot_name"], workdir)
legacy_session_output = resolve_session_capture_path(
workspace_root,
session,
capture_spec["raw_screenshot_name"],
)
for stale_path in (
preferred_capture_path,
workdir / capture_spec["raw_screenshot_name"],
legacy_session_output,
):
stale_path.unlink(missing_ok=True)
def reset_target_page() -> None: def reset_target_page() -> None:
run_playwright(["--session", session, "goto", target_url], cwd=workdir, timeout=120) run_playwright(["--session", session, "goto", target_url], cwd=workdir, timeout=120)
run_playwright( run_playwright(
...@@ -1737,7 +1766,7 @@ def capture_tableau_view( ...@@ -1737,7 +1766,7 @@ def capture_tableau_view(
f"tmp-{capture_spec['capture_id']}-capture.js", f"tmp-{capture_spec['capture_id']}-capture.js",
build_export_image_js( build_export_image_js(
capture_spec["inner_frame_fragment"], capture_spec["inner_frame_fragment"],
str((workdir / capture_spec["raw_screenshot_name"]).resolve()), str(preferred_capture_path.resolve()),
viewport=VIEWPORT, viewport=VIEWPORT,
), ),
) )
...@@ -1871,11 +1900,12 @@ def capture_tableau_view( ...@@ -1871,11 +1900,12 @@ def capture_tableau_view(
wait_script.unlink(missing_ok=True) wait_script.unlink(missing_ok=True)
capture_script.unlink(missing_ok=True) capture_script.unlink(missing_ok=True)
local_output = workdir / capture_spec["raw_screenshot_name"] captured_path = locate_session_file(
if local_output.exists(): workspace_root,
normalize_image_size(local_output, {"width": 1400, "height": 3760}) session,
return local_output capture_spec["raw_screenshot_name"],
captured_path = locate_session_file(workspace_root, session, capture_spec["raw_screenshot_name"]) workdir=workdir,
)
normalize_image_size(captured_path, {"width": 1400, "height": 3760}) normalize_image_size(captured_path, {"width": 1400, "height": 3760})
return captured_path return captured_path
......
...@@ -341,6 +341,18 @@ def write_js(workdir: Path, name: str, content: str) -> Path: ...@@ -341,6 +341,18 @@ def write_js(workdir: Path, name: str, content: str) -> Path:
return path return path
def resolve_playwright_download_path(filename: str, workdir: Path) -> Path:
"""Helper."""
path = workdir / ".playwright-downloads" / filename
path.parent.mkdir(parents=True, exist_ok=True)
return path
def resolve_session_capture_path(root: Path, session: str, filename: str) -> Path:
"""Helper."""
return root / "output" / "playwright" / session / filename
def build_login_js(username: str, password: str) -> str: def build_login_js(username: str, password: str) -> str:
"""Helper.""" """Helper."""
payload = {"username": username, "password": password} payload = {"username": username, "password": password}
...@@ -591,26 +603,26 @@ def load_state_if_present(session: str, state_path: Path, *, cwd: Path) -> None: ...@@ -591,26 +603,26 @@ def load_state_if_present(session: str, state_path: Path, *, cwd: Path) -> None:
pass pass
def locate_session_file(root: Path, session: str, filename: str) -> Path: def locate_session_file(
root: Path,
session: str,
filename: str,
*,
workdir: Path | None = None,
) -> Path:
"""Helper.""" """Helper."""
search_roots = [ candidates: list[Path] = []
root / "output" / "playwright", if workdir is not None:
root / "output" / "vip-report", candidates.extend(
root, [
] resolve_playwright_download_path(filename, workdir),
matches: list[Path] = [] workdir / filename,
for search_root in search_roots: ]
if search_root.exists(): )
matches.extend(search_root.rglob(filename)) candidates.append(resolve_session_capture_path(root, session, filename))
for candidate in candidates:
if len(matches) == 1: if candidate.exists():
return matches[0] return candidate
if matches:
return sorted(
{item.resolve() for item in matches},
key=lambda item: item.stat().st_mtime,
reverse=True,
)[0]
raise FileNotFoundError(f"Unable to locate {filename} under {root}.") raise FileNotFoundError(f"Unable to locate {filename} under {root}.")
...@@ -707,8 +719,18 @@ def capture_tableau_view( ...@@ -707,8 +719,18 @@ def capture_tableau_view(
) -> Path: ) -> Path:
"""Helper.""" """Helper."""
target_url = f"{base_url}{capture_spec['hash_url']}" target_url = f"{base_url}{capture_spec['hash_url']}"
local_output = workdir / capture_spec["raw_screenshot_name"] preferred_capture_path = resolve_playwright_download_path(capture_spec["raw_screenshot_name"], workdir)
local_output.unlink(missing_ok=True) legacy_session_output = resolve_session_capture_path(
workspace_root,
session,
capture_spec["raw_screenshot_name"],
)
for stale_path in (
preferred_capture_path,
workdir / capture_spec["raw_screenshot_name"],
legacy_session_output,
):
stale_path.unlink(missing_ok=True)
run_playwright(["--session", session, "goto", target_url], cwd=workdir, timeout=120) run_playwright(["--session", session, "goto", target_url], cwd=workdir, timeout=120)
run_playwright( run_playwright(
["--session", session, "resize", str(VIEWPORT["width"]), str(VIEWPORT["height"])], ["--session", session, "resize", str(VIEWPORT["width"]), str(VIEWPORT["height"])],
...@@ -726,7 +748,7 @@ def capture_tableau_view( ...@@ -726,7 +748,7 @@ def capture_tableau_view(
f"tmp-{capture_spec['capture_id']}-{time.time_ns()}-capture.js", f"tmp-{capture_spec['capture_id']}-{time.time_ns()}-capture.js",
build_export_image_js( build_export_image_js(
capture_spec["inner_frame_fragment"], capture_spec["inner_frame_fragment"],
str((workdir / capture_spec["raw_screenshot_name"]).resolve()), str(preferred_capture_path.resolve()),
viewport=VIEWPORT, viewport=VIEWPORT,
), ),
) )
...@@ -770,11 +792,12 @@ def capture_tableau_view( ...@@ -770,11 +792,12 @@ def capture_tableau_view(
configure_script.unlink(missing_ok=True) configure_script.unlink(missing_ok=True)
capture_script.unlink(missing_ok=True) capture_script.unlink(missing_ok=True)
if local_output.exists(): captured_path = locate_session_file(
wait_for_image_ready(local_output) workspace_root,
normalize_image_size(local_output, {"width": 1400, "height": 3360}) session,
return local_output capture_spec["raw_screenshot_name"],
captured_path = locate_session_file(workspace_root, session, capture_spec["raw_screenshot_name"]) workdir=workdir,
)
wait_for_image_ready(captured_path) wait_for_image_ready(captured_path)
normalize_image_size(captured_path, {"width": 1400, "height": 3360}) normalize_image_size(captured_path, {"width": 1400, "height": 3360})
return captured_path return captured_path
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment