import { BimfaceSDKLoader, BimfaceSDKLoaderConfig, Glodon } from 'bimfacesdkloader'; import eventBus from './eventBus'; import * as echarts from 'echarts'; import * as $ from 'jquery'; import loadVueComponent from './loadVueComponent'; let app, viewer, drawableContainer, clickHandler, extObjMng, videoManager, anchorMng; // 加载模型 const loadModel = (viewToken, domElement, callback) => { const config = new BimfaceSDKLoaderConfig(); config.viewToken = viewToken; BimfaceSDKLoader.load(config).then((viewMetaData) => { if (viewMetaData.viewType == "3DView") { // ======== 判断是否为3D模型 ======== // 获取DOM元素 let webAppConfig = new Glodon.Bimface.Application.WebApplication3DConfig(); webAppConfig.domElement = domElement; // 允许爆炸 webAppConfig.enableExplosion = true; //允许材质替换 webAppConfig.enableReplaceMaterial = true; // 创建WebApplication app = new Glodon.Bimface.Application.WebApplication3D(webAppConfig); // 从WebApplication获取viewer3D对象 viewer = app.getViewer(); // 添加待显示的模型 viewer.loadModel({ // 待加载模型的浏览凭证 viewToken: viewToken, }); viewer.addEventListener(Glodon.Bimface.Viewer.Viewer3DEvent.ViewAdded, () => { let drawableContainerConfig = new Glodon.Bimface.Plugins.Drawable.DrawableContainerConfig(); drawableContainerConfig.viewer = viewer; drawableContainer = new Glodon.Bimface.Plugins.Drawable.DrawableContainer(drawableContainerConfig); extObjMng = new Glodon.Bimface.Plugins.ExternalObject.ExternalObjectManager(viewer); let videoManagerConfig = new Glodon.Bimface.Plugins.Videos.VideoManagerConfig() videoManagerConfig.viewer = viewer; videoManager = new Glodon.Bimface.Plugins.Videos.VideoManager(videoManagerConfig); let anchorMngConfig = new Glodon.Bimface.Plugins.Anchor.AnchorManagerConfig(); anchorMngConfig.viewer = viewer; anchorMng = new Glodon.Bimface.Plugins.Anchor.AnchorManager(anchorMngConfig); if (callback && typeof callback == "function") callback(); }) window.viewer = viewer; } }); } // 恢复全部状态 const resetStatus = () => { if (!viewer) return; floorExploded && viewer.getModel().clearFloorExplosion(); drawableContainer && drawableContainer.clear(); progressAnimation && cancelAnimationFrame(progressAnimation); elevationAnimation && cancelAnimationFrame(elevationAnimation); sectionPlane && sectionPlane.exit(); extObjMng && extObjMng.clear(); videoManager && videoManager.clear(); anchorMng && anchorMng.clear(); viewer.showAllComponents(); viewer.clearAllRooms(); viewer.restoreAllDefault(); viewer.getModel().clearAllBlinkComponents(); viewer.getModel().clearGlowEffect(); viewer.render(); onClick(() => { }); eventBus.trigger('reset'); } // 设置相机视角 const setCameraStatus = (status) => { return new Promise((resolve) => { viewer.setCameraStatus(status, resolve); }); } // 绑定模型点击事件 const onClick = (fn) => { if (clickHandler) { viewer.removeEventListener(Glodon.Bimface.Viewer.Viewer3DEvent.MouseClicked, clickHandler); } clickHandler = fn; viewer.addEventListener(Glodon.Bimface.Viewer.Viewer3DEvent.MouseClicked, clickHandler); } // 添加引线标签 // 引线标签Demo https://bimface.com/developer-jsdemo#830 const addLeadLabel = (config, onClick) => { let leadLabelConfig = new Glodon.Bimface.Plugins.Drawable.LeadLabelConfig(); let leadLabel = new Glodon.Bimface.Plugins.Drawable.LeadLabel({ ...leadLabelConfig, ...config }); onClick && leadLabel.onClick(onClick); drawableContainer.addItem(leadLabel); } // 添加自定义标签 // 自定义标签Demo https://bimface.com/developer-jsdemo#828 const addCustomItem = (config, onClick, callback) => { let customItemConfig = new Glodon.Bimface.Plugins.Drawable.CustomItemConfig(); let customItem = new Glodon.Bimface.Plugins.Drawable.CustomItem({ ...customItemConfig, ...config }); onClick && customItem.onClick(onClick); drawableContainer.addItem(customItem); if (callback && typeof callback == "function") callback(customItem); } // 删除自定义标签通过id const deleteCustomItemById = (id) => { drawableContainer.removeItemById(id); } // 显示自定义标签通过ids const showCustomItemById = (ids) => { drawableContainer.showItemsById(ids); } // 隐藏自定义标签通过ids const hideCustomItemById = (ids) => { drawableContainer.hideItemsById(ids); } // 添加图片标签 const addImage = (config, onClick) => { let imageConfig = new Glodon.Bimface.Plugins.Drawable.ImageConfig(); let image = new Glodon.Bimface.Plugins.Drawable.Image({ ...imageConfig, ...config }); onClick && image.onClick(onClick); drawableContainer.addItem(image); } // 封装自定义标签的容器 const getCustomContainer = () => { const setCss = (dom, css) => { Object.entries(css).forEach(([key, value]) => { dom.style[key] = value; }) } const div = document.createElement('div'); setCss(div, { background: '#fff', borderRadius: '5px', border: '2px solid rgb(31, 147, 255)', position: 'relative', boxShadow: '0 0 10px #333' }); const leadLine = document.createElement('div'); setCss(leadLine, { background: 'rgb(31, 147, 255)', width: '50px', height: '1px', position: 'absolute', top: '20px', left: '-50px', borderTop: '1px solid rgb(31, 147, 255)', borderBottom: '1px solid rgb(31, 147, 255)', }); const leadLine2 = document.createElement('div'); setCss(leadLine2, { background: 'rgb(31, 147, 255)', width: '50px', height: '1px', position: 'absolute', top: '32px', left: '-96px', border: '1px solid rgb(31, 147, 255)', borderRight: 'none', transform: 'rotate(-30deg)', borderRadius: '5px 0 0 5px' }); div.appendChild(leadLine); div.appendChild(leadLine2); return div; } // 隐藏外墙 const hideOutWall = () => { viewer.getModel().hideComponentsByObjectData([{ categoryId: '-2000170' }, { categoryId: '-2000171' }, { categoryId: '-2000151' }, { categoryId: '-2000014' }, { familyType: 'Exterior - Insulation on Masonry' }, { familyType: 'Generic - 200mm' }]); } //设置构建透明根据构建id const setTransparentComponentsById = (ids) => { viewer.transparentComponentsById(ids); viewer.render(); } //取消构建设置半透明状态通过构建id const setOpaqueComponentsById = (ids) => { viewer.transparentComponentsById(ids); viewer.render(); } // 发光效果 // 发光效果Demo https://bimface.com/developer-jsdemo#1114 const glowSelection = () => { resetStatus(); viewer.enableGlowEffect(true); onClick((data) => { viewer.getModel().clearGlowEffect(); if (viewer.getModel().getSelectedComponents().length > 0) { viewer.getModel().setGlowEffectById([data.objectId], { type: "outline", color: new Glodon.Web.Graphics.Color(255, 255, 190, 1), intensity: 0.3, spread: 4 }); } viewer.render(); }) } // 闪烁效果 // 闪烁效果Demo https://bimface.com/developer-jsdemo#993 const blinkSelection = () => { resetStatus(); viewer.enableBlinkComponents(true); onClick((data) => { viewer.getModel().clearAllBlinkComponents(); if (viewer.getModel().getSelectedComponents().length > 0) { viewer.getModel().addBlinkComponentsById([data.objectId]); } viewer.render(); }) } // 锚点效果 // 锚点效果Demo https://bimface.com/developer-jsdemo#1117 const anchorSelection = () => { resetStatus(); onClick((data) => { anchorMng.clear(); if (viewer.getModel().getSelectedComponents().length > 0) { let prismPointConfig = new Glodon.Bimface.Plugins.Anchor.PrismPointConfig(); prismPointConfig.position = data.worldPosition; const boundingBox = viewer.getModel().getBoundingBoxById("140056"); if (boundingBox) { prismPointConfig.position.z = boundingBox.max.z; } prismPointConfig.duration = 1500; prismPointConfig.size = 3000; const prismPoint = new Glodon.Bimface.Plugins.Anchor.PrismPoint(prismPointConfig); anchorMng.addItem(prismPoint); } }) } // 楼层爆炸 // 楼层爆炸Demo https://bimface.com/developer-jsdemo#1012 let floorList; let floorExploded = false; const floorExplosion = ({ direction, list, ratio }) => { floorExploded = true; hideOutWall(); const execute = () => { viewer.getModel().setFloorExplosion(ratio || 3, list || floorList, direction || { x: 0, y: 0, z: 1 }); viewer.render(); } if (!floorList) { viewer.getFloors(function (data) { if (!data) { console.log('No floor data.'); return; } floorList = data.map(item => item.id); execute(); }); } else { execute(); } } // 通过楼层爆炸展示对应楼层内景 const showFloor = async () => { resetStatus(); viewer.getModel().hideComponentsByObjectData([{ familyType: 'Furred Ceiling' }, { familyType: '600 x 600mm Grid' }]) floorExplosion({ list: ['694', '136342'], ratio: 5 }); await setCameraStatus({ "name": "persp", "position": { "x": -18581.90102579501, "y": -43385.96948291367, "z": 48259.49574346754 }, "target": { "x": 183683.96553301584, "y": 184022.91100671078, "z": -138602.42728235415 }, "up": { "x": 0.34773591007493626, "y": 0.39095752305370535, "z": 0.8521924383682755 }, "near": 30.987299999188124, "far": 225023.77345792603, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); } // 楼层斜向爆炸 展示多个楼层内景 const showFloorBias = async () => { resetStatus(); viewer.getModel().hideComponentsByObjectData([{ familyType: 'Furred Ceiling' }, { familyType: '600 x 600mm Grid' }]) floorExplosion({ direction: { x: -1, y: 1, z: 1 }, ratio: 5 }); await setCameraStatus({ "name": "persp", "position": { "x": 11240.411621892461, "y": -102529.34741011732, "z": 65558.92527280154 }, "target": { "x": 43243.82648777891, "y": 220893.25417478292, "z": -82485.86591627813 }, "up": { "x": 0.04082046922112373, "y": 0.41252263958919705, "z": 0.9100322857563509 }, "near": 25552.128419500546, "far": 204849.5409590415, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); addLeadLabel({ worldPosition: { x: 32990.244621434686, y: 7855.8522796793095, z: 33122.67578124999 }, text: '3F: 研发中心' }); addLeadLabel({ worldPosition: { x: 43951.33038984035, y: -3319.9946107938667, z: 17299.43750000001 }, text: '2F: 商务中心' }); } // 剖切模拟施工进度 // 剖切面Demo https://bimface.com/developer-jsdemo#1108 let sectionPlane = null; let originPt = { x: 0, y: 0, z: 7600 }; let planeDirection = { x: 0, y: 0, z: 1 }; let sectionPlaneOffset = 500; let progressAnimation = null; const createSectionPlane = () => { if (sectionPlane) { return; } let sectionPlaneConfig = new Glodon.Bimface.Plugins.Section.SectionPlaneConfig(); sectionPlaneConfig.viewer = viewer; sectionPlane = new Glodon.Bimface.Plugins.Section.SectionPlane(sectionPlaneConfig); sectionPlane.setPlane(Glodon.Bimface.Plugins.Section.SectionPlanePlane.Z); sectionPlane.setDirection(Glodon.Bimface.Plugins.Section.SectionPlaneDirection.Forward); sectionPlane.setPositionByPlane(originPt, planeDirection, sectionPlaneOffset); sectionPlane.setObjectsByObjectData([ { categoryId: "-2000011", family: "基本墙" }, { categoryId: "-2001330" } ]); sectionPlane.hidePlane(); } const progressMonitor = () => { resetStatus(); viewer.getModel().hideComponentsByObjectData([ { levelName: "Roof" }, { levelName: "Parapet" }, { levelName: "03 - Floor", categoryId: "-2000038" }, { categoryId: "-2000023" } ]); setCameraStatus({ "name": "persp", "position": { "x": -30219.946765163415, "y": -45491.65416486451, "z": 29660.465140231066 }, "target": { "x": 207832.38340026487, "y": 170233.69288006236, "z": -126343.72635548069 }, "up": { "x": 0.3236896665312058, "y": 0.2933266544203183, "z": 0.8995468156730366 }, "fov": 45, "zoom": 1, "version": 1, "coordinateSystem": "world" }); sectionPlane || createSectionPlane(); progressAnimation && cancelAnimationFrame(progressAnimation); const animate = () => { progressAnimation = requestAnimationFrame(animate); sectionPlaneOffset += 100; if (sectionPlaneOffset > 3500) { sectionPlaneOffset = 500; } sectionPlane.setPositionByPlane(originPt, planeDirection, sectionPlaneOffset); viewer.render(); } animate(); } // 获取房间列表 let roomList; const getRoomList = async () => { return new Promise((resolve) => { if (roomList) { resolve(roomList); } else { viewer.getModel().getAreas((data) => { const { rooms } = data[2]; roomList = rooms; resolve(roomList); }) } }) } // 显示房间 const showRooms = async () => { resetStatus(); showFloor(); const rooms = await getRoomList(); rooms.forEach((roomData) => { const { boundary, id } = roomData; viewer.createRoom(boundary, 2000, id); }) viewer.render(); } // 通过不同颜色显示房间温度 // 创建房间 https://bimface.com/developer-jsdemo#1032 const showRoomTemperature = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const color0 = new Glodon.Web.Graphics.Color(0, 255, 0, 0.2); const color1 = new Glodon.Web.Graphics.Color(255, 255, 0, 0.2); const color2 = new Glodon.Web.Graphics.Color(255, 0, 0, 0.2); const colorList = [color0, color1, color2]; rooms.forEach((roomData) => { const { boundary, id } = roomData; const color = colorList[Math.floor(Math.random() * 3)]; viewer.createRoom(boundary, 2000, id, color, color); }) viewer.render(); onClick((data) => { drawableContainer && drawableContainer.clear(); const { worldPosition } = data; addLeadLabel({ worldPosition, text: '房间温度:26 ℃', }); }) } // 显示房间人流量 const showRoomPerson = async () => { await showRoomTemperature(); onClick((data) => { drawableContainer && drawableContainer.clear(); const { worldPosition } = data; addLeadLabel({ worldPosition, text: '当前人数:12', }); }) } // 通过不同颜色表示会议室预定情况 const showMeetingRoom = async () => { const meetingRoomIndex = [1, 4, 11, 19]; resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const color0 = new Glodon.Web.Graphics.Color(0, 255, 0, 0.2); const color2 = new Glodon.Web.Graphics.Color(255, 0, 0, 0.2); const colorList = [color0, color2]; meetingRoomIndex.forEach((index) => { const roomData = rooms[index]; const { boundary, id } = roomData; const color = colorList[Math.floor(Math.random() * 2)]; viewer.createRoom(boundary, 2000, id, color, color); }) viewer.render(); onClick((data) => { drawableContainer && drawableContainer.clear(); const { worldPosition } = data; addLeadLabel({ worldPosition, text: '302会议室\r\n\r\n预定人: 张三\r\n开始时间: 14:30:00\r\n结束时间: 15:30:00', height: 100 }); }) } // 展示耗电图表 (基于echarts) const showRoomElecChart = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const roomData = rooms[11]; const { boundary, id } = roomData; viewer.createRoom(boundary, 2000, id); viewer.render(); const div = getCustomContainer(); const chartDiv = document.createElement('div'); chartDiv.style.width = '600px'; chartDiv.style.height = '400px'; div.appendChild(chartDiv); addCustomItem({ worldPosition: { x: -6825.774153559483, y: 12198.622346237365, z: 1610.6135227595976 }, content: div, width: 600, height: 400, offsetX: 350, opacity: 1, }); const myChart = echarts.init(chartDiv); // 指定图表的配置项和数据 const option = { title: { text: '用电量分布', }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } }, toolbox: { show: true, feature: { saveAsImage: {} } }, xAxis: { type: 'category', boundaryGap: false, // prettier-ignore data: ['00:00', '01:15', '02:30', '03:45', '05:00', '06:15', '07:30', '08:45', '10:00', '11:15', '12:30', '13:45', '15:00', '16:15', '17:30', '18:45', '20:00', '21:15', '22:30', '23:45'] }, yAxis: { type: 'value', axisLabel: { formatter: '{value} W' }, axisPointer: { snap: true } }, visualMap: { show: false, dimension: 0, pieces: [ { lte: 6, color: 'green' }, { gt: 6, lte: 8, color: 'red' }, { gt: 8, lte: 14, color: 'green' }, { gt: 14, lte: 17, color: 'red' }, { gt: 17, color: 'green' } ] }, series: [ { name: 'Electricity', type: 'line', smooth: true, // prettier-ignore data: [300, 280, 250, 260, 270, 300, 550, 500, 400, 390, 380, 390, 400, 500, 600, 750, 800, 700, 600, 400], markArea: { itemStyle: { color: 'rgba(255, 173, 177, 0.4)' }, data: [ [ { name: 'Morning Peak', xAxis: '07:30' }, { xAxis: '10:00' } ], [ { name: 'Evening Peak', xAxis: '17:30' }, { xAxis: '21:15' } ] ] } } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); } // 房间详情,可在自定义标签中加入iframe或自行封装内容进行展示 const showRoomWebsite = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const roomData = rooms[11]; const { boundary, id } = roomData; viewer.createRoom(boundary, 2000, id); viewer.render(); const container = getCustomContainer(); container.style.height = '400px'; const frame = document.createElement('iframe'); frame.src = 'https://bimface.com/'; frame.width = 1190; frame.height = 800; frame.frameBorder = 0; frame.style.transform = 'scale(0.5) translate(-50%, -50%)'; container.appendChild(frame); addCustomItem({ worldPosition: { x: -3160.922652317966, y: -21960.96903375262, z: 29064.386718749993 }, content: container, width: 600, height: 400, offsetX: 350, opacity: 1, }); } // 将Vue Component插入自定义标签 const showSthFromVueComponent = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); const rooms = await getRoomList(); const roomData = rooms[11]; const { boundary, id } = roomData; viewer.createRoom(boundary, 2000, id); viewer.render(); const container = getCustomContainer(); const div = document.createElement('div'); container.appendChild(div); addCustomItem({ worldPosition: { x: -3160.922652317966, y: -21960.96903375262, z: 29064.386718749993 }, content: container, width: 600, height: 400, offsetX: 350, opacity: 1, }); loadVueComponent(div); } // 通过颜色覆盖显示各楼层用能情况 const showElecArea = async () => { resetStatus(); hideOutWall(); await setCameraStatus({ "name": "persp", "position": { "x": 64840.35214354617, "y": -68511.2525964906, "z": 18326.863098710433 }, "target": { "x": -88901.31809446408, "y": 247356.65487049, "z": -45974.16210384361 }, "up": { "x": -0.07879790601614875, "y": 0.16188945742798264, "z": 0.9836578132567969 }, "near": 30.987299996758253, "far": 205860.68880166902, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.7750257997936016, "coordinateSystem": "world" }); viewer.getModel().overrideComponentsColorByObjectData([{ levelName: '01 - Entry Level' }], new Glodon.Web.Graphics.Color(255, 80, 80, 0.3)); viewer.getModel().overrideComponentsColorByObjectData([{ levelName: '02 - Floor' }], new Glodon.Web.Graphics.Color(255, 255, 80, 0.4)); viewer.getModel().overrideComponentsColorByObjectData([{ levelName: '03 - Floor' }, { levelName: 'Roof' }], new Glodon.Web.Graphics.Color(80, 255, 80, 0.4)); viewer.getModel().overrideComponentsColorByObjectData([{ categoryId: '-2001340' }, { categoryId: '-2001340' }, { categoryId: '-2001360' }], new Glodon.Web.Graphics.Color(150, 150, 150, 1)); viewer.getModel().hideComponentsByObjectData([{ categoryId: '-2001360' }]); addLeadLabel({ worldPosition: { x: 54545.6439964876, y: -21582.57905456956, z: 2000 }, text: '1F能耗:12000kwh', }); addLeadLabel({ worldPosition: { x: 54545.6439964876, y: -21582.57905456956, z: 6000 }, text: '2F能耗:8000kwh', }); addLeadLabel({ worldPosition: { x: 54545.6439964876, y: -21582.57905456956, z: 10000 }, text: '3F能耗:5000kwh', }); } let elevationAnimation; const elevationPositionList = [ { x: 3017.7083642874286, y: -17867.4624208377, z: 0, direction: 1 }, { x: 51137.538027890434, y: -17857.7162947923, z: 7000, direction: -1 } ]; const getElevationBoundary = (position) => { const pt0 = [position.x - 1000, position.y - 1000, position.z]; const pt1 = [position.x - 1000, position.y + 1000, position.z]; const pt2 = [position.x + 1000, position.y + 1000, position.z]; const pt3 = [position.x + 1000, position.y - 1000, position.z]; return viewer.createBoundary([pt0, pt1, pt2, pt3, pt0]); }; // 电梯运行模拟,基于房间 const showElevation = async () => { resetStatus(); await setCameraStatus({ "name": "persp", "position": { "x": 3575.1548085656814, "y": -73273.35356177477, "z": 14980.742555679171 }, "target": { "x": 104565.36505385478, "y": 266903.3467217405, "z": -25323.69883819677 }, "up": { "x": 0.03211961944006518, "y": 0.10818843515523709, "z": 0.993611389098216 }, "near": 30.987299996241962, "far": 197123.90516035885, "zoom": 1, "version": 1, "fov": 45, "aspect": 1.8838992332968236, "coordinateSystem": "world" }); viewer.getModel().overrideComponentsColorByObjectData([{ levelName: '01 - Entry Level' }, { levelName: '02 - Floor' }, { levelName: '03 - Floor' }, { levelName: 'Roof' }, { levelName: 'Parapet' }], new Glodon.Web.Graphics.Color(255, 255, 255, 0.4)); viewer.getModel().restoreComponentsColorByObjectData([{ categoryId: '-2001340' }, { categoryId: '-2001340' }, { categoryId: '-2001360' }]); const animate = () => { viewer.clearAllRooms(); viewer.drawableContainer.clear(); elevationPositionList.forEach((elevationPosition, index) => { elevationPosition.z = elevationPosition.z + 50 * elevationPosition.direction; if (elevationPosition.z < 0) { elevationPosition.z = 0; elevationPosition.direction = 1; } if (elevationPosition.z > 9000) { elevationPosition.z = 9000; elevationPosition.direction = -1; } viewer.createRoom(getElevationBoundary(elevationPosition), 3000, `elevation_${index}`); addLeadLabel({ worldPosition: { ...elevationPosition, z: elevationPosition.z + 3000 }, text: `电梯编号:ELEV_${index + 1}\r\n当前楼层:${Math.floor(elevationPosition.z / 3000) + 1}`, height: 50, id: `elevation_${index}` }); viewer.render(); }); elevationAnimation = requestAnimationFrame(animate); } animate(); } // 视频监控展示 const cameraList = [ { x: -5726.9008039386945, y: -19753.945826512583, z: 30000 }, { x: -6095.6074387552935, y: -3808.760009765628, z: 30000 }, { x: 15496.400137445688, y: -19546.919708011246, z: 30000 }, { x: 15496.400137445688, y: -19546.919708011246, z: 30000 }, { x: 708.6683505627907, y: -7404.043737439564, z: 30000 } ] const showCamera = async () => { resetStatus(); await showFloor(); drawableContainer && drawableContainer.clear(); cameraList.forEach((worldPosition, index) => { addImage({ worldPosition, id: `Camera_${index}`, src: '/camera.png', }, () => { if (drawableContainer.getItemById('cameraDetail')) { drawableContainer.removeItemById('cameraDetail'); } const container = getCustomContainer(); container.style.width = '500px'; const div = document.createElement('div'); container.appendChild(div); div.style.paddingTop = '5px'; div.style.background = '#ffffff'; div.innerHTML = `
监控编号:Camera_${index}