Fix BIM version model loading

This commit is contained in:
CODEX 2026-06-24 19:03:28 +03:00
parent 31bb673b44
commit bc8f70da9c
2 changed files with 43 additions and 6 deletions

View File

@ -319,9 +319,11 @@ let modelVersionHistoryLoading = false;
let modelVersionUploading = false;
let versionHistoryModal = null;
let loadModelAsyncRef = null;
let versionModelCounter = 0;
let emptyWheelNavigationRestoreTimer = null;
let lastSurfaceDollyFactor = null;
let lastSurfaceDollyFactorAt = 0;
const MODEL_LOAD_TIMEOUT_MS = 120000;
const GUEST_TOOLBAR_ACTIONS = new Set(["measure", "section", "projection"]);
const memoryStore = new Map(); // url -> ArrayBuffer
const blobUrls = [];
@ -4700,6 +4702,13 @@ const uploadBuffer = async (bytes, filename, options = {}) => {
const getVersionKey = (version) => version?.versionId || `version-${version?.version || "unknown"}`;
const makeVersionModelId = (version) => {
versionModelCounter += 1;
const rawKey = version?.versionId || version?.version || version?.originalFilename || versionModelCounter;
const safeKey = String(rawKey).replace(/[^a-z0-9_-]+/gi, "-").replace(/^-+|-+$/g, "") || "version";
return `model-version-${safeKey}-${versionModelCounter}`;
};
const getModelVersionIdentity = (entry = getPrimaryModelEntry()) => {
const meta = entry?.meta || {};
const direct = {
@ -4896,13 +4905,18 @@ const openModelVersion = async (version) => {
if (settings?.viewerSettings) {
meta.viewerSettings = settings.viewerSettings;
}
const previousModelId = previousEntry?.model?.id || null;
const nextModelId = makeVersionModelId(version);
if (previousModelId && transformStore[previousModelId]) {
transformStore[nextModelId] = safeClone(transformStore[previousModelId]);
}
await loadModelAsyncRef({
type: viewerType,
url: viewerSrc,
name: version.originalFilename || previousEntry?.name || "model",
replace: true,
preserveMeta: true,
id: previousEntry?.model?.id || "model",
id: nextModelId,
meta,
});
modelVersionHistory = {
@ -6093,6 +6107,7 @@ const initViewer = async () => {
isMemory,
name,
replace,
requestedId: forcedId || null,
url,
});
const xktDataSource = inferredType === "xkt"
@ -6112,7 +6127,7 @@ const initViewer = async () => {
dataSource: xktDataSource || gltfDataSource || lasDataSource || stlDataSource || undefined,
});
const id = forcedId || (replace ? "model" : `model-${++modelCounter}`);
const requestedId = forcedId || (replace ? "model" : `model-${++modelCounter}`);
let srcToLoad = url;
if (inferredType === "obj" && typeof url === "string" && url.startsWith("memory:") && memoryStore.has(url)) {
const blobUrl = URL.createObjectURL(new Blob([memoryStore.get(url)], { type: "text/plain" }));
@ -6120,7 +6135,7 @@ const initViewer = async () => {
srcToLoad = blobUrl;
}
const loadOpts = {
id,
id: requestedId,
src: srcToLoad,
edges: edges ?? (inferredType === "gltf" || inferredType === "las" ? false : toggleEdges.checked),
};
@ -6129,12 +6144,17 @@ const initViewer = async () => {
if (inferredType === "stl") loadOpts.smoothNormals = true;
const currentModel = currentLoader.load(loadOpts);
const id = currentModel?.id || requestedId;
if (id !== requestedId && transformStore[requestedId] && !transformStore[id]) {
transformStore[id] = safeClone(transformStore[requestedId]);
}
sceneModels[id] = currentModel;
modelTypes[id] = inferredType;
currentModel.on("loaded", () => {
reportViewerEvent("model-loaded", {
id,
requestedId,
inferredType,
name,
objectCount: Object.keys(viewer.scene.objects || {}).length,
@ -6180,6 +6200,7 @@ const initViewer = async () => {
currentModel.on("error", (err) => {
reportViewerEvent("model-error", {
id,
requestedId,
inferredType,
name,
error: err?.message || String(err),
@ -6225,8 +6246,24 @@ const initViewer = async () => {
reject(new Error("Не удалось инициировать загрузку модели"));
return;
}
model.on("loaded", () => resolve(model));
model.on("error", (err) => reject(new Error(err?.message || err)));
let settled = false;
let timer = null;
const settle = (handler, value) => {
if (settled) return;
settled = true;
if (timer) window.clearTimeout(timer);
handler(value);
};
model.on("loaded", () => settle(resolve, model));
model.on("error", (err) => settle(reject, new Error(err?.message || err)));
if (!settled) {
timer = window.setTimeout(() => {
setLoading(false);
updateNavCubeVisibility();
updatePanelsVisibility();
settle(reject, new Error("Загрузка модели заняла слишком много времени"));
}, MODEL_LOAD_TIMEOUT_MS);
}
});
loadModelAsyncRef = loadModelAsync;

View File

@ -697,6 +697,6 @@
<input id="fileInput" class="hidden" type="file"
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
<script type="module" src="/dcViewer.js?v=58"></script>
<script type="module" src="/dcViewer.js?v=59"></script>
</body>
</html>