109 lines
3.9 KiB
JavaScript
109 lines
3.9 KiB
JavaScript
// Query ERP parent plan table for two group numbers.
|
|
// Read-only — no clicks, no modifications, no exports.
|
|
const { chromium } = require('playwright-core');
|
|
|
|
const PROFILE = 'C:\\Users\\wxy\\AppData\\Local\\LTJT-ERP-Hermes-Chrome';
|
|
const CHROME = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';
|
|
const PLAN_URL = 'https://ltjt.yunzhi.run/System/Business/plan.asp';
|
|
|
|
const TARGETS = ['LW-260806A-A', 'LW-260623A-A'];
|
|
|
|
async function main() {
|
|
const context = await chromium.launchPersistentContext(PROFILE, {
|
|
executablePath: CHROME,
|
|
headless: false,
|
|
viewport: { width: 1440, height: 900 },
|
|
});
|
|
const page = context.pages()[0] || await context.newPage();
|
|
|
|
try {
|
|
await page.goto(PLAN_URL, { waitUntil: 'domcontentloaded', timeout: 60000 });
|
|
await page.waitForTimeout(5000);
|
|
|
|
// Check for login
|
|
const loginInput = await page.$('input[name="UserName"]');
|
|
if (loginInput) {
|
|
console.log(JSON.stringify({ status: 'login_required', message: 'ERP session expired' }));
|
|
return;
|
|
}
|
|
|
|
// Search by departure date 2026-08-06
|
|
// Set date range: S_chufariqi and S_chufarizhi
|
|
await page.locator('input[name="riqi"][value="chufari"]').check().catch(() => {});
|
|
await page.waitForTimeout(800);
|
|
await page.locator('#S_chufariqi').fill('2026-8-6');
|
|
await page.locator('#S_chufarizhi').fill('2026-8-6');
|
|
await page.waitForTimeout(300);
|
|
await page.locator('#SearchButton').click();
|
|
await page.waitForTimeout(8000);
|
|
|
|
// Extract all rows from the plan table
|
|
const rows = await page.evaluate(() => {
|
|
return Array.from(document.querySelectorAll('tr')).map((tr, idx) => {
|
|
const text = tr.innerText.replace(/\s+/g, ' ').trim();
|
|
const links = Array.from(tr.querySelectorAll('a')).map(a => ({
|
|
text: a.innerText.trim(),
|
|
href: a.getAttribute('href') || '',
|
|
onclick: a.getAttribute('onclick') || '',
|
|
}));
|
|
return { idx, text, links };
|
|
});
|
|
});
|
|
|
|
const results = [];
|
|
|
|
for (const target of TARGETS) {
|
|
// Find rows containing this group number
|
|
const candidateRows = rows.filter(r => r.text.includes(target));
|
|
|
|
if (candidateRows.length === 0) {
|
|
results.push({
|
|
groupNo: target,
|
|
found: false,
|
|
message: '未在计划表中找到该团号',
|
|
});
|
|
continue;
|
|
}
|
|
|
|
for (const row of candidateRows) {
|
|
// Check for 拼单 link
|
|
const pinDanLink = row.links.find(l => l.text === '拼单');
|
|
const chaZhangLink = row.links.find(l => l.text === '查账');
|
|
const deleteLink = row.links.find(l => l.text === '删除');
|
|
const modifyLink = row.links.find(l => l.text === '修改');
|
|
|
|
// Extract product name and planned guests from row text
|
|
// Row format: [idx] [status] [groupNo] [op] [type.] [product] [date] [duration] [returnDate] [plannedGuests] ...
|
|
const text = row.text;
|
|
const idxMatch = text.match(/^(\d+)/);
|
|
const statusMatch = text.match(/(收客中|已停止|已取消)/);
|
|
const productMatch = text.match(/常规团\.\s*(.+?)\s+\d{4}-\d{1,2}-\d{1,2}/);
|
|
const plannedMatch = text.match(/计划(\d+)/);
|
|
|
|
results.push({
|
|
groupNo: target,
|
|
found: true,
|
|
rowIdx: idxMatch ? idxMatch[1] : null,
|
|
status: statusMatch ? statusMatch[1] : null,
|
|
product: productMatch ? productMatch[1] : null,
|
|
plannedGuests: plannedMatch ? parseInt(plannedMatch[1]) : null,
|
|
hasPinDan: !!pinDanLink,
|
|
hasChaZhang: !!chaZhangLink,
|
|
hasDelete: !!deleteLink,
|
|
hasModify: !!modifyLink,
|
|
allLinks: row.links.map(l => l.text).filter(Boolean),
|
|
preview: text.slice(0, 400),
|
|
});
|
|
}
|
|
}
|
|
|
|
console.log(JSON.stringify({ status: 'ok', results }, null, 2));
|
|
} catch (err) {
|
|
console.log(JSON.stringify({ status: 'error', message: err.message }));
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
}
|
|
|
|
main();
|