import { emit as emitEvent } from "@/iview/utils/emitter.js"; export const LIST_ROW_PATCH_EVENT = "iview:list-row-patch"; export function getValueByPath(obj, path) { if (!obj || !path) return null; return path.split(".").reduce((acc, key) => acc?.[key], obj); } export function resolvePatchRowKeyValue(detail, rowKeyField = "guid") { if (!detail) return null; return ( detail.rowKeyValue ?? detail.patch?.[rowKeyField] ?? detail.patch?.guid ?? detail.row?.[rowKeyField] ?? detail.row?.guid ?? null ); } /** * @param {Record} record * @param {{ rowPatchKey?: string, rowKeyField?: string }} [options] */ export function resolveRowMatchKey(record, { rowPatchKey, rowKeyField = "guid" } = {}) { if (!record || typeof record !== "object") return null; if (rowPatchKey) { const nested = getValueByPath(record, rowPatchKey); if (nested != null && nested !== "") return nested; } const row = record; return row[rowKeyField] ?? row.guid ?? row.rowKey ?? null; } /** * 就地合并 dataSource 中匹配的行(保持行对象引用,便于嵌套 skuInfo 与抽屉联动) * @param {unknown[]} dataSource * @param {object} detail * @param {{ rowPatchKey?: string, rowKeyField?: string, rowPatchMergePath?: string }} [options] * @returns {boolean} */ export function applyRowPatchToDataSource(dataSource, detail, options = {}) { if (!Array.isArray(dataSource) || !detail) return false; const rowKeyField = options.rowKeyField || "guid"; const rowKeyValue = resolvePatchRowKeyValue(detail, rowKeyField); if (rowKeyValue == null) return false; const idx = dataSource.findIndex( (row) => String(resolveRowMatchKey(row, options)) === String(rowKeyValue), ); if (idx < 0) return false; const row = dataSource[idx]; if (!row || typeof row !== "object") return false; if (detail.type === "replace" && detail.row && typeof detail.row === "object") { Object.assign(row, detail.row); const mergePath = options.rowPatchMergePath; if (mergePath) { const nested = getValueByPath(row, mergePath); const nestedFromRow = getValueByPath(detail.row, mergePath); if (nested && nestedFromRow && typeof nested === "object" && typeof nestedFromRow === "object") { Object.assign(nested, nestedFromRow); } } return true; } const patch = detail.patch; if (!patch || typeof patch !== "object") return false; const mergePath = options.rowPatchMergePath; if (mergePath) { const parts = mergePath.split("."); let target = row; for (let i = 0; i < parts.length - 1; i++) { const key = parts[i]; if (!target[key] || typeof target[key] !== "object") { target[key] = {}; } target = target[key]; } const leafKey = parts[parts.length - 1]; if (!target[leafKey] || typeof target[leafKey] !== "object") { target[leafKey] = {}; } Object.assign(target[leafKey], patch); } Object.keys(patch).forEach((key) => { if (key in row) row[key] = patch[key]; }); return true; } export function emitListRowPatch(detail) { emitEvent(LIST_ROW_PATCH_EVENT, detail); }