[Frontend] 系統監控 - 樓層平面圖前端程序建置 | ajax 連續發送防呆hide | a | 設備基本資料串接 | [Backend] startup 允許靜態文件 CORS

This commit is contained in:
dev01 2022-11-17 10:49:49 +08:00
parent 690d06cbf4
commit 2912dfebee
6 changed files with 325 additions and 301 deletions

View File

@ -24,6 +24,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.AspNetCore.Http;
namespace Backend
{
@ -159,7 +160,13 @@ namespace Backend
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append("Access-Control-Allow-Origin", "*");
}
});
app.UseRouting();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

View File

@ -110,48 +110,47 @@
return strHtml;
}
function drawInfoTabBlo() {
let strHtml = `<table class="table table-bordered table-striped text-center m-0">
<tbody>
<tr>
<td>設備編號</td>
<td>B01-B2-19F-CR-001</td>
<td>3D 座標</td>
<td>113</td>
</tr>
<tr>
<td>設備名稱</td>
<td>A區迴路001</td>
<td>forge dbid</td>
<td>101</td>
</tr>
<tr>
<td>廠牌</td>
<td>飛利浦 Philip</td>
<td>IP</td>
<td>192.168.1.105</td>
</tr>
<tr>
<td>型號</td>
<td>BH065</td>
<td></td>
<td></td>
</tr>
<tr>
<td>原廠文件</td>
<td><a href="#">2022使用手冊.pdf</a></td>
<td></td>
<td></td>
</tr>
<tr>
<td>型號</td>
<td>BH065</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>`
return strHtml;
function drawInfoTabBlo(devGuid) {
let tabEle = $(`<table class="table table-bordered table-striped text-center m-0">`);
let tbody = tabEle.append("<tbody>");
let columnNames = ["設備編號", "設備名稱"];
$.each(columnNames, (index, colName) => {
let tr = $("<tr></tr>");
let td = $("<td></td>");
td.text(colName);
tr.append(td);
tbody.append(tr);
})
let url = baseApiUrl + "/api/Device/GetBaseDevice";
let sendData = {
device_guid: devGuid,
};
objSendData.Data = sendData;
ytAjax = new YourTeam.Ajax(url, objSendData, function (res) {
if (!res || res.code != "0000" || !res.data) {
} else {
tbody.find("tr").eq(0).append(creEle("td", res.data.device_number));
tbody.find("tr").eq(1).append(creEle("td", res.data.full_name));
}
}, null, "POST").send();
//let strHtml = `<table class="table table-bordered table-striped text-center m-0">
// <tbody>
// <tr>
// <td>設備編號</td>
// <td>B01-B2-19F-CR-001</td>
// </tr>
// <tr>
// <td>設備名稱</td>
// <td>A區迴路001</td>
// </tr>
// </tbody>
// </table>`
return tabEle.prop("outerHTML");
}
function drawErrRecTabBlo() {
@ -206,41 +205,47 @@
}
function initPopover() {
$("[name=devItem]").YTTooltip({
html: `<div class="card m-1 border device-wrap">
<div class="card-header p-2 px-3">
<div id="card-tab" class="row justify-content-end nav nav-tabs" role="tablist">
<button type="button" id="state-tab" class="btn btn-icon nav-link active" role="tab" data-tabname="cardTab" data-target="#state"><i class="fa fa-desktop icon"></i></button>
<button type="button" id="info-tab" class="btn btn-icon nav-link" role="tab" data-tabname="cardTab" data-target="#info"><i class="fa fa-cog icon"></i></button>
<button type="button" id="errRec-tab" class="btn btn-icon nav-link" role="tab" data-tabname="cardTab" data-target="#errRec"><i class="fas fa-exclamation-triangle"></i></button>
<button type="button" id="opeRec-tab" class="btn btn-icon nav-link" role="tab" data-tabname="cardTab" data-target="#opeRec"><i class="fa fa-bars icon"></i></button>
</div>
</div>
<div class="card-body p-2 tab-content">
$("[name=devItem]").each((index, ele) => {
let devNum = $(ele).data("number"); //設備編號
let devGuid = $(ele).data("id"); //guid
$(ele).YTTooltip({
html: `<div class="card m-1 border device-wrap">
<div class="card-header p-2 px-3">
<div id="card-tab" class="row justify-content-end nav nav-tabs" role="tablist">
<button type="button" id="state-tab" class="btn btn-icon nav-link active" role="tab" data-tabname="cardTab" data-target="#state"><i class="fa fa-desktop icon"></i></button>
<button type="button" id="info-tab" class="btn btn-icon nav-link" role="tab" data-tabname="cardTab" data-target="#info"><i class="fa fa-cog icon"></i></button>
<button type="button" id="errRec-tab" class="btn btn-icon nav-link" role="tab" data-tabname="cardTab" data-target="#errRec"><i class="fas fa-exclamation-triangle"></i></button>
<button type="button" id="opeRec-tab" class="btn btn-icon nav-link" role="tab" data-tabname="cardTab" data-target="#opeRec"><i class="fa fa-bars icon"></i></button>
</div>
</div>
<div class="card-body p-2 tab-content">
<div id="state" class="show active" data-tabname="cardTab" data-tabrole="child">
${drawStateTabBlo()}
</div>
<div id="info" data-tabname="cardTab" data-tabrole="child">
${drawInfoTabBlo()}
</div>
<div id="errRec" data-tabname="cardTab" data-tabrole="child">
${drawErrRecTabBlo()}
</div>
<div id="opeRec" data-tabname="cardTab" data-tabrole="child">
${drawOpeRecTabBlo()}
</div>
<div id="state" class="show active" data-tabname="cardTab" data-tabrole="child">
${drawStateTabBlo()}
</div>
<div id="info" data-tabname="cardTab" data-tabrole="child">
</div>
<div id="errRec" data-tabname="cardTab" data-tabrole="child">
${drawErrRecTabBlo()}
</div>
<div id="opeRec" data-tabname="cardTab" data-tabrole="child">
${drawOpeRecTabBlo()}
</div>
</div>
</div>`,
group:"device",
onShow: function (tooltipEle, oriEle) {
console.log($(oriEle).data("number"))
var tab = new YT.Tab({ tabName: "cardTab" })
loadOpeRecTable();
}
</div>
</div>`,
group: "device",
onShow: function (tooltipEle, oriEle) {
var tab = new YT.Tab({ tabName: "cardTab" })
//基本資料tab block
$("#info").append(drawInfoTabBlo(devGuid))
loadOpeRecTable();
}
})
})
function loadOpeRecTable() {
let url = "https://api.npoint.io/31e717774a0f5822cc7b";

View File

@ -5,7 +5,7 @@
</style>
<div class="row">
<div id="floChart"></div>
<div id="floChart" style="height : 80vh!important;width:100%"></div>
</div>
@ -15,237 +15,245 @@
$(function () {
initChart();
chartHandler();
getFloData();
})
function getFloData() {
let url = baseApiUrl + "/api/Device/GetDeviceList";
let sendData = {
main_system_tag: pageAct.sysMainTag,
building_tag: pageAct.buiTag,
floor_tag: pageAct.floTag,
};
objSendData.Data = sendData;
ytAjax = new YourTeam.Ajax(url, objSendData, function (res) {
if (!res || res.code != "0000" || !res.data) {
} else {
chartHandler(`${baseImgUrl}/upload/floor_map/${res.data[0].floor_map_name}`);
}
}, null, "POST").send();
}
function initChart() {
let chartDom = $("#floChart")[0];
floChart = echarts.init(chartDom, null, { width: 'auto' });
}
function getSvg() {
"/upload/floor_map/c0de2199-e62b-4f82-b7f7-abacd4e1cd17.svg"
}
function chartHandler() {
function chartHandler(url) {
floChart.clear();
/*let url = `${baseApiUrl}/upload/graph_manage/de08e7ee-9839-4403-90e5-754dec4e389b.jpg`*/
let url = `${baseImgUrl}/upload/floor_map/2e5be49c-f8e8-4977-b5b6-db4d95ff9691.svg`
download(url)
//ytAjax = new YourTeam.Ajax(url, null, function (res) {
// if (svg == undefined || svg == null) {
// return;
// }
// echarts.registerMap('floor_svg', { svg: svg });
// option = {
// // animationDurationUpdate: 1500,
// tooltip: {
// formatter: function (params) {
// if (params.data.device_node_guid != undefined && params.data.device_node_guid != null && params.data.device_node_guid != "") {
// return `名稱:${params.data.device_node_full_name}<br>
// Guid${params.data.device_node_guid}`
// }
// else {
// return `名稱:${params.data.device_full_name}<br>
// Guid${params.data.device_guid}`
// }
// }
// },
// toolbox: { //工具欄
// show: false
// },
// geo: {
// map: 'floor_svg',
// roam: true,
// scaleLimit: { //限制放大縮小倍數
// max: 32,
// min: 2.5
// },
// layoutSize: '100%',
// layoutCenter: ['50%', '50%'],
// zoom: 2.5,
// silent: true
// },
// series: [
// { //不管有無被選擇(圓點)
// type: 'scatter',
// coordinateSystem: 'geo',
// geoIndex: 0,
// symbol: 'circle',
// symbolSize: 10,
// symbolOffset: [10, 10],
// label: {
// show: false
// },
// data: currentData,
// z: 2
// },
// { //未選擇的設備(icon)
// type: 'scatter',
// coordinateSystem: 'geo',
// geoIndex: 0,
// symbolSize: 30,
// label: {
// formatter: '{b}',
// position: 'bottom',
// show: true,
// backgroundColor: 'orange'
// },
// emphasis: {
// label: {
// show: true,
// fontSize: '20',
// fontWeight: 'bold',
// color: 'yellow'
// }
// },
// selectedMode: 'single',
// data: null,
// z: 1
// },
// { //被選擇的設備(icon)
// type: 'effectScatter',
// coordinateSystem: 'geo',
// geoIndex: 0,
// showEffectOn: 'render',
// symbolSize: 30,
// label: {
// formatter: '{b}',
// position: 'bottom',
// show: true,
// backgroundColor: 'orange'
// },
// emphasis: {
// label: {
// show: true,
// fontSize: '20',
// fontWeight: 'bold',
// color: 'yellow'
// }
// },
// selectedMode: 'single',
// data: null,
// z: 1
// },
// { //編輯模式底下的設備(圓點,只會有一個)
// type: 'scatter',
// coordinateSystem: 'geo',
// geoIndex: 0,
// symbol: 'circle',
// symbolSize: 10,
// symbolOffset: [10, 10],
// label: {
// show: false
// },
// data: currentData,
// z: 2
// },
// { //編輯模式底下的設備(icon只會有一個)
// type: 'scatter',
// coordinateSystem: 'geo',
// geoIndex: 0,
// symbolSize: 30,
// label: {
// formatter: '{b}',
// position: 'bottom',
// show: true,
// backgroundColor: 'orange'
// },
// emphasis: {
// label: {
// show: true,
// fontSize: '20',
// fontWeight: 'bold',
// color: 'yellow'
// }
// },
// data: null,
// z: 1
// },
// ],
// };
// floChart.setOption(option);
// floChart.getZr().on('click', function (params) {
// console.log("click", params);
// var pixelPoint = [params.offsetX, params.offsetY];
// var dataPoint = floChart.convertFromPixel({ geoIndex: 0 }, pixelPoint);
// console.log(dataPoint);
// if (floor_map_mode == "edit") {
// temp_device_on_floor_map = [{
// device_guid: selected_temp_device.device_guid,
// device_full_name: selected_temp_device.device_full_name,
// device_node_guid: selected_temp_device.device_node_guid ? selected_temp_device.device_node_guid : null,
// device_node_full_name: selected_temp_device.device_node_full_name ? selected_temp_device.device_node_full_name : null,
// status: selected_temp_device.status,
// value: dataPoint
// }];
// }
// // currentData.push([dataPoint[0], dataPoint[1], 1]);
// // floChart.setOption(option);
// });
// floChart.on('selectchanged', function (params) {
// console.log("selectchanged", params);
// // currentData.push([dataPoint[0], dataPoint[1], 1]);
// // floChart.setOption(option);
// currentData = $.map(currentData, function (item) {
// item.selected = false;
// return item;
// });
// if (params.selected.length > 0) {
// currentData[params.selected[0].seriesIndex - 1].selected = true;
// }
// });
// // floChart.getZr().on('mousewheel', function (params) {
// // console.log(params)
// // })
// floChart.on('georoam', function (params) {
// var zoom = floChart.getOption().geo[0].zoom;
// if (zoom <= 2.5) {
// ResetFloorMap();
// floChart.setOption({
// geo: {
// roam: 'scale'
// },
// });
// } else {
// floChart.setOption({
// geo: {
// roam: true
// },
// });
// }
// });
//}).send();
//$.get(`${baseImgUrl}/device/GetFloorSvg/c0de2199-e62b-4f82-b7f7-abacd4e1cd17.svg`, function (svg) {
$.get(url, function (svg) {
if (svg == undefined || svg == null) {
return;
}
//})
// .fail(function () {
// toast_warning("查無該樓層地圖")
// floChart.clear();
// });
echarts.registerMap('floor_svg', { svg: svg });
option = {
// animationDurationUpdate: 1500,
//tooltip: {
// formatter: function (params) {
// if (params.data.device_node_guid != undefined && params.data.device_node_guid != null && params.data.device_node_guid != "") {
// return `名稱:${params.data.device_node_full_name}<br>
// Guid${params.data.device_node_guid}`
// }
// else {
// return `名稱:${params.data.device_full_name}<br>
// Guid${params.data.device_guid}`
// }
// }
//},
toolbox: { //工具欄
show: false
},
geo: {
map: 'floor_svg',
roam: true,
scaleLimit: { //限制放大縮小倍數
max: 32,
min: 2.5
},
layoutSize: '100%',
layoutCenter: [],
zoom: 2.5,
silent: true
},
series: [
{ //不管有無被選擇(圓點)
type: 'scatter',
coordinateSystem: 'geo',
geoIndex: 0,
symbol: 'circle',
symbolSize: 10,
symbolOffset: [10, 10],
label: {
show: false
},
/*data: currentData,*/
z: 2
},
{ //未選擇的設備(icon)
type: 'scatter',
coordinateSystem: 'geo',
geoIndex: 0,
symbolSize: 30,
label: {
formatter: '{b}',
position: 'bottom',
show: true,
backgroundColor: 'orange'
},
emphasis: {
label: {
show: true,
fontSize: '20',
fontWeight: 'bold',
color: 'yellow'
}
},
selectedMode: 'single',
data: null,
z: 1
},
{ //被選擇的設備(icon)
type: 'effectScatter',
coordinateSystem: 'geo',
geoIndex: 0,
showEffectOn: 'render',
symbolSize: 30,
label: {
formatter: '{b}',
position: 'bottom',
show: true,
backgroundColor: 'orange'
},
emphasis: {
label: {
show: true,
fontSize: '20',
fontWeight: 'bold',
color: 'yellow'
}
},
selectedMode: 'single',
data: null,
z: 1
},
{ //編輯模式底下的設備(圓點,只會有一個)
type: 'scatter',
coordinateSystem: 'geo',
geoIndex: 0,
symbol: 'circle',
symbolSize: 10,
symbolOffset: [10, 10],
label: {
show: false
},
/*data: currentData,*/
z: 2
},
{ //編輯模式底下的設備(icon只會有一個)
type: 'scatter',
coordinateSystem: 'geo',
geoIndex: 0,
symbolSize: 30,
label: {
formatter: '{b}',
position: 'bottom',
show: true,
backgroundColor: 'orange'
},
emphasis: {
label: {
show: true,
fontSize: '20',
fontWeight: 'bold',
color: 'yellow'
}
},
data: null,
z: 1
},
],
};
floChart.setOption(option);
console.log(floChart)
floChart.getZr().on('click', function (params) {
console.log("click", params);
var pixelPoint = [params.offsetX, params.offsetY];
var dataPoint = floChart.convertFromPixel({ geoIndex: 0 }, pixelPoint);
console.log(dataPoint);
if (floor_map_mode == "edit") {
temp_device_on_floor_map = [{
device_guid: selected_temp_device.device_guid,
device_full_name: selected_temp_device.device_full_name,
device_node_guid: selected_temp_device.device_node_guid ? selected_temp_device.device_node_guid : null,
device_node_full_name: selected_temp_device.device_node_full_name ? selected_temp_device.device_node_full_name : null,
status: selected_temp_device.status,
value: dataPoint
}];
}
// currentData.push([dataPoint[0], dataPoint[1], 1]);
// floChart.setOption(option);
});
//floChart.on('selectchanged', function (params) {
// console.log("selectchanged", params);
// // currentData.push([dataPoint[0], dataPoint[1], 1]);
// // floChart.setOption(option);
// currentData = $.map(currentData, function (item) {
// item.selected = false;
// return item;
// });
// if (params.selected.length > 0) {
// currentData[params.selected[0].seriesIndex - 1].selected = true;
// }
//});
// floChart.getZr().on('mousewheel', function (params) {
// console.log(params)
// })
floChart.on('georoam', function (params) {
var zoom = floChart.getOption().geo[0].zoom;
if (zoom <= 2.5) {
ResetFloorMap();
floChart.setOption({
geo: {
roam: 'scale'
},
});
} else {
floChart.setOption({
geo: {
roam: true
},
});
}
});
})
.fail(function () {
toast_warning("查無該樓層地圖")
floChart.clear();
});
}
</script>

View File

@ -43,3 +43,7 @@ function defDev(obj) {
let defSrc = 'img/defdev.png';
obj.src = defSrc;
}
function creEle(ele,text) {
return $(`<${ele}>${text}</${ele}>`);
}

View File

@ -123,9 +123,9 @@ class Ajax {
*/
send = function (conType = this.contentType.Json, sendData = null, successFunction = null, errorFunction = null) {
if (!CheckMultiSend(this.apiUrl, this.type, this.dataToString(this.sendData))) { //連點防呆
return false;
}
//if (!CheckMultiSend(this.apiUrl, this.type, this.dataToString(this.sendData))) { //連點防呆
// return false;
//}
if (sendData) {
this.sendData = sendData;
}

View File

@ -175,7 +175,7 @@ namespace FrontendWebApi.ApiControllers
try
{
var sqlString = $@"select full_name, InitMapName as map_name, floor_map_name + '.svg' as floor_map_name from floor where deleted = 0 and building_tag = @building_tag and full_name = ifnull(@floor_tag, full_name)";
var sqlString = $@"select full_name, InitMapName as map_name, concat(floor_map_name,'.svg') as floor_map_name from floor where deleted = 0 and building_tag = @building_tag and full_name = ifnull(@floor_tag, full_name)";
var param = new { @building_tag = fd.building_tag, @floor_tag = fd.floor_tag };
var fl = await backendRepository.GetAllAsync<FloorList>(sqlString, param);