$(function () { $(".dropdown-menu.dropdown-select-menu").each((index, value) => { setDropdownItem(value); }); }); /** * fn 定義 | 手動初始化 Bootstrap dropdown select */ $.fn.droSetItem = function () { setDropdownItem(this); return this; }; /** * fn 定義 | 輸出含原元素 html */ $.fn.outerHtml = function () { return $(this).prop("outerHTML"); }; /** * fn 定義 | Loading 操作 * @param {any} type - close / start / exceed , exceed => 繼續執行並可切換文字 * @param {any} text - 右下角 Alert 文字 */ $.fn.Loading = function (type = "close", text) { let ele = this; let aleObj = $(this)[0]._aleObj; let showStatus = $(ele).data("loading-show-status"); function closeLoading() { $(ele).data("loading-show-status", "close"); $("body").css("overflow", "auto"); $(aleObj.ele).YTAlert().hide(); $(ele).animate({ opacity: 0 }, 300, () => { if ($(ele).data("loading-show-status") == "close") { $(ele).hide(); } }); } function showLoading() { $(ele).data("loading-show-status", "show"); $("body").css("overflow", "hidden"); let aleObj = YT.Alert.Tip(text || "讀取中,請稍後", "show"); $(ele)[0]._aleObj = aleObj; $(ele).show(); $(ele).animate({ opacity: 1 }, 300); $(aleObj.ele).YTAlert().text(text); } if (type == "close") { closeLoading(); } else if (type == "exceed") { $(aleObj.ele).YTAlert().text(text); } else if (type == "start") { showLoading(); } return $(this); }; $.fn.YTAlert = function () { let th = { element: this }; th.hide = function (delay = 0) { let obj = this; setTimeout(function () { $(obj.element).fadeOut(300); alertIdArray.splice( $.inArray($(obj.element).prop("id"), alertIdArray), 1 ); setTimeout(function () { $(obj.element).remove(); }, 1000); }, delay); }; th.text = function (text) { let obj = this; let id = $(obj.element).prop("id").split("tip-alert-")[1]; $(`#alert-text-${id}`).text(text); }; return th; }; /** * 設置 bootstrap dropdown 為下拉選單 * @param {any} menuEle - .dropdown-menu element */ function setDropdownItem(menuEle) { if ($(menuEle).find(".dropdown-item.active").length == 0) { $(menuEle).find(".dropdown-item").first().addClass("active"); } let actText = $(menuEle).find(".dropdown-item.active").first().text(); let actEleId = $(menuEle).prop("id"); $(`.dropdown-toggle[data-target=${actEleId}]`).text(actText); /*actChaCallback($(menuEle).find(".dropdown-item.active"))*/ $(menuEle).trigger("active:change", $(menuEle).find(".dropdown-item.active")); //點選選項 add active class onEvent( "click", ".dropdown-menu.dropdown-select-menu .dropdown-item", function () { $(this) .parent(".dropdown-menu.dropdown-select-menu") .find(".dropdown-item") .removeClass("active"); $(this).addClass("active"); setDropdownItem($(this).parent(".dropdown-menu.dropdown-select-menu")); } ); } /** * 預設設備圖像 * @param {any} obj */ function defDev(obj) { let defSrc = "img/defdev.png"; obj.src = defSrc; } /** * jquery datatable - ajax send data reset * @param {any} table * @param {any} sendData */ function dtAjaxResetSendData(table, sendData) { table.context[0].ajax.data = function (d) { d = sendData; return JSON.stringify(d); }; } /** * element 建造 * @param {any} text * @param {any} id * @param {any} name * @param {any} cls * @param {any} data * @param {any} attr */ function eleBuild( text = null, id = null, name = null, cls = [], data = {}, attr = {} ) { (cls = cls ?? []), (data = data ?? {}), (attr = attr ?? {}); id = id ? `id="${id}"` : ""; name = name ? `name="${name}"` : ""; cls = cls.length != 0 ? `class="${cls.join(" ")}"` : ""; data = data.length != 0 ? `${Object.keys(data) .map((x) => `data-${x}="${data[x]}"`) .join(" ")}` : ""; attr = attr ? `${Object.keys(attr) .map((x) => `${x}="${attr[x]}"`) .join(" ")}` : ""; let attrArr = [], attrText = ""; attrArr = [id, name, cls, data, attr]; attrText = attrArr.filter((x) => x != "").join(" "); text = text === null ? "" : text; return { attrText: attrText, text: text }; } function creEle( ele, text = null, id = null, name = null, cls = [], data = {}, attr = {} ) { let comp = eleBuild(text, id, name, cls, data, attr); return $(`<${ele} ${comp.attrText}>${comp.text}`); } function creDiv( cls = [], attr = {}, id = null, name = null, data = {}, text = null ) { return creEle("div", text, id, name, cls, data, attr); } function creBtn( text = null, id = null, name = null, cls = [], data = {}, attr = {} ) { return creEle("button", text, id, name, cls, data, attr); } function creBtnHtml( text = null, id = null, name = null, cls = [], data = {}, attr = {} ) { return creEle("button", text, id, name, cls, data, attr).prop("outerHTML"); } function creSelect( id = null, cls = [], name = null, data = {}, attr = {}, text = null ) { return creEle("select", text, id, name, cls, data, attr); } function creOption( text = null, value = null, data = {}, attr = {}, cls = [], name = null, id = null ) { value != null ? (attr.value = value) : attr; return creEle("option", text, id, name, cls, data, attr); } function creImg( ele, text = null, id = null, name = null, cls = [], data = {}, attr = {} ) { let comp = eleBuild(text, id, name, cls, data, attr); return $(`<${ele} ${comp.attrText}>${comp.text}`); } function creI( cls = [], data = {}, attr = {}, id = null, name = null, text = null ) { return creEle("i", text, id, name, cls, data, attr); } function creA( text = null, attr = {}, cls = [], id = null, data = {}, name = null ) { return creEle("a", text, id, name, cls, data, attr); } function creSpan( text = null, cls = [], id = null, attr = {}, data = {}, name = null ) { return creEle("span", text, id, name, cls, data, attr); } /** * 根據該棟建築底下的'所有'電梯執行緒物件 * */ class ElevatorHandler { constructor(ele, option = {}) { this.ele = ele; this.eleId = ""; this.eleWra = $("
"); this.speed = 0.3; this.movStatus = {}; // {id:elevator01,value:0} 0=no 1=up 2=down this.floorHeight = typeof option.fHeight == "undefined" ? 60 : option.fHeight; this.floorWidth = typeof option.fWidth == "undefined" ? 45 : option.fWidth; this.floors = typeof option.floors == "undefined" ? [{}] : option.floors; this.elevators = typeof option.elevators == "undefined" ? [{}] : option.elevators; // {id:elevator01} this.curElevFloor = typeof option.curElevFloor == "undefined" ? {} : option.curElevFloor; this.setTimeout = null; this.init(); } // 所有電梯初始化 init = function () { this.setTabWra(); this.setTabFloor(); // 若已有每個設備的所在樓層,則預設到該樓層位置 if (Object.keys(this.curElevFloor).length != 0) { $.each(Object.keys(this.curElevFloor), (idx, elevKey) => { this.setElevFloor(elevKey, this.curElevFloor[elevKey]); }); } }; // 設置 wrapper setTabWra = function () { let id = $(this.ele).prop("id"); this.eleId = id; if ($(this.ele).parent(".elevator-table-wrapper").length != 0) { $(this.ele).unwrap(".elevator-table-wrapper"); } let wrapper = creDiv(["elevator-table-wrapper"], null, `${id}_wrapper`); $(this.ele).wrap(wrapper); this.eleWra = wrapper; }; // 設置 table 樓層 setTabFloor = function () { let _w = this.floorWidth, _h = this.floorHeight; let thead = creEle("thead"), tbody = creEle("tbody"); let _floors = this.floors, _ele = this.ele, _elevators = this.elevators; //樓層從小到大 _floors = _floors .oSort("sort") .reverse() .map((x) => x.name); let theadTr = creEle("tr"); for (let e = 1; e <= _elevators.length + 2; e++) { let th = creEle("th"); th.css({ width: `${_w}px`, height: `${_h}px`, position: "relative" }); if (e != 1 && e != _elevators.length + 2) { let elevId = _elevators[e - 2]?.id; // 電梯方框 let span = creEle("span", null, "elevator-item-" + elevId, null, [ "elevator-item", ]); let spanUp = creEle("span", null, null, null, ["elevator-item-toup"]); let spanDown = creEle("span", null, null, null, [ "elevator-item-todown", ]); span.css({ width: `${_w - 3}px`, height: `${_h - 3}px`, top: `1.5px`, left: "1.5px", transition: `transform ${1 / this.speed }s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`, }); spanUp.css({ width: `${_w - 3}px`, height: `${(_h - 3) / 2}px`, top: `1.5px`, left: "1.5px", transition: `transform ${1 / this.speed }s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`, }); spanDown.css({ width: `${_w - 3}px`, height: `${(_h - 3) / 2}px`, top: `1.5px`, left: "1.5px", transition: `transform ${1 / this.speed }s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`, top: `${1.5 + (_h - 3) / 2}px`, }); th.append(spanUp); th.append(span); th.append(spanDown); } theadTr.append(th); } thead.css("position", "absolute"); thead.append(theadTr); //樓層表格建置 tbody for (let f = 1; f <= _floors.length; f++) { let tr = creEle("tr"); for (let e = 1; e <= _elevators.length + 2; e++) { let td = creEle("td"); td.css({ width: `${_w}px`, height: `${_h}px` }); if (e == 1) { td.addClass("t-black"); td.text(_floors[f - 1]); } else if (e == _elevators.length + 2) { } else { let div = creDiv([ "d-flex", "justify-content-center", "align-items-end", "h-100", ]); div.append(``); td.append(div); } tr.append(td); } tbody.append(tr); } $(_ele).append(thead); $(_ele).append(tbody); //表格外圍無框線 $(_ele) .find("tbody tr") .each((index, tr) => { $(tr).find("td:eq(0)").css("border-left", "0"); $(tr).find("td:eq(-1)").css("border-right", "0"); if (index == 0) { $(tr) .find("td") .each((index, td) => { $(td).css("border-top", "0"); }); } else if (index == $("#floorTable tbody tr").length - 1) { $(tr) .find("td") .each((index, td) => { $(td).css("border-bottom", "0"); }); } }); }; // 設置某個電梯到某個樓層 setElevFloor = function (elevId, floId) { let curFloId = this.curElevFloor[elevId]; let curSort = this.floors .filter((x) => x.id == curFloId) .map((x) => x.sort)[0]; let tarSort = this.floors .filter((x) => x.id == floId) .map((x) => x.sort)[0]; let gapFloor = tarSort - curSort; let cssEle = [ $(`#elevator-item-${elevId}`)[0], $(`#elevator-item-${elevId}`).prev("span.elevator-item-toup")[0], $(`#elevator-item-${elevId}`).next("span.elevator-item-todown")[0], ]; if (this.movStatus[elevId] != 0) { $(cssEle).css( "transition", `transform ${(1 / this.speed) * Math.abs(gapFloor) }s cubic-bezier(0, 0, 0.62, 1) 0s` ); } clearTimeout(this.setTimeout); this.setTimeout = setTimeout(() => { $(cssEle).css( "transition", `transform ${(1 / this.speed) * Math.abs(gapFloor) }s cubic-bezier(0.43, 0.05, 0.62, 1) 0s` ); this.setEleUpDownStyle(elevId); }, (1 / this.speed) * Math.abs(gapFloor) * 1000); this.setEleUpDownStyle(elevId); this.curElevFloor[elevId] = floId; $(cssEle).css( "transition", `transform ${(1 / this.speed) * Math.abs(gapFloor) }s cubic-bezier(0.43, 0.05, 0.62, 1) 0s` ); $(cssEle).css( "transform", `translateY(${this.floorHeight * (this.floors.length - tarSort)}px)` ); }; // 設定現在電梯狀態 (往上/往下/停止) setEleMovStatus = function (elevId, status) { this.movStatus[elevId] = status; }; // 電梯方框 往上或往下閃爍 setEleUpDownStyle = function (elevId) { if (this.movStatus[elevId] == 1) { $(`#elevator-item-${elevId}`) .next("span.elevator-item-todown") .removeClass("light-flash-c-bd"); $(`#elevator-item-${elevId}`) .prev("span.elevator-item-toup") .addClass("light-flash-c-bd") .css("--flash-color-1", "#44ea8e") .css("--flash-color-2", "rgba(255,255,255,0)"); } else if (this.movStatus[elevId] == 2) { $(`#elevator-item-${elevId}`) .prev("span.elevator-item-toup") .removeClass("light-flash-c-bd"); $(`#elevator-item-${elevId}`) .next("span.elevator-item-todown") .addClass("light-flash-c-bd") .css("--flash-color-1", "#44ea8e") .css("--flash-color-2", "rgba(255,255,255,0)"); } else { $(`#elevator-item-${elevId}`) .prev("span.elevator-item-toup") .removeClass("light-flash-c-bd"); $(`#elevator-item-${elevId}`) .next("span.elevator-item-todown") .removeClass("light-flash-c-bd"); } }; // 設定現在某個電梯所在樓層 setCurElevFloor = function (elevId, floId) { this.curElevFloor[elevId] = floId; }; // 重新繪製 redraw = function () { $(this.ele).empty(); this.setTabFloor(); if (Object.keys(this.curElevFloor).length != 0) { $.each(Object.keys(this.curElevFloor), (idx, elevKey) => { this.setElevFloor(elevKey, this.curElevFloor[elevKey]); }); } }; } // 從數字週數轉為中文週數 function dayToChiDay(num) { let chiDay = ["週日", "週一", "週二", "週三", "週四", "週五", "週六"]; return chiDay[num]; } // 取得現在或前後時間,輸出單位依據 type function getTimeByType(type = null, cal = 0, unit = "d") { let now = new Date(); return strToDate(now, type, cal, unit); } // 取得某當下時間或前後時間,輸出單位依據 type function strToDate(text, type = null, cal = 0, unit = "d") { let dec = 24 * 60 * 60 * 1000; if (unit == "d") { dec = 24 * 60 * 60 * 1000; } else if (unit == "h") { dec = 60 * 60 * 1000; } else if (unit == "m") { dec = 60 * 1000; } else if (unit == "s") { dec = 1000; } let calDay = function (_d, _cal) { return new Date(_d.getTime() + cal * dec); }; let tarDate = new Date(text); let result = 0; if (type == "year") { result = calDay(tarDate, cal).getFullYear(); } else if (type == "month") { result = calDay(tarDate, cal).getMonth(); } else if (type == "date") { result = calDay(tarDate, cal).getDate(); } else if (type == "day") { result = calDay(tarDate, cal).getDay(); } else { result = calDay(tarDate, cal); } return result; } // 將只有時間(Hms) 格式轉換為當日的時間 function fullTime(time) { let nowDate = displayDate(new Date(), "date"); return new Date(nowDate + " " + time); } function dateRanCutPart(start, end, cutNum) { let sTime = new Date(start).getTime(); let eTime = new Date(end).getTime(); let cutTimeArr = []; if (sTime < eTime) return []; let partNum = (sTime - eTime) / cutNum; for (let i = eTime; i <= sTime; i = i + partNum) { cutTimeArr.push(i); } cutTimeArr.forEach((x) => new Date(x)); return cutTimeArr; } function isJSON(str) { try { JSON.parse(str); return true; } catch { return false; } } function addBsToast( container, type = "warning", title = "", content = "", id, datas = {}, option = {} ) { datas = Object.keys(datas).length != 0 ? `${Object.keys(datas) .map((x) => `data-${x}="${datas[x]}"`) .join(" ")}` : ""; let iconClass = option.iconHtml ?? `fas fa-exclamation-triangle`; let strHtml = ``; } /** * 取得資料庫電梯設備,根據 baja 訂閱移動 3D 電梯 * */ class Forge3DElevFull { constructor(option = {}) { this.allElevDevList = []; //全電梯設備清單 this.subSeviceData = []; //每個設備訂閱點位值 this.floList = []; this.elev3DBind = {}; this.elev3DOption = {}; this.elev3DObj = []; this.viewer = option.viewer ?? null; this.ordPath = option.ordPath ?? {}; this.sysMainTag = option.system_tag ?? "ELEV"; this.sysSubTag = option.name_tag ?? "EL"; this.selector = option.selector ?? "#forgeViewer"; this.bajaChaCallback = option.bajaChaCallback ?? null; this.bajaEndCallback = option.bajaEndCallback ?? null; this.sensorObjs = option.sensorObjs ?? null; } init = function () { // 系統大類、小類固定 this.ordPath.system_tag = this.sysMainTag; this.ordPath.name_tag = this.sysSubTag; // if (pageAct.sysSubTag === "M12") { // console.log("@@",pageAct, pageAct.sysSubTag) // this.getSensorDevList(); // } this.getElevDevList(); }; // 訂閱電梯設備 subElevDevice = function () { let myBaja = new subscriptionDevices(); let ordPath = this.ordPath; myBaja.setSubscribeDevicesByBql(ordPath); myBaja.setSubscribeDevicesCallBack((data) => { this.bajaChaCallback ? this.bajaChaCallback(data) : ""; if (this.allElevDevList.length == 0) { return false; } data.device_number = data.device_number_full; let matchDevice = this.allElevDevList.filter( (x) => x.device_number == data.device_number )[0]; if (!matchDevice) { return; } //將訂閱值塞入 subSeviceData if ( this.subSeviceData.findIndex( (x) => x.device_number == matchDevice.device_number ) == -1 ) { let obj = {}; obj.device_number = matchDevice.device_number; this.subSeviceData.push(obj); } let subData = this.subSeviceData.filter( (x) => x.device_number == matchDevice.device_number )[0]; if (subData) { subData[data.point_name] = data.value; } if (data.point_name == "CP") { if (this.elev3DObj.length != 0) { let elevObj = this.elev3DObj.filter( (x) => x.nodeId == this.elev3DBind[matchDevice.device_number] )[0]; if (elevObj && elevObj.id) { elevObj.obj.setElevatorFloor(data.value); elevObj.obj.movElevator(); } } } }); myBaja.setSubscribeDeviceEndCallBack((data) => { this.floList = data .filter((x) => x.point_name.startsWith("SP_FLS_")) .map((x) => x?.point_name?.split("SP_FLS_")[1]) .Distinct(); this.set3DElevOpt(data); this.bajaEndCallback != null ? this.bajaEndCallback() : ""; }); }; // 電梯 3D Option 設置 set3DElevOpt = function (data) { let devNumArr = data .map((x) => { return { devNum: x.device_number_full, priority: this.allElevDevList.filter( (y) => y.device_number == x.device_number_full )[0]?.priority, }; }) .DistinctBy("devNum"); devNumArr = devNumArr.oSort("priority"); $.each(devNumArr, (idx, devObj) => { let devNum = devObj.devNum; let subData = this.subSeviceData.filter( (x) => x.device_number == devNum )[0]; if (subData) { //// 左側 3D 電梯 nodeID 與 device_number match //if (Object.keys(elev3DBind).indexOf(devNum) == -1 && viewer3DNodeIds.length != 0) { // elev3DBind[devNum] = viewer3DNodeIds[Object.keys(elev3DBind).length]; //} // 左側 3D 電梯 Viewer Option 設置 /*elev3DOption.nodes = Object.keys(elev3DBind).map(x => elev3DBind[x]);*/ this.elev3DOption.nodeId = this.elev3DBind[devNum]; this.elev3DOption.floorHeight = this.floList.map((x) => { return { floor: x }; }); this.elev3DOption.floorHeight.forEach((floObj, idx) => { if (floObj.floor.startsWith("B")) { let floor = parseInt(floObj.floor.split("B")[1].split("F")[0]); floObj.height = floor * -13; } else { let floor = parseInt(floObj.floor.split("F")[0]); if (floor == 1) { floObj.height = 0; } else if (floor == 2) { floObj.height = 14.75; } else { floObj.height = 14.75 + (floor - 2) * 9.75; } } }); if (this.elev3DObj.length != 0) { let elevObj = this.elev3DObj.filter( (x) => x.nodeId == this.elev3DBind[devNum] )[0]; if (!elevObj.id) { elevObj.id = devNum; } elevObj.obj = Object.assign(elevObj.obj, this.elev3DOption); elevObj.obj.init(() => { let frags = elevObj.obj.fragProxys.filter( (x) => x.nodeId == this.elev3DBind[devNum] ); frags.forEach((fragProxy) => { fragProxy.frag.position.z = this.elev3DOption.floorHeight.filter( (x) => x.floor == subData["CP"] )[0]?.height ?? 0; let start = 0; // 改變感測器熱點位置 this.sensorObjs && this.sensorObjs[0]?.changePos( node + 2, fragProxy.frag.position.z ); // if (node === 15200 && start == 0) { // start = 1; // } fragProxy.frag.updateAnimTransform(); }); elevObj.obj.viewer.impl.sceneUpdated(true); }); } } }); this.set3DElevPos(); }; // 電梯 3D 位置呈現 set3DElevPos = function () { let nodeIds = this.allElevDevList .filter((x) => !isNaN(parseInt(x.forge_dbid))) .map((x) => { return { devNum: x.device_number, nodeId: parseInt(x.forge_dbid) }; }); $.each(nodeIds, (idx, item) => { this.elev3DBind[item.devNum] = item.nodeId; }); nodeIds = nodeIds.map((x) => x.nodeId); $.each(nodeIds, (idx, node) => { let options = { element: $(this.selector), viewer: this.viewer, nodeId: node, floorHeight: this.elev3DOption.floorHeight ?? [], sensorObjs: this.sensorObjs, inited: function () { }, }; let elevator3DObj = new elevator3D(options); let devNum = Object.keys(this.elev3DBind).filter( (x) => this.elev3DBind[x] == node )[0]; let subData = this.subSeviceData.filter( (x) => x.device_number == devNum )[0]; if (this.elev3DObj.filter((x) => x.nodeId == node).length == 0) { this.elev3DObj.push({ id: devNum, nodeId: node, obj: elevator3DObj }); } if (subData) { let elevObj = this.elev3DObj.filter((x) => x.nodeId == node)[0]; if (!elevObj.id) { elevObj.id = devNum; } elevObj.obj = Object.assign(elevObj, elevator3DObj ?? {}); elevObj.obj.init(() => { let frags = elevObj.obj.fragProxys.filter((x) => x.nodeId == node); frags.forEach((fragProxy) => { fragProxy.frag.position.z = this.elev3DOption.floorHeight.filter( (x) => x.floor == subData["CP"] )[0]?.height ?? 0; let start = 0; this.sensorObjs && this.sensorObjs[0]?.changePos( node + 2, fragProxy.frag.position.z ); // if (node === 15200 && start == 0) { // // 改變感測器熱點位置 // start = 1; // } fragProxy.frag.updateAnimTransform(); }); elevObj.obj.viewer.impl.sceneUpdated(true); }); } }); }; // 取得設備列表 getElevDevList = function () { let url = baseApiUrl + "/api/Device/GetDeviceList"; let sendData = { sub_system_tag: this.ordPath.name_tag, building_tag: this.ordPath.building_tag, }; objSendData.Data = sendData; ytAjax = new YourTeam.Ajax( url, objSendData, (res) => { if (!res || res.code != "0000" || !res.data) { } else { $.each(res.data, (index, floObj) => { $.each(floObj.device_list, (index2, devObj) => { this.allElevDevList.push(devObj); }); }); this.subElevDevice(); } }, null, "POST" ).send(); }; getNodeIds = function () { return this.elev3DObj.map((x) => x.nodeId); }; } /** * 取得資料庫溫度感測器 * 1. baja 取得溫度感測器改變顏色 * 2. 參數取得要移動到的電梯位置 * */ class Forge3DSensor { constructor(option = {}) { this.subDeviceData = []; //每個設備訂閱點位值 this.viewer = option.viewer ?? null; this.ordPath = option.ordPath; // TPE_B1 this.sysMainTag = "ME"; this.sysSubTag = "M12"; this.selector = "#forgeViewer"; this.heatMap = null; this.bajaChaCallback = option.bajaChaCallback ?? null; this.bajaEndCallback = option.bajaEndCallback ?? null; this.floorHeight = 0; this.dataVizExtn = null; this.DataVizCore = null; this.tempVal = 20; this.curDevice = option.curDevice ?? null; this.deviceList = option.deviceList ?? null; this.selector = option.selector ?? "#forgeViewer"; this.elevCb = option.elevCb ?? null; this.#init(); } static sensorTimes = 0; #init = async function () { // 系統大類、小類固定 this.ordPath.system_tag = this.sysMainTag; this.ordPath.name_tag = this.sysSubTag; // this.dataVizExtn = await this.viewer.loadExtension( // "Autodesk.DataVisualization" // ); // this.DataVizCore = Autodesk.DataVisualization.Core; await this.registerHotPoint(); this.addSensorHotspotList(this.curDevice.forge_dbid, 35); this.subSensorDevice(); this.elevCb && this.elevCb(); }; // // 建立熱點 // async addHotPoint() { // // this.dataVizExtn.removeAllViewables() // await this.registerHotPoint() // this.subSensorDevice(); // // console.log("2",this.dataVizExtn) // } async registerHotPoint(color = "") { if (Forge3DSensor.sensorTimes === 1) { var viewer = this.viewer; const dataVizExtn = await viewer.loadExtension( "Autodesk.DataVisualization" ); const DataVizCore = Autodesk.DataVisualization.Core; const viewableType = DataVizCore.ViewableType.SPRITE; //DataVizCore.ViewableType.SPRITE; const spriteColor = new THREE.Color(0xff8c00); // const highlightedColor = new THREE.Color(0xe0e0ff); let spriteIcon = "/file/img/forge/sensor_circle.svg"; if (location.href.indexOf("localhost:5966") != -1) { spriteIcon = "/img/forge/sensor_circle.svg"; } const style = new DataVizCore.ViewableStyle( viewableType, spriteColor, spriteIcon ); const viewableData = new DataVizCore.ViewableData(); viewableData.spriteSize = 30; // Sprites as points of size 24 x 24 pixels this.deviceList.forEach((myData, index) => { const dbId = myData.forge_dbid; const myPosition = myData.position; const viewable = new DataVizCore.SpriteViewable( myPosition, style, dbId ); myData._dbId = dbId; viewableData.addViewable(viewable); }); await viewableData.finish(); dataVizExtn.addViewables(viewableData); viewer.addEventListener( DataVizCore.MOUSE_CLICK, this.onSpriteClicked.bind(this) ); // SPRITE_SELECTED // viewer.addEventListener(this.DataVizCore.MOUSE_CLICK_OUT, onSpriteClickedOut.bind(this)); } } // ---------------- 熱點點擊事件 -------------------- onSpriteClicked(event) { event.hasStopped = true; const dbIdStart = 10; if (event != undefined && event != null) { if (event.dbId >= dbIdStart) { let myData = this.deviceList.find((x) => x.forge_dbid == event.dbId); console.log("site", myData); // this.changeColorForSensorHotspot(event.dbId, this.tempVal); myData && moveViewToDevice(myData.forge_dbid); //移動視角至該設備 myData && $(this.selector).trigger("autodesk:click:sprite", { event, myData }); } else { $(this.selector).trigger("autodesk:clickOut:sprite", { event }); } } } // 改變熱點位置 async changePos(dbId, positionZ) { const dataVizExtn = await viewer.loadExtension( "Autodesk.DataVisualization" ); dataVizExtn?.invalidateViewables(dbId, (viewable) => { // console.log(viewable._position) const z = viewable._position.z + positionZ; const newPos = { ...viewable._position, z }; return { // Move the viewable to a new location. position: newPos, }; }); } // 溫度感測器 sprite 隨溫度變化 static lowerTempForSensor = []; static normalTempForSensor = []; static highTempForSensor = []; static highestTempForSensor = []; async addSensorHotspotList(dbid, temp) { let index = Math.floor(temp / 10) - 1 || 0; // 清空資料 Forge3DSensor.lowerTempForSensor = Forge3DSensor.lowerTempForSensor.filter( (point) => point !== dbid ); Forge3DSensor.normalTempForSensor = Forge3DSensor.normalTempForSensor.filter((point) => point !== dbid); Forge3DSensor.highTempForSensor = Forge3DSensor.highTempForSensor.filter( (point) => point !== dbid ); Forge3DSensor.highestTempForSensor = Forge3DSensor.highestTempForSensor.filter((point) => point !== dbid); const temps = [ new THREE.Color(0x00009c), new THREE.Color(0xffff31), new THREE.Color(0xff8c00), new THREE.Color(0xff0000), ]; switch (index) { case -1: Forge3DSensor.lowerTempForSensor.push(dbid); break; case 0: Forge3DSensor.lowerTempForSensor.push(dbid); break; case 1: Forge3DSensor.normalTempForSensor.push(dbid); break; case 2: Forge3DSensor.highTempForSensor.push(dbid); break; case 3: Forge3DSensor.highestTempForSensor.push(dbid); break; default: Forge3DSensor.highTempForSensor.push(dbid); break; } if ( (Forge3DSensor.lowerTempForSensor.length, Forge3DSensor.normalTempForSensor.length, Forge3DSensor.highTempForSensor.length, Forge3DSensor.highestTempForSensor.length, allDevList.length) ) { await this.changeColorForSensorHotspot( Forge3DSensor.lowerTempForSensor, temps[0] ); await this.changeColorForSensorHotspot( Forge3DSensor.normalTempForSensor, temps[1] ); await this.changeColorForSensorHotspot( Forge3DSensor.highTempForSensor, temps[2] ); await this.changeColorForSensorHotspot( Forge3DSensor.highestTempForSensor, temps[3] ); } } async changeColorForSensorHotspot(viewablesToUpdate, color) { const dataVizExtn = await viewer.loadExtension( "Autodesk.DataVisualization" ); dataVizExtn.invalidateViewables(viewablesToUpdate, (viewable) => { return { color: color, }; }); } // 訂閱sensor設備 subSensorDevice() { let myBaja = new subscriptionDevices(); myBaja.setSubscribeDevicesByBql(this.ordPath); myBaja.setSubscribeDevicesCallBack((data) => { this.bajaChaCallback ? this.bajaChaCallback(data) : ""; if (this.curDevice == null) { return false; } data.device_number = data.device_number_full; // "TPE_B1_ME_M12_U1F_NA_TH_N1" (forge TPE_B1_ME_M12_R2F_NA_TH_N1) //將訂閱值塞入 subDeviceData if ( this.subDeviceData.findIndex( (d) => d.device_number == this.curDevice.id ) == -1 ) { let obj = {}; obj.device_number = this.curDevice.id; obj.dbid = this.curDevice.roomDbId; this.subDeviceData.push(obj); } let subData = this.subDeviceData.find( (x) => x.device_number == this.curDevice.id ); if (subData) { subData = { ...subData, [data.point_name]: data.value }; } if (data.point_name == "Temp" || data.point_name == "TEMP") { this.tempVal = !isNaN(parseInt(data.value)) ? parseInt(data.value) : 0; this.curDevice = { ...this.curDevice, temp: !isNaN(parseInt(data.value)) ? parseInt(data.value) : 0, }; if (data.device_number_full === this.curDevice.id) { this.addSensorHotspotList( this.curDevice.forge_dbid, this.curDevice.temp ); } } let matchDevice = allDevList.find( (x) => x.device_number == data.device_number_full ); let norDevPoiName = matchDevice.device_normal_point_name; let cloDevPoiName = matchDevice.device_close_point_name; let errDevPoiName = matchDevice.device_error_point_name; if ( data.point_name == norDevPoiName && data.value == matchDevice.device_normal_point_value ) { //顯示正常燈號 $(`#${matchDevice.device_number}_status`) .attr("data-light-type", "normal") .data("light-type", "normal"); } else if ( data.point_name == cloDevPoiName && data.value == matchDevice.device_close_point_value ) { $(`#${matchDevice.device_number}_status`) .attr("data-light-type", "close") .data("light-type", "close"); } else if ( data.point_name == errDevPoiName && data.value == matchDevice.device_error_point_value ) { $(`#${matchDevice.device_number}_status`) .attr("data-light-type", "error") .data("light-type", "error"); } setLightColor(); setDevItemPoiValBySub(data); $(loadEle).Loading("close"); }); myBaja.setSubscribeDeviceEndCallBack((data) => { if ( data.findIndex( (x) => x.point_name == "Temp" || x.point_name == "TEMP" ) != -1 ) { // 顯示溫度條 showHeat("[name=forgeHeatBar]"); } }); // window.x = 28 // setInterval(()=>{ // this.changeColorForSensorHotspot(this.curDevice.forge_dbid, x++) // }, 2000) } }