/** * fix-place 浏览器脚本(纯字符串)。禁止改为 function 传入 page.evaluate。 */ export const INVOKE_CAPTURED_PLACE_CHANGED = `(arg) => { const pid = arg.pid; const desc = arg.desc; const loc = arg.loc || {}; const handlers = window.__rpaPlaceChangedHandlers || []; if (!handlers.length) { return { ok: false, reason: "no-captured-handlers", handlerCount: 0 }; } const active = document.activeElement; const lat = typeof loc.latitude === "number" ? loc.latitude : typeof loc.lat === "number" ? loc.lat : 0; const lng = typeof loc.longitude === "number" ? loc.longitude : typeof loc.lng === "number" ? loc.lng : 0; const placePayload = { place_id: pid, formatted_address: desc, name: (desc.split(",")[0] || "").trim(), geometry: { location: { lat: function() { return lat; }, lng: function() { return lng; }, }, }, address_components: loc.addressComponents || loc.address_components || [], }; const ordered = handlers.slice().reverse(); const activeInput = active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA") ? active : null; const tryInvoke = function(entry) { const inst = entry.instance; const handler = entry.handler; if (!inst || typeof handler !== "function") { return { ok: false, reason: "bad-entry" }; } const originalGetPlace = typeof inst.getPlace === "function" ? inst.getPlace.bind(inst) : function() { return {}; }; inst.getPlace = function() { return placePayload; }; try { handler.call(inst); return { ok: true, reason: "handler-invoked" }; } catch (e) { return { ok: false, reason: "handler-threw:" + String(e) }; } finally { setTimeout(function() { inst.getPlace = originalGetPlace; }, 120); } }; if (activeInput) { for (let i = 0; i < ordered.length; i += 1) { const entry = ordered[i]; if (entry.inputEl === activeInput) { const result = tryInvoke(entry); if (result.ok) { return { ok: true, reason: result.reason, handlerCount: handlers.length }; } } } } for (let j = 0; j < ordered.length; j += 1) { const fallback = tryInvoke(ordered[j]); if (fallback.ok) { return { ok: true, reason: fallback.reason, handlerCount: handlers.length }; } } return { ok: false, reason: "all-handlers-failed", handlerCount: handlers.length }; }`; export const TRIGGER_GOOGLE_PLACE_CHANGED = `(arg) => { const pid = arg.pid; const desc = arg.desc; const gmaps = window.google; const resolveInstance = function() { const instances = window.__rpaAutocompleteInstances || []; if (instances.length > 0) { return instances[instances.length - 1]; } if (gmaps && gmaps.maps && gmaps.maps.places && gmaps.maps.places.Autocomplete) { const AutocompleteCtor = gmaps.maps.places.Autocomplete; const globalKeys = Object.keys(window).filter(function(k) { try { return window[k] instanceof AutocompleteCtor; } catch (e) { return false; } }); if (globalKeys.length > 0) { return window[globalKeys[0]]; } } const pacInput = document.querySelector(".pac-target-input") || document.querySelector("#react-quoter-landing-plugin input"); if (!pacInput) { return null; } const keys = Object.keys(pacInput); for (let i = 0; i < keys.length; i += 1) { const key = keys[i]; if (key.indexOf("gm_") !== 0) continue; const val = pacInput[key]; if (val && typeof val.getPlace === "function") { return val; } } return null; }; const autocompleteInstance = resolveInstance(); if (!autocompleteInstance) { return { ok: false, reason: "no-autocomplete-instance" }; } if (!gmaps || !gmaps.maps || !gmaps.maps.event || typeof gmaps.maps.event.trigger !== "function") { return { ok: false, reason: "google-maps-unavailable" }; } const originalGetPlace = autocompleteInstance.getPlace.bind(autocompleteInstance); autocompleteInstance.getPlace = function() { return { place_id: pid, formatted_address: desc, name: desc.split(",")[0], geometry: { location: { lat: function() { return 0; }, lng: function() { return 0; } } }, }; }; gmaps.maps.event.trigger(autocompleteInstance, "place_changed"); setTimeout(function() { autocompleteInstance.getPlace = originalGetPlace; }, 100); return { ok: true, reason: "triggered" }; }`; export const CHECK_PICKUP_IN_REACT_STATE = `() => { const widget = document.querySelector("#react-quoter-landing-plugin"); if (!widget) return false; const fiberKey = Object.keys(widget).find(function(k) { return k.indexOf("__reactFiber$") === 0 || k.indexOf("__reactInternalInstance$") === 0; }); if (!fiberKey) return false; let fiber = widget[fiberKey]; while (fiber) { const state = fiber.stateNode && fiber.stateNode.state; if (state) { const pickup = state.pickupAddress || state.pickup || (state.addresses && state.addresses.pickup); if (pickup && (pickup.placeId || pickup.formattedAddress)) { return true; } } fiber = fiber.return; } return false; }`; export const INJECT_REACT_STATE = `(arg) => { const sideArg = arg.sideArg; const pid = arg.pid; const loc = arg.loc; const desc = arg.desc; const widget = document.querySelector("#react-quoter-landing-plugin"); if (!widget) return false; const fiberKey = Object.keys(widget).find(function(k) { return k.indexOf("__reactFiber$") === 0 || k.indexOf("__reactInternalInstance$") === 0; }); if (!fiberKey) return false; let fiber = widget[fiberKey]; while (fiber) { const stateNode = fiber.stateNode; if (stateNode && typeof stateNode.setState === "function") { const state = stateNode.state; if (state && ("pickupAddress" in state || "pickup" in state || "addresses" in state)) { const addressData = { placeId: pid, location: loc, formattedAddress: desc, isCommitted: true, }; const stateKey = sideArg === "pickup" ? "pickupAddress" : "deliveryAddress"; stateNode.setState({ [stateKey]: addressData }); return true; } } fiber = fiber.return; } return false; }`;