|
|
/**
|
|
|
* 填完 ZIP 后 dump Pickup Type 全部 option(role=option / listbox li)
|
|
|
*/
|
|
|
import fs from "node:fs";
|
|
|
import path from "node:path";
|
|
|
import { launchRpaBrowser } from "@/lib/rpa/browser-launch";
|
|
|
import { createRpaBrowserContext } from "@/lib/rpa/browser-context";
|
|
|
import { ensureFlockLoggedIn } from "@/workers/rpa/flock/login";
|
|
|
import {
|
|
|
fillLoggedInPickupDate,
|
|
|
openFlockLoggedInQuoteEntry,
|
|
|
} from "@/workers/rpa/flock/logged-in-form";
|
|
|
import { defaultFlockPickupDateIso } from "@/lib/flock/pickup-date";
|
|
|
|
|
|
function isoToDisplay(iso: string): string {
|
|
|
const [y, m, d] = iso.split("-");
|
|
|
return y && m && d ? `${m}/${d}/${y}` : iso;
|
|
|
}
|
|
|
|
|
|
async function main() {
|
|
|
const storagePath =
|
|
|
process.env.FLOCK_LOGGED_IN_STORAGE_STATE_PATH?.trim() ||
|
|
|
path.join(process.cwd(), ".rpa", "flock-logged-in-storage.json");
|
|
|
const browser = await launchRpaBrowser({ headless: true, incognito: false });
|
|
|
try {
|
|
|
const context = await createRpaBrowserContext(browser, {
|
|
|
storageState: storagePath,
|
|
|
});
|
|
|
const page = await context.newPage();
|
|
|
const login = await ensureFlockLoggedIn(page, context);
|
|
|
if (!login.ok) throw new Error(login.errorMessage);
|
|
|
await page.goto("https://app.flockfreight.com/home", {
|
|
|
waitUntil: "domcontentloaded",
|
|
|
});
|
|
|
if (!(await openFlockLoggedInQuoteEntry(page))) {
|
|
|
throw new Error("open form failed");
|
|
|
}
|
|
|
|
|
|
await fillLoggedInPickupDate(page, isoToDisplay(defaultFlockPickupDateIso()));
|
|
|
await page.getByRole("textbox", { name: /Pickup ZIP/i }).fill("30326");
|
|
|
await page.waitForTimeout(800);
|
|
|
|
|
|
const combo = page.getByRole("combobox", { name: /Pickup Type/i }).first();
|
|
|
await combo.waitFor({ state: "visible", timeout: 15_000 });
|
|
|
await combo.click({ force: true });
|
|
|
await page.waitForTimeout(800);
|
|
|
|
|
|
// 多种选择器
|
|
|
const byRole = await page.getByRole("option").allTextContents();
|
|
|
const byLi = await page
|
|
|
.locator('[role="listbox"] [role="option"], [role="listbox"] li, ul[role="listbox"] > *')
|
|
|
.allTextContents();
|
|
|
|
|
|
// 键盘滚一圈再采
|
|
|
for (let i = 0; i < 30; i++) {
|
|
|
await page.keyboard.press("ArrowDown");
|
|
|
await page.waitForTimeout(50);
|
|
|
}
|
|
|
const afterScroll = await page.getByRole("option").allTextContents();
|
|
|
|
|
|
const normalize = (arr: string[]) =>
|
|
|
[
|
|
|
...new Set(
|
|
|
arr
|
|
|
.map((t) => t.replace(/\s+/g, " ").trim())
|
|
|
.filter(Boolean),
|
|
|
),
|
|
|
];
|
|
|
|
|
|
const out = {
|
|
|
byRole: normalize(byRole),
|
|
|
byLi: normalize(byLi),
|
|
|
afterScroll: normalize(afterScroll),
|
|
|
url: page.url(),
|
|
|
};
|
|
|
const file = path.join(
|
|
|
process.cwd(),
|
|
|
".rpa",
|
|
|
"flock-form-matrix",
|
|
|
"pickup-type-options.json",
|
|
|
);
|
|
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
|
fs.writeFileSync(file, JSON.stringify(out, null, 2));
|
|
|
console.log(JSON.stringify(out, null, 2));
|
|
|
} finally {
|
|
|
await browser.close();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
main().catch((e) => {
|
|
|
console.error(e);
|
|
|
process.exit(1);
|
|
|
});
|