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

/**
 * 销售开单页面选择器
 */
const selectors = {
  // 导航
  moreMenu: 'text=更多',
  saleOrderMenu: 'text=销售开单',
  
  // 切换类型
  consignmentTab: 'uni-view:has-text("代卖")',
  
  // 商品选择
  productOption: (productName: string) => `text=${productName}`,
  selectBatchButton: 'text=请选择批次',
  batchList: '.batch-list .batch-item',
  confirmButton: 'text=确认',
  
  // 数量和价格输入
  quantityInput: 'uni-view:has-text("斤")',
  priceInput: 'uni-view:has-text("元/斤")',
  numberKey: (key: string) => `.number-keyboard uni-view[data-key="${key}"]`,
  completeButton: 'text=完成',
  
  // 客户选择
  selectCustomerButton: 'text=选择客户',
  customerItem: '.customer-item',
  
  // 支付
  collectPaymentButton: 'text=收款',
  payWayItem: '.pay-way-item',
  confirmPaymentButton: 'text=确定',
  
  // 成功提示
  successMessage: 'text=收款成功',
};

/**
 * 销售开单页面类
 * 处理销售开单相关操作
 */
export class SalePage extends BasePage {
  // 导航定位器
  readonly moreMenu: Locator;
  readonly saleOrderMenu: Locator;
  
  // 切换类型
  readonly consignmentTab: Locator;
  
  // 批次选择
  readonly selectBatchButton: Locator;
  readonly batchList: Locator;
  readonly confirmButton: Locator;
  
  // 客户选择
  readonly selectCustomerButton: Locator;
  readonly customerItem: Locator;
  
  // 支付
  readonly collectPaymentButton: Locator;
  readonly payWayItem: Locator;
  readonly confirmPaymentButton: Locator;
  readonly completeButton: Locator;

  constructor(page: Page) {
    super(page);
    
    this.moreMenu = page.getByText('更多');
    this.saleOrderMenu = page.getByText('销售开单');
    this.consignmentTab = page.locator('uni-view').filter({ hasText: /^代卖$/ }).first();
    this.selectBatchButton = page.getByText('请选择批次');
    this.batchList = page.locator('.batch-list .batch-item');
    this.confirmButton = page.getByText('确认');
    this.selectCustomerButton = page.getByText('选择客户');
    this.customerItem = page.locator('.customer-item');
    this.collectPaymentButton = page.getByText('收款');
    this.payWayItem = page.locator('.pay-way-item');
    this.confirmPaymentButton = page.getByText('确定');
    this.completeButton = 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 openSaleOrder(): Promise<void> {
    await this.saleOrderMenu.click();
  }

  /**
   * 导航到销售开单(完整流程)
   */
  async navigateToSaleOrder(): Promise<void> {
    await this.gotoHome();
    await this.openMoreMenu();
    await this.openSaleOrder();
  }

  /**
   * 切换到代卖模式
   */
  async switchToConsignment(): Promise<void> {
    await this.consignmentTab.click();
  }

  /**
   * 选择商品
   * @param productName 商品名称
   */
  async selectProduct(productName: string): Promise<void> {
    await this.page.getByText(productName).click();
  }

  /**
   * 打开批次选择弹窗
   */
  async openBatchSelection(): Promise<void> {
    await this.selectBatchButton.click();
    await this.batchList.first().waitFor({ state: 'attached', timeout: 10000 });
  }

  /**
   * 选择批次
   * @param batchIndex 批次索引(可选,不传则随机选择)
   */
  async selectBatch(batchIndex?: number): Promise<number> {
    // 确保批次列表已打开
    const count = await this.batchList.count();
    if (count === 0) {
      throw new Error('未找到任何批次项');
    }
    
    const selectedIndex = batchIndex ?? Math.floor(Math.random() * count);
    console.log(`选择第 ${selectedIndex + 1} 个批次项`);
    
    await this.batchList.nth(selectedIndex).click();
    return selectedIndex;
  }

  /**
   * 确认批次选择
   */
  async confirmBatchSelection(): Promise<void> {
    await this.confirmButton.click();
  }

  /**
   * 输入数量
   * @param quantity 数量(数字字符串)
   */
  async enterQuantity(quantity: string): Promise<void> {
    // 点击数量输入框
    await this.page.locator('uni-view').filter({ hasText: /^斤$/ }).first().click();
    
    // 输入数字
    for (const digit of quantity) {
      await this.page.locator(`.number-keyboard uni-view[data-key="${digit}"]`).click();
    }
  }

  /**
   * 输入单价
   * @param price 单价(数字字符串)
   */
  async enterPrice(price: string): Promise<void> {
    // 点击单价输入框
    await this.page.locator('uni-view').filter({ hasText: /^元\/斤$/ }).first().click();
    
    // 输入数字
    for (const digit of price) {
      await this.page.locator(`.number-keyboard uni-view[data-key="${digit}"]`).click();
    }
  }

  /**
   * 点击完成按钮(商品选择完成)
   */
  async clickComplete(): Promise<void> {
    await this.completeButton.click();
  }

  /**
   * 打开客户选择
   */
  async openCustomerSelection(): Promise<void> {
    await this.selectCustomerButton.click();
    await this.customerItem.first().waitFor({ state: 'attached' });
  }

  /**
   * 选择客户
   * @param customerIndex 客户索引(默认选择第一个)
   */
  async selectCustomer(customerIndex: number = 0): Promise<void> {
    await this.customerItem.nth(customerIndex).click();
  }

  /**
   * 点击收款按钮
   */
  async clickCollectPayment(): Promise<void> {
    await this.collectPaymentButton.click();
    await this.payWayItem.first().waitFor({ state: 'attached' });
  }

  /**
   * 选择支付方式
   * @param payWayIndex 支付方式索引(默认选择第一个)
   */
  async selectPayWay(payWayIndex: number = 0): Promise<void> {
    await this.payWayItem.nth(payWayIndex).click();
  }

  /**
   * 确认支付
   */
  async confirmPayment(): Promise<void> {
    await this.confirmPaymentButton.click();
  }

  /**
   * 验证收款成功
   */
  async expectPaymentSuccess(): Promise<void> {
    await expect(this.page.getByText('收款成功')).toBeVisible();
  }

  /**
   * 完整的销售开单流程(代卖模式)
   * @param productName 商品名称
   * @param quantity 数量
   * @param price 单价
   * @param customerIndex 客户索引
   * @param payWayIndex 支付方式索引
   */
  async createConsignmentSaleOrder(
    productName: string,
    quantity: string = '1',
    price: string = '1',
    customerIndex: number = 0,
    payWayIndex: number = 0
  ): Promise<void> {
    // 导航
    await this.navigateToSaleOrder();
    
    // 切换代卖
    await this.switchToConsignment();
    
    // 选择商品
    await this.selectProduct(productName);
    
    // 选择批次
    await this.openBatchSelection();
    await this.selectBatch();
    await this.confirmBatchSelection();
    
    // 输入数量和价格
    await this.enterQuantity(quantity);
    await this.enterPrice(price);
    await this.clickComplete();
    
    // 选择客户
    await this.openCustomerSelection();
    await this.selectCustomer(customerIndex);
    
    // 收款
    await this.clickCollectPayment();
    await this.selectPayWay(payWayIndex);
    await this.confirmPayment();
    
    // 验证成功
    await this.expectPaymentSuccess();
  }

  /**
   * 获取批次数量
   */
  async getBatchCount(): Promise<number> {
    await this.batchList.first().waitFor({ state: 'attached', timeout: 10000 });
    return this.batchList.count();
  }

  /**
   * 获取客户数量
   */
  async getCustomerCount(): Promise<number> {
    await this.customerItem.first().waitFor({ state: 'attached' });
    return this.customerItem.count();
  }
}