[前端] 修改歷史資料前端程序, 增加下載function

[後端] 修改歷史資料下載流程
This commit is contained in:
dev02 2023-07-17 17:41:58 +08:00
parent 3e8daf7759
commit 100a5bdc07
5 changed files with 333 additions and 44 deletions

View File

@ -70,7 +70,7 @@
<script> <script>
var historyTable = null; var historyTable = null;
hisFirst = true; hisFirst = true;
$(function () { $(function () {
initList(); initList();
@ -468,7 +468,11 @@
let v = {}; let v = {};
v.starttime = (pageAct.dateType == "month" ? new Date($('#getmonth').val()) : new Date($('#his_startdate').val())); v.starttime = (pageAct.dateType == "month" ? new Date($('#getmonth').val()) : new Date($('#his_startdate').val()));
v.endtime = $('#his_enddate input').val() === "" ? null : new Date($('#his_enddate input').val()); v.endtime = $('#his_enddate input').val() === "" ? null : new Date($('#his_enddate input').val());
v.dateType = pageAct.dateType; v.dateType = pageAct.dateType;
v.building_tag = pageAct.buiTag;
v.device_number = pageAct.deviceNumber;
v.device_item = pageAct.deviceItem;
v.deviceComName = pageAct.deviceComName;
objSendData.Data = v; objSendData.Data = v;
$.ajax({ $.ajax({
@ -493,7 +497,7 @@
$(loadEle).Loading("close"); $(loadEle).Loading("close");
}, },
complete: (xhr) => { complete: (xhr) => {
setLoading(false); $(loadEle).Loading("close");
}, },
}); });
} }

View File

