|
|
@@ -164,6 +164,9 @@ function getRecentChinaDates(days: number): Date[] {
|
|
|
|
|
|
const STATISTIC_POST_URL = 'https://channels.weixin.qq.com/platform/statistic/post';
|
|
|
const TAB_SINGLE_VIDEO_SELECTORS = [
|
|
|
+ // 与当前后台 DOM 一致:ul.weui-desktop-tab_navs_inner 下 li.weui-desktop-tab_nav 内的 a
|
|
|
+ 'ul.weui-desktop-tab_navs_inner li.weui-desktop-tab_nav a:has-text("单篇视频")',
|
|
|
+ 'li.weui-desktop-tab_nav a:has-text("单篇视频")',
|
|
|
'div.weui-desktop-tab__navs ul li:nth-child(2) a',
|
|
|
'a:has-text("单篇视频")',
|
|
|
];
|
|
|
@@ -325,9 +328,9 @@ export class WeixinVideoWorkStatisticsImportService {
|
|
|
}
|
|
|
|
|
|
for (const sel of TAB_SINGLE_VIDEO_SELECTORS) {
|
|
|
- const loc = page.locator(sel).first;
|
|
|
- if ((await loc.count()) > 0) {
|
|
|
- await loc.click().catch(() => undefined);
|
|
|
+ const baseLoc = page.locator(sel);
|
|
|
+ if ((await baseLoc.count()) > 0) {
|
|
|
+ await baseLoc.nth(0).click().catch(() => undefined);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -335,9 +338,9 @@ export class WeixinVideoWorkStatisticsImportService {
|
|
|
|
|
|
postListData.list = [];
|
|
|
for (const sel of NEAR_30_DAYS_SELECTORS) {
|
|
|
- const loc = page.locator(sel).first;
|
|
|
- if ((await loc.count()) > 0) {
|
|
|
- await loc.click().catch(() => undefined);
|
|
|
+ const baseLoc = page.locator(sel);
|
|
|
+ if ((await baseLoc.count()) > 0) {
|
|
|
+ await baseLoc.nth(0).click().catch(() => undefined);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -416,17 +419,17 @@ export class WeixinVideoWorkStatisticsImportService {
|
|
|
|
|
|
const ensureSingleVideoNear30 = async () => {
|
|
|
for (const sel of TAB_SINGLE_VIDEO_SELECTORS) {
|
|
|
- const loc = page.locator(sel).first;
|
|
|
- if ((await loc.count()) > 0) {
|
|
|
- await loc.click().catch(() => undefined);
|
|
|
+ const baseLoc = page.locator(sel);
|
|
|
+ if ((await baseLoc.count()) > 0) {
|
|
|
+ await baseLoc.nth(0).click().catch(() => undefined);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
await page.waitForTimeout(2000);
|
|
|
for (const sel of NEAR_30_DAYS_SELECTORS) {
|
|
|
- const loc = page.locator(sel).first;
|
|
|
- if ((await loc.count()) > 0) {
|
|
|
- await loc.click().catch(() => undefined);
|
|
|
+ const baseLoc = page.locator(sel);
|
|
|
+ if ((await baseLoc.count()) > 0) {
|
|
|
+ await baseLoc.nth(0).click().catch(() => undefined);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -463,13 +466,14 @@ export class WeixinVideoWorkStatisticsImportService {
|
|
|
const viewBtn = page.locator(sel);
|
|
|
if ((await viewBtn.count()) > 0) {
|
|
|
try {
|
|
|
- await viewBtn.first.waitFor({ timeout: 3000 });
|
|
|
- await viewBtn.first.click();
|
|
|
+ await viewBtn.nth(0).waitFor({ state: 'visible', timeout: 3000 });
|
|
|
+ await viewBtn.nth(0).click();
|
|
|
viewClicked = true;
|
|
|
break;
|
|
|
} catch {
|
|
|
// next selector
|
|
|
}
|
|
|
+ }
|
|
|
}
|
|
|
if (!viewClicked) {
|
|
|
totalSkipped += 1;
|
|
|
@@ -580,9 +584,11 @@ export class WeixinVideoWorkStatisticsImportService {
|
|
|
`[WX WorkStats] accountId=${account.id} 完成: 处理 ${totalProcessed} 个, 跳过 ${totalSkipped} 个, 新增 ${inserted} 条, 更新 ${updated} 条` +
|
|
|
(worksUpdated > 0 ? `, works 表更新 ${worksUpdated} 条` : '')
|
|
|
);
|
|
|
+ if (shouldClose) await browser.close().catch(() => undefined);
|
|
|
return { inserted, updated };
|
|
|
- } finally {
|
|
|
+ } catch (e) {
|
|
|
if (shouldClose) await browser.close().catch(() => undefined);
|
|
|
+ throw e;
|
|
|
}
|
|
|
}
|
|
|
}
|