function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
/**
 * PisellTopology - 门店设备拓扑图
 *
 * 当前默认行为：
 * - 挂载时调用 `GET /tenant/device` 拉取设备数组（不再读 floor-plan）
 * - 按设备 `type_code` 动态生成 elementKinds，并以近似正方形网格自动布局
 * - 永远阅读模式，关闭编辑/连线/调色板
 */
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import classNames from 'classnames';
import { PisellFloorMapLayout, FloorMapZoneElement, FLOOR_MAP_ZONE_ELEMENT_KIND, wrapFloorMapOnSaveWithRemotePersist } from '@pisell/materials';
import useEngineContext from "../../hooks/useEngineContext";
import topologyLocaleTexts from "./locales";
import { locales } from '@pisell/utils';
import { request } from "../../utils";
import { TopologyDeviceCard } from "./TopologyDeviceCard";
import { TopologyFloorMapEditToggle } from "./components/TopologyFloorMapEditToggle";
import { TopologyConnectionLegend } from "./components/TopologyConnectionLegend";
import { reconcileTopologyView, TOPOLOGY_DEVICE_KIND_VALUES, extractRawDeviceList, extractRawDeviceConnectionList } from "./topologyDeviceListView";
import { fetchTopologyDeviceConnectionList, fetchTopologyDeviceList } from "./topologyDeviceApi";
import { PISELL_TOPOLOGY_FLOOR_PLAN_CODE, TOPOLOGY_DEVICES_DATA_SOURCE_KEY, TOPOLOGY_MAIN_CANVAS_ID } from "./topologyFloorPlanConstants";
import { useTopologyFloorPlan } from "./floorPlan/useTopologyFloorPlan";
import { saveViewConfigToShopFloorPlan, toastFloorPlanSaveError } from "./floorPlan/topologyFloorPlanApi";
import "./PisellTopology.less";
var PREFIX = 'pisell-topology';

/** Story / 无引擎时占位，避免 request.getRequest 未注入报错 */
var PREVIEW_HTTP_CLIENT = {
  get: function () {
    var _get = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) switch (_context.prev = _context.next) {
          case 0:
            return _context.abrupt("return", {
              data: []
            });
          case 1:
          case "end":
            return _context.stop();
        }
      }, _callee);
    }));
    function get() {
      return _get.apply(this, arguments);
    }
    return get;
  }(),
  post: function () {
    var _post = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) switch (_context2.prev = _context2.next) {
          case 0:
            return _context2.abrupt("return", {
              data: {}
            });
          case 1:
          case "end":
            return _context2.stop();
        }
      }, _callee2);
    }));
    function post() {
      return _post.apply(this, arguments);
    }
    return post;
  }(),
  put: function () {
    var _put = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) switch (_context3.prev = _context3.next) {
          case 0:
            return _context3.abrupt("return", {
              data: {}
            });
          case 1:
          case "end":
            return _context3.stop();
        }
      }, _callee3);
    }));
    function put() {
      return _put.apply(this, arguments);
    }
    return put;
  }(),
  remove: function () {
    var _remove = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) switch (_context4.prev = _context4.next) {
          case 0:
            return _context4.abrupt("return", {
              data: {}
            });
          case 1:
          case "end":
            return _context4.stop();
        }
      }, _callee4);
    }));
    function remove() {
      return _remove.apply(this, arguments);
    }
    return remove;
  }(),
  custom: function () {
    var _custom = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) switch (_context5.prev = _context5.next) {
          case 0:
            return _context5.abrupt("return", {
              data: {}
            });
          case 1:
          case "end":
            return _context5.stop();
        }
      }, _callee5);
    }));
    function custom() {
      return _custom.apply(this, arguments);
    }
    return custom;
  }()
};

