[前端] 修改歷史資料前端程序, 增加下載function
[後端] 修改歷史資料下載流程
This commit is contained in:
parent
3e8daf7759
commit
100a5bdc07
@ -70,7 +70,7 @@
|
||||
|
||||
<script>
|
||||
var historyTable = null;
|
||||
hisFirst = true;
|
||||
hisFirst = true;
|
||||
$(function () {
|
||||
initList();
|
||||
|
||||
@ -468,7 +468,11 @@
|
||||
let v = {};
|
||||
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.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;
|
||||
|
||||
$.ajax({
|
||||
@ -493,7 +497,7 @@
|
||||
$(loadEle).Loading("close");
|
||||
},
|
||||
complete: (xhr) => {
|
||||
setLoading(false);
|
||||
$(loadEle).Loading("close");
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -1652,3 +1652,36 @@ function btnSelCss(elem) {
|
||||
$(elem).removeClass('btn-secondary');
|
||||
$(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;
|
||||
}
|
||||
}
|
@ -16,10 +16,6 @@ using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using NPOI.XSSF.UserModel;
|
||||
using NPOI.SS.UserModel;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using NPOI.HPSF;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace FrontendWebApi.ApiControllers
|
||||
{
|
||||
@ -47,22 +43,91 @@ namespace FrontendWebApi.ApiControllers
|
||||
/// <param name="lhe"></param>
|
||||
/// <returns></returns>
|
||||
[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>();
|
||||
|
||||
if (lhe == null)
|
||||
{
|
||||
apiResult.Code = "0001";
|
||||
apiResult.Msg = "沒有資料匯入";
|
||||
return apiResult;
|
||||
}
|
||||
//if (lhe == null)
|
||||
//{
|
||||
// apiResult.Code = "0001";
|
||||
// apiResult.Msg = "沒有資料匯入";
|
||||
// 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();
|
||||
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
|
||||
{
|
||||
#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設定
|
||||
IFont font12 = workbook.CreateFont();
|
||||
font12.FontName = "新細明體";
|
||||
@ -126,34 +191,31 @@ namespace FrontendWebApi.ApiControllers
|
||||
cell.CellStyle = styleLine12;
|
||||
#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;
|
||||
row = sheet.CreateRow(RowPosition);
|
||||
for (var i = 0; i < 4; i++)
|
||||
cell = row.CreateCell(i);
|
||||
if (i == 0)
|
||||
{
|
||||
cell = row.CreateCell(i);
|
||||
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;
|
||||
cell.SetCellValue(d.type);
|
||||
}
|
||||
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.Msg = "系統內部錯誤,請聯絡管理者。 Msg: " + exception.Message;
|
||||
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
|
||||
return Ok(apiResult);
|
||||
throw exception;
|
||||
}
|
||||
|
||||
var ms = new NpoiMemoryStream
|
||||
@ -1200,5 +1262,167 @@ namespace FrontendWebApi.ApiControllers
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +295,35 @@ namespace FrontendWebApi.Models
|
||||
public DateTime? endtime { get; set; }
|
||||
public string dateType { 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; }
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,8 @@
|
||||
"Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
|
||||
"Port": "js2LutKe+rdjzdxMPQUrvQ==",
|
||||
//"Database": "VJB2XC+lAtzuHObDGMVOAA==", //30
|
||||
//"Database": "IgYBsgG2VLKKxFb64j7LOA==", //wsp
|
||||
"Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome
|
||||
"Database": "IgYBsgG2VLKKxFb64j7LOA==", //wsp
|
||||
//"Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome
|
||||
//"Database": "siTUcDaC/g2yGTMFWD72Kg==", //tpe_dome_hotel
|
||||
//"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office
|
||||
//"Database": "Rq7Gn4x6LwBvVtl7GY8LbA==", //MCUT
|
||||
|
Loading…
Reference in New Issue
Block a user