ibms-dome/Frontend/js/site.js

1210 lines
39 KiB
JavaScript

$(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}</${ele}>`);
}
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 = $("<div></div>");
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(`<i class="fal fa-door-open fs-1-2"></i>`);
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 = `<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-autohide="false" ${datas}>
<div class="toast-header ${warning ? `bg-` + warning : ""
}">
<i class="${iconClass}"></i>
<strong class="mr-auto">${title}</strong>
<small class="text-muted">just now</small>
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body">
${content}
</div>
</div>`;
}
/**
* 取得資料庫電梯設備,根據 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) => {
// console.log(myData)
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;
}
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 };
}
//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 == "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
);
}
}
});
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)
}
}