#!/usr/bin/env python3 """Capture deeper business edit states from already reachable list pages.""" from __future__ import annotations import json import sys import time from collections import deque from pathlib import Path from typing import Any import capture_action_states as actions import mirror_logged_in_site as mirror TASKS = [ { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/price", "click_text": "物业费2.5", "slug": "item_edit_01", "label": "收费项编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/price", "click_text": "按公式计算", "slug": "pricing_edit_02", "label": "定价编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/price", "pre_click_ids": ["tab-advancedConfig", "tab-chargeItem"], "click_text": "新增", "slug": "item_create_03", "label": "收费项新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/contractManage/contractList", "click_text": "新建合同", "slug": "contract_create_00", "label": "合同新建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/contractManage/contractList", "click_text": "查看", "slug": "contract_view_01", "label": "合同查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/contractManage/contractList", "click_text": "编辑", "slug": "contract_edit_02", "label": "合同编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/activeService/activeServicePlan", "click_text": "创建计划", "slug": "service_plan_create_00", "label": "服务计划创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/activeService/activeServicePlan", "click_text": "复制计划", "pre_select_first_row": True, "capture_after_pre_clicks": True, "slug": "service_plan_copy_01", "label": "服务计划复制", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/activeService/activeServicePlan", "click_text": "批量修改验收人", "pre_select_first_row": True, "slug": "service_plan_batch_accept_02", "label": "服务计划批量修改验收人", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/activeService/activeServicePlan", "click_text": "一键生成计划", "slug": "service_plan_generate_03", "label": "服务计划一键生成", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/activeService/activeServicePlan", "click_text": "查看", "slug": "service_plan_view_04", "label": "服务计划查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/activeService/activeServicePlan", "click_text": "编辑", "slug": "service_plan_edit_05", "label": "服务计划编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/activeService/activeServicePlan", "click_text": "查看记录", "slug": "service_plan_record_06", "label": "服务计划记录", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/propertyCompany", "click_text": "查看评价明细", "slug": "property_company_detail_00", "label": "物业服务人查看评价明细", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorFile/elevatorArchives", "click_text": "新增", "slug": "elevator_create_00", "label": "电梯档案新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorFile/elevatorArchives", "click_text": "详情", "slug": "elevator_detail_01", "label": "电梯档案详情", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/equipmentManage/equipmentFiling/equipmentArchives", "click_text": "新增", "slug": "equipment_create_00", "label": "设备档案新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/equipmentManage/equipmentFiling/equipmentArchives", "click_text": "详情", "slug": "equipment_detail_01", "label": "设备档案详情", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/cleanFile/cleanArchives", "click_text": "新增", "slug": "clean_archive_create_00", "label": "清洁档案新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/greenManage/greenFile/greenArchives", "click_text": "新增", "slug": "green_archive_create_00", "label": "绿化档案新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/energySourceOperat/energyFile/energyArchives", "click_text": "新增", "slug": "energy_public_create_00", "label": "公区能源档案新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/energySourceOperat/energyFile/energyMeterList", "click_text": "添加", "slug": "energy_family_create_00", "label": "家庭能源档案添加", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/energySourceOperat/energyFile/energyMeterList", "click_text": "编辑", "slug": "energy_family_edit_01", "label": "家庭能源档案编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/energySourceOperat/publicAreaControl/energyPlan", "click_text": "创建计划", "slug": "energy_plan_create_00", "label": "能源计划创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/parkingRecord/parkingSpaceFile", "click_text": "新增", "slug": "parking_space_create_00", "label": "车位档案新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/parkingRecord/parkingSpaceFile", "click_text": "编辑", "slug": "parking_space_edit_01", "label": "车位档案编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/parkingRecord/vehicleArchives", "click_text": "添加", "slug": "vehicle_archive_create_00", "label": "车辆档案添加", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/parkingRecord/vehicleArchives", "click_text": "编辑", "slug": "vehicle_archive_edit_01", "label": "车辆档案编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/diversifiedEconomy/record", "click_text": "新建多经档案", "slug": "diversified_record_create_00", "label": "多经档案新建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/diversifiedEconomy/record", "click_text": "编辑", "slug": "diversified_record_edit_01", "label": "多经档案编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/homeEnterpriseService/cafeteria/canteenArchives", "click_text": "添加", "slug": "canteen_archive_create_00", "label": "食堂档案添加", }, { "source_url": "https://hc-pos.sqygj.cn/#/homeEnterpriseService/cafeteria/canteenArchives", "click_text": "查看", "slug": "canteen_archive_view_01", "label": "食堂档案查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/homeEnterpriseService/cafeteria/canteenArchives", "click_text": "编辑", "slug": "canteen_archive_edit_02", "label": "食堂档案编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/cleanFile/cleanEquipment", "click_text": "新增", "slug": "clean_equipment_create_00", "label": "清洁设备新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/greenManage/greenFile/greenEquipment", "click_text": "新增", "slug": "green_equipment_create_00", "label": "绿化设备新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/cleanFile/cleanContract", "click_text": "新建合同", "slug": "clean_contract_create_00", "label": "清洁合同新建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/cleanFile/cleanContract", "click_text": "编辑", "slug": "clean_contract_edit_01", "label": "清洁合同编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/greenManage/greenFile/greenContract", "click_text": "新建合同", "slug": "green_contract_create_00", "label": "绿化合同新建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/greenManage/greenFile/greenContract", "click_text": "编辑", "slug": "green_contract_edit_01", "label": "绿化合同编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorFile/elevatorContract", "click_text": "新建合同", "slug": "elevator_contract_create_00", "label": "电梯合同新建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorFile/elevatorContract", "click_text": "查看", "slug": "elevator_contract_view_01", "label": "电梯合同查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorFile/elevatorContract", "click_text": "编辑", "slug": "elevator_contract_edit_02", "label": "电梯合同编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/equipmentManage/equipmentFiling/equipmentContract", "click_text": "新建合同", "slug": "equipment_contract_create_00", "label": "设备合同新建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/equipmentManage/equipmentPlan/equipmentPlanList", "click_text": "创建计划", "slug": "equipment_plan_create_00", "label": "设备保养计划创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/equipmentManage/equipmentPlan/equipmentPlanList", "click_text": "编辑", "slug": "equipment_plan_edit_01", "label": "设备保养计划编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/equipmentManage/equipmentPlan/equipmentPlanList", "click_text": "查看记录", "slug": "equipment_plan_record_02", "label": "设备保养计划记录", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityManage/dailySecurity/securityPlan", "click_text": "创建计划", "slug": "security_plan_create_00", "label": "安防计划创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityManage/dailySecurity/securityPlan", "click_text": "查看记录", "slug": "security_plan_record_01", "label": "安防计划记录", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityManage/specialPhysica", "click_text": "编辑", "slug": "security_special_physical_edit_00", "label": "安防测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/parkingRecord/parkingContract", "click_text": "新建合同", "slug": "parking_contract_create_00", "label": "车场合同新建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/dailyOperation/maintenancePlan", "click_text": "创建计划", "slug": "parking_maintenance_plan_create_00", "label": "车场运维计划创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/dailyOperation/maintenancePlan", "click_text": "编辑", "slug": "parking_maintenance_plan_edit_01", "label": "车场运维计划编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/dailyOperation/maintenancePlan", "click_text": "查看记录", "slug": "parking_maintenance_plan_record_02", "label": "车场运维计划记录", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorPlan/elevatorPlanList", "click_text": "创建计划", "slug": "elevator_plan_create_00", "label": "电梯维保计划创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorPlan/elevatorPlanList", "click_text": "编辑", "slug": "elevator_plan_edit_01", "label": "电梯维保计划编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorPlan/elevatorPlanList", "click_text": "查看记录", "slug": "elevator_plan_record_02", "label": "电梯维保计划记录", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/dailyClean/cleanPlan", "click_text": "创建计划", "slug": "clean_plan_create_00", "label": "清洁计划创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/dailyClean/cleanPlan", "click_text": "编辑", "slug": "clean_plan_edit_01", "label": "清洁计划编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/dailyClean/cleanPlan", "click_text": "查看记录", "slug": "clean_plan_record_02", "label": "清洁计划记录", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/greenManage/dailyGreen/greenPlan", "click_text": "创建计划", "slug": "green_plan_create_00", "label": "绿化计划创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/greenManage/dailyGreen/greenPlan", "click_text": "查看记录", "slug": "green_plan_record_01", "label": "绿化计划记录", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/greenManage/greenSpecialPhysical", "click_text": "编辑", "slug": "green_special_physical_edit_00", "label": "绿化测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityManage/securityFile/securityEquipment", "click_text": "新增", "slug": "security_equipment_create_00", "label": "安防设备新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityManage/securityFile/securityEquipment", "click_text": "详情", "slug": "security_equipment_detail_01", "label": "安防设备详情", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/communityBasicsInfo", "click_text": "编辑", "slug": "community_basics_edit_00", "label": "楼宇信息编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/basicsInfo", "click_text": "编辑", "slug": "basic_info_edit_00", "label": "项目信息编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/spatialRegion", "click_text": "新增空间", "slug": "spatial_region_space_create_00", "label": "网格划分新增空间", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/spatialRegion", "click_text": "新增网格", "slug": "spatial_region_grid_create_01", "label": "网格划分新增网格", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/spatialRegion", "click_text": "编辑", "slug": "spatial_region_edit_02", "label": "网格划分编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/communicate", "click_text": "创建计划", "slug": "communicate_create_00", "label": "政务沟通创建计划", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/communicate", "click_text": "编辑", "slug": "communicate_edit_01", "label": "政务沟通编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/laborQuotaManagement/PTUGroup", "click_text": "创建PTU组合", "slug": "ptu_group_create_00", "label": "劳动分工创建PTU组合", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/laborQuotaManagement/PTUGroup", "click_text": "编辑", "slug": "ptu_group_edit_01", "label": "劳动分工编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/budgetManage/operatingBudget", "click_text": "新增", "slug": "operating_budget_create_00", "label": "业务预算新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/budgetManage/operatingBudget", "click_text": "编辑", "slug": "operating_budget_edit_01", "label": "业务预算编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/budgetManage/forecastBudget", "click_text": "新增预算预测", "slug": "forecast_budget_create_00", "label": "预算预测新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/budgetManage/forecastBudget", "click_text": "添加业务项", "slug": "forecast_budget_add_item_01", "label": "预算预测添加业务项", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/budgetManage/budgetOrgan", "pre_click_texts": ["\u8d26\u6237\u4fe1\u606f"], "capture_after_pre_clicks": True, "slug": "budget_organ_account_info_00", "label": "\u9884\u7b97\u7f16\u5236\u8d26\u6237\u4fe1\u606f", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/budgetManage/budgetOrgan", "pre_click_texts": ["\u4eba\u5458\u5916\u5305\u8d39\u7528"], "capture_after_pre_clicks": True, "slug": "budget_organ_personnel_outsourcing_01", "label": "\u9884\u7b97\u7f16\u5236\u4eba\u5458\u5916\u5305\u8d39\u7528", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/budgetManage/budgetOrgan", "pre_click_texts": ["\u804c\u5de5\u85aa\u916c"], "capture_after_pre_clicks": True, "slug": "budget_organ_salary_02", "label": "\u9884\u7b97\u7f16\u5236\u804c\u5de5\u85aa\u916c", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/metadataManage/subjectManage", "pre_click_texts": ["\u5c55\u5f00"], "capture_after_pre_clicks": True, "slug": "subject_manage_expand_00", "label": "\u79d1\u76ee\u7ba1\u7406\u5c55\u5f00", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/metadataManage/subjectManage", "pre_click_texts": ["\u5168\u90e8\u5c55\u5f00"], "capture_after_pre_clicks": True, "slug": "subject_manage_expand_all_01", "label": "\u79d1\u76ee\u7ba1\u7406\u5168\u90e8\u5c55\u5f00", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/charging", "click_text": "创建计费", "slug": "charging_create_00", "label": "计费创建", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/receivable", "click_text": "查看", "slug": "receivable_view_00", "label": "应收查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/salesOrder", "click_text": "查看", "slug": "sales_order_view_00", "label": "销单查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/caseList", "click_text": "添加", "slug": "case_list_create_00", "label": "案例指导添加", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/caseList", "click_text": "编辑", "slug": "case_list_edit_01", "label": "案例指导编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/committeeMember", "click_text": "添加业委会成员", "slug": "committee_member_create_00", "label": "业委会成员添加", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/committeeMember", "click_text": "查看", "slug": "committee_member_view_01", "label": "业委会成员查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/committeeMember", "click_text": "编辑", "slug": "committee_member_edit_02", "label": "业委会成员编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/communityCulture", "click_text": "新增", "slug": "community_culture_create_00", "label": "社区文化新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/party", "click_text": "新增", "slug": "party_create_00", "label": "党建活动新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/industryCommitte", "click_text": "创建计划", "slug": "industry_committe_create_00", "label": "业主大会创建计划", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/industryCommitte", "click_text": "查看", "slug": "industry_committe_view_01", "label": "业主大会查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/industryCommitte", "click_text": "编辑", "slug": "industry_committe_edit_02", "label": "业主大会编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/industryCommitte", "click_text": "查看记录", "slug": "industry_committe_record_03", "label": "业主大会查看记录", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/personnelList", "click_text": "绑定", "slug": "personnel_bind_00", "label": "住户档案微信绑定", }, { "source_url": "https://hc-pos.sqygj.cn/#/aiProduct/urgePayment/houseLawsuit", "pre_select_first_row": True, "click_text": "批量修改阶段", "slug": "house_lawsuit_stage_edit_00", "label": "委案流程批量修改阶段", }, { "source_url": "https://hc-pos.sqygj.cn/#/aiProduct/urgePayment/houseLawsuit", "pre_select_first_row": True, "click_text": "批量修改流程结果", "slug": "house_lawsuit_result_edit_01", "label": "委案流程批量修改结果", }, { "source_url": "https://hc-pos.sqygj.cn/#/aiProduct/urgePayment/houseLawsuit", "pre_select_first_row": True, "click_text": "批量修改案件时间", "slug": "house_lawsuit_time_edit_02", "label": "委案流程批量修改时间", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/advancePayment", "click_text": "查看", "slug": "advance_payment_view_00", "label": "预缴查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/budgetManage/financialApproval", "click_text": "查看", "slug": "financial_approval_view_00", "label": "财务审批查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/consideration", "click_text": "新建投票", "slug": "consideration_create_00", "label": "议事表决新建投票", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/consideration", "click_text": "查看", "slug": "consideration_view_01", "label": "议事表决查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/serviceProvider", "direct_url": "https://hc-pos.sqygj.cn/#/projectProfile/addAreaManage", "direct_capture": True, "slug": "service_provider_area_create_00", "label": "服务商管理新增管理区", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/serviceProvider", "direct_url": "https://hc-pos.sqygj.cn/#/projectProfile/editAreaManage?data=%5Bobject%20Object%5D", "direct_capture": True, "slug": "service_provider_area_edit_01", "label": "服务商管理编辑管理区", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/accepterManage", "click_text": "通过", "slug": "accepter_manage_approve_00", "label": "共建组织通过确认", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/accepterManage", "click_text": "拒绝", "slug": "accepter_manage_reject_01", "label": "共建组织拒绝确认", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/accepterManage", "click_text": "禁用", "slug": "accepter_manage_disable_02", "label": "共建组织禁用确认", }, { "source_url": "https://hc-pos.sqygj.cn/#/communitySMG/accepterManage", "click_text": "启用", "slug": "accepter_manage_enable_03", "label": "共建组织启用确认", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/organization/workOrderReport", "pre_click_texts": ["展开"], "click_text": "查看", "slug": "workorder_report_view_00", "label": "异常设置查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/organization/workOrderReport", "pre_click_texts": ["展开"], "click_text": "编辑", "slug": "workorder_report_edit_01", "label": "异常设置编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/energySourceOperat/energyConservation/energySourceMetering", "click_text": "添加", "slug": "energy_source_metering_create_00", "label": "能源计量添加", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/contractManage/checkStandardLibrary", "click_text": "新增", "slug": "check_standard_create_00", "label": "5A标准新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/contractManage/checkStandardLibrary", "click_text": "查看", "slug": "check_standard_view_01", "label": "5A标准查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/contractManage/checkStandardLibrary", "click_text": "编辑", "slug": "check_standard_edit_02", "label": "5A标准编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/diagnosis/5Aphysical", "click_text": "编辑", "slug": "physical_5a_edit_00", "label": "5A测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/diagnosis/customizedPhysical", "click_text": "新增体检套餐", "slug": "customized_physical_create_00", "label": "定制测评新增套餐", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/diagnosis/customizedPhysical", "click_text": "编辑", "slug": "customized_physical_edit_01", "label": "定制测评编辑套餐", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/diagnosis/specialPhysical", "click_text": "编辑", "slug": "special_physical_edit_00", "label": "专项测评编辑套餐", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/payableExamine", "click_text": "人工添加", "slug": "payable_examine_create_00", "label": "应付管控人工添加", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/payableExamine", "click_text": "编辑", "slug": "payable_examine_edit_01", "label": "应付管控编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/payableList", "click_text": "查看", "slug": "payable_list_view_00", "label": "应付查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/expenseApproval", "click_text": "查看", "slug": "expense_approval_view_00", "label": "支出审批查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/expenseList", "click_text": "确认已付款", "slug": "expense_list_paid_confirm_00", "label": "支出记录已付款确认", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/expenseList", "click_text": "付款遇到疑问", "slug": "expense_list_question_confirm_01", "label": "支出记录付款疑问确认", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/salaryExamine", "pre_select_first_row": True, "click_text": "应付管控申请", "slug": "salary_examine_apply_00", "label": "薪酬管控申请", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/salaryPayable", "click_text": "查看", "slug": "salary_payable_view_00", "label": "薪酬应付查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/invoice", "click_text": "登录认证", "slug": "invoice_login_auth_00", "label": "发票登录认证", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/invoice", "click_text": "人脸认证", "slug": "invoice_face_auth_01", "label": "发票人脸认证", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/paymentSub", "click_text": "支付状态更新", "slug": "payment_sub_status_update_00", "label": "支付分账支付状态更新", }, { "source_url": "https://hc-pos.sqygj.cn/#/dataPlatform/home", "click_text": "查看报告", "slug": "data_platform_report_view_00", "label": "智能报告查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/energySourceOperat/energySourcMicrobrain", "click_text": "核定及查看数据", "slug": "energy_microbrain_confirm_00", "label": "能源报表核定数据", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/revenueManage/metering", "click_text": "编辑录入本", "slug": "metering_edit_book_00", "label": "计量编辑录入本", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/costControl/expenseItem", "click_text": "编辑", "slug": "expense_item_edit_00", "label": "支出项编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/customerVisit/customerVisitRectification", "click_text": "新建工单", "slug": "customer_visit_rectification_create_00", "label": "整改跟踪新建工单", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/reportRepair", "click_text": "查看", "text_occurrence": 2, "slug": "report_repair_view_02", "label": "报事报修查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/customerCare", "click_text": "录入关怀", "slug": "customer_care_create_00", "label": "客户关怀录入", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/serviceReport", "click_text": "编辑", "slug": "service_report_edit_00", "label": "服务报告编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/customerVisit/customerVisitPlan", "click_text": "一键修复", "slug": "customer_visit_plan_repair_confirm_00", "label": "拜访计划一键修复确认", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/cleanRectification", "click_text": "新建工单", "slug": "clean_rectification_create_00", "label": "清洁整改新建工单", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/cleanSpecialPhysical", "click_text": "编辑", "slug": "clean_special_physical_edit_00", "label": "清洁测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/equipmentManage/specialPhysical", "click_text": "编辑", "slug": "equipment_special_physical_edit_00", "label": "设备测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/greenManage/greenRectifi", "click_text": "新建工单", "slug": "green_rectification_create_00", "label": "绿化整改新建工单", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityManage/securityRecti", "click_text": "新建工单", "slug": "security_rectification_create_00", "label": "安防整改新建工单", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/energySourceOperat/energyRecti", "click_text": "新建工单", "slug": "energy_rectification_create_00", "label": "节能整改新建工单", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorExamination", "click_text": "编辑", "slug": "elevator_examination_edit_00", "label": "电梯测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/parkingOperation/maintenRectif", "click_text": "新建工单", "slug": "parking_rectification_create_00", "label": "车场维修新建工单", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/satisfaction/satisfactionSurvey/rectification", "click_text": "新建工单", "slug": "satisfaction_rectification_create_00", "label": "满意度整改新建工单", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityProduction/rectificationImplementation/emergencyPlan", "click_text": "添加", "slug": "emergency_plan_create_00", "label": "紧急事件预案添加", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityProduction/rectificationImplementation/emergencyPlan", "click_text": "编辑", "slug": "emergency_plan_edit_01", "label": "紧急事件预案编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityProduction/dangerousGrid", "click_text": "新增空间", "slug": "dangerous_grid_space_create_00", "label": "危险源网格新增空间", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityProduction/dangerousGrid", "click_text": "新增网格", "slug": "dangerous_grid_grid_create_01", "label": "危险源网格新增网格", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityProduction/dangerousGrid", "click_text": "编辑", "slug": "dangerous_grid_edit_02", "label": "危险源网格编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/fullForceAssaultSMG/fullForceAssault/5Aphysical", "click_text": "编辑", "slug": "full_assault_5a_edit_00", "label": "全员5A测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/fullForceAssaultSMG/fullForceAssault/specialPhysical", "click_text": "编辑", "slug": "full_assault_special_edit_00", "label": "全员专项测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/fullForceAssaultSMG/fullForceAssault/customizedPhysical", "click_text": "编辑", "slug": "full_assault_custom_edit_00", "label": "全员定制测评编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/fullForceAssaultSMG/fullForceAssault/diagnosticReport", "click_text": "编辑", "slug": "full_assault_diagnostic_edit_00", "label": "全员测评报告编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/fullForceAssaultSMG/fullForceAssault/diagnosticReport", "click_text": "查看", "slug": "full_assault_diagnostic_view_01", "label": "全员测评报告查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/diagnosis/diagnosticReport", "click_text": "编辑", "slug": "diagnostic_report_edit_00", "label": "测评报告编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/diagnosis/diagnosticReport", "click_text": "查看", "slug": "diagnostic_report_view_01", "label": "测评报告查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/contentOperation/noticePublic", "click_text": "查看", "text_occurrence": 2, "slug": "notice_public_view_02", "label": "通知公告查看", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/contentOperation/noticePublic", "click_text": "查看", "text_occurrence": 3, "slug": "notice_public_readonly_03", "label": "通知公告只读页", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/contentOperation/noticePublic", "click_text": "查看", "text_occurrence": 4, "slug": "notice_public_edit_04", "label": "通知公告编辑页", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/materialManage/purchaseStorage", "click_text": "添加物料", "slug": "purchase_storage_create_00", "label": "采购入库添加物料", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/materialManage/purchaseStorage", "click_text": "编辑", "slug": "purchase_storage_edit_01", "label": "采购入库编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/materialManage/inventoryManage", "click_text": "添加新物料", "slug": "inventory_manage_create_00", "label": "库存管理添加新物料", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/materialManage/inventoryManage", "click_text": "详情", "slug": "inventory_manage_detail_01", "label": "库存管理详情", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/materialManage/inventoryManage", "click_text": "入库", "slug": "inventory_manage_in_02", "label": "库存管理入库", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/materialManage/inventoryManage", "click_text": "出库", "slug": "inventory_manage_out_03", "label": "库存管理出库", }, { "source_url": "https://hc-pos.sqygj.cn/#/systemManage/projectConfig/internalControl/theReportModule", "click_text": "编辑", "slug": "report_module_edit_00", "label": "报告模组编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/systemManage/projectConfig/majorSettings/paySetting", "click_text": "添加支付场景", "slug": "pay_setting_create_00", "label": "支付配置新增支付场景", }, { "source_url": "https://hc-pos.sqygj.cn/#/systemManage/projectConfig/majorSettings/invoiceSetting", "click_text": "新增", "slug": "invoice_setting_create_00", "label": "票据配置新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/systemManage/projectConfig/majorSettings/invoiceSetting", "click_text": "编辑", "slug": "invoice_setting_edit_01", "label": "票据配置编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/satisfaction/satisfactionSurvey/investigation", "click_text": "新建投票", "slug": "investigation_vote_create_00", "label": "调查报告新建投票", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/satisfaction/satisfactionSurvey/investigation", "click_text": "查看", "text_occurrence": 2, "slug": "investigation_vote_view_01", "label": "调查报告查看投票", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/satisfaction/satisfactionSurvey/investigation", "click_text": "统计", "text_occurrence": 1, "slug": "investigation_vote_stats_02", "label": "调查报告投票统计", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/satisfaction/satisfactionSurvey/investigation", "pre_click_texts": [ {"text": "统计", "occurrence": 1} ], "click_text": "查看详情", "slug": "investigation_vote_stats_detail_03", "label": "调查报告统计详情", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityProduction/rectificationImplementation/rectify", "pre_click_texts": [ {"text": "新建工单"} ], "click_text": "来自内控", "slug": "rectify_create_internal_00", "label": "整改工单新建内控", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/securityProduction/rectificationImplementation/rectify", "pre_click_texts": [ {"text": "新建工单"} ], "click_text": "来自住户", "slug": "rectify_create_resident_01", "label": "整改工单新建住户", }, { "source_url": "https://hc-pos.sqygj.cn/#/aiProduct/urgePayment/houseVacancy", "click_text": "新增项目催缴政策", "slug": "urge_policy_create_00", "label": "项目催收政策新增", }, { "source_url": "https://hc-pos.sqygj.cn/#/aiProduct/urgePayment/houseVacancy", "click_text": "编辑", "slug": "urge_policy_edit_01", "label": "项目催收政策编辑", }, { "source_url": "https://hc-pos.sqygj.cn/#/aiProduct/urgePayment/urgeVisitPlan", "click_text": "一键修复", "slug": "urge_visit_plan_repair_confirm_00", "label": "催收拜访计划一键修复确认", }, { "source_url": "https://hc-pos.sqygj.cn/#/change/password", "click_text": "获取验证码", "slug": "change_password_code_countdown_00", "label": "修改密码获取验证码倒计时", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/businessTaxCank/financeReport/arrearsReport", "click_text": "全部催收", "slug": "arrears_report_urge_all_confirm_00", "label": "账单拖欠报表全部催收", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/energySourceOperat/publicAreaControl/EnergyReport", "click_text": "智能识别供电局账单", "slug": "energy_report_ai_identify_00", "label": "供电局账单智能识别", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/activeService/activeServiceRect", "click_text": "即将开展", "slug": "active_service_rect_upcoming_00", "label": "服务记录即将开展", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/organization/workOrderStaffing", "click_text": "我的发布", "slug": "work_order_staffing_my_publish_00", "label": "审批管理我的发布", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/organization/workOrderStaffing", "click_text": "转单发布", "slug": "work_order_staffing_transfer_publish_01", "label": "审批管理转单发布", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/basicManagement/organization/workOrderStaffing", "click_text": "我的协同", "slug": "work_order_staffing_my_collab_02", "label": "审批管理我的协同", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/cleanManage/dailyClean/cleanRecord", "click_text": "即将开展", "slug": "clean_record_upcoming_00", "label": "清洁记录即将开展", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/elevatorManage/elevatorPlan/elevatorPlanRecord", "click_text": "即将开展", "slug": "elevator_plan_record_upcoming_00", "label": "维保记录即将开展", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/equipmentManage/equipmentPlan/equipmentPlanRecord", "click_text": "即将开展", "slug": "equipment_plan_record_upcoming_00", "label": "保养记录即将开展", }, { "source_url": "https://hc-pos.sqygj.cn/#/aiProduct/videoQualityInspection", "click_text": "视频详情", "slug": "video_quality_detail_00", "label": "视频质检视频详情", }, { "source_url": "https://hc-pos.sqygj.cn/#/propertySMG/customerOperations/customerServices/customerVisit/customerVisitRecord", "click_text": "作业记录", "slug": "customer_visit_record_job_record_00", "label": "拜访记录作业记录", }, ] def click_by_id(cdp_port: int, element_id: str) -> bool: script = f""" (() => {{ const visible = (el) => {{ if (!el) return false; const rect = el.getBoundingClientRect(); const style = getComputedStyle(el); return rect.width > 0 && rect.height > 0 && rect.left < window.innerWidth && rect.top < window.innerHeight && rect.right > 0 && rect.bottom > 0 && style.display !== "none" && style.visibility !== "hidden" && style.pointerEvents !== "none"; }}; const target = document.getElementById({json.dumps(element_id)}); if (!target) return JSON.stringify({{ clicked: false, reason: "missing" }}); target.scrollIntoView({{ block: "center", inline: "center" }}); if (!visible(target)) return JSON.stringify({{ clicked: false, reason: "hidden" }}); target.click(); return JSON.stringify({{ clicked: true }}); }})() """ result = mirror.eval_json(cdp_port, script) return bool(isinstance(result, dict) and result.get("clicked")) def click_visible_text(cdp_port: int, text: str, occurrence: int = 0) -> bool: script = f""" (() => {{ const targetText = {json.dumps(text, ensure_ascii=False)}; const occurrence = {occurrence}; const visible = (el) => {{ if (!el) return false; const rect = el.getBoundingClientRect(); const style = getComputedStyle(el); return rect.width > 0 && rect.height > 0 && rect.left < window.innerWidth && rect.top < window.innerHeight && rect.right > 0 && rect.bottom > 0 && style.display !== "none" && style.visibility !== "hidden" && style.pointerEvents !== "none"; }}; const normalize = (value) => (value || "").replace(/\\s+/g, " ").trim(); const matches = [...document.querySelectorAll("button,a,[role='button'],.el-button,.el-link")] .filter((el) => visible(el) && normalize(el.innerText || el.textContent || "") === targetText); if (occurrence >= matches.length) return JSON.stringify({{ clicked: false }}); const target = matches[occurrence]; target.scrollIntoView({{ block: "center", inline: "center" }}); target.click(); return JSON.stringify({{ clicked: true }}); }})() """ result = mirror.eval_json(cdp_port, script) return bool(isinstance(result, dict) and result.get("clicked")) def click_text_any(cdp_port: int, text: str, occurrence: int = 0) -> bool: script = f""" (() => {{ const targetText = {json.dumps(text, ensure_ascii=False)}; const occurrence = {occurrence}; const visible = (el) => {{ if (!el) return false; const rect = el.getBoundingClientRect(); const style = getComputedStyle(el); return rect.width > 0 && rect.height > 0 && rect.left < window.innerWidth && rect.top < window.innerHeight && rect.right > 0 && rect.bottom > 0 && style.display !== "none" && style.visibility !== "hidden" && style.pointerEvents !== "none"; }}; const normalize = (value) => (value || "").replace(/\\s+/g, " ").trim(); const matches = []; for (const raw of document.querySelectorAll("button,a,[role='button'],[role='menuitem'],.el-button,.el-link,.el-dropdown-menu__item,li,span,div,td")) {{ const textValue = normalize(raw.innerText || raw.textContent || ""); if (textValue !== targetText) continue; const node = raw.closest("button,a,[role='button'],[role='menuitem'],.el-button,.el-link,.el-dropdown-menu__item,li") || raw; if (!visible(node)) continue; matches.push(node); }} if (occurrence >= matches.length) return JSON.stringify({{ clicked: false }}); const target = matches[occurrence]; target.scrollIntoView({{ block: "center", inline: "center" }}); target.click(); return JSON.stringify({{ clicked: true }}); }})() """ result = mirror.eval_json(cdp_port, script) return bool(isinstance(result, dict) and result.get("clicked")) def click_task_target(cdp_port: int, task: dict[str, Any]) -> bool: text_occurrence = int(task.get("text_occurrence", 0)) if click_visible_text(cdp_port, task["click_text"], text_occurrence): return True matches = [item for item in actions.list_action_candidates(cdp_port) if item.get("text") == task["click_text"]] if matches: candidate_occurrence = int(task.get("occurrence", 0)) if candidate_occurrence < len(matches): actions.click_action_candidate(cdp_port, matches[candidate_occurrence]["id"]) return True return click_text_any(cdp_port, task["click_text"], text_occurrence) def select_first_table_row(cdp_port: int) -> bool: script = r""" (() => { const table = document.querySelector(".el-table"); if (!table || !table.__vue__) return JSON.stringify({ selected: false, reason: "no table vm" }); const vm = table.__vue__; const rows = vm.store && vm.store.states && vm.store.states.data; if (!rows || !rows.length) return JSON.stringify({ selected: false, reason: "no rows" }); vm.toggleRowSelection(rows[0], true); const selection = vm.store.states.selection || []; return JSON.stringify({ selected: selection.length > 0, count: selection.length }); })() """ result = mirror.eval_json(cdp_port, script) return bool(isinstance(result, dict) and result.get("selected")) def run_pre_clicks(cdp_port: int, task: dict[str, Any]) -> None: if task.get("pre_select_first_row"): if not select_first_table_row(cdp_port): raise RuntimeError("pre-select first row failed") time.sleep(1) for element_id in task.get("pre_click_ids", []): if not click_by_id(cdp_port, element_id): raise RuntimeError(f"pre-click target not found: {element_id}") time.sleep(2) for step in task.get("pre_click_texts", []): if isinstance(step, str): text = step occurrence = 0 else: text = str(step.get("text", "")).strip() occurrence = int(step.get("occurrence", 0)) if not text: raise RuntimeError("pre-click text missing") if not click_task_target(cdp_port, {"click_text": text, "text_occurrence": occurrence}): raise RuntimeError(f"pre-click text not found: {text}#{occurrence}") time.sleep(2) def wait_for_state_change(cdp_port: int, baseline: dict[str, Any], timeout: int) -> dict[str, Any]: start = time.time() last_signature: tuple[Any, ...] | None = None stable_ticks = 0 while time.time() - start < timeout: time.sleep(1) current = actions.collect_view_state(cdp_port) visible_text = current.get("visibleButtons", []) signature = ( current.get("href"), current.get("title"), current.get("appHtmlLen"), tuple(visible_text), tuple(current.get("overlayTitles", [])), tuple(current.get("visibleOverlayTitles", [])), tuple(current.get("visibleMessages", [])), current.get("visibleDialogs"), current.get("visibleForms"), ) changed = ( current.get("href") != baseline.get("href") or current.get("title") != baseline.get("title") or int(current.get("appHtmlLen", 0)) != int(baseline.get("appHtmlLen", 0)) or tuple(visible_text) != tuple(baseline.get("visibleButtons", [])) or tuple(current.get("visibleOverlayTitles", [])) != tuple(baseline.get("visibleOverlayTitles", [])) or tuple(current.get("visibleMessages", [])) != tuple(baseline.get("visibleMessages", [])) or int(current.get("visibleDialogs", 0)) != int(baseline.get("visibleDialogs", 0)) or int(current.get("visibleForms", 0)) != int(baseline.get("visibleForms", 0)) ) if changed and int(current.get("loadingMasks", 0)) == 0: stable_ticks = stable_ticks + 1 if signature == last_signature else 0 if stable_ticks >= 1: return current last_signature = signature return actions.collect_view_state(cdp_port) def capture_to_dir( cdp_port: int, source_url: str, output_dir: Path, slug: str, label: str, downloaded_assets: dict[str, Path], asset_failures: list[dict[str, str]], asset_failure_urls: set[str], ) -> dict[str, Any]: html = mirror.get_rendered_html(cdp_port) state = actions.collect_view_state(cdp_port) current_url = state.get("href") or source_url base_dir = mirror.build_page_dir(output_dir, source_url) variant_dir = base_dir / f"__deep_{slug}" variant_dir.mkdir(parents=True, exist_ok=True) discovered_assets = mirror.discover_asset_urls(html, current_url) pending_assets = deque(sorted(discovered_assets)) local_asset_map: dict[str, Path] = {} while pending_assets: asset_url = pending_assets.popleft() if asset_url in downloaded_assets: local_asset_map[asset_url] = downloaded_assets[asset_url] continue existing_path = mirror.build_asset_path(output_dir, asset_url) if existing_path.exists(): downloaded_assets[asset_url] = existing_path local_asset_map[asset_url] = existing_path continue try: payload = mirror.fetch_url(asset_url) except Exception as exc: # noqa: BLE001 if asset_url not in asset_failure_urls: asset_failures.append({"url": asset_url, "error": str(exc)}) asset_failure_urls.add(asset_url) continue local_path = mirror.build_asset_path(output_dir, asset_url) mirror.safe_write_bytes(local_path, payload) downloaded_assets[asset_url] = local_path local_asset_map[asset_url] = local_path if local_path.suffix.lower() == ".css": css_text = payload.decode("utf-8", errors="ignore") for nested in sorted(mirror.discover_css_urls(css_text, asset_url)): if nested not in downloaded_assets: pending_assets.append(nested) for asset_url, local_path in list(local_asset_map.items()): if local_path.suffix.lower() != ".css": continue css_text = local_path.read_text(encoding="utf-8", errors="ignore") rewritten = mirror.rewrite_css_urls(css_text, asset_url, local_path, downloaded_assets) mirror.safe_write_text(local_path, rewritten) rewritten_html = mirror.rewrite_html_asset_urls(html, current_url, variant_dir, output_dir, downloaded_assets) html_path = variant_dir / "index.html" mirror.safe_write_text(html_path, rewritten_html) metadata = { "source_url": source_url, "final_url": current_url, "title": state.get("title", ""), "label": label, "html_path": str(html_path.relative_to(output_dir)), "overlay_titles": state.get("overlayTitles", []), "visible_buttons": state.get("visibleButtons", []), } mirror.safe_write_text(variant_dir / "action.json", json.dumps(metadata, ensure_ascii=False, indent=2)) return metadata def main() -> int: if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(encoding="utf-8") if hasattr(sys.stderr, "reconfigure"): sys.stderr.reconfigure(encoding="utf-8") output_dir = Path(".").resolve() downloaded_assets: dict[str, Path] = {} asset_failures: list[dict[str, str]] = [] asset_failure_urls: set[str] = set() captured: list[dict[str, Any]] = [] failures: list[dict[str, str]] = [] for task in TASKS: task_url = task.get("direct_url", task["source_url"]) print(f"[task] {task['label']} {task_url}", flush=True) try: actions.open_fresh_page(9223, task_url, 20) actions.dismiss_global_notices(9223) initial = actions.collect_view_state(9223) run_pre_clicks(9223, task) baseline = actions.collect_view_state(9223) if task.get("direct_capture"): if int(baseline.get("appHtmlLen", 0)) <= 1000: raise RuntimeError("direct page did not render enough content") elif task.get("capture_after_pre_clicks"): if baseline == initial: raise RuntimeError("no stable UI change after pre-clicks") else: clicked = click_task_target(9223, task) if not clicked: raise RuntimeError(f"click target not found: {task['click_text']}") changed = wait_for_state_change(9223, baseline, 20) current = actions.collect_view_state(9223) if current == baseline and changed == baseline: raise RuntimeError(f"no stable UI change after click: {task['click_text']}") item = capture_to_dir( 9223, task["source_url"], output_dir, task["slug"], task["label"], downloaded_assets, asset_failures, asset_failure_urls, ) captured.append(item) print(f" [saved] {item['html_path']}", flush=True) except Exception as exc: # noqa: BLE001 failures.append({"source_url": task["source_url"], "label": task["label"], "error": str(exc)}) print(f" [fail] {exc}", flush=True) manifest = { "host": "hc-pos.sqygj.cn", "captured_deep_states": len(captured), "downloaded_assets": len(downloaded_assets), "asset_failures": asset_failures, "failures": failures, "items": captured, } mirror.safe_write_text( output_dir / "deep-action-manifest-hc-pos.sqygj.cn.json", json.dumps(manifest, ensure_ascii=False, indent=2), ) print( f"[done] captured={len(captured)} asset_failures={len(asset_failures)} failures={len(failures)}", flush=True, ) return 0 if not failures else 1 if __name__ == "__main__": raise SystemExit(main())