[Frontend][全域功能] YTTab 程序調整 | [系統監控] 溫度條ui補上 | 自動須量編輯程序建置 | 自動須量圖表建置 | [FrontendWebApi] GetAutDemVal variable automated_demand_response 取得自動須量 api 建置 | 編輯自動須量 api 調整

This commit is contained in:
dev01 2023-01-09 19:15:27 +08:00
parent f4e837212d
commit 571130c2bf
8 changed files with 231 additions and 30 deletions

View File

@ -74,7 +74,10 @@
</div>`; </div>`;
break; break;
case 3: case 3:
strHtml = `<div name="forgeViewer" style="height:85vh;"></div>`; strHtml = `<div class="d-flex mb-4" style="gap:15px">
${setTopHeatBar()}
</div>
<div name="forgeViewer" style="height:85vh;"></div>`;
break; break;
} }
@ -92,11 +95,12 @@
} }
myBaja.setSubscribeDevicesByBql(ordPath); myBaja.setSubscribeDevicesByBql(ordPath);
myBaja.setSubscribeDevicesCallBack(function (data) { myBaja.setSubscribeDevicesCallBack(function (data) {
console.log(data)
let matchDevice = allDevList.filter(x => x.device_number == data.device_number_full)[0]; let matchDevice = allDevList.filter(x => x.device_number == data.device_number_full)[0];
if (!matchDevice) { if (!matchDevice) {
return false; return false;
} }
console.log(data)
//將訂閱值塞入 subDeviceData //將訂閱值塞入 subDeviceData
if (subDeviceData.findIndex(x => x.device_number == matchDevice.device_number) == -1) { if (subDeviceData.findIndex(x => x.device_number == matchDevice.device_number) == -1) {
let obj = {}; let obj = {};
@ -142,10 +146,10 @@
}); });
} }
function lightDevForgeSpotLig(devObj) { function lightDevForgeSpotLig(devObj) {
let position = isJSON(devObj.device_coordinate_3d) ? JSON.parse(devObj.device_coordinate_3d) : {};
newLight(position);
} }
// 從設備訂閱更新每個設備卡片即時點位 // 從設備訂閱更新每個設備卡片即時點位
@ -211,6 +215,12 @@
return strHtml; return strHtml;
} }
// 設置 Forge 3D 溫度條
function setTopHeatBar() {
let strHtml = `<canvas name="forgeHeatBar" width="200" height="30" style="z-index:9999"></canvas>`;
return strHtml;
}
// forge 3D 異常點位變紅色 // forge 3D 異常點位變紅色
function setForgeHotSpotColor(device) { function setForgeHotSpotColor(device) {
let subData = subDeviceData.filter(x => x.device_number == device.device_number)[0] let subData = subDeviceData.filter(x => x.device_number == device.device_number)[0]
@ -331,14 +341,19 @@
</div>` </div>`
return strHtml; return strHtml;
} }
function iframeResize(obj) { function iframeResize(obj) {
obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px'; obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px';
} }
function show3DModel(urn) { function show3DModel(urn) {
$(loadEle).Loading("start"); $(loadEle).Loading("start");
getLightData(allDevList);
launchViewerForHotspot(urn, (viewer, nodeIds) => { launchViewerForHotspot(urn, (viewer, nodeIds) => {
showHeat("[name=forgeHeatBar]");
let devDbIds = allDevList.map(x => x.forge_dbid); let devDbIds = allDevList.map(x => x.forge_dbid);
/*hideAllObjects(devDbIds);*/ /*hideAllObjects(devDbIds);*/
setTransparentBuilding(0, devDbIds); setTransparentBuilding(0, devDbIds);
$(loadEle).Loading("close"); $(loadEle).Loading("close");

View File

@ -93,6 +93,20 @@ input:-webkit-autofill { background-color: rgba(0, 0, 0, 0.15) !important; }
.device-wrap .card-body #info, .device-wrap .card-body #errRec, .device-wrap .card-body #opeRec { min-width: 500px; } .device-wrap .card-body #info, .device-wrap .card-body #errRec, .device-wrap .card-body #opeRec { min-width: 500px; }
.scrolledTable { overflow-y: auto; clear: both; max-height:100%;} .scrolledTable { overflow-y: auto; clear: both; max-height:100%;}
/*a[data-tabname="topFunBtn"] { color: #fff }
a[data-tabname="topFunBtn"].active { color: #886ab5 }
a[data-tabname="topFunBtn"]:hover { color: var(--theme-primary-50); }
.userblock {
color:#fff;
}
.userblock:hover { color: var(--theme-primary-50); }
.dropdown.show .userblock { color: var(--theme-primary-50) !important; }*/
.page-header a {color:#fff !important;}
.page-header a:hover { color: var(--theme-primary-50) !important; }
.page-header a.active { color: var(--theme-primary-500) !important; }
.dropdown.show a { color: var(--theme-primary-50) !important; }
@media screen and (max-width: 576px) { .yt-left-navbar { width: 100%; max-width: 100%; margin-top: 0; } @media screen and (max-width: 576px) { .yt-left-navbar { width: 100%; max-width: 100%; margin-top: 0; }
} }

View File

@ -180,7 +180,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
</div> </div>
<div class="dropdown"> <div class="dropdown">
<a class="dropdown-toggle" href="javascript:;" role="button" id="buiActDrop" <a class="dropdown-toggle fs-1" href="javascript:;" role="button" id="buiActDrop"
data-target="buiList" data-toggle="dropdown" aria-haspopup="true"> data-target="buiList" data-toggle="dropdown" aria-haspopup="true">
</a> </a>
@ -199,8 +199,11 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
<!--<img src="img/demo/avatars/avatar-admin.png" class="profile-image rounded-circle" <!--<img src="img/demo/avatars/avatar-admin.png" class="profile-image rounded-circle"
alt="Dr. Codex Lantern">--> alt="Dr. Codex Lantern">-->
<!--you can also add username next to the avatar with the codes below:--> <!--you can also add username next to the avatar with the codes below:-->
<span id="usrName" class="ml-1 mr-2 text-truncate text-truncate-header hidden-xs-down"></span> <div class="row m-0 justify-content-center userblock">
<i class="ni ni-chevron-down hidden-xs-down"></i> <i class="fas fa-user-circle fs-1-5 w-100 text-center"></i>
<span id="usrName" class="text-truncate text-truncate-header hidden-xs-down"></span>
</div>
</a> </a>
<div id="logoutList" class="dropdown-menu dropdown-menu-right dropdown-lg"> <div id="logoutList" class="dropdown-menu dropdown-menu-right dropdown-lg">
@ -772,7 +775,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
"lib/statistics/flot/flot.bundle", "lib/statistics/flot/flot.bundle",
"lib/statistics/peity/peity.bundle", "lib/statistics/peity/peity.bundle",
"lib/jquery-validation/dist/jquery.validate", "lib/jquery-validation/dist/jquery.validate",
"lib/jquery-validation/dist/additional-methods.min", /*"lib/jquery-validation/dist/additional-methods.min",*/ /* 會影響 messages_zh_TW 文字呈現 */
"lib/jquery-validation/dist/localization/messages_zh_TW", "lib/jquery-validation/dist/localization/messages_zh_TW",
"lib/jquery-ui/jquery-ui.min", "lib/jquery-ui/jquery-ui.min",
"lib/chart.js/Chart.min", "lib/chart.js/Chart.min",
@ -840,10 +843,11 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
if (isJSON(sessionStorage.getItem("pageAct"))) { if (isJSON(sessionStorage.getItem("pageAct"))) {
lastPageAct = JSON.parse(sessionStorage.getItem("pageAct")); lastPageAct = JSON.parse(sessionStorage.getItem("pageAct"));
} }
if (lastPageAct.sysSubTag) { if (lastPageAct.sysSubTag && lastPage == "systemMonitor") {
$(`#subSysBtn${lastPageAct.sysSubTag}`).click(); $(`#subSysBtn${lastPageAct.sysSubTag}`).click();
$("#sysMonTopBtn").YTTab("set");
} else { } else {
$(`[name=topFunBtn][data-page=${lastPage}]`).click(); $(`[data-tabname=topFunBtn][data-page=${lastPage}]`).YTTab("setAndClick");
} }
/*$(`[name=topFunBtn][data-page=${lastPage}]`).click();*/ /*$(`[name=topFunBtn][data-page=${lastPage}]`).click();*/
@ -911,12 +915,17 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
onEvent("click", "[name=topFunBtn]", function () { onEvent("click", "[name=topFunBtn]", function () {
_ytTabInited = []; _ytTabInited = [];
let page = $(this).data("page"); let page = $(this).data("page");
if (!page) {
return;
}
if (page != "systemMonitor") { if (page != "systemMonitor") {
$("#sysMonBtnList .dropdown-item").removeClass("active"); $("#sysMonBtnList .dropdown-item").removeClass("active");
pageAct.sysMainTag = null; pageAct.sysMainTag = null;
pageAct.sysSubTag = null;
} else { } else {
setSysTagForPageAct(this); setSysTagForPageAct(this);
$("#sysMonTopBtn").YTTab("set");
$(`#subSysBtn${pageAct.sysSubTag}`).YTTab("set");
} }
$.each(tolSubList, (idx, sub) => { $.each(tolSubList, (idx, sub) => {
sub.unsubscribeAll(); sub.unsubscribeAll();
@ -934,6 +943,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
} }
getUserInfo(); getUserInfo();
sessionStorage.setItem("lastPage", page); sessionStorage.setItem("lastPage", page);
sessionStorage.setItem("pageAct", JSON.stringify(pageAct)); sessionStorage.setItem("pageAct", JSON.stringify(pageAct));
$("#app").load(`_${page}.html`, loadCallback); $("#app").load(`_${page}.html`, loadCallback);
@ -945,6 +955,13 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
location.href = "/logout"; location.href = "/logout";
}) })
onEvent("click", "#sysMonBtnList a", function (e) {
//pageAct.sysMainTag = $(this).data("subSysObj").main_system_tag;
//pageAct.sysSubTag = $(this).data("subSysObj").sub_system_tag;
//pageAct.sysSubName = $(this).data("subSysObj").full_name;
//pageAct.sysSubObj = $(this).data("subSysObj");
//getDevItem();
})
onEvent("active:change", "#buiList", function (e, actEle) { onEvent("active:change", "#buiList", function (e, actEle) {
if (actEle) { if (actEle) {
@ -961,6 +978,12 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
} }
}) })
onEvent("yt:tab:prechange", "[data-tabname=topFunBtn]", function (e, arg) {
if ($(this)[0].id == "sysMonTopBtn" || !$(this).data("page")) {
arg.cancel = true;
}
})
onEvent("click", "#testsysbtn", function () { onEvent("click", "#testsysbtn", function () {
}) })
@ -1460,7 +1483,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
} else { } else {
let strHtml = `<div class="btn-group mx-4"> let strHtml = `<div class="btn-group mx-4">
<a href="javascript:;" name="topFunBtn" data-page="dashboard" class="text-center"> <a href="javascript:;" name="topFunBtn" data-page="dashboard" data-tabname="topFunBtn" class="text-center">
<i class="fal fa-home fa-2x"></i><br>首頁 <i class="fal fa-home fa-2x"></i><br>首頁
</a> </a>
<!--<div class="dropdown-menu"> <!--<div class="dropdown-menu">
@ -1473,7 +1496,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
$.each(res.data, function (i, v) { $.each(res.data, function (i, v) {
if (v.authCode == 'PF1') { if (v.authCode == 'PF1') {
strHtml += `<div class="btn-group mx-4" > strHtml += `<div class="btn-group mx-4" >
<a href="javascript:;" id="sysMonTopBtn" class="text-center" data-toggle="navbar" data-target="#sysMonNavbar" aria-haspopup="true" aria-expanded="false"> <a href="javascript:;" id="sysMonTopBtn" class="text-center" data-toggle="navbar" data-target="#sysMonNavbar" data-tabname="topFunBtn" aria-haspopup="true" aria-expanded="false">
<i class="fal fa-tv fa-2x"></i><br>${v.subName} <i class="fal fa-tv fa-2x"></i><br>${v.subName}
</a> </a>
@ -1482,9 +1505,9 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
hasMonitor = true; hasMonitor = true;
} }
else { else {
let icon = v.authCode == 'PF2' ? 'fa-chart-pie' : v.authCode == 'PF3' ? 'fa-chart-area' : v.authCode == 'PF4' ? 'fa-bell' : v.authCode == 'PF5' ? 'fa-server' : v.authCode == 'PF6' ? 'fa-image' : v.authCode == 'PF7' ? 'fa-user' : ''; let icon = v.authCode == 'PF2' ? 'fa-chart-pie' : v.authCode == 'PF3' ? 'fa-chart-area' : v.authCode == 'PF4' ? 'fa-chart-line' : v.authCode == 'PF5' ? 'fa-bell' : v.authCode == 'PF6' ? 'fa-server' : v.authCode == 'PF7' ? 'fa-image' : v.authCode == 'PF8' ? 'fa-user' : '';
strHtml += `<div class="btn-group mx-4"> strHtml += `<div class="btn-group mx-4">
<a href="javascript:;" name="topFunBtn" class="dropdown-toggle no-arrow text-center" <a href="javascript:;" name="topFunBtn" data-tabname="topFunBtn" class="dropdown-toggle no-arrow text-center"
data-page="${v.showView}"> data-page="${v.showView}">
<i class="fal ${icon} fa-2x"></i><br>${v.subName} <i class="fal ${icon} fa-2x"></i><br>${v.subName}
</a> </a>

View File

@ -334,7 +334,7 @@ function onDocumentLoadSuccess(doc, eleOption) {
if (lightDataList != undefined && lightDataList != null && lightDataList.length > 0) { if (lightDataList != undefined && lightDataList != null && lightDataList.length > 0) {
lightDataList.forEach((myData, index) => { lightDataList.forEach((myData, index) => {
//if (myData.priority == 5) { //if (myData.priority == 5) {
const position = JSON.parse(myData.device_node_coordinate_3d); const position = JSON.parse(myData.device_coordinate_3d);
lightList.push({ dbid: myData.forge_dbid, spotLight: newLight(position) }); lightList.push({ dbid: myData.forge_dbid, spotLight: newLight(position) });
//} //}
}); });
@ -1167,6 +1167,42 @@ function showAllObjects() {
} }
} }
function showHeat(selector) {
const labels = [
`${(10).toFixed(2)}${"°C"}`,
`${(40 / 2).toFixed(2)}${"°C"}`,
`${(30).toFixed(2)}${"°C"}`
];
const colorStops = ['blue', 'green', 'yellow', 'red'];
createHeatmapRect(labels, colorStops, selector);
}
function createHeatmapRect(labels, colorStops, selector) {
if (!$(selector)[0]) {
return;
}
const context = $(selector)[0].getContext('2d');
let i, len;
context.clearRect(0, 0, 300, 50);
context.fillStyle = 'back';//white
for (i = 0, len = labels.length; i < len; i++) {
let x = 10 + 280 * i / (len - 1);
if (i === len - 1) {
x -= context.measureText(labels[i]).width;
}
else if (i > 0) {
x -= 0.5 * context.measureText(labels[i]).width;
}
context.fillText(labels[i], x, 10);
}
const gradient = context.createLinearGradient(0, 0, 300, 0);
for (i = 0, len = colorStops.length; i < len; i++) {
gradient.addColorStop(i / (len - 1), colorStops[i]);
}
context.fillStyle = gradient;
context.fillRect(10, 20, 280, 20);
}
//======================== 外部呼叫function =========================== //======================== 外部呼叫function ===========================
//紀錄熱點座標 //紀錄熱點座標
function getHopspotPoint(data) { function getHopspotPoint(data) {

View File

@ -368,16 +368,29 @@ function dayToChiDay(num) {
} }
// 取得現在或前後時間,輸出單位依據 type // 取得現在或前後時間,輸出單位依據 type
function getTimeByType(type = null, cal = 0) { function getTimeByType(type = null, cal = 0, unit = "d") {
let now = new Date(); let now = new Date();
return strToDate(now, type, cal); return strToDate(now, type, cal, unit);
} }
// 取得某當下時間或前後時間,輸出單位依據 type // 取得某當下時間或前後時間,輸出單位依據 type
function strToDate(text, type = null, cal = 0) { function strToDate(text, type = null, cal = 0, unit = "d") {
let calDay = function (_d, _cal) { let dec = 24 * 60 * 60 * 1000;
return new Date(_d.getTime() + (cal * 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 tarDate = new Date(text);
let result = 0; let result = 0;
if (type == "year") { if (type == "year") {
@ -394,6 +407,23 @@ function strToDate(text, type = null, cal = 0) {
return result; return result;
} }
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) { function isJSON(str) {
try { try {
JSON.parse(str); JSON.parse(str);

View File

@ -307,7 +307,14 @@ function displayDate(dateTime, dateType = "YMdHms", locale = 'zh-TW') {
if (dateTime) { if (dateTime) {
let regex = /^\/Date\((\d+)\)\/$/gm; let regex = /^\/Date\((\d+)\)\/$/gm;
let t = Date.parse(dateTime); //若從資料庫回傳 /Date(xxxxxxxxxxxxxx)/ DateTime格式 let t = null; //若從資料庫回傳 /Date(xxxxxxxxxxxxxx)/ DateTime格式
if (typeof dateTime == "number" && dateTime > 1000000) {
dateTime = new Date(dateTime);
}
t = Date.parse(dateTime);
if (regex.test(dateTime)) { if (regex.test(dateTime)) {
t = parseInt(dateTime.replace(regex, '$1')); t = parseInt(dateTime.replace(regex, '$1'));
} }
@ -354,9 +361,30 @@ function displayDate(dateTime, dateType = "YMdHms", locale = 'zh-TW') {
hour = d.getHours(); hour = d.getHours();
minute = d.getMinutes(); minute = d.getMinutes();
} }
date = [year, String(month).padStart(2, '0'), String(day).padStart(2, '0')].filter(n => n).join("/"); date = [year, String(month).padStart(2, '0'), String(day).padStart(2, '0')].filter(n => n).join("/");
time = [String(hour).padStart(2, '0'), String(minute).padStart(2, '0')].filter(n => n).join(":");
result = date.toString() + " " + time.toString(); time = [String(hour).padStart(2, '0'), String(minute).padStart(2, '0')];
if (dateType != "date" && dateType != "time" && dateType != "datetime") {
let showArr = [];
if (year) showArr.push(year);
if (month) showArr.push(month.toString().padStart(2, '0'));
if (day) showArr.push(day.toString().padStart(2, '0'));
if (showArr.length != 0) {
result += showArr.join("/");
showArr = [];
}
if (hour) showArr.push(hour.toString().padStart(2, '0'));
if (minute) showArr.push(minute.toString().padStart(2, '0'));
if (second) showArr.push(second.toString().padStart(2, '0'));
if (millisecond) showArr.push(millisecond.toString().padStart(3, '0'));
if (showArr.length != 0) {
result += " " + showArr.join(":");
}
} else {
result = date.toString() + " " + time.toString();
}
if (dateType == "date") { if (dateType == "date") {
result = date.toString(); result = date.toString();

View File

@ -103,7 +103,7 @@ class YourTeamNavbar {
$("[data-toggle=navbar]").each((idx, ele) => { $("[data-toggle=navbar]").each((idx, ele) => {
let target = $(ele).data("target"); let target = $(ele).data("target");
if ($(this.element)[0] == $(target)[0]) { if ($(this.element)[0] == $(target)[0]) {
$(ele).off("click").on("click", () => { $(ele).on("click", () => {
this.toggle(); this.toggle();
}) })
} }

View File

@ -33,7 +33,10 @@ function initTabsByEle() {
class YourTeamTab { class YourTeamTab {
constructor(option = {}) { constructor(option = {}) {
this.tabName = option.tabName ?? null; this.tabName = option.tabName ?? null;
this.activeEle = null;
this.eventArg = { cancel: false };
this.init() this.init()
} }
init = function () { init = function () {
@ -44,23 +47,49 @@ class YourTeamTab {
this.event(); this.event();
$(`[data-tabname=${this.tabName}][data-tabrole=child]`).css("display", "none"); $(`[data-tabname=${this.tabName}][data-tabrole=child]`).css("display", "none");
if ($(`[data-tabname=${this.tabName}][data-target].active`).length == 0) { if ($(`[data-tabname=${this.tabName}][data-target].active`).length == 0) {
$(`[data-tabname=${this.tabName}][data-target]`).first().trigger("click"); let parTabEle = $(`[data-tabname=${this.tabName}][data-target]`).first();
if (parTabEle.data("toggle") == "tab" || !parTabEle.data("toggle")) {
$(`[data-tabname=${this.tabName}][data-target]`).first().trigger("click");
}
} else { } else {
$(`[data-tabname=${this.tabName}][data-target].active`).first().trigger("click"); $(`[data-tabname=${this.tabName}][data-target].active`).first().trigger("click");
} }
_ytTabInited.push(this.tabName); _ytTabInited.push(this.tabName);
this.setThisObj();
}
setThisObj = function () {
$(`[data-tabname=${this.tabName}]`).each((idx, ele) => {
$(ele)[0]._ytTab = this;
})
}
setActItem = function (element) {
this.activeEle = element;
}
updActClass = function () {
$(`[data-tabname=${this.tabName}]:not([data-tabrole=child])`).removeClass("active");
$(this.activeEle).addClass("active");
} }
event = function () { event = function () {
let clsObj = this; let clsObj = this;
// Tab Item 按鈕 click // Tab Item 按鈕 click
$(`[data-tabname=${this.tabName}]`).off("click").on("click", function (e) { $(`[data-tabname=${this.tabName}]`).on("click", function (e) {
let target = $(this).data("target"); let target = $(this).data("target");
let obj = this; let obj = this;
$(`[data-tabname=${clsObj.tabName}]:not([data-tabrole=child])`).removeClass("active"); clsObj.eventArg.cancel = false;
$(obj).addClass("active"); $(obj).trigger("yt:tab:prechange", clsObj.eventArg)
if (clsObj.eventArg.cancel) {
return;
}
clsObj.activeEle = obj;
clsObj.updActClass();
// 觸發 yt:tab:change事件 // 觸發 yt:tab:change事件
$(obj).trigger("yt:tab:change"); $(obj).trigger("yt:tab:change");
if (target) { if (target) {
@ -80,4 +109,30 @@ class YourTeamTab {
} }
} }
$.fn.YTTab = function (method,...arg) {
let tabObj = $(this)[0]._ytTab;
if (!tabObj) {
let tabName = $(this).data("tabname");
if (tabName && _ytTabInited.indexOf(tabName) == -1) {
let ytTab = new YT.Tab({ tabName: tabName })
_ytTabInited.push(tabName);
tabObj = ytTab;
} else {
return this;
}
}
if (method == "set") {
tabObj.setActItem(this);
tabObj.updActClass();
} else if (method == "setAndClick") {
tabObj.setActItem(this);
$(this).click();
}
return tabObj;
}
YT.Tab = YT.Tab || YourTeamTab; YT.Tab = YT.Tab || YourTeamTab;