diff --git a/Frontend/_sysElevator.html b/Frontend/_sysElevator.html index 00fb4f1..5d206ab 100644 --- a/Frontend/_sysElevator.html +++ b/Frontend/_sysElevator.html @@ -981,7 +981,7 @@ subDeviceSetEleManNotSerFloor(master); }); myBaja.setSubscribeDeviceEndCallBack(function (data) { - + let devNumArr = data.map(x => { return { devNum: x.device_number_full, priority: allDevList.filter(y => y.device_number == x.device_number_full)[0]?.priority } }).DistinctBy("devNum"); devNumArr = devNumArr.oSort("priority"); $.each(devNumArr, (idx, devObj) => { @@ -1032,6 +1032,7 @@ }) reloadEleManTable(setEleManTabDataFromBaja()); + $(loadEle).Loading("close"); }) } diff --git a/Frontend/css/site.css b/Frontend/css/site.css index 223a160..974af21 100644 --- a/Frontend/css/site.css +++ b/Frontend/css/site.css @@ -103,6 +103,7 @@ input.toggle:checked { .loading-bg { background: #0000009c; background-repeat: no-repeat; + opacity:0; width: 100%; height: 100vh; position: fixed; diff --git a/Frontend/css/yourteam/plugins/yt-alert/ytpop-alert.css b/Frontend/css/yourteam/plugins/yt-alert/ytpop-alert.css new file mode 100644 index 0000000..4191e84 --- /dev/null +++ b/Frontend/css/yourteam/plugins/yt-alert/ytpop-alert.css @@ -0,0 +1,26 @@ +.alert[id^=success-alert] { + background-color: #3AB14D; +} + +.alert[id^=danger-alert] { + background-color: #dc3545; +} + +.alert[id^=tip-alert] { + background-color: #498ae5; +} + +.yt-alert { + display: none; + position: fixed; + z-index: 3000; + bottom: 2%; + right: 2%; + width: 300px; + background-color: #dc3545; + color: white; + border-radius:5px; + display: flex; + align-items: center; + gap: 7px; +} diff --git a/Frontend/index.html b/Frontend/index.html index a46863a..ebed679 100644 --- a/Frontend/index.html +++ b/Frontend/index.html @@ -33,10 +33,12 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li + + @@ -1496,7 +1498,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
-
運維管理
@@ -2528,7 +2530,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li - + @@ -2537,6 +2539,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li + - + diff --git a/Frontend/js/site.js b/Frontend/js/site.js index 63dfd10..55248fa 100644 --- a/Frontend/js/site.js +++ b/Frontend/js/site.js @@ -19,9 +19,66 @@ $.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; + + function closeLoading() { + $("body").css("overflow", "auto"); + $(aleObj.ele).YTAlert().hide(); + $(ele).animate({ opacity: 0 }, 300, () => { + $(ele).hide(); + }) + } + function showLoading() { + $("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 + * @param {any} menuEle - .dropdown-menu element */ function setDropdownItem(menuEle) { if ($(menuEle).find(".dropdown-item.active").length == 0) { @@ -52,6 +109,11 @@ function defDev(obj) { 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; @@ -59,6 +121,7 @@ function dtAjaxResetSendData(table,sendData) { } } + /** * element 建造 * @param {any} text @@ -108,6 +171,9 @@ function creOption(text = null, value = null, data = {}, attr = {}, cls = [], na return creEle("option", text, id, name, cls, data, attr); } +/** + * 根據該棟建築底下的'所有'電梯執行緒物件 + * */ class ElevatorHandler { constructor(ele, option = {}) { this.ele = ele; @@ -124,9 +190,11 @@ class ElevatorHandler { 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]); @@ -158,16 +226,16 @@ class ElevatorHandler { for (let e = 1; e <= _elevators.length + 2; e++) { let th = creEle("th"); - th.css({ "width": `${_w}px`, "height": `${_h}px` }); + 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`, "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`, "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`, "transition":`transform ${1 / this.speed}s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`,"top":`${1.5 + (_h-3) / 2}px`}) + 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); @@ -221,26 +289,18 @@ class ElevatorHandler { } + // 設置某個電梯到某個樓層 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]] - clearTimeout(this.setTimeout); - console.log("123",this.movStatus) if (this.movStatus[elevId] != 0) { $(cssEle).css("transition", `transform ${1 / this.speed * Math.abs(gapFloor)}s cubic-bezier(0, 0, 0.62, 1) 0s`); } - //if (gapFloor < 0) { - // this.movStatus[elevId] = 2; - //} else if (gapFloor > 0) { - // this.movStatus[elevId] = 1; - //} else { - // this.movStatus[elevId] = 0; - //} + clearTimeout(this.setTimeout); this.setTimeout = setTimeout(() => { - /*this.movStatus[elevId] = 0;*/ $(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) @@ -250,10 +310,12 @@ class ElevatorHandler { $(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") @@ -269,10 +331,12 @@ class ElevatorHandler { } } + // 設定現在某個電梯所在樓層 setCurElevFloor = function (elevId,floId) { this.curElevFloor[elevId] = floId; } + // 重新繪製 redraw = function () { $(this.ele).empty(); this.setTabFloor(); diff --git a/Frontend/js/yourteam/plugins/yt-alert/ytpop-alert.js b/Frontend/js/yourteam/plugins/yt-alert/ytpop-alert.js new file mode 100644 index 0000000..6a99500 --- /dev/null +++ b/Frontend/js/yourteam/plugins/yt-alert/ytpop-alert.js @@ -0,0 +1,120 @@ + +alertIdArray = []; +window.YT = typeof YT == "undefined" ? {} : YT; +window.YT.Alert = { Success: null, Error: null, Tip: null }; + + +YT.Alert.Success = function (text) { + let ranId = Math.floor(Math.random() * 100000); + $("body").append(``) + + //紀錄上一筆出現的alert + alertIdArray.push("success-alert-" + ranId) + alertIdArray.length > 2 ? alertIdArray.shift() : "" + $("#success-alert-" + ranId).fadeIn(300); + //判斷上一筆是否還存在頁面中 + if (typeof ($("#" + alertIdArray[0]).css("bottom")) != "undefined" && $("#" + alertIdArray[0]).css("display") != "none" && (alertIdArray[1] != "" || alertIdArray[1] != null)) { + //存在的話下一個alert出現在前一個alert上面 + let newAlertWidth = parseInt($("#" + alertIdArray[0]).css("bottom").split('px')[0]) + parseInt($("#" + alertIdArray[0]).css("height")) + 10 + "px" + $("#" + alertIdArray[1]).css("bottom", newAlertWidth); + } + $("#success-alert-" + ranId).click(function () { + $("#success-alert-" + ranId).fadeOut(300); + }) + + setTimeout(function () { $("#success-alert-" + ranId).fadeOut(300); }, 6000); + setTimeout(function () { + $("#success-alert-" + ranId).remove(); + alertIdArray.splice($.inArray("#success-alert-" + ranId, alertIdArray), 1); + }, 7000); + +} + +YT.Alert.Error = function (text) { + let ranId = Math.floor(Math.random() * 100000); + $("body").append(``) + + alertIdArray.push("danger-alert-" + ranId); + alertIdArray.length > 2 ? alertIdArray.shift() : "" + $("#danger-alert-" + ranId).fadeIn(300); + if (typeof ($("#" + alertIdArray[0]).css("bottom")) != "undefined" && $("#" + alertIdArray[0]).css("display") != "none" && (alertIdArray[1] != "" || alertIdArray[1] != null)) { + let newAlertWidth = parseInt($("#" + alertIdArray[0]).css("bottom").split('px')[0]) + parseInt($("#" + alertIdArray[0]).css("height")) + 10 + "px" + $("#" + alertIdArray[1]).css("bottom", newAlertWidth); + } + $("#danger-alert-" + ranId).click(function () { + $("#danger-alert-" + ranId).fadeOut(300); + }) + + setTimeout(function () { + $("#danger-alert-" + ranId).fadeOut(300); + alertIdArray.splice($.inArray("#danger-alert-" + ranId, alertIdArray), 1); + }, 6000); + setTimeout(function () { $("#danger-alert-" + ranId).remove(); }, 7000); + +} + +YT.Alert.Tip = function (text, type = null, color = null) { + let ranId = Math.floor(Math.random() * 100000); + $("body").append(``) + + alertIdArray.push("tip-alert-" + ranId); + alertIdArray.length > 2 ? alertIdArray.shift() : "" + if (color != null) { + $("#tip-alert-" + ranId).css("background-color", color); + } + + if (type == null) { + $("#tip-alert-" + ranId).fadeIn(300); + if (typeof ($("#" + alertIdArray[0]).css("bottom")) != "undefined" && $("#" + alertIdArray[0]).css("display") != "none" && (alertIdArray[1] != "" || alertIdArray[1] != null)) { + let newAlertWidth = parseInt($("#" + alertIdArray[0]).css("bottom").split('px')[0]) + parseInt($("#" + alertIdArray[0]).css("height")) + 10 + "px" + $("#" + alertIdArray[1]).css("bottom", newAlertWidth); + } + $("#tip-alert-" + ranId).click(function () { + $("#tip-alert-" + ranId).fadeOut(300); + }) + setTimeout(function () { + $("#tip-alert-" + ranId).fadeOut(300); + alertIdArray.splice($.inArray("#tip-alert-" + ranId, alertIdArray), 1); + }, 6000); + + setTimeout(function () { $("#tip-alert-" + ranId).remove(); }, 7000); + } else if (type == "show") { + $("#tip-alert-" + ranId).fadeIn(300); + } else if (type == "hide") { + $("#tip-alert-" + ranId).fadeOut(300); + alertIdArray.splice($.inArray("#tip-alert-" + ranId, alertIdArray), 1); + setTimeout(function () { + $("#tip-alert-" + ranId).remove(); + }, 1000); + } + return { id: "#tip-alert-" + ranId, ele: $("#tip-alert-" + ranId) }; + +} + + +//因非使用 Require 引用,$.fn 被二次引用 jquery.js 吃掉,則移至 site.js + +//$.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; +//} + diff --git a/Frontend/js/yourteam/yourteam.ajax.class.js b/Frontend/js/yourteam/yourteam.ajax.class.js index 215fef6..9f17d06 100644 --- a/Frontend/js/yourteam/yourteam.ajax.class.js +++ b/Frontend/js/yourteam/yourteam.ajax.class.js @@ -58,7 +58,8 @@ class Ajax { */ successFunction = function (data,callback) { if (data && data.unauthorized == 401) { - location.href = "login.html"; + localStorage.removeItem("JWT-Authorization"); + location.href = "/login"; } if (callback) { callback(data); @@ -79,6 +80,7 @@ class Ajax { window.alert("執行失敗,請聯絡客服人員。"); } else if (xhr.status == "401") { window.alert("登入時間超時,請重新登入!"); + localStorage.removeItem("JWT-Authorization"); location.href = "~/Login/Login"; } }