You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

910 lines
26 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* Priority1 询价页 — 动态表单逻辑映射Feathery / #container-mh
*
* 用途RPA / Cursor 在任意分支下知道「下一步填什么、怎么填」。
* 探测来源scripts/probe-priority1-shipment-types.ts → .rpa/priority1-shipment-probe/
* 最后校验2026-06-26
*/
import type { Priority1DemoInput } from "@/workers/rpa/priority1/demo-input";
import type {
ExpeditedTrailerType,
FtlAdditionalService,
FtlTrailerType,
Priority1ShipmentType,
} from "@/workers/rpa/priority1/shipment-types";
import {
EXPEDITED_TRAILER,
FTL_ADDITIONAL,
FTL_TRAILER,
OPEN_DECK_SUBTYPES,
SHIPMENT_TYPE_CONFIG,
expeditedLiftgateAvailable,
} from "@/workers/rpa/priority1/shipment-types";
/** 页面根与入口 */
export const PRIORITY1_FORM_META = {
entryUrl: "https://www.priority1.com/instant-freight-quotes/#New%20Step%201",
container: "#container-mh",
submitButton: /GET INSTANT QUOTES/i,
quoteApiPattern: /api-static-2\.feathery\.io\/api\/custom_request/i,
/** Feathery 卡片:禁止 .check(),用 force click黑底 rgb(0,0,0) = 已选 */
featheryCardRule:
"click({ force: true, noWaitAfter: true }) + 点击卡片文字;以 checkbox.checked 或黑底高亮为准",
} as const;
export type FieldControl =
| "text"
| "select"
| "date"
| "phone"
| "feathery_card"
| "checkbox_label";
export type FormFieldDef = {
/** 逻辑键,对应 demo-input 或分支状态 */
key: string;
/** 页面可见标题(中英) */
label: string;
selector: string;
control: FieldControl;
required: boolean;
/** 下拉/卡片可选值 */
options?: readonly string[];
/** 推荐演示默认值 */
demoDefault?: string;
/** Priority1DemoInput 字段名(若有) */
demoKey?: keyof Priority1DemoInput;
section?: string;
notes?: string;
};
export type FormBranch = {
id: string;
description: string;
/** 父级选择条件,全部满足时追加下列字段 */
when: Record<string, string>;
fields: FormFieldDef[];
};
export type FormStepPlan = {
step: "step1" | "step2";
order: number;
field: FormFieldDef;
/** 本次应写入/选择的值 */
value: string;
/** 给操作员的简短中文指令 */
instruction: string;
};
/** ─── Step 1三种类型共用 ─── */
export const STEP1_FIELDS: FormFieldDef[] = [
{
key: "shipmentType",
label: "Shipment Type / 运输类型",
selector: "#cb_st_ltl | #cb_st_ftl | #cb_st_exp",
control: "feathery_card",
required: true,
options: ["Less Than Truckload", "Full Truckload", "Expedited"],
section: "Step 1",
notes: "三选一卡片;探测到 checkbox id 为 cb_st_ltl / cb_st_ftl / cb_st_exp非 cb_st_expedited",
},
{
key: "originZip",
label: "Pickup ZIP Code / 起运邮编",
selector: "#origin-zip",
control: "text",
required: true,
demoDefault: "32801",
demoKey: "originZip",
},
{
key: "destinationZip",
label: "Delivery ZIP Code / 目的邮编",
selector: "#destination-zip",
control: "text",
required: true,
demoDefault: "28202",
demoKey: "destinationZip",
},
{
key: "shipmentFrequency",
label: "Shipments Per Month / 发货频次",
selector: "#freight-shipment",
control: "select",
required: true,
options: [
"1-5",
"5-10",
"10-30",
"30-100",
"100+",
"One Time Shipment",
],
demoDefault: "One Time Shipment",
demoKey: "shipmentFrequency",
},
{
key: "pickupDate",
label: "Pickup Date / 提货日",
selector: "#pickup-date",
control: "date",
required: true,
demoDefault: "07/14/2026",
demoKey: "pickupDate",
notes: "格式 MM/DD/YYYY",
},
{
key: "email",
label: "Business Email / 商务邮箱",
selector: "#business-email",
control: "text",
required: true,
demoKey: "email",
},
{
key: "phone",
label: "Phone / 电话",
selector: "#client-phone",
control: "phone",
required: true,
demoKey: "phone",
notes: "需先选 United States再 sequential 输入 10 位数字",
},
];
/** Step 1 各类型哈希回退(按钮提交失败时) */
export const STEP2_HASH_FALLBACK: Record<Priority1ShipmentType, string> = {
ltl: "#V4.1%20Step%202%20-%20LTL",
ftl: "#New%20Step%202%20-%20Truckload",
expedited: "#New%20Step%202%20-%20Expedited",
};
/** Step 2 就绪探测选择器 */
export const STEP2_READY_SELECTOR: Record<Priority1ShipmentType, string> = {
ltl: "#length",
ftl: "#Commodity",
expedited: "#cb_stt_sv",
};
/** ─── LTL Step 2 ─── */
export const LTL_STEP2_FIELDS: FormFieldDef[] = [
{ key: "lengthIn", label: "Length (in)", selector: "#length", control: "text", required: true, demoKey: "lengthIn", demoDefault: "48" },
{ key: "widthIn", label: "Width (in)", selector: "#width", control: "text", required: true, demoKey: "widthIn", demoDefault: "40" },
{ key: "heightIn", label: "Height (in)", selector: "#height", control: "text", required: true, demoKey: "heightIn", demoDefault: "48" },
{ key: "weightLb", label: "Total Weight (lb)", selector: "#weight", control: "text", required: true, demoKey: "weightLb", demoDefault: "500", notes: "单票 LTL 常见 1501800 lb" },
{
key: "packaging",
label: "What are you shipping? / 包装类型",
selector: "#freight-package",
control: "select",
required: true,
options: ["Pallet", "Crate", "Box", "Bundle"],
demoDefault: "Pallet",
demoKey: "packaging",
},
{ key: "palletCount", label: "Number of Pallets", selector: "#number-of-pallets", control: "text", required: true, demoKey: "palletCount", demoDefault: "2" },
{
key: "freightClass",
label: "Freight Class",
selector: "#freight-type",
control: "select",
required: true,
options: ["Not Sure", "50", "55", "60", "65", "70", "77.5", "85", "92.5", "100", "110", "125", "150", "175", "200", "250", "300", "400", "500"],
demoDefault: "70",
demoKey: "freightClass",
notes: "备用选择器 #freight-class",
},
{
key: "pickupLocation",
label: "Pickup Location Type",
selector: "#PickupLocation",
control: "select",
required: true,
options: [
"Residence / Home Business",
"Business (with loading docks or forklift)",
"Business (no loading dock, no forklift)",
],
demoKey: "pickupLocation",
},
{
key: "pickupServices",
label: "Pickup Accessorials / 提货附加",
selector: "getByLabel",
control: "checkbox_label",
required: false,
options: [
"Liftgate at Pickup",
"Inside Pickup",
"Limited Access Pickup",
"Residential Pickup",
],
demoKey: "pickupServices",
notes: "按标签文本点击,非稳定 id",
},
{
key: "deliveryLocation",
label: "Delivery Location Type",
selector: "#DropoffLocation",
control: "select",
required: true,
options: [
"Residence / Home Business",
"Business (with loading docks or forklift)",
"Business (no loading dock, no forklift)",
],
demoKey: "deliveryLocation",
},
{
key: "deliveryServices",
label: "Delivery Accessorials / 派送附加",
selector: "getByLabel",
control: "checkbox_label",
required: false,
options: [
"Liftgate at Delivery",
"Inside Delivery",
"Delivery Appointment",
"Call Before Delivery",
"Limited Access Delivery",
"Hazardous Material",
"Residential Delivery",
],
demoKey: "deliveryServices",
},
];
/** ─── FTL Step 2主拖车四选一决定后续子表单─── */
export const FTL_TRAILER_FIELDS: FormFieldDef[] = [
{
key: "ftlTrailer_dry_van",
label: "Dry Van",
selector: "#cb_stt_ftl1",
control: "feathery_card",
required: false,
section: "Select Trailer Type *",
notes: "53ft最多 26 托盘 / 45000 lb",
},
{
key: "ftlTrailer_open_deck",
label: "Open Deck",
selector: "#cb_stt_ftl2",
control: "feathery_card",
required: false,
section: "Select Trailer Type *",
},
{
key: "ftlTrailer_temperature_controlled",
label: "Temperature Controlled",
selector: "#cb_stt_ftl3",
control: "feathery_card",
required: false,
section: "Select Trailer Type *",
},
{
key: "ftlTrailer_ftl_expedited",
label: "Expedited",
selector: "#cb_stt_ftl4",
control: "feathery_card",
required: false,
section: "Select Trailer Type *",
notes: "FTL 下的 Expedited 子流,与主类型 Expedited 不同",
},
];
/** FTL 条件分支:选中主拖车后出现 */
export const FTL_CONDITIONAL_BRANCHES: FormBranch[] = [
{
id: "ftl_open_deck",
description: "Open Deck → 子类型下拉",
when: { ftlTrailer: "open_deck" },
fields: [
{
key: "openDeckSubtype",
label: "Open Deck Type",
selector: "select:has(option:Flatbed)",
control: "select",
required: true,
options: OPEN_DECK_SUBTYPES,
demoDefault: "48 Foot Flatbed",
demoKey: "openDeckSubtype",
notes:
"选中 Open Deck 后出现;实现见 form-interactions.selectOpenDeckSubtype原生 select → combobox → 文本点击)",
},
],
},
{
id: "ftl_temp",
description: "Temperature Controlled → 温控区间",
when: { ftlTrailer: "temperature_controlled" },
fields: [
{
key: "tempMinF",
label: "Minimum Temperature (°F)",
selector: "#minimum-temperature",
control: "text",
required: true,
demoDefault: "32",
demoKey: "tempMinF",
notes: "录制确认 id=#minimum-temperature非 placeholder",
},
{
key: "tempMaxF",
label: "Maximum Temperature (°F)",
selector: "#maximum-temperature",
control: "text",
required: true,
demoDefault: "40",
demoKey: "tempMaxF",
notes: "录制确认 id=#maximum-temperature",
},
],
},
{
id: "ftl_expedited_sub",
description: "FTL Expedited 拖车 → 三选一子车型Large Straight 时可选 Liftgate",
when: { ftlTrailer: "ftl_expedited" },
fields: [
{
key: "ftlExpeditedTrailer_sprinter",
label: "Sprinter Van",
selector: "#cb_stt_sv",
control: "feathery_card",
required: true,
section: "Select Expedited Trailer Type",
},
{
key: "ftlExpeditedTrailer_small",
label: "Small Straight Box Truck",
selector: "#cb_stt_ssbt",
control: "feathery_card",
required: false,
section: "Select Expedited Trailer Type",
},
{
key: "ftlExpeditedTrailer_large",
label: "Large Straight Box Truck",
selector: "#cb_stt_lsbt",
control: "feathery_card",
required: false,
section: "Select Expedited Trailer Type",
},
{
key: "expeditedLiftgate",
label: "Liftgate",
selector: "text=Liftgate",
control: "checkbox_label",
required: false,
demoKey: "expeditedLiftgate",
},
],
},
];
/** FTL 附加服务(可选,多选) */
export const FTL_ADDITIONAL_FIELDS: FormFieldDef[] = [
{
key: "full_ftl",
label: "Full FTL",
selector: "#cb_as_ftl1",
control: "feathery_card",
required: false,
section: "Additional Services (Optional)",
notes: "实现见 form-interactions.selectFtlAdditionalServicecheckbox 用 #container-mh 根定位,勿嵌套 section",
},
{
key: "partial_ptl",
label: "Partial PTL",
selector: "#cb_as_ftl2",
control: "feathery_card",
required: false,
section: "Additional Services (Optional)",
notes: "同上 selectFtlAdditionalService",
},
{
key: "team_drivers",
label: "Team Drivers",
selector: "#cb_as_ftl3",
control: "feathery_card",
required: false,
section: "Additional Services (Optional)",
notes: "同上 selectFtlAdditionalService",
},
];
/** FTL / Expedited 共用货描与重量 */
export const FTL_EXPEDITED_CARGO_FIELDS: FormFieldDef[] = [
{
key: "commodity",
label: "What are you shipping? / 货描",
selector: "#Commodity",
control: "text",
required: true,
demoDefault: "Electronics",
demoKey: "commodity",
notes: "自由文本;演示默认填 Electronics",
},
{
key: "weightLb",
label: "Total Weight (lb)",
selector: "#weight",
control: "text",
required: true,
demoKey: "weightLb",
notes: "FTL Dry Van 演示 1200018000Expedited Sprinter ≤3500",
},
];
export const FTL_ONLY_CARGO_FIELDS: FormFieldDef[] = [
{
key: "palletCount",
label: "Number of Pallets",
selector: "#Pallets",
control: "text",
required: true,
demoKey: "palletCount",
demoDefault: "18",
notes: "Dry Van 上限约 26 托盘",
},
];
/** ─── Expedited 主类型 Step 2无四卡 FTL 拖车步)─── */
export const EXPEDITED_TRAILER_FIELDS: FormFieldDef[] = [
{
key: "expedited_sprinter",
label: "Sprinter Van",
selector: "#cb_stt_sv",
control: "feathery_card",
required: false,
section: "Select Trailer Type *",
notes: "最大约 3500 lb / 3 托盘",
},
{
key: "expedited_small",
label: "Small Straight Box Truck",
selector: "#cb_stt_ssbt",
control: "feathery_card",
required: false,
section: "Select Trailer Type *",
},
{
key: "expedited_large",
label: "Large Straight Box Truck",
selector: "#cb_stt_lsbt",
control: "feathery_card",
required: false,
section: "Select Trailer Type *",
},
];
/** 按拖车推荐重量上限lb */
export const WEIGHT_HINTS: Record<string, { min: number; max: number; pallets?: string }> = {
"ftl:dry_van": { min: 8000, max: 42000, pallets: "1226" },
"ftl:open_deck": { min: 5000, max: 45000, pallets: "822" },
"ftl:temperature_controlled": { min: 5000, max: 40000, pallets: "1024" },
"expedited:sprinter_van": { min: 200, max: 3500, pallets: "13" },
"expedited:small_straight": { min: 500, max: 8000, pallets: "48" },
"expedited:large_straight": { min: 1000, max: 10000, pallets: "814" },
};
function readDemoValue(
demo: Priority1DemoInput,
field: FormFieldDef,
): string {
if (field.demoKey) {
const raw = demo[field.demoKey];
if (Array.isArray(raw)) return raw.join(",");
if (typeof raw === "boolean") return raw ? "true" : "false";
if (raw != null && raw !== "") return String(raw);
}
return field.demoDefault ?? "";
}
function instructionFor(field: FormFieldDef, value: string): string {
switch (field.control) {
case "feathery_card":
return `在「${field.section ?? field.label}」点击卡片「${value}」,确认黑底高亮`;
case "select":
return `下拉 ${field.selector} 选择「${value}`;
case "checkbox_label":
return value.includes(",")
? `勾选标签:${value}`
: `点击标签「${value}」勾选`;
case "phone":
return `选 US 区号后输入 ${value}`;
default:
return `${field.selector} 填入「${value}`;
}
}
/** 从 Priority1DemoInput 生成完整填写计划(决策树展开) */
export function buildPriority1FormPlan(
demo: Priority1DemoInput,
): FormStepPlan[] {
const plan: FormStepPlan[] = [];
let order = 0;
const push = (step: "step1" | "step2", field: FormFieldDef, value: string) => {
if (!value && field.required) return;
order += 1;
plan.push({
step,
order,
field,
value,
instruction: instructionFor(field, value),
});
};
// Step 1
const stCfg = SHIPMENT_TYPE_CONFIG[demo.shipmentType];
push("step1", STEP1_FIELDS[0]!, stCfg.displayName.split("")[0]!.trim());
for (const f of STEP1_FIELDS.slice(1)) {
push("step1", f, readDemoValue(demo, f));
}
// Step 2 — 按类型分支
if (demo.shipmentType === "ltl") {
for (const f of LTL_STEP2_FIELDS) {
if (f.key === "pickupServices" || f.key === "deliveryServices") {
const list =
f.key === "pickupServices" ? demo.pickupServices : demo.deliveryServices;
for (const svc of list) push("step2", f, svc);
continue;
}
push("step2", f, readDemoValue(demo, f));
}
return plan;
}
if (demo.shipmentType === "ftl") {
const trailerMeta = FTL_TRAILER[demo.ftlTrailer];
push(
"step2",
{
key: "ftlTrailer",
label: trailerMeta.label,
selector: trailerMeta.selector,
control: "feathery_card",
required: true,
section: "Select Trailer Type *",
demoKey: "ftlTrailer",
},
trailerMeta.label,
);
const branch = FTL_CONDITIONAL_BRANCHES.find(
(b) => b.when.ftlTrailer === demo.ftlTrailer,
);
if (branch) {
for (const f of branch.fields) {
if (f.key.startsWith("ftlExpeditedTrailer_")) {
const sub = EXPEDITED_TRAILER[demo.ftlExpeditedTrailer];
if (f.label === sub.label) push("step2", f, sub.label);
continue;
}
if (
f.key === "expeditedLiftgate" &&
demo.expeditedLiftgate &&
expeditedLiftgateAvailable(demo.ftlExpeditedTrailer)
) {
push("step2", f, "Liftgate");
continue;
}
if (f.key === "expeditedLiftgate") continue;
push("step2", f, readDemoValue(demo, f));
}
}
for (const svc of demo.ftlAdditionalServices) {
const meta = FTL_ADDITIONAL[svc];
const def = FTL_ADDITIONAL_FIELDS.find((x) => x.key === svc);
if (def) push("step2", def, meta.label);
}
for (const f of FTL_EXPEDITED_CARGO_FIELDS) {
push("step2", f, readDemoValue(demo, f));
}
if (demo.ftlTrailer !== "ftl_expedited") {
for (const f of FTL_ONLY_CARGO_FIELDS) {
push("step2", f, readDemoValue(demo, f));
}
}
return plan;
}
// expedited
const expMeta = EXPEDITED_TRAILER[demo.expeditedTrailer];
push(
"step2",
{
key: "expeditedTrailer",
label: expMeta.label,
selector: expMeta.selector,
control: "feathery_card",
required: true,
section: "Select Trailer Type *",
demoKey: "expeditedTrailer",
},
expMeta.label,
);
for (const f of FTL_EXPEDITED_CARGO_FIELDS) {
push("step2", f, readDemoValue(demo, f));
}
if (
demo.expeditedLiftgate &&
expeditedLiftgateAvailable(demo.expeditedTrailer)
) {
push("step2", {
key: "expeditedLiftgate",
label: "Liftgate",
selector: "text=Liftgate",
control: "checkbox_label",
required: false,
}, "Liftgate");
}
return plan;
}
/** 给定当前状态,返回「下一批」应处理的字段(模拟动态表单) */
export function getNextFields(
state: {
shipmentType: Priority1ShipmentType;
step: 1 | 2;
ftlTrailer?: FtlTrailerType;
ftlAdditionalDone?: boolean;
cargoDone?: boolean;
},
): FormFieldDef[] {
if (state.step === 1) return STEP1_FIELDS;
if (state.shipmentType === "ltl") return LTL_STEP2_FIELDS;
if (state.shipmentType === "expedited") {
if (!state.cargoDone) {
return [...EXPEDITED_TRAILER_FIELDS, ...FTL_EXPEDITED_CARGO_FIELDS];
}
return [];
}
// ftl
if (!state.ftlTrailer) return FTL_TRAILER_FIELDS;
const branch = FTL_CONDITIONAL_BRANCHES.find(
(b) => b.when.ftlTrailer === state.ftlTrailer,
);
const cargoFields =
state.ftlTrailer === "ftl_expedited"
? FTL_EXPEDITED_CARGO_FIELDS
: [...FTL_EXPEDITED_CARGO_FIELDS, ...FTL_ONLY_CARGO_FIELDS];
const tail = [...FTL_ADDITIONAL_FIELDS, ...cargoFields];
return branch ? [...branch.fields, ...tail] : tail;
}
/** 场景速查:选 A → 接下来填什么 */
export const SCENARIO_CHEATSHEET: Array<{
path: string;
steps: string[];
}> = [
{
path: "LTL 标准单票",
steps: [
"Step1 选 Less Than Truckload → ZIP/日期/联系信息 → GET INSTANT QUOTES",
"Step2 尺寸 L×W×H → Total Weight → Packaging=Pallet → #托盘 → Freight Class",
"Pickup/Dropoff 地点类型 → 可选附加勾选 → 提交报价",
],
},
{
path: "FTL Dry Van + Full FTL",
steps: [
"Step1 选 Full Truckload",
"Step2 选 Dry Van 卡片 →(无子表单)",
"Additional Services 可点 Full FTL / Partial PTL / Team Drivers",
"What are you shipping?=Pallet → Weight≈15000 → Pallets≈18 → 提交",
],
},
{
path: "FTL Open Deck",
steps: [
"选 Open Deck → 出现 Open Deck Type 下拉Flatbed/Step Deck/Conestoga/Goose Neck RGN",
"再填货描/重量/托盘",
],
},
{
path: "FTL Temperature Controlled",
steps: ["选 Temperature Controlled → Min/Max °F → 货描/重量/托盘"],
},
{
path: "FTL 内嵌 Expedited",
steps: [
"选 Expedited第四张 FTL 卡)→ Select Expedited Trailer Type 三选一",
"Large Straight 时可选 Liftgate → 货描/重量(无 Number of Pallets 字段)",
],
},
{
path: "Expedited 主类型",
steps: [
"Step1 选 Expedited#cb_st_exp",
"Step2 直接三卡Sprinter / Small Straight / Large Straight",
"货描 + Total Weight无托盘字段Large Straight 才出现尾板附加服务",
],
},
];
/** 全字段可选值目录(供 RPA / 文档引用) */
export function collectFieldOptionsCatalog(): Array<{
step: string;
key: string;
label: string;
options: string[];
notes?: string;
}> {
const rows: Array<{
step: string;
key: string;
label: string;
options: string[];
notes?: string;
}> = [];
const add = (step: string, fields: FormFieldDef[]) => {
for (const f of fields) {
if (!f.options?.length) continue;
rows.push({
step,
key: f.key,
label: f.label,
options: [...f.options],
notes: f.notes,
});
}
};
add("Step 1", STEP1_FIELDS);
add("Step 2 LTL", LTL_STEP2_FIELDS);
add("Step 2 FTL 拖车", FTL_TRAILER_FIELDS);
add("Step 2 FTL 附加", FTL_ADDITIONAL_FIELDS);
add("Step 2 Expedited 拖车", EXPEDITED_TRAILER_FIELDS);
for (const b of FTL_CONDITIONAL_BRANCHES) {
add(`Step 2 FTL 分支/${b.id}`, b.fields);
}
return rows;
}
/** 导出为 Markdown 参考(可写入文件或打印) */
export function formatFormLogicReference(
demo?: Priority1DemoInput,
opts?: { includeHeader?: boolean; sectionTitle?: string },
): string {
const includeHeader = opts?.includeHeader ?? true;
const lines: string[] = [];
if (includeHeader) {
lines.push(
"# Priority1 动态表单逻辑映射",
"",
`入口:${PRIORITY1_FORM_META.entryUrl}`,
`容器:${PRIORITY1_FORM_META.container}`,
"",
"## 决策规则",
`- ${PRIORITY1_FORM_META.featheryCardRule}`,
"- Step1 提交失败时用 STEP2_HASH_FALLBACK 哈希导航",
"",
"## 场景速查",
);
for (const s of SCENARIO_CHEATSHEET) {
lines.push(`### ${s.path}`);
for (const step of s.steps) lines.push(`- ${step}`);
lines.push("");
}
}
if (demo) {
const title = opts?.sectionTitle ?? "当前输入展开计划";
lines.push(`## ${title}`);
lines.push("```");
for (const row of buildPriority1FormPlan(demo)) {
lines.push(
`${row.order}. [${row.step}] ${row.field.label}${row.value}`,
);
lines.push(` ${row.instruction}`);
}
lines.push("```");
}
return lines.join("\n");
}
export type Priority1PathRef = {
id: string;
title: string;
persona: string;
input: Priority1DemoInput;
verified: "recorded" | "logic-only";
};
/** 完整参考:字段目录 + 路径矩阵 + 各 canonical 路径展开 */
export function formatCompleteFormLogicReference(
paths: Priority1PathRef[],
): string {
const lines: string[] = [
"# Priority1 动态表单逻辑映射",
"",
`入口:${PRIORITY1_FORM_META.entryUrl}`,
`容器:${PRIORITY1_FORM_META.container}`,
"",
"## 决策规则",
`- ${PRIORITY1_FORM_META.featheryCardRule}`,
"- Step1 提交失败时用 STEP2_HASH_FALLBACK 哈希导航",
"",
"## 录制说明",
"- 本文件由 `npm run export:priority1-form-reference` 从 `form-logic-map.ts` + `demo-input.ts` 自动生成,**请勿手改**",
"- **不能**仅靠本文件自动录制;需对每条 `logic-only` 路径执行 `npm run record:priority1` 手动走一遍",
"- 全矩阵批量:`benchmark:priority1-canonical-matrix`24 条 canonical",
"- 随机批量:`benchmark:priority1-10cases`LTL、`benchmark:priority1-ftl-expedited`",
"",
"## 场景速查6 种表单结构)",
];
for (const s of SCENARIO_CHEATSHEET) {
lines.push(`### ${s.path}`);
for (const step of s.steps) lines.push(`- ${step}`);
lines.push("");
}
lines.push("## 全字段可选值");
lines.push("");
lines.push("| 步骤 | 字段 | 可选值 |");
lines.push("|------|------|--------|");
for (const row of collectFieldOptionsCatalog()) {
const opts = row.options.join(" / ");
lines.push(`| ${row.step} | ${row.label} | ${opts} |`);
}
lines.push("");
lines.push("## 路径矩阵(全部 canonical 用例)");
lines.push("");
lines.push("| ID | 路径 | 用户画像 | 验证状态 |");
lines.push("|----|------|----------|----------|");
for (const p of paths) {
const status = p.verified === "recorded" ? "已录制" : "待录制";
lines.push(`| ${p.id} | ${p.title} | ${p.persona} | ${status} |`);
}
lines.push("");
const recorded = paths.filter((p) => p.verified === "recorded").length;
const pending = paths.length - recorded;
lines.push(
`> 共 **${paths.length}** 条路径:${recorded} 已录制 / ${pending} 待录制。`,
);
lines.push(
"> LTL/FTL/Expedited 的 **选项组合**(如不同 ZIP、重量不改变表单结构仅改变字段值上表覆盖全部 **结构分支** + 代表性选项。",
);
lines.push("");
for (const p of paths) {
lines.push("---");
lines.push("");
lines.push(`## 演示展开:${p.id}${p.title}`);
lines.push("");
lines.push(`> ${p.persona}`);
lines.push("");
lines.push(
formatFormLogicReference(p.input, {
includeHeader: false,
sectionTitle: "填写步骤",
}),
);
lines.push("");
}
lines.push(
"> 源逻辑:`form-logic-map.ts` · 用例:`demo-input.ts` → `PRIORITY1_CANONICAL_PATHS`",
);
return lines.join("\n");
}