89 lines
7.8 KiB
Python
89 lines
7.8 KiB
Python
import asyncio, json, os, re
|
||
from playwright.async_api import async_playwright
|
||
"""Съёмка экранов React-макета dkb_24.09.26 headless-браузером → PNG + report.json.
|
||
python scripts/mockup_crawl.py docs/mockup/dkb_24.09.26/dkb_24.09.26.html docs/mockup/screens
|
||
Зависимости: pip install playwright && playwright install chromium
|
||
"""
|
||
import sys
|
||
URL = "file://" + os.path.abspath(sys.argv[1])
|
||
OUT = sys.argv[2]
|
||
REPORT = {}
|
||
SLUG = {'Шахматка':'chess','Таблица корректировки':'corrections','Гудвилл':'goodwill','КФО':'kfo','КФО Общий':'kfo-total','Подтверждение КФО клиента':'kfo-client','Показать ЮЛ без ИНН':'osv-no-inn','Указать':'osv-map-counterparty','ЮЛ':'le','ГСК':'gsk','ГСЗ':'gsz','История':'history','Архив':'archive'}
|
||
|
||
async def click_text(pg, text, tag=None, nth=0, exact=False):
|
||
ok = await pg.evaluate("""([text, tag, nth, exact]) => {
|
||
const els=[...document.querySelectorAll(tag || 'button, a, [role=tab], [role=menuitem], tr, li, div')]
|
||
.filter(e => { const t=(e.innerText||'').trim().replace(/\\s+/g,' '); return (exact ? t===text : t.startsWith(text)) && e.getBoundingClientRect().width>5; });
|
||
const e = els[nth]; if(!e) return false; e.scrollIntoView({block:'center'}); e.click(); return true; }""", [text, tag, nth, exact])
|
||
await pg.wait_for_timeout(600); return ok
|
||
|
||
async def snap(pg, name, note=""):
|
||
await pg.screenshot(path=f"{OUT}/{name}.png")
|
||
d = await pg.evaluate("""() => { const q=s=>[...document.querySelectorAll(s)]; const t=e=>(e.innerText||'').trim().replace(/\\s+/g,' ');
|
||
const modal = q('[class*=modal],[class*=Modal],[role=dialog],[class*=drawer],[class*=Drawer],[class*=overlay]').filter(e=>e.getBoundingClientRect().width>100).map(t).slice(0,1).map(x=>x.slice(0,600));
|
||
return {heads:q('h1,h2,h3').map(t).filter(Boolean).slice(0,10), buttons:[...new Set(q('button').map(t).filter(x=>x&&x.length<50))],
|
||
cols:[...new Set(q('th').map(t).filter(Boolean))].slice(0,40), crumbs:q('[class*=crumb],[class*=Crumb]').map(t).slice(0,1),
|
||
modal, labels:[...new Set(q('label, [class*=label], [class*=Label]').map(t).filter(x=>x&&x.length<40))].slice(0,30),
|
||
body:t(document.body).slice(0,3000)} }""")
|
||
d["note"]=note; REPORT[name]=d
|
||
print(f"## {name} {d['crumbs']} {d['heads'][:3]} | cols={d['cols'][:16]} | modal={bool(d['modal'])}")
|
||
return d
|
||
|
||
SIDEBAR = {'Новая консолидация','Группы компаний','Монозаемщики','ГК и организации','ЮЛ вне ГК','Единое хранилище','Журнал действий'}
|
||
|
||
async def fresh(pg):
|
||
await pg.goto(URL); await pg.evaluate("() => { localStorage.clear(); sessionStorage.clear(); }"); await pg.goto(URL); await pg.wait_for_timeout(1600)
|
||
|
||
async def goto_report(pg):
|
||
await fresh(pg)
|
||
await click_text(pg, "Группы компаний", "button"); await click_text(pg, "Консолидации", "button"); await click_text(pg, "К отчетности", "button")
|
||
|
||
async def main():
|
||
async with async_playwright() as p:
|
||
b = await p.chromium.launch(); pg = await b.new_page(viewport={"width":1600,"height":1000})
|
||
# --- карточка отчёта и вкладки
|
||
await goto_report(pg); d = await snap(pg, "30-report-osv", "вкладка ОСВ по умолчанию")
|
||
for i, t in enumerate(["Шахматка","Таблица корректировки","Гудвилл","КФО","КФО Общий","Подтверждение КФО клиента"]):
|
||
if await click_text(pg, t, "button", 0, True):
|
||
if i == 0: await snap(pg, "31-00-inn-warning", "модалка «Остались неуказанные ИНН» при уходе с ОСВ")
|
||
await click_text(pg, "Перейти", "button", 0, True)
|
||
await snap(pg, f"31-{i+1:02d}-{SLUG[t]}", f"вкладка {t}")
|
||
# сводная ОСВ: доп. кнопки
|
||
await click_text(pg, "ОСВ", "button", 0, True)
|
||
for t in ["Показать ЮЛ без ИНН", "Указать"]:
|
||
if await click_text(pg, t, "button"): await snap(pg, f"32-{SLUG[t]}", f"ОСВ → {t}"); await goto_report(pg)
|
||
# изменить статус
|
||
if await click_text(pg, "Изменить статус", "button"): await snap(pg, "33-change-status", "модалка смены статуса")
|
||
# --- список консолидаций: взять в работу, документы организации, состав, чек-лист
|
||
await fresh(pg)
|
||
await click_text(pg, "Группы компаний", "button"); await click_text(pg, "Консолидации", "button")
|
||
await snap(pg, "34-consolidations", "список консолидаций ГК + организации")
|
||
for t, n in [("Взять в работу","35-take-in-work"),("Редактировать состав","36-edit-members"),("Скачать чек-лист","37-checklist"),("Импорт","38-import")]:
|
||
if await click_text(pg, t, "button"): await snap(pg, n, t); await pg.keyboard.press("Escape"); await click_text(pg,"Отмена","button"); await click_text(pg,"Закрыть","button")
|
||
if await click_text(pg, "Документы", "button"):
|
||
await snap(pg, "39-org-documents", "панель первичных документов организации")
|
||
for t, n in [("Загрузить документы","40-upload"),("Загрузить","40-upload")]:
|
||
if await click_text(pg, t, "button"): await snap(pg, n, t); await pg.keyboard.press("Escape"); await click_text(pg,"Отмена","button"); break
|
||
# открыть документ (строка таблицы в панели)
|
||
if await click_text(pg, "", "[class*=drawer] tr, [class*=Drawer] tr, [class*=panel] tr, [class*=Panel] tr", 1):
|
||
await snap(pg, "41-document-view", "просмотр/проверка распознавания документа")
|
||
# --- новая консолидация
|
||
await fresh(pg)
|
||
await click_text(pg, "Новая консолидация", "button"); await snap(pg, "42-new-consolidation", "модалка создания консолидации")
|
||
# --- справочник ГК: карточка ГК (стартовый экран)
|
||
await fresh(pg)
|
||
await snap(pg, "50-directory-gk", "справочник ГК и организации (стартовый экран)")
|
||
for t, n in [("Создать ГК/ЮЛ","51-create-gk"),("Импорт из файла","52-import-file")]:
|
||
if await click_text(pg, t, "button"): await snap(pg, n, t); await pg.keyboard.press("Escape"); await click_text(pg,"Отмена","button")
|
||
# правая панель: вкладки ЮЛ/ГСК/ГСЗ
|
||
for t in ["ЮЛ","ГСК","ГСЗ","История","Архив"]:
|
||
if await click_text(pg, t, "button", 0, True): await snap(pg, f"53-{SLUG[t]}", f"вкладка {t} в карточке ГК")
|
||
# кликнуть по ЮЛ в составе ГК
|
||
if await click_text(pg, "ООО", None, 0): await snap(pg, "54-legal-entity", "карточка ЮЛ")
|
||
# --- монозаёмщики, ЕХ, журнал, ЮЛ вне ГК (кратко)
|
||
for t, n in [("Монозаемщики","60-mono"),("ЮЛ вне ГК","61-le-outside"),("Единое хранилище","62-ex"),("Журнал действий","63-audit")]:
|
||
await fresh(pg); await click_text(pg, t, "button"); await snap(pg, n, t)
|
||
json.dump(REPORT, open(f"{OUT}/report.json","w"), ensure_ascii=False, indent=1)
|
||
await b.close()
|
||
asyncio.run(main())
|