/** 给所有 `topologyDevice:*` kind 共用一份 device card 渲染函数（图标内置兜底） */
function buildDeviceRenderItemByKind(kindValues, devicesById) {
  var map = {};
  map[FLOOR_MAP_ZONE_ELEMENT_KIND] = function (item) {
    var _item$name, _item$_sceneElement;
    return /*#__PURE__*/React.createElement(FloorMapZoneElement, {
      name: (_item$name = item.name) !== null && _item$name !== void 0 ? _item$name : (_item$_sceneElement = item._sceneElement) === null || _item$_sceneElement === void 0 ? void 0 : _item$_sceneElement.name
    });
  };
  var _iterator = _createForOfIteratorHelper(kindValues),
    _step;
  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var kind = _step.value;
      map[kind] = function (item) {
        var _item$_sceneElement2;
        var binding = (_item$_sceneElement2 = item._sceneElement) === null || _item$_sceneElement2 === void 0 ? void 0 : _item$_sceneElement2.dataBinding;
        var device = (binding === null || binding === void 0 ? void 0 : binding.recordId) != null ? devicesById.get(String(binding.recordId)) : undefined;
        return /*#__PURE__*/React.createElement(TopologyDeviceCard, {
          item: item,
          device: device
        });
      };
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  return map;
}
export function PisellTopology(props) {
  var _engineCtx$engine, _engineCtx$appHelper, _reconciled$dataSourc;
  var className = props.className,
    style = props.style,
    devicesProp = props.devices,
    overviewHudProp = props.overviewHud,
    _props$mode = props.mode,
    propMode = _props$mode === void 0 ? 'read' : _props$mode,
    floorPlanCodeProp = props.floorPlanCode,
    floorPlanCanvasWidth = props.floorPlanCanvasWidth,
    floorPlanCanvasHeight = props.floorPlanCanvasHeight,
    floorPlanName = props.floorPlanName,
    floorPlanSort = props.floorPlanSort,
    floorPlanStatus = props.floorPlanStatus,
    putFloorPlan = props.putFloorPlan,
    onFloorPlanPersisted = props.onFloorPlanPersisted;
  var floorPlanCode = (floorPlanCodeProp === null || floorPlanCodeProp === void 0 ? void 0 : floorPlanCodeProp.trim()) || PISELL_TOPOLOGY_FLOOR_PLAN_CODE;
  var overviewHud = overviewHudProp === false ? false : overviewHudProp === true || overviewHudProp === undefined ? undefined : overviewHudProp;
  var engineCtx = useEngineContext();
  var engineLocale = (engineCtx === null || engineCtx === void 0 || (_engineCtx$engine = engineCtx.engine) === null || _engineCtx$engine === void 0 || (_engineCtx$engine = _engineCtx$engine.props) === null || _engineCtx$engine === void 0 ? void 0 : _engineCtx$engine.locale) || 'zh-CN';
  var engineRequest = engineCtx === null || engineCtx === void 0 || (_engineCtx$appHelper = engineCtx.appHelper) === null || _engineCtx$appHelper === void 0 || (_engineCtx$appHelper = _engineCtx$appHelper.utils) === null || _engineCtx$appHelper === void 0 ? void 0 : _engineCtx$appHelper.request;
  locales.init(topologyLocaleTexts, engineLocale);
  request.setRequest(engineRequest !== null && engineRequest !== void 0 ? engineRequest : PREVIEW_HTTP_CLIENT);
  useEffect(function () {
    if (engineRequest) {
      request.setRequest(engineRequest);
    }
  }, [engineRequest]);

  /** 接口拉到的原始设备数组；外部传 devices 时直接走 props（兼容低代码 mock） */
  var _useState = useState([]),
    _useState2 = _slicedToArray(_useState, 2),
    rawDevices = _useState2[0],
    setRawDevices = _useState2[1];
  /** 设备连接（边）数组，挂载时和 devices 一并请求 */
  var _useState3 = useState([]),
    _useState4 = _slicedToArray(_useState3, 2),
    rawConnections = _useState4[0],
    setRawConnections = _useState4[1];
  /**
   * 设备列表请求是否已结束（成功或失败）。
   * 在 floor-plan 与 devices 都就绪前不把「空 reconcile 结果」灌进 FloorMapLayout，
   * 否则编辑态草稿会先固化成空白画布。
   */
  var _useState5 = useState(function () {
      return Boolean(devicesProp && devicesProp.length > 0);
    }),
    _useState6 = _slicedToArray(_useState5, 2),
    devicesFetchSettled = _useState6[0],
    setDevicesFetchSettled = _useState6[1];
  useEffect(function () {
    if (devicesProp && devicesProp.length > 0) {
      setRawConnections([]);
      setDevicesFetchSettled(true);
      return;
    }
    setDevicesFetchSettled(false);
    var cancelled = false;
    /**
     * 并发拉设备列表 + 连接列表：连接里的 source/target 都是设备 id，
     * 所以只要两个接口都返回，就能把 edges 投到节点上一起渲染。
     */
    Promise.all([fetchTopologyDeviceList(), fetchTopologyDeviceConnectionList()]).then(function (_ref) {
      var _ref2 = _slicedToArray(_ref, 2),
        deviceRes = _ref2[0],
        connectionRes = _ref2[1];
      if (cancelled) return;
      var devices = extractRawDeviceList(deviceRes.response);
      var conns = extractRawDeviceConnectionList(connectionRes.response);
      setRawDevices(devices);
      setRawConnections(conns);
    }).catch(function (error) {
      if (cancelled) return;
      console.error('[PisellTopology] 拉取设备 / 连接失败:', error);
      setRawDevices([]);
      setRawConnections([]);
    }).finally(function () {
      if (!cancelled) setDevicesFetchSettled(true);
    });
    return function () {
      cancelled = true;
    };
  }, [devicesProp]);

  /** 外部 devices（TopologyDeviceRow[]）走兼容路径：把它们当作已经转换好的设备记录 */
  var propRawDevices = useMemo(function () {
    if (!devicesProp || devicesProp.length === 0) return [];
    return devicesProp.map(function (row, index) {
      var _row$id, _row$name, _row$sn, _row$status;
      return {
        id: (_row$id = row.id) !== null && _row$id !== void 0 ? _row$id : "prop-".concat(index),
        type_code: 'unknown',
        name: (_row$name = row.name) !== null && _row$name !== void 0 ? _row$name : null,
        model: row.model ? {
          name: {
            original: row.model
          }
        } : null,
        number: (_row$sn = row.sn) !== null && _row$sn !== void 0 ? _row$sn : null,
        status: (_row$status = row.status) !== null && _row$status !== void 0 ? _row$status : null
      };
    });
  }, [devicesProp]);
  var effectiveRawDevices = propRawDevices.length > 0 ? propRawDevices : rawDevices;

  /** 内部编辑切换：mode='read' 时受画布编辑按钮控制；mode='edit' 时强制编辑 */
  var _useState7 = useState(false),
    _useState8 = _slicedToArray(_useState7, 2),
    mapEditInternal = _useState8[0],
    setMapEditInternal = _useState8[1];
  var effectiveMode = propMode === 'edit' || mapEditInternal ? 'edit' : 'read';
  var forceEditFromProps = propMode === 'edit';

  /**
   * Floor-plan 集成：从远端拉「已保存」的 sceneElements/edges 作为对账基线。
   * 当外部直接传 `devices` 时（低代码预览 / mock）跳过远端，避免覆盖测试数据。
   */
  var enableFloorPlanSync = !devicesProp || devicesProp.length === 0;
  var _useTopologyFloorPlan = useTopologyFloorPlan({
      floorPlanCode: floorPlanCode,
      enabled: enableFloorPlanSync
    }),
    floorPlanRemoteId = _useTopologyFloorPlan.floorPlanRemoteId,
    savedSceneElements = _useTopologyFloorPlan.savedSceneElements,
    savedEdges = _useTopologyFloorPlan.savedEdges,
    floorPlanLoaded = _useTopologyFloorPlan.isLoaded,
    applyLocalSave = _useTopologyFloorPlan.applyLocalSave,
    setRemoteFloorPlanView = _useTopologyFloorPlan.setRemoteFloorPlanView;

  /** floor-plan + 设备列表都就绪后再 reconcile，避免先渲染空白画布 */
  var isViewReady = devicesFetchSettled && (!enableFloorPlanSync || floorPlanLoaded);

  /**
   * 三态对账：rawDevices + rawConnections + savedSceneElements/Edges → 最终 config。
   * 不开启 floor-plan 同步时（外部 devices 模式）走 savedSceneElements=undefined 的
   * 全量 auto-layout 分支，行为与之前一致。
   */
  var reconciled = useMemo(function () {
    if (!isViewReady) return null;
    return reconcileTopologyView({
      rawDevices: effectiveRawDevices,
      rawConnections: rawConnections,
      savedSceneElements: enableFloorPlanSync ? savedSceneElements : undefined,
      savedEdges: enableFloorPlanSync ? savedEdges : undefined
    });
  }, [isViewReady, effectiveRawDevices, rawConnections, enableFloorPlanSync, savedSceneElements, savedEdges]);
  var baseFloorConfig = useMemo(function () {
    var canEditCanvas = effectiveMode === 'edit';
    var core = reconciled === null || reconciled === void 0 ? void 0 : reconciled.config;
    if (!core) {
      return {
        canvases: [{
          id: TOPOLOGY_MAIN_CANVAS_ID,
          name: 'Devices',
          order: 0,
          enabled: true,
          mapLayer: {
            showGrid: false,
            backgroundColor: '#ffffff'
          }
        }],
        canvasUi: {
          canCreate: canEditCanvas,
          canEdit: canEditCanvas
        },
        elementKinds: [],
        sceneElements: [],
        edges: []
      };
    }
    return _objectSpread(_objectSpread({}, core), {}, {
      canvasUi: {
        canCreate: canEditCanvas,
        canEdit: canEditCanvas
      }
    });
  }, [reconciled, effectiveMode]);
  var dataSources = (_reconciled$dataSourc = reconciled === null || reconciled === void 0 ? void 0 : reconciled.dataSources) !== null && _reconciled$dataSourc !== void 0 ? _reconciled$dataSourc : {
    devices: []
  };

  /**
   * 自动持久化：新设备首次落到画布上时，把 reconciled config 写回 floor-plan，
   * 让下一轮反查就能命中已保存基线、不再被识别为「新增」。
   *
   * 防抖 / 防循环：
   * - 仅在 floor-plan 已加载、有 remoteId、确实新增了设备 时触发
   * - 用 ref 记下「正在保存的 reconciled.config」与「上次成功保存的 sceneElements 引用」
   *   避免同一个 reconciled 反复触发
   */
  var inflightSaveRef = useRef(null);
  useEffect(function () {
    var _reconciled$config$sc, _reconciled$config$sc2, _reconciled$config$sc3, _reconciled$config$ed;
    if (!enableFloorPlanSync) return;
    if (!isViewReady || !reconciled) return;
    if (!floorPlanLoaded) return;
    if (floorPlanRemoteId == null) return;
    if (effectiveRawDevices.length === 0) return;
    if (((_reconciled$config$sc = (_reconciled$config$sc2 = reconciled.config.sceneElements) === null || _reconciled$config$sc2 === void 0 ? void 0 : _reconciled$config$sc2.length) !== null && _reconciled$config$sc !== void 0 ? _reconciled$config$sc : 0) === 0) return;
    if (reconciled.addedDeviceIds.length === 0) return;
    /** 用户正在编辑：不抢用户的未提交变更 */
    if (effectiveMode === 'edit') return;
    var token = Symbol('topology-autosave');
    inflightSaveRef.current = token;
    var sceneSnapshot = (_reconciled$config$sc3 = reconciled.config.sceneElements) !== null && _reconciled$config$sc3 !== void 0 ? _reconciled$config$sc3 : [];
    var edgeSnapshot = (_reconciled$config$ed = reconciled.config.edges) !== null && _reconciled$config$ed !== void 0 ? _reconciled$config$ed : [];
    saveViewConfigToShopFloorPlan(floorPlanRemoteId, reconciled.config, {
      canvasWidth: floorPlanCanvasWidth,
      canvasHeight: floorPlanCanvasHeight,
      code: floorPlanCode,
      name: floorPlanName,
      sort: floorPlanSort,
      status: floorPlanStatus,
      putFloorPlan: putFloorPlan != null ? function (planId, body) {
        return putFloorPlan(planId, body);
      } : undefined
    }).then(function () {
      if (inflightSaveRef.current !== token) return;
      applyLocalSave({
        sceneElements: sceneSnapshot,
        edges: edgeSnapshot
      });
      onFloorPlanPersisted === null || onFloorPlanPersisted === void 0 || onFloorPlanPersisted();
    }).catch(function (err) {
      console.warn('[PisellTopology] auto-save floor-plan failed:', err);
    });
  }, [enableFloorPlanSync, isViewReady, floorPlanLoaded, floorPlanRemoteId, reconciled, effectiveRawDevices.length, effectiveMode, floorPlanCode, floorPlanCanvasWidth, floorPlanCanvasHeight, floorPlanName, floorPlanSort, floorPlanStatus, putFloorPlan, onFloorPlanPersisted, applyLocalSave]);
  var devicesById = useMemo(function () {
    var _ref3;
    var list = (_ref3 = dataSources[TOPOLOGY_DEVICES_DATA_SOURCE_KEY]) !== null && _ref3 !== void 0 ? _ref3 : [];
    return new Map(list.map(function (d) {
      return [d.id, d];
    }));
  }, [dataSources]);
  var renderItemByKind = useMemo(function () {
    return buildDeviceRenderItemByKind(TOPOLOGY_DEVICE_KIND_VALUES, devicesById);
  }, [devicesById]);
  var floorMapLayoutRef = useRef(null);

  /**
   * 用户点编辑模式 toolbar 的「保存」时：把当前视图持久化到 floor-plan，
   * 并把保存视图作为新基线写回（保证下一轮 reconcile 不再当作「新增」）。
   */
  var onSaveWithApi = useMemo(function () {
    var persistTargetId = floorPlanRemoteId;
    var canPersist = enableFloorPlanSync && persistTargetId != null && Number.isFinite(persistTargetId) && persistTargetId > 0;
    return wrapFloorMapOnSaveWithRemotePersist({
      canPersist: canPersist,
      persistTargetId: persistTargetId !== null && persistTargetId !== void 0 ? persistTargetId : 0,
      persist: function persist(id, config) {
        return saveViewConfigToShopFloorPlan(id, config, {
          canvasWidth: floorPlanCanvasWidth,
          canvasHeight: floorPlanCanvasHeight,
          code: floorPlanCode,
          name: floorPlanName,
          sort: floorPlanSort,
          status: floorPlanStatus,
          putFloorPlan: putFloorPlan != null ? function (planId, body) {
            return putFloorPlan(planId, body);
          } : undefined
        });
      },
      setRemoteFloorPlanView: setRemoteFloorPlanView,
      onFloorPlanPersisted: onFloorPlanPersisted,
      prevOnSave: props.onSave,
      onPersistError: toastFloorPlanSaveError
    });
  }, [enableFloorPlanSync, floorPlanRemoteId, floorPlanCanvasWidth, floorPlanCanvasHeight, floorPlanCode, floorPlanName, floorPlanSort, floorPlanStatus, putFloorPlan, setRemoteFloorPlanView, onFloorPlanPersisted, props.onSave]);

  /**
   * 编辑态「自动排列」：
   * 用 connection-aware 全量布局（忽略已保存位置）重排所有真实设备，把新版 config
   * 灌入画布草稿（进 undo 栈，可撤销）。**不**直接持久化到 floor-plan，
   * 等用户手动点「完成编辑」时再走原有 `onSaveWithApi` 流程保存。
   */
  var handleAutoArrange = useCallback(function () {
    var _floorMapLayoutRef$cu, _floorMapLayoutRef$cu2;
    if (effectiveRawDevices.length === 0) return;
    var _reconcileTopologyVie = reconcileTopologyView({
        rawDevices: effectiveRawDevices,
        rawConnections: rawConnections
      }),
      config = _reconcileTopologyVie.config;
    /** 保留当前画布的 canvasUi（编辑权限）等运行时配置，仅替换 sceneElements / edges 等几何信息 */
    var next = _objectSpread(_objectSpread(_objectSpread({}, baseFloorConfig), config), {}, {
      canvasUi: baseFloorConfig.canvasUi
    });
    (_floorMapLayoutRef$cu = floorMapLayoutRef.current) === null || _floorMapLayoutRef$cu === void 0 || (_floorMapLayoutRef$cu2 = _floorMapLayoutRef$cu.applySceneSnapshot) === null || _floorMapLayoutRef$cu2 === void 0 || _floorMapLayoutRef$cu2.call(_floorMapLayoutRef$cu, next);
  }, [effectiveRawDevices, rawConnections, baseFloorConfig]);
  return /*#__PURE__*/React.createElement("div", {
    className: "".concat(PREFIX, "-root")
  }, /*#__PURE__*/React.createElement("div", {
    className: "".concat(PREFIX, "-legend-anchor")
  }, /*#__PURE__*/React.createElement(TopologyConnectionLegend, null)), /*#__PURE__*/React.createElement(PisellFloorMapLayout, {
    ref: floorMapLayoutRef,
    className: classNames(PREFIX, className),
    style: _objectSpread({
      width: '100%',
      height: '100%',
      minHeight: 0,
      flex: 1
    }, style),
    items: [],
    renderItem: function renderItem() {
      return null;
    },
    floorMapConfig: baseFloorConfig,
    dataSources: dataSources,
    loading: !isViewReady,
    mode: effectiveMode,
    itemUnit: "pixel",
    enableEdges: true,
    enableHover: false,
    toolbarShowSave: effectiveMode === 'edit',
    onSave: onSaveWithApi,
    renderItemByKind: renderItemByKind,
    floorMapViewportOverlay: overviewHud,
    viewportOverlayPlacement: "top-start",
    controls: {
      showZoom: true,
      showFitBounds: true,
      showReset: true,
      showGridToggle: false,
      horizontalAlign: 'end'
    },
    onExitEdit: forceEditFromProps ? undefined : function () {
      return setMapEditInternal(false);
    },
    viewportDockTrailing: /*#__PURE__*/React.createElement(TopologyFloorMapEditToggle, {
      mapEditInternal: mapEditInternal,
      setMapEditInternal: setMapEditInternal,
      floorMapLayoutRef: floorMapLayoutRef,
      forceEditMode: forceEditFromProps,
      onAutoArrange: enableFloorPlanSync ? handleAutoArrange : undefined
    }),
    pan: {
      enabled: true
    },
    zoom: {
      autoFitOnMount: true,
      min: 0.25,
      max: 2
    }
  }));
}
export var PisellTopologyCore = PisellTopology;