/** * 识图传方报价:请求侧增量组装 * 首次全量 drugs;同味数下只传 quote_token + drugs_patch */ export type QuoteDrugRow = { drug_id: number; name?: string; number?: number; price?: number; way_id?: number; [key: string]: unknown; }; /** 比较两味报价药品是否等价(用于算 patch) */ export function isSameQuoteDrug( a?: QuoteDrugRow | null, b?: QuoteDrugRow | null, ): boolean { if (!a || !b) return false; return ( Number(a.drug_id || 0) === Number(b.drug_id || 0) && Number(a.number || 0) === Number(b.number || 0) && Number(a.price || 0) === Number(b.price || 0) && String(a.name || '') === String(b.name || '') && Number(a.way_id || 0) === Number(b.way_id || 0) ); } /** * 组装增量报价入参 * 为什么:点选改一味时不必每次 POST 整方 drugs,服务端用 token 缓存整方再 merge patch */ export function buildIncrementalQuotePayload(opts: { scalars: Record; drugs: QuoteDrugRow[]; quoteToken?: string; lastQuoteDrugs?: QuoteDrugRow[] | null; }): { payload: Record; nextLastDrugs: QuoteDrugRow[] } { const scalars = opts.scalars || {}; const drugs = Array.isArray(opts.drugs) ? opts.drugs : []; const quoteToken = String(opts.quoteToken || '').trim(); const prev = Array.isArray(opts.lastQuoteDrugs) ? opts.lastQuoteDrugs : null; const payload: Record = { ...scalars }; if (quoteToken) { payload.quote_token = quoteToken; } if (!quoteToken || !prev || prev.length !== drugs.length) { payload.drugs = drugs; return { payload, nextLastDrugs: drugs }; } const patches: Array<{ index: number; drug: QuoteDrugRow }> = []; for (let i = 0; i < drugs.length; i++) { if (!isSameQuoteDrug(prev[i], drugs[i])) { patches.push({ index: i, drug: drugs[i] }); } } if (patches.length === 0) { return { payload, nextLastDrugs: prev }; } if (patches.length >= drugs.length) { payload.drugs = drugs; } else { payload.drugs_patch = patches; } return { payload, nextLastDrugs: drugs }; }