#!/usr/bin/env python # -*- coding: utf-8 -*- ''' @File : filter_page.py @Time : 2024/11/21 14:55:10 @Author : dulip3ng @Version : 1.0 @Desc : None ''' import re import time from pages.locator.filter_page_locator import FilterPageLocator from playwright.sync_api import Page, expect from common.field_type import FieldType from common.condition_row import ConditionRow from pages.base_page import BasePage class FilterPage(BasePage): """ 过滤弹出框页面模型,适用于普通过滤弹出框,如在列表中点击过滤后弹出的过滤框 """ def check_all_org(self): """ 勾选所有组织复选框,如果已经是勾选状态则不操作 **用法:** FilterPage.check_all_org() :return: """ # 多数情况下勾选所有组织是过滤界面第一个操作,偶发点击失效情况,加入2s等待时间确保稳定性 time.sleep(2) locator_click = self.page.locator(FilterPageLocator.ALL_ORG_LOC) locator_get_state = self.page.locator(FilterPageLocator.ALL_ORG_GET_CHECK_STATE_LOC) expect(locator_click).to_be_enabled() print(locator_get_state.is_checked()) if not locator_get_state.is_checked(): locator_click.click() def uncheck_all_org(self): """ 取消勾选所有组织复选框,如果已经未勾选状态则不操作 **用法:** FilterPage.uncheck_all_org() :return: """ # 多数情况下勾选所有组织是过滤界面第一个操作,偶发点击失效情况,加入2s等待时间确保稳定性 time.sleep(2) locator_click = self.page.locator(FilterPageLocator.ALL_ORG_LOC) locator_get_state = self.page.locator(FilterPageLocator.ALL_ORG_GET_CHECK_STATE_LOC) expect(locator_click).to_be_enabled() print(locator_get_state.is_checked()) if locator_get_state.is_checked(): print("22") locator_click.click() def check_org(self, *orgs:str): """ 根据给定组织编码或名称,勾选组织 **用法:** FilterPage.check_org("100.1") FilterPage.check_org("100.1", "鲁泰纺织股份") :param orgs: 组织编码或名称,可传多个,模糊匹配 :return: """ self.page.locator(FilterPageLocator.ORG_ARROW_LOC).click() for org in orgs: self.page.locator(FilterPageLocator.ORG_MULTI_ITEM_ARGS_LOC % org).click() self.page.locator(FilterPageLocator.ORG_SELECT_OK_BTN_LOC).click() def check_entity(self, *entitys_name:str): """ 根据给定实体,勾选实体 **用法:** FilterPage.check_entity("明细信息") FilterPage.check_entity("明细信息", "财务信息") **注意:** 未进行勾选状态判断,未勾选状态下调用一次为勾选,再次调用为取消勾选 :param entitys_name: 实体名称 :return: """ for entity in entitys_name: self.page.locator(FilterPageLocator.ENTITY_CHECKBOX_ARGS_LOC % entity).click() def click_tool_bar_button(self, button_name:str): """ 点击过滤框页面菜单行按钮 **用法:** FilterPage.click_tool_bar_button("删除全部") :param button_name: 按钮名称 :return: """ self.page.locator(FilterPageLocator.TOOL_BAR_BTN_ARGS_LOC % button_name).click() def set_condition(self, row:int, condition_name:str): """ 按行设置过滤条件项 **用法:** FilterPage.set_condition(1, "基本信息-衬衣订单号") **注意:** 部分单据中存在相同字段名在不同页签的情况,此时模糊匹配无法找到正确选项值,推荐使用条件项全称精确匹配 :param row: 行号,从1开始 :param condition_name: 条件项全称 :return: """ self.click_tool_bar_button("新增行") locator = self.page.locator(FilterPageLocator.FILTER_CONDITION_ARGS_LOC % ((row - 1) * 35)) locator.fill(condition_name) # 条件项赋值后默认不弹出选项框,输入空格再删除,以便弹出选项框进行选择 locator.press_sequentially(" ") locator.press("Backspace") self.page.locator(FilterPageLocator.CONDITION_ITEM_ARGS_LOC % condition_name).click() def set_operator(self, row:int, operator:str): """ 设置过滤条件操作符号 **用法:** FilterPage.set_operator(1, "包含") :param row: 行号 :param operator: 操作符名称 :return: """ self.page.locator(FilterPageLocator.COMPARE_TYPE_ARGS_LOC % ((row - 1) * 35)).click() self.page.locator(FilterPageLocator.COMPARE_ITEM_ARGS_LOC % operator).click() def _set_text(self, row:int, value:str): """ 条件值字段,文本字段类型赋值 **用法:** FilterPage.set_text(1, "内销") 使用FilterPage.set_condition_value()方法代替,此方法无需区分字段类型 :param row: 行号,从1开始 :param value: 条件值 :return: """ self.page.locator(FilterPageLocator.CONDITION_TEXT_FIELD_ARGS_LOC % ((row - 1) * 35)).fill(value) def _set_date(self, row:int, value:str): """ 条件值字段,日期字段类型赋值 **用法:** FilterPage.set_date(1, "2024-11-25") 使用FilterPage.set_condition_value()方法代替,此方法无需区分字段类型 :param row: 行号,从1开始 :param value: 条件值,格式"2024-11-25" :return: """ self.page.locator(FilterPageLocator.CONDITION_DATE_FIELD_ARGS_LOC % ((row - 1) * 35)).fill(value) self.click_blank() def _set_select(self, row:int, value:str): """ 条件值字段,下拉列表字段类型赋值 **用法:** FilterPage.set_select(1, "创建") 使用FilterPage.set_condition_value()方法代替,此方法无需区分字段类型 :param row: 行号,从1开始 :param value: 条件值 :return: """ self.page.locator(FilterPageLocator.CONDITION_SELECT_FIELD_ARGS_LOC % ((row - 1) * 35)).click() self.page.locator(FilterPageLocator.CONDITION_SELECT_ITEM_ARGS_LOC % value).click() def _set_base(self, row:int, value:str): """ 条件值字段,基础资料字段类型赋值 **用法:** FilterPage.set_base(1, "P010001") 使用FilterPage.set_condition_value()方法代替,此方法无需区分字段类型 :param row: 行号,从1开始 :param value: 条件值 :return: """ # CONDITION_BASE_FIELD_ARGS_LOC input元素可操作性检查不通过,CONDITION_BASE_FIELD_SPAN_ARGS_LOC span劫持,这里直接对span进行点击 self.page.locator(FilterPageLocator.CONDITION_BASE_FIELD_SPAN_ARGS_LOC % ((row - 1) * 35)).click() self.page.locator(FilterPageLocator.CONDITION_BASE_FIELD_ARGS_LOC % ((row - 1) * 35)).fill(value) self.page.locator(FilterPageLocator.CONDITION_BASE_FIELD_ARGS_LOC % ((row - 1) * 35)).press_sequentially(" ") self.page.locator(FilterPageLocator.CONDITION_BASE_ITEM_ARGS_LOC % value).press_sequentially(" ") def _set_text_area(self, row:int, value:str): """ 条件值字段,大文本字段类型赋值 **用法:** FilterPage.set_text_area(1, "大文本字段值1234567890") 使用FilterPage.set_condition_value()方法代替,此方法无需区分字段类型 :param row: 行号,从1开始 :param value: 条件值 :return: """ self.page.locator(FilterPageLocator.CONDITION_TEXTAREA_ARGS_LOC % ((row - 1) * 35)).fill(value) def set_logic(self, row:int, value:str): """ 设置逻辑符号,如并且 **用法:** FilterPage.set_logic(1, "并且") :param row: 行号,从1开始 :param value: 逻辑符号,取并且,或者 :return: """ self.page.locator(FilterPageLocator.LOGIC_ARGS_LOC % ((row - 1) * 35)).click() self.page.locator(FilterPageLocator.COMPARE_ITEM_ARGS_LOC % value).click() def _parse_condition_value_field_type(self, row:int) -> FieldType: """ 根据条件项元素属性,自动解析条件值项字段类型 **用法:** FilterPage._parse_condition_value_field_type(1) **注意:** 1.金蝶大版本升级后,判断依据可能会调整 2.当前支持v8.2 :param row: 行号,从1开始 :return: """ data_role = self.page.locator(FilterPageLocator.PARSE_CONDITION_VALUE_FIELD_TYPE_ARGS_LOC % ((row - 1) * 35)).get_attribute("data-attdata") pattern = "xtype\":\"([a-zA-Z0-9]+)" match_strs = re.findall(pattern, data_role) if match_strs: match match_strs[0]: case "textfield": return FieldType.TEXT case "bosf7field": return FieldType.BASE case "kdeditcombo" | "kdcombo": return FieldType.SELECT case "kdmulticombo": return FieldType.MULTISELECT case "kdtextarea" | "kdlangtextarea" | "kdtabpage": return FieldType.TEXTAREA case "datefield": return FieldType.DATE return FieldType.UNKNOWN def set_condition_value(self, row:int, value:str, field_type: FieldType = None): """ 条件值字段赋值,不给定字段类型时自动解析字段类型,推荐不给定,方便统一调用形式 **用法:** FilterPage.set_condition_value(1, "26024001") FilterPage.set_condition_value(1, "26024001", FieldType.TEXT) :param row: 行号,从1开始 :param value: 条件值 :param field_type: 条件值字段类型,可选 :return: """ if field_type is None: field_type = self._parse_condition_value_field_type(row) match field_type: case FieldType.TEXT: self.set_text(row, value) case FieldType.SELECT: self.set_select(row, value) case FieldType.BASE: self.set_base(row, value) case FieldType.DATE: self.set_date(row, value) case FieldType.TEXTAREA: self.set_text_area(row, value) case _: raise TypeError("未匹配到过滤页面过滤条件输入框字段类型。") def click_ok_button(self): """ 点击确定,开始过滤 **用法:** FilterPage.click_ok_button() :return: """ self.page.locator(FilterPageLocator.FILTER_OK_BUTTON_LOC).click() def set_condition_row(self, row:int, condition_name:str, condition_value:str=None, operator:str=None, logic:str=None): """ 设置一行过滤条件 **用法:** FilterPage.set_condition_row(1, "创建日期", operator="今天") FilterPage.set_condition_row(1, "衬衣订单号", "26024001") FilterPage.set_condition_row(1, "衬衣订单号", "26024", "包含") FilterPage.set_condition_row(1, "衬衣订单号", "26024", "包含", "或者") :param row: 行号,从1,开始 :param condition_name: 过滤条件名 :param condition_value: 过滤条件值,可选 :param operator: 操作符,可选 :param logic: 逻辑符,可选 :return: """ self.set_condition(row, condition_name) if operator: self.set_operator(row, operator) if condition_value: self.set_condition_value(row, condition_value) if logic: self.set_logic(row, logic) def filter(self, *condition_row: ConditionRow): """ 根据条件对象进行过滤,默认勾选全部组织 **用法:** cond1 = ConditionRow(1, "基本信息-衬衣订单号", "123456", "包含", "或者") cond2 = ConditionRow(2, "单据状态", "已审核") FilterPage.filter(cond1, cond2) :param condition_row: 条件对象,ConditionRow(row:int, condition_name:str, condition_value:str=None, operator:str=None, logic:str=None), 可传多个 :return: """ self.check_all_org() self.click_tool_bar_button("全部删除") time.sleep(1) for cr in condition_row: self.set_condition_row(cr.row, cr.condition_name, cr.condition_value, cr.operator, cr.logic) self.click_ok_button()