consignmentPage.ts 9.41 KB
import { Page, Locator, expect } from '@playwright/test';
import { BasePage } from './basePage';

/**
 * 代销入库页面选择器
 */
const selectors = {
  // 导航
  moreMenu: 'text=更多',
  consignmentInMenu: 'text=代销入库',
  addConsignmentButton: 'text=新增代卖入库',
  
  // 仓库选择
  warehouseSelector: '.nut-input__mask',
  warehouseOption: (warehouseName: string) => `uni-view:has-text("${warehouseName}")`,
  mainTitleOption: '.mainTitle',
  
  // 批次别名输入
  batchAliasInput: 'uni-input:has-text("请输入批次别名") input',
  
  // 商品选择
  productListButton: 'text=商品清单点击选择商品',
  productOption: (productName: string) => `text=${productName}`,
  numberKey: (key: string) => `text=${key}`,
  
  // 费用
  addExpenseButton: 'text=入库费用添加费用',
  expenseItem: '.box-item',
  amountInput: '[role="spinbutton"]',
  paymentItem: '.payment-item',
  
  // 操作
  createButton: 'text=创建',
  saveButton: 'text=保存',
  doneButton:'text=完成',
  
  // 验证
  batchNameInList: (batchName: string) => `uni-scroll-view:has-text("${batchName}")`,
};

/**
 * 代销入库页面类
 * 处理代销入库相关操作
 */
export class ConsignmentPage extends BasePage {
  // 导航定位器
  readonly moreMenu: Locator;
  readonly consignmentInMenu: Locator;
  readonly addConsignmentButton: Locator;
  
  // 仓库选择
  readonly warehouseSelector: Locator;
  readonly mainTitleOption: Locator;
  
  // 批次别名
  readonly batchAliasInput: Locator;
  
  // 商品选择
  readonly productListButton: Locator;
  
  // 费用
  readonly addExpenseButton: Locator;
  readonly expenseItem: Locator;
  readonly amountInput: Locator;
  readonly paymentItem: Locator;
  
  // 操作按钮
  readonly createButton: Locator;
  readonly saveButton: Locator;
  readonly doneButton:Locator;

  constructor(page: Page) {
    super(page);
    
    this.moreMenu = page.getByText('更多');
    this.consignmentInMenu = page.getByText('代销入库').first();
    this.addConsignmentButton = page.getByText('新增代卖入库');
    this.warehouseSelector = page.locator('.nut-input__mask').first();
    this.mainTitleOption = page.locator('.mainTitle').first();
    this.batchAliasInput = page.locator('uni-input').filter({ hasText: '请输入批次别名' }).getByRole('textbox');
    this.productListButton = page.getByText('商品清单点击选择商品');
    this.addExpenseButton = page.getByText('入库费用添加费用');
    this.expenseItem = page.locator('.box-item');
    this.amountInput = page.getByRole('spinbutton');
    this.paymentItem = page.locator('.payment-item');
    this.createButton = page.getByText('创建', { exact: true });
    this.saveButton = page.getByText('保存');
    this.doneButton = page.getByText('完成')
  }

  /**
   * 导航到首页并等待加载
   */
  async gotoHome(): Promise<void> {
    await this.navigate('/');
    await this.page.waitForLoadState('networkidle', { timeout: 30000 });
  }

  /**
   * 打开更多菜单
   */
  async openMoreMenu(): Promise<void> {
    await this.moreMenu.click();
  }

  /**
   * 打开代销入库菜单
   */
  async openConsignmentIn(): Promise<void> {
    await this.consignmentInMenu.click();
  }

  /**
   * 点击新增代卖入库
   */
  async clickAddConsignment(): Promise<void> {
    await this.addConsignmentButton.click();
  }

  /**
   * 导航到新增代销入库页面(完整流程)
   */
  async navigateToNewConsignment(): Promise<void> {
    await this.gotoHome();
    await this.openMoreMenu();
    await this.openConsignmentIn();
    await this.clickAddConsignment();
  }

  /**
   * 选择仓库
   * @param warehouseName 仓库名称(可选,默认选择第一个)
   */
  async selectWarehouse(warehouseName?: string): Promise<void> {
    // 点击仓库选择器
    await this.warehouseSelector.click();
    
    if (warehouseName) {
      // 选择指定仓库
      await this.page.locator('uni-view').filter({ hasText: new RegExp(`^${warehouseName}$`) }).nth(1).click();
    } else {
      // 默认选择第一个
      await this.mainTitleOption.click();
    }
  }

  /**
   * 选择第二个仓库
   */
  async selectSecondWarehouse(): Promise<void> {
    await this.page.locator('uni-view:nth-child(4) > .nut-cell__value > .nut-form-item__body__slots > .nut-input > .nut-input__value > .nut-input__mask').click();
    await this.page.locator('uni-view').filter({ hasText: /^东区普通仓库$/ }).nth(1).click();
  }

  /**
   * 输入批次别名
   * @param alias 批次别名
   */
  async enterBatchAlias(alias: string): Promise<void> {
    await this.batchAliasInput.click();
    await this.batchAliasInput.clear();
    await this.batchAliasInput.fill(alias);
  }

  /**
   * 打开商品选择列表
   */
  async openProductList(): Promise<void> {
    await this.productListButton.click();
  }

  /**
   * 选择商品
   * @param productName 商品名称
   */
  async selectProduct(productName: string): Promise<void> {
    // 在商品选择弹窗中选择商品,使用first()避免多个匹配项导致的strict mode violation
    await this.page.locator('.productName').getByText(productName).click();
  }

  /**
   * 输入商品数量
   * @param quantity 数量(数字字符串,如 "10")
   */
  async enterProductQuantity(quantity: string): Promise<void> {
    for (const digit of quantity) {
      await this.page.getByText(digit, { exact: true }).click();
    }
  }

  /**
   * 完成商品选择
   */
  async completeProductSelection(): Promise<void> {
    await this.doneButton.click(); // 点击完成按钮(同保存按钮)
    await this.saveButton.click()
  }

  /**
   * 选择商品并输入数量
   * @param productName 商品名称
   * @param quantity 数量
   */
  async selectProductWithQuantity(productName: string, quantity: string): Promise<void> {
    await this.openProductList();
    await this.selectProduct(productName);
    await this.enterProductQuantity(quantity);
    await this.completeProductSelection();
  }

  /**
   * 添加费用项
   * @param expenseIndex 费用项索引(默认第一个)
   * @param amount 金额
   */
  async addExpense(expenseIndex: number = 0, amount: string = '1'): Promise<void> {
    // 打开费用选择
    await this.addExpenseButton.click();
    
    // 等待费用列表加载
    await this.expenseItem.first().waitFor({ state: 'attached' });
    
    // 选择费用项
    await this.expenseItem.nth(expenseIndex).click();
    await this.page.getByText('确定').click();
    
    // 输入金额
    await this.page.getByText('金额*0.00').click();
    await this.amountInput.click();
    await this.amountInput.fill(amount);
  }

  /**
   * 选择支付方式
   * @param paymentIndex 支付方式索引(默认第一个)
   */
  async selectPaymentMethod(paymentIndex: number = 0): Promise<void> {
    // 点击支付方式选择器
    await this.page.locator('uni-view:nth-child(6) > .nut-cell__value > .nut-form-item__body__slots > .nut-input > .nut-input__value > .nut-input__mask').click();
    
    // 等待支付方式列表加载
    await this.paymentItem.first().waitFor({ state: 'attached' });
    
    // 选择支付方式
    await this.paymentItem.nth(paymentIndex).click();
    await this.page.getByText('确定').click();
  }

  /**
   * 点击创建按钮
   */
  async clickCreate(): Promise<void> {
    await this.createButton.click();
  }

  /**
   * 等待创建完成
   */
  async waitForCreationComplete(): Promise<void> {
    await this.page.waitForLoadState('networkidle');
    await this.wait(1000); // 额外等待1秒,适配uni-app页面渲染延迟
  }

  /**
   * 验证批次创建成功
   * @param batchName 批次名称
   */
  async expectBatchCreated(batchName: string): Promise<void> {
    await expect(this.page.locator('uni-scroll-view').getByText(batchName)).toBeVisible();
  }

  /**
   * 完整的代销入库创建流程
   * @param batchAlias 批次别名
   * @param productName 商品名称
   * @param quantity 数量
   * @param amount 费用金额
   */
  async createConsignmentOrder(
    batchAlias: string,
    productName: string,
    quantity: string = '10',
    amount: string = '1'
  ): Promise<void> {
    // 导航到新增页面
    await this.navigateToNewConsignment();
    
    // 选择仓库
    await this.selectWarehouse();
    await this.selectSecondWarehouse();
    
    // 输入批次别名
    await this.enterBatchAlias(batchAlias);
    
    // 选择商品
    await this.selectProductWithQuantity(productName, quantity);
    
    // 添加费用
    await this.addExpense(0, amount);
    await this.selectPaymentMethod(0);
    
    // 创建
    await this.clickCreate();
    await this.waitForCreationComplete();
    
    // 验证
    await this.expectBatchCreated(batchAlias);
  }

  /**
   * 简化的代销入库创建流程(不添加费用)
   * @param batchAlias 批次别名
   * @param productName 商品名称
   * @param quantity 数量
   */
  async createSimpleConsignmentOrder(
    batchAlias: string,
    productName: string,
    quantity: string = '10'
  ): Promise<void> {
    // 导航到新增页面
    await this.navigateToNewConsignment();
    
    // 选择仓库
    await this.selectWarehouse();
    await this.selectSecondWarehouse();
    
    // 输入批次别名
    await this.enterBatchAlias(batchAlias);
    
    // 选择商品
    await this.selectProductWithQuantity(productName, quantity);
    
    // 创建
    await this.clickCreate();
    await this.waitForCreationComplete();
  }
}