@ -1651,4 +1651,37 @@ function btnSelCss(elem) {
}); });
$(elem).removeClass('btn-secondary'); $(elem).removeClass('btn-secondary');
$(elem).addClass('btn-info'); $(elem).addClass('btn-info');
}
/**
* 下載檔案
* @param {any} url
* @param {any} filename
*/
async function downloadByBlob(res, blob, filename, fetchOption, callback = null) {
// 擷取回傳 header > content-disposition (後端定義檔案名稱)
let disposition = res.getResponseHeader("Content-Disposition");
let sDowName = "";
if (disposition) {
// 解析出名稱
sDowName = disposition.split(/filename\*=(?:utf-8'')?(.*)/gi)[1];
if (sDowName.toLowerCase().startsWith("utf-8''"))
sDowName = decodeURIComponent(sDowName.replace(/utf-8''/i, ""));
else sDowName = sDowName.replace(/['"]/g, "");
sDowName = decodeURIComponent(sDowName);
}
// 隱形a標籤
const a = document.createElement("a");
let href = URL.createObjectURL(blob);
if (href) {
a.href = href;
a.download = filename || sDowName || "";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
callback ? callback() : "";
return true;
} else {
return false;
}
} }

View File

@ -16,10 +16,6 @@ using System.Threading.Tasks;
using System.Xml; using System.Xml;
using NPOI.XSSF.UserModel; using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel; using NPOI.SS.UserModel;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.StaticFiles;
using NPOI.HPSF;
using Google.Protobuf.WellKnownTypes;
namespace FrontendWebApi.ApiControllers namespace FrontendWebApi.ApiControllers
{ {
@ -47,22 +43,91 @@ namespace FrontendWebApi.ApiControllers
/// <param name="lhe"></param> /// <param name="lhe"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public async Task<ActionResult<ApiResult<string>>> OpeExportExcel([FromBody] List<HistoryExport> lhe) [Route("api/ExportHistory")]
public FileResult OpeExportExcel([FromBody] HistoryExport lhe)
{ {
ApiResult<string> apiResult = new ApiResult<string>(); ApiResult<string> apiResult = new ApiResult<string>();
if (lhe == null) //if (lhe == null)
{ //{
apiResult.Code = "0001"; // apiResult.Code = "0001";
apiResult.Msg = "沒有資料匯入"; // apiResult.Msg = "沒有資料匯入";
return apiResult; // return apiResult;
} //}
var fileDateName = lhe.dateType == "today" ? lhe.starttime.ToString("yyyy-MM-dd")
: lhe.dateType == "month" ? lhe.starttime.ToString("yyyy-MM")
: lhe.starttime.ToString("yyyy-MM-dd") + "_" + ((DateTime)lhe.endtime).ToString("yyyy-MM-dd");
var fileName = "歷史資料_" + fileDateName + ".xlsx";
IWorkbook workbook = new XSSFWorkbook(); IWorkbook workbook = new XSSFWorkbook();
var fileDateName = lhe.FirstOrDefault().dateType == "month" ? lhe.FirstOrDefault().starttime.ToString("yyyy-MM") : lhe.FirstOrDefault().endtime == null ? lhe.FirstOrDefault().starttime.ToString("yyyy-MM-dd") : lhe.FirstOrDefault().starttime.ToString("yyyy-MM-dd") + "_" + ((DateTime)lhe.FirstOrDefault().endtime).ToString("yyyy-MM-dd");
var fileName = "歷史資料_"+fileDateName+".xlsx";
try try
{ {
#region obix
EDFunction ed = new EDFunction();
var obixApiConfig = new ObixApiConfig();
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
var variableObix = backendRepository.GetAllAsync<KeyValue>(sqlObix).Result;
obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
obixApiConfig.UserName = ed.AESDecrypt(variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
obixApiConfig.Password = ed.AESDecrypt(variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
#endregion obix
#region get device and device_item(point)
var device = backendRepository.GetAllAsync<Device>($"select * from device where deleted = 0 and is_link = 1 and device_number = '{lhe.device_number}'").Result;
var devicePoint = backendRepository.GetAllAsync<Device_item>($"select * from device_item where deleted = 0 and is_link = 1 and is_show_history = 1 and device_building_tag = '{lhe.building_tag}' and points = '{lhe.device_item}'").Result;
#endregion
#region get data from niagara
lhe.endtime = lhe.dateType == "today" ? lhe.starttime : lhe.dateType == "month" ? lhe.starttime.AddMonths(1) : lhe.endtime;
var startTimestamp = string.Format("{0}T00:00:00.000+08:00", lhe.starttime.ToString("yyyy-MM-dd"));
var endTimestamp = string.Format("{0}T23:59:59.000+08:00", lhe.endtime?.ToString("yyyy-MM-dd"));
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{startTimestamp}' />
<abstime name='end' val='{endTimestamp}' />
<reltime name='interval' val='PT15M' />
</obj>";
List<HistoryExport> he = new List<HistoryExport>();
var archiveRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{lhe.deviceComName}/{lhe.device_number}_{lhe.device_item}/~historyRollup/");
archiveRequest.Method = "POST";
archiveRequest.Headers.Add("Authorization", "Basic " + encoded);
archiveRequest.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = archiveRequest.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
var archiveResponse = (HttpWebResponse)archiveRequest.GetResponse();
var archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd();
archiveResponse.Dispose();
archiveResponse.Close();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(archiveResponseContent);
var archiveJson = JsonConvert.SerializeXmlNode(xmlDocument);
var archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson);
if (!archiveJsonResult.ContainsKey("err"))
{
var ArrangeRawDatas = ArrangeRawData(new DeviceNumberPoint() { DeviceNumber = lhe.device_number, Point = lhe.device_item, FullDeviceNumberPoint = lhe.device_number + "_" + lhe.device_item}, archiveJsonResult);
if (ArrangeRawDatas != null && ArrangeRawDatas.Count > 0)
{
foreach (var ard in ArrangeRawDatas)
{
HistoryExport hed = new HistoryExport();
hed.type = devicePoint.Where(x => x.device_building_tag == lhe.building_tag && x.points == ard["@point"].ToString()).Select(x => x.full_name).FirstOrDefault();
hed.deviceName = device.Where(x => x.device_number == ard["@device_number"].ToString()).Select(x => x.full_name).FirstOrDefault();
hed.value = (double)((decimal)ard["@avg_rawdata"]);
hed.timestamp = Convert.ToDateTime(ard["@start_timestamp"].ToString());
hed.building_tag = lhe.building_tag;
he.Add(hed);
}
}
}
#endregion
#region excel設定 #region excel設定
IFont font12 = workbook.CreateFont(); IFont font12 = workbook.CreateFont();
font12.FontName = "新細明體"; font12.FontName = "新細明體";
@ -126,34 +191,31 @@ namespace FrontendWebApi.ApiControllers
cell.CellStyle = styleLine12; cell.CellStyle = styleLine12;
#endregion #endregion
if (lhe.Count > 0) foreach (var d in he)
{ {
foreach (var he in lhe) RowPosition += 1;
row = sheet.CreateRow(RowPosition);
for (var i = 0; i < 4; i++)
{ {
RowPosition += 1; cell = row.CreateCell(i);
row = sheet.CreateRow(RowPosition); if (i == 0)
for (var i = 0; i < 4; i++)
{ {
cell = row.CreateCell(i); cell.SetCellValue(d.type);
if (i == 0)
{
cell.SetCellValue(he.type);
}
if (i == 1)
{
cell.SetCellValue(he.deviceName);
}
if (i == 2)
{
cell.SetCellValue(he.value);
}
if (i == 3)
{
cell.SetCellValue(he.timestamp.ToString("yyyy-MM-dd HH:mm") + ":00");//
}
cell.CellStyle = style12;
} }
if (i == 1)
{
cell.SetCellValue(d.deviceName);
}
if (i == 2)
{
cell.SetCellValue(d.value);
}
if (i == 3)
{
cell.SetCellValue(d.timestamp.ToString("yyyy-MM-dd HH:mm") + ":00");//
}
cell.CellStyle = style12;
} }
} }
} }
@ -162,7 +224,7 @@ namespace FrontendWebApi.ApiControllers
apiResult.Code = "9999"; apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。 Msg: " + exception.Message; apiResult.Msg = "系統內部錯誤,請聯絡管理者。 Msg: " + exception.Message;
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
return Ok(apiResult); throw exception;
} }
var ms = new NpoiMemoryStream var ms = new NpoiMemoryStream
@ -1200,5 +1262,167 @@ namespace FrontendWebApi.ApiControllers
} }
return Ok(apiResult); return Ok(apiResult);
} }
private List<Dictionary<string, object>> ArrangeRawData(DeviceNumberPoint deviceNumberPoint, JObject jsonResult)
{
List<Dictionary<string, object>> arrangeRawDatas = new List<Dictionary<string, object>>();
try
{
var histories = jsonResult["obj"]["list"]["obj"];
var rawdateCount = Convert.ToInt32(jsonResult["obj"]["int"]["@val"].ToString());
if (rawdateCount == 0)
{
return null;
}
if (histories != null && histories.HasValues)
{
if (rawdateCount > 1)
{ //多筆資料
foreach (var history in histories)
{
Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
arrangeRawData.Add("@point", deviceNumberPoint.Point);
//時間
if (history["abstime"] != null && history["abstime"].HasValues)
{
foreach (var abstime in history["abstime"])
{
var name = abstime["@name"].ToString();
switch (name)
{
case "start":
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@start_timestamp", startTimstamp);
break;
case "end":
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@end_timestamp", endTimstamp);
break;
}
}
}
//區間內資料筆數
if (history["int"] != null && history["int"].HasValues)
{
var count = Convert.ToInt32(history["int"]["@val"].ToString());
arrangeRawData.Add("@count_rawdata", count);
}
//整合數值(最大、最小、平均、總和)
if (history["real"] != null && history["real"].HasValues)
{
foreach (var real in history["real"])
{
var name = real["@name"].ToString();
switch (name)
{
case "min":
var min = Convert.ToDecimal(real["@val"].ToString());
arrangeRawData.Add("@min_rawdata", min);
break;
case "max":
var max = Convert.ToDecimal(real["@val"].ToString());
arrangeRawData.Add("@max_rawdata", max);
break;
case "avg":
var avg = Convert.ToDecimal(real["@val"].ToString());
arrangeRawData.Add("@avg_rawdata", avg);
break;
case "sum":
var sum = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@sum_rawdata", sum);
break;
}
}
}
arrangeRawData.Add("@is_complete", 1);
arrangeRawData.Add("@repeat_times", 0);
arrangeRawData.Add("@fail_reason", null);
arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
arrangeRawDatas.Add(arrangeRawData);
}
}
else
{ //單筆資料
Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
arrangeRawData.Add("@point", deviceNumberPoint.Point);
//時間
if (histories["obj"]["abstime"] != null && histories["obj"]["abstime"].HasValues)
{
foreach (var abstime in histories["obj"]["abstime"])
{
var name = abstime["@name"].ToString();
switch (name)
{
case "start":
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@start_timestamp", startTimstamp);
break;
case "end":
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@end_timestamp", endTimstamp);
break;
}
}
}
//區間內資料筆數
if (histories["obj"]["int"] != null && histories["obj"]["int"].HasValues)
{
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
arrangeRawData.Add("@count_rawdata", count);
}
//整合數值(最大、最小、平均、總和)
if (histories["obj"]["real"] != null && histories["obj"]["real"].HasValues)
{
foreach (var real in histories["obj"]["real"])
{
var name = real["@name"].ToString();
switch (name)
{
case "min":
var min = Convert.ToDecimal(real["@val"].ToString());
arrangeRawData.Add("@min_rawdata", min);
break;
case "max":
var max = Convert.ToDecimal(real["@val"].ToString());
arrangeRawData.Add("@max_rawdata", max);
break;
case "avg":
var avg = Convert.ToDecimal(real["@val"].ToString());
arrangeRawData.Add("@avg_rawdata", avg);
break;
case "sum":
var sum = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@sum_rawdata", sum);
break;
}
}
}
arrangeRawData.Add("@is_complete", 1);
arrangeRawData.Add("@repeat_times", 0);
arrangeRawData.Add("@fail_reason", null);
arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
arrangeRawDatas.Add(arrangeRawData);
}
}
return arrangeRawDatas;
}
catch (Exception ex)
{
return arrangeRawDatas;
}
}
} }
} }

View File

@ -295,7 +295,35 @@ namespace FrontendWebApi.Models
public DateTime? endtime { get; set; } public DateTime? endtime { get; set; }
public string dateType { get; set; } public string dateType { get; set; }
public string type { get; set; } public string type { get; set; }
public string device_number { get; set; }
public string device_item { get; set; }
public string deviceComName { get; set; }
public string building_tag { get; set; }
} }
public class DeviceNumberPoint
{
public string DeviceNumber { get; set; }
public string Point { get; set; }
public string FullDeviceNumberPoint { get; set; }
}
public class Device_item : Actor
{
public int id { get; set; }
public string device_item_guid { get; set; }
public string device_area_tag { get; set; }
public string device_building_tag { get; set; }
public string device_system_tag { get; set; }
public string device_name_tag { get; set; }
public string full_name { get; set; }
public string points { get; set; }
public string unit { get; set; }
public byte is_show { get; set; }
public byte is_show_riserDiagram { get; set; }
public byte is_controll { get; set; }
public byte is_bool { get; set; }
public byte is_link { get; set; }
public int is_show_history { get; set; }
}
} }

View File

@ -17,8 +17,8 @@
"Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201 "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
"Port": "js2LutKe+rdjzdxMPQUrvQ==", "Port": "js2LutKe+rdjzdxMPQUrvQ==",
//"Database": "VJB2XC+lAtzuHObDGMVOAA==", //30 //"Database": "VJB2XC+lAtzuHObDGMVOAA==", //30
//"Database": "IgYBsgG2VLKKxFb64j7LOA==", //wsp "Database": "IgYBsgG2VLKKxFb64j7LOA==", //wsp
"Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome //"Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome
//"Database": "siTUcDaC/g2yGTMFWD72Kg==", //tpe_dome_hotel //"Database": "siTUcDaC/g2yGTMFWD72Kg==", //tpe_dome_hotel
//"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office //"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office
//"Database": "Rq7Gn4x6LwBvVtl7GY8LbA==", //MCUT //"Database": "Rq7Gn4x6LwBvVtl7GY8LbA==", //MCUT