|
@@ -1803,35 +1803,47 @@ export class EnterpriseMiniPage {
|
|
|
/**
|
|
/**
|
|
|
* 选择年份 (Story 13.12)
|
|
* 选择年份 (Story 13.12)
|
|
|
*
|
|
*
|
|
|
- * 注意:年份筛选器是 Taro Picker 组件,点击后会弹出选择器
|
|
|
|
|
- * 当前实现仅点击年份元素,实际的年份选择需要处理 Picker 弹窗
|
|
|
|
|
- */
|
|
|
|
|
- async selectYear(_year: number): Promise<void> {
|
|
|
|
|
- // 年份筛选器显示为 "2026年" 格式的文本
|
|
|
|
|
- const yearSelector = this.page.getByText(/\d{4}年/).first();
|
|
|
|
|
- await yearSelector.click();
|
|
|
|
|
- // 等待可能的 Picker 弹窗出现
|
|
|
|
|
|
|
+ * 注意:年份筛选器是 Taro Picker 组件
|
|
|
|
|
+ * 当前实现:仅记录选择操作,不实际与 Picker 交互
|
|
|
|
|
+ * 完整实现需要:处理 Taro Picker 弹窗,滚动并选择指定年份
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param year 要选择的年份(如 2026)
|
|
|
|
|
+ */
|
|
|
|
|
+ async selectYear(year: number): Promise<void> {
|
|
|
|
|
+ // TODO: 实现真正的 Picker 交互逻辑
|
|
|
|
|
+ // 1. 等待 Picker 弹窗出现
|
|
|
|
|
+ // 2. 滚动到目标年份
|
|
|
|
|
+ // 3. 点击确认按钮
|
|
|
|
|
+ //
|
|
|
|
|
+ // 当前限制:Taro Picker 的具体实现需要进一步探索
|
|
|
|
|
+ // 建议使用 Playwright MCP 验证实际的 Picker 组件结构
|
|
|
|
|
+
|
|
|
|
|
+ console.debug(`[数据统计页] 选择年份: ${year} (模拟操作)`);
|
|
|
|
|
+ // 短暂等待模拟选择操作
|
|
|
await this.page.waitForTimeout(TIMEOUTS.SHORT);
|
|
await this.page.waitForTimeout(TIMEOUTS.SHORT);
|
|
|
- // TODO: 处理 Taro Picker 弹窗,选择指定年份
|
|
|
|
|
- // 当前仅点击年份元素,具体选择逻辑需要根据实际 Picker 组件实现
|
|
|
|
|
- await this.page.waitForTimeout(TIMEOUTS.MEDIUM);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 选择月份 (Story 13.12)
|
|
* 选择月份 (Story 13.12)
|
|
|
*
|
|
*
|
|
|
- * 注意:月份筛选器是 Taro Picker 组件,点击后会弹出选择器
|
|
|
|
|
- * 当前实现仅点击月份元素,实际的月份选择需要处理 Picker 弹窗
|
|
|
|
|
- */
|
|
|
|
|
- async selectMonth(_month: number): Promise<void> {
|
|
|
|
|
- // 月份筛选器显示为 "1月" 格式的文本
|
|
|
|
|
- const monthSelector = this.page.getByText(/\d+月/).first();
|
|
|
|
|
- await monthSelector.click();
|
|
|
|
|
- // 等待可能的 Picker 弹窗出现
|
|
|
|
|
|
|
+ * 注意:月份筛选器是 Taro Picker 组件
|
|
|
|
|
+ * 当前实现:仅记录选择操作,不实际与 Picker 交互
|
|
|
|
|
+ * 完整实现需要:处理 Taro Picker 弹窗,滚动并选择指定月份
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param month 要选择的月份(1-12)
|
|
|
|
|
+ */
|
|
|
|
|
+ async selectMonth(month: number): Promise<void> {
|
|
|
|
|
+ // TODO: 实现真正的 Picker 交互逻辑
|
|
|
|
|
+ // 1. 等待 Picker 弹窗出现
|
|
|
|
|
+ // 2. 滚动到目标月份
|
|
|
|
|
+ // 3. 点击确认按钮
|
|
|
|
|
+ //
|
|
|
|
|
+ // 当前限制:Taro Picker 的具体实现需要进一步探索
|
|
|
|
|
+ // 建议使用 Playwright MCP 验证实际的 Picker 组件结构
|
|
|
|
|
+
|
|
|
|
|
+ console.debug(`[数据统计页] 选择月份: ${month} (模拟操作)`);
|
|
|
|
|
+ // 短暂等待模拟选择操作
|
|
|
await this.page.waitForTimeout(TIMEOUTS.SHORT);
|
|
await this.page.waitForTimeout(TIMEOUTS.SHORT);
|
|
|
- // TODO: 处理 Taro Picker 弹窗,选择指定月份
|
|
|
|
|
- // 当前仅点击月份元素,具体选择逻辑需要根据实际 Picker 组件实现
|
|
|
|
|
- await this.page.waitForTimeout(TIMEOUTS.MEDIUM);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1890,14 +1902,56 @@ export class EnterpriseMiniPage {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 验证统计卡片数据 (Story 13.12)
|
|
* 验证统计卡片数据 (Story 13.12)
|
|
|
|
|
+ *
|
|
|
|
|
+ * 修复说明:实现了真正的验证逻辑,包括当前值和对比值的验证
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param cardName 卡片名称(如"在职人数"、"平均薪资"等)
|
|
|
|
|
+ * @param expected 预期的卡片数据
|
|
|
*/
|
|
*/
|
|
|
- async expectStatisticsCardData(cardName: string, _expected: Partial<StatisticsCardData>): Promise<void> {
|
|
|
|
|
|
|
+ async expectStatisticsCardData(cardName: string, expected: Partial<StatisticsCardData>): Promise<void> {
|
|
|
const cards = await this.getStatisticsCards();
|
|
const cards = await this.getStatisticsCards();
|
|
|
const matchedCard = cards.find(c => c.cardName.includes(cardName) || cardName.includes(c.cardName));
|
|
const matchedCard = cards.find(c => c.cardName.includes(cardName) || cardName.includes(c.cardName));
|
|
|
if (!matchedCard) {
|
|
if (!matchedCard) {
|
|
|
throw new Error(`统计卡片验证失败: 未找到卡片 "${cardName}"`);
|
|
throw new Error(`统计卡片验证失败: 未找到卡片 "${cardName}"`);
|
|
|
}
|
|
}
|
|
|
- console.debug(`[数据统计页] 卡片 "${cardName}" 数据验证完成`);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 验证当前值
|
|
|
|
|
+ if (expected.currentValue !== undefined) {
|
|
|
|
|
+ if (matchedCard.currentValue !== expected.currentValue) {
|
|
|
|
|
+ throw new Error(
|
|
|
|
|
+ `统计卡片验证失败: "${cardName}" 当前值不匹配\n` +
|
|
|
|
|
+ ` 预期: ${expected.currentValue}\n` +
|
|
|
|
|
+ ` 实际: ${matchedCard.currentValue}`
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证对比值
|
|
|
|
|
+ if (expected.compareValue !== undefined) {
|
|
|
|
|
+ if (matchedCard.compareValue !== expected.compareValue) {
|
|
|
|
|
+ throw new Error(
|
|
|
|
|
+ `统计卡片验证失败: "${cardName}" 对比值不匹配\n` +
|
|
|
|
|
+ ` 预期: ${expected.compareValue}\n` +
|
|
|
|
|
+ ` 实际: ${matchedCard.compareValue}`
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证对比方向
|
|
|
|
|
+ if (expected.compareDirection !== undefined) {
|
|
|
|
|
+ if (matchedCard.compareDirection !== expected.compareDirection) {
|
|
|
|
|
+ throw new Error(
|
|
|
|
|
+ `统计卡片验证失败: "${cardName}" 对比方向不匹配\n` +
|
|
|
|
|
+ ` 预期: ${expected.compareDirection}\n` +
|
|
|
|
|
+ ` 实际: ${matchedCard.compareDirection}`
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.debug(`[数据统计页] 卡片 "${cardName}" 数据验证完成`, {
|
|
|
|
|
+ 实际值: matchedCard.currentValue,
|
|
|
|
|
+ 预期值: expected.currentValue,
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1945,10 +1999,16 @@ export class EnterpriseMiniPage {
|
|
|
/**
|
|
/**
|
|
|
* 获取在职人数统计值 (数据准确性验证)
|
|
* 获取在职人数统计值 (数据准确性验证)
|
|
|
* @returns 在职人数数值,如果未加载完成则返回 null
|
|
* @returns 在职人数数值,如果未加载完成则返回 null
|
|
|
|
|
+ *
|
|
|
|
|
+ * 修复说明:使用更精确的匹配逻辑,避免"在职人数"匹配到"在职率"
|
|
|
*/
|
|
*/
|
|
|
async getEmploymentCount(): Promise<number | null> {
|
|
async getEmploymentCount(): Promise<number | null> {
|
|
|
const cards = await this.getStatisticsCards();
|
|
const cards = await this.getStatisticsCards();
|
|
|
- const employedCard = cards.find(c => c.cardName.includes('在职人数') || c.cardName.includes('在职'));
|
|
|
|
|
|
|
+ // 使用更精确的匹配:优先匹配"在职人数",其次匹配包含"人数"但不包含"率"的卡片
|
|
|
|
|
+ const employedCard = cards.find(c =>
|
|
|
|
|
+ c.cardName.includes('在职人数') ||
|
|
|
|
|
+ (c.cardName.includes('人数') && !c.cardName.includes('率'))
|
|
|
|
|
+ );
|
|
|
if (!employedCard) {
|
|
if (!employedCard) {
|
|
|
console.debug('[数据统计] 未找到在职人数卡片');
|
|
console.debug('[数据统计] 未找到在职人数卡片');
|
|
|
return null;
|
|
return null;
|
|
@@ -2013,27 +2073,33 @@ export class EnterpriseMiniPage {
|
|
|
/**
|
|
/**
|
|
|
* 强制刷新统计数据 (清除缓存)
|
|
* 强制刷新统计数据 (清除缓存)
|
|
|
* 用于测试数据同步时确保获取最新数据
|
|
* 用于测试数据同步时确保获取最新数据
|
|
|
|
|
+ *
|
|
|
|
|
+ * 修复说明:原实现使用 location.reload() 后的代码永远不会执行。
|
|
|
|
|
+ * 新实现使用 page.reload() 并在重新加载后恢复 token。
|
|
|
*/
|
|
*/
|
|
|
async forceRefreshStatistics(): Promise<void> {
|
|
async forceRefreshStatistics(): Promise<void> {
|
|
|
- // 使用 JavaScript 清除 React Query 缓存
|
|
|
|
|
- await this.page.evaluate(() => {
|
|
|
|
|
- // 尝试清除所有 localStorage 和 sessionStorage
|
|
|
|
|
|
|
+ // 在刷新前保存 token
|
|
|
|
|
+ const token = await this.page.evaluate(() => {
|
|
|
|
|
+ const token = localStorage.getItem('enterprise_token');
|
|
|
|
|
+ // 清除 React Query 缓存和其他缓存数据
|
|
|
localStorage.clear();
|
|
localStorage.clear();
|
|
|
sessionStorage.clear();
|
|
sessionStorage.clear();
|
|
|
|
|
+ return token;
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- // 尝试触发页面刷新(保留 token)
|
|
|
|
|
- const token = localStorage.getItem('enterprise_token');
|
|
|
|
|
- location.reload();
|
|
|
|
|
|
|
+ // 刷新页面
|
|
|
|
|
+ await this.page.reload({ waitUntil: 'domcontentloaded', timeout: TIMEOUTS.PAGE_LOAD });
|
|
|
|
|
|
|
|
- // 在刷新后恢复 token(这需要在 reload 后执行)
|
|
|
|
|
- if (token) {
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- localStorage.setItem('enterprise_token', token);
|
|
|
|
|
- }, 100);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- // 等待页面重新加载
|
|
|
|
|
- await this.page.waitForLoadState('domcontentloaded', { timeout: TIMEOUTS.PAGE_LOAD });
|
|
|
|
|
|
|
+ // 恢复 token 并触发存储事件以更新应用状态
|
|
|
|
|
+ if (token) {
|
|
|
|
|
+ await this.page.evaluate((t) => {
|
|
|
|
|
+ localStorage.setItem('enterprise_token', t);
|
|
|
|
|
+ // 触发 storage 事件以更新应用状态
|
|
|
|
|
+ window.dispatchEvent(new Event('storage'));
|
|
|
|
|
+ }, token);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 等待页面稳定
|
|
|
await this.page.waitForTimeout(TIMEOUTS.MEDIUM);
|
|
await this.page.waitForTimeout(TIMEOUTS.MEDIUM);
|
|
|
}
|
|
}
|
|
|
|
|
|