TdevWebScadaController.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. using Microsoft.AspNetCore.Authorization;
  2. using Microsoft.AspNetCore.Mvc;
  3. using Microsoft.Extensions.Logging;
  4. using Newtonsoft.Json;
  5. using Ropin.Inspection.Api.Common;
  6. using Ropin.Inspection.Api.Controllers;
  7. using Ropin.Inspection.Model;
  8. using Ropin.Inspection.Service;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Net.Http;
  13. using System.Net;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. using InfluxData.Net.InfluxDb;
  17. using InfluxData.Net.Common.Enums;
  18. using Org.BouncyCastle.Utilities.Collections;
  19. using Ropin.Inspection.Common.Helper;
  20. using System.IO;
  21. using NPOI.SS.UserModel;
  22. using NPOI.XSSF.UserModel;
  23. using Ropin.Inspection.Model.Common;
  24. using InfluxData.Net.InfluxDb.Models.Responses;
  25. using System.Data;
  26. using System.Linq.Expressions;
  27. using Ropin.Core.Common;
  28. using Renci.SshNet;
  29. using Microsoft.AspNetCore.Mvc.RazorPages;
  30. using Microsoft.Extensions.Configuration;
  31. namespace Ropin.Inspection.Api
  32. {
  33. public class TdevWebScadaController : BaseController
  34. {
  35. public ILogger<TdevWebScadaController> _logger { get; }
  36. private readonly ITdevWebScadaService _TdevWebScadaService;
  37. private InfluxDbClient clientDb;
  38. private readonly IConfiguration _configuration;
  39. /// <summary>
  40. /// 构造函数
  41. /// </summary>
  42. /// <param name="TdevWebScadaService"></param>
  43. /// <param name="logger"></param>
  44. public TdevWebScadaController(ITdevWebScadaService TdevWebScadaService, ILogger<TdevWebScadaController> logger, IConfiguration configuration)
  45. {
  46. _TdevWebScadaService = TdevWebScadaService;
  47. _logger = logger;
  48. _configuration = configuration;
  49. }
  50. /// <summary>
  51. /// 通过id获取云组态信息
  52. /// </summary>
  53. /// <param name="id"></param>
  54. /// <returns></returns>
  55. [HttpGet("GetWebScadaAsync/{id}")]
  56. [AllowAnonymous]
  57. public async Task<ApiResult> GetWebScadaAsync(string id)
  58. {
  59. if (string.IsNullOrEmpty(id))
  60. {
  61. return new ApiResult(ReturnCode.GeneralError);
  62. }
  63. try
  64. {
  65. var content = await _TdevWebScadaService.GetConditionAsync(new TdevWebScadaSearchModel { C_ID = id });
  66. return new ApiResult<TdevWebScadaViewModel>(content.FirstOrDefault());
  67. }
  68. catch (Exception ex)
  69. {
  70. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  71. }
  72. }
  73. /// <summary>
  74. /// 获取所有云组态
  75. /// </summary>
  76. /// <returns></returns>
  77. [HttpGet("GetWebScadasAsync")]
  78. public async Task<ApiResult> GetWebScadasAsync()
  79. {
  80. try
  81. {
  82. var contentList = await _TdevWebScadaService.GetAllAsync();
  83. return new ApiResult<IEnumerable<TdevWebScadaViewModel>>(contentList);
  84. }
  85. catch (Exception ex)
  86. {
  87. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  88. }
  89. }
  90. /// <summary>
  91. /// 通过云组态名称条件查询
  92. /// </summary>
  93. /// <param name="searchModel"></param>
  94. /// <returns></returns>
  95. [HttpPost("GetWebScadasByAsync")]
  96. public async Task<ApiResult> GetWebScadasByAsync(TdevWebScadaSearchModel searchModel)
  97. {
  98. if (searchModel == null)
  99. {
  100. return new ApiResult(ReturnCode.ArgsError);
  101. }
  102. searchModel.IsPagination = false;
  103. try
  104. {
  105. var contentList = await _TdevWebScadaService.GetConditionAsync(searchModel);
  106. return new ApiResult<PagesModel<TdevWebScadaViewModel>>(new PagesModel<TdevWebScadaViewModel>(contentList, searchModel));
  107. }
  108. catch (Exception ex)
  109. {
  110. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  111. }
  112. }
  113. /// <summary>
  114. /// 创建云组态
  115. /// </summary>
  116. /// <param name="content"></param>
  117. /// <returns></returns>
  118. [HttpPost("CreateWebScadaAsync")]
  119. public async Task<ApiResult> CreateWebScadaAsync(TdevWebScadaViewModel content)
  120. {
  121. if (content == null)
  122. {
  123. return new ApiResult(ReturnCode.ArgsError);
  124. }
  125. try
  126. {
  127. await _TdevWebScadaService.CreateOneAsync(content);
  128. }
  129. catch (Exception ex)
  130. {
  131. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  132. }
  133. return new ApiResult(ReturnCode.Success);
  134. }
  135. /// <summary>
  136. /// 删除云组态
  137. /// </summary>
  138. /// <param name="id"></param>
  139. /// <returns></returns>
  140. [HttpDelete("DeleteWebScadaAsync/{id}")]
  141. public async Task<ApiResult> DeleteWebScadaAsync(string id)
  142. {
  143. if (string.IsNullOrEmpty(id))
  144. {
  145. return new ApiResult(ReturnCode.GeneralError);
  146. }
  147. try
  148. {
  149. await _TdevWebScadaService.DeleteAsync(id);
  150. }
  151. catch (Exception ex)
  152. {
  153. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  154. }
  155. return new ApiResult(ReturnCode.Success);
  156. }
  157. /// <summary>
  158. /// 更新云组态
  159. /// </summary>
  160. /// <param name="id"></param>
  161. /// <param name="updateModel"></param>
  162. /// <returns></returns>
  163. [HttpPut("UpdateWebScadaAsync/{id}")]
  164. public async Task<ApiResult> UpdateWebScadaAsync(string id, TdevWebScadaUpdateModel updateModel)
  165. {
  166. if (string.IsNullOrEmpty(id))
  167. {
  168. return new ApiResult(ReturnCode.GeneralError);
  169. }
  170. try
  171. {
  172. await _TdevWebScadaService.UpdateAsync(id, updateModel);
  173. }
  174. catch (Exception ex)
  175. {
  176. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  177. }
  178. return new ApiResult(ReturnCode.Success);
  179. }
  180. /// <summary>
  181. /// 取设备点历史数据
  182. /// </summary>
  183. /// <returns></returns>
  184. [HttpGet("GetDevSpotSeries")]
  185. [AllowAnonymous]
  186. public async Task<object> GetDevSpotSeries()
  187. {
  188. try
  189. {
  190. HttpClient httpClient = new HttpClient();
  191. var msgData = new TpushMsgModel
  192. {
  193. };
  194. var httpRequestMessage = new HttpRequestMessage
  195. {
  196. Method = HttpMethod.Get,
  197. RequestUri = new Uri("http://www.dgt.net.cn:94/Device/GetDevSpotSeries"),
  198. Content = new StringContent(JsonConvert.SerializeObject(msgData), Encoding.UTF8, "application/json")
  199. };
  200. var response = await httpClient.SendAsync(httpRequestMessage);
  201. string responseResult = await response.Content.ReadAsStringAsync();
  202. return responseResult;
  203. }
  204. catch (Exception ex)
  205. {
  206. return null;
  207. }
  208. }
  209. /// <summary>
  210. /// 发送命令到设备
  211. /// </summary>
  212. /// <param name="boxNo"></param>
  213. /// <param name="searchModel"></param>
  214. /// <returns></returns>
  215. [HttpPost("PublishDeviceCommandByAsync")]
  216. [AllowAnonymous]
  217. public async Task<object> GetDevicePointByAsync([FromQuery] string boxNo, [FromBody] DeviceCommandModel model)
  218. {
  219. try
  220. {
  221. HttpClient httpClient = new HttpClient();
  222. //var msgData = new TpushMsgModel
  223. //{
  224. //};
  225. var httpRequestMessage = new HttpRequestMessage
  226. {
  227. Method = HttpMethod.Post,
  228. RequestUri = new Uri("http://60.204.212.71:95/api/Value/PublishDeviceCommandByAsync?boxNo=" + boxNo),
  229. Content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json")
  230. };
  231. var response = await httpClient.SendAsync(httpRequestMessage);
  232. string responseResult = await response.Content.ReadAsStringAsync();
  233. return responseResult;
  234. }
  235. catch (Exception ex)
  236. {
  237. return null;
  238. }
  239. }
  240. /// <summary>
  241. /// 条件获取历史数据
  242. /// </summary>
  243. /// <param name="point"></param>
  244. /// <param name="start"></param>
  245. /// <param name="end"></param>
  246. /// <returns></returns>
  247. [HttpPost("GetDevSpotSeriesAsync")]
  248. [AllowAnonymous]
  249. public async Task<object> GetDevSpotSeriesAsync(DevSpotSeriesSearchModel searchModel)
  250. {
  251. if (searchModel == null || searchModel.point.Length == 0)
  252. {
  253. return new ApiResult(ReturnCode.ArgsError);
  254. }
  255. try
  256. {
  257. //var contentList = await _TdevWebScadaService.GetConditionAsync(searchModel);
  258. //return new ApiResult<PagesModel<TdevWebScadaViewModel>>(new PagesModel<TdevWebScadaViewModel>(contentList, searchModel));
  259. //string strStart = searchModel.start.ToString("yyyy-MM-ddTHH:mm:ssZ");
  260. //string strEnd = searchModel.end.ToString("yyyy-MM-ddTHH:mm:ssZ");
  261. string strStart = searchModel.start.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  262. string strEnd = searchModel.end.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  263. string strId = searchModel.point[0];
  264. string strIds = string.Join('|', searchModel.point);
  265. IniInflux();
  266. //传入查询命令,支持多条
  267. var queries = new[]
  268. {
  269. //"SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id = '"+strId+"' order by time desc TZ('Asia/Shanghai')"
  270. "SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id =~/^"+strIds+"$/ order by time desc TZ('Asia/Shanghai')"
  271. //"SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id = '"+strId+"' order by time desc"
  272. };
  273. var dbName = "fanyidb";
  274. //从指定库中查询数据
  275. var response = await clientDb.Client.QueryAsync(queries, dbName);
  276. if (!response.Any()) {
  277. var data = new
  278. {
  279. tabName=new string[0],
  280. data = new PagesModel<object>(null, searchModel)
  281. };
  282. return new ApiResult<object>(data);
  283. }
  284. //得到Serie集合对象(返回执行多个查询的结果)
  285. List<Serie> series = response.ToList();
  286. //取出第一条命令的查询结果,是一个集合
  287. var list = series[0].Values;
  288. var serie1s = list.Select(x => new Serie1
  289. {
  290. Time = x[0].ToString(),
  291. ID = x[1].ToString(),
  292. Value = Convert.ToDecimal(x[2]),
  293. Name = x[3].ToString()
  294. }).ToList();
  295. //var tabName1 = serie1s.GroupBy(x => x.Name).ToList();
  296. var tabName1 = serie1s.GroupBy(x => new { x.ID,x.Name}).ToList();
  297. //var dataTable = serie1s.ToPivotTable(x => x.Name, x => x.Time, x => x.Any() ? x.Average(s => s.Value) : 0);
  298. var dataTable = serie1s.ToPivotTable(x => x.Name, x => x.Time, x => x.Any() ? x.Select(s => s.Value).First() : 0);
  299. string[] tabName = new string[tabName1.Count + 1];
  300. IList<IList<object>> tabVlue = new List<IList<object>>();
  301. tabName[0] = "记录时间";
  302. int num = 1;
  303. //foreach (var item in tabName1)
  304. //{
  305. // tabName[num] = item.Key;
  306. // num++;
  307. //}
  308. foreach (var item in tabName1)
  309. {
  310. int index = tabName1.FindIndex(t => t.Key.ID == searchModel.point[num - 1]);
  311. string vals = tabName1.Find(t => t.Key.ID == searchModel.point[num - 1]).Key.Name;
  312. tabName[num] = vals;
  313. num++;
  314. }
  315. for (int i = 0; i < dataTable.Rows.Count; i++)
  316. {
  317. string[] objects=new string[tabName.Length];
  318. for (int j = 0; j < dataTable.Columns.Count; j++)
  319. {
  320. //var vals = dataTable.Rows[i][j].ToString();
  321. //objects[j]= vals;
  322. if (j>0)
  323. {
  324. int index = tabName1.FindIndex(t => t.Key.ID == searchModel.point[j-1]);
  325. var vals1 = dataTable.Rows[i][index+1].ToString();
  326. objects[j] = vals1;
  327. }
  328. else
  329. {
  330. var vals = dataTable.Rows[i][j].ToString();
  331. objects[j] = vals;
  332. }
  333. }
  334. tabVlue.Add(objects);
  335. }
  336. //从集合中取出第一条数据
  337. //var info_model = list.FirstOrDefault();
  338. //return list;
  339. if (tabVlue.Any())
  340. {
  341. searchModel.TotalCount = tabVlue.First() != null ? tabVlue.ToList().Count : 0;
  342. PagesModel<object> pages = new PagesModel<object>(searchModel.IsPagination ? tabVlue.Skip((searchModel.PageIndex - 1) * searchModel.PageSize).Take(searchModel.PageSize) : tabVlue, searchModel);
  343. var data = new
  344. {
  345. tabName,
  346. data= pages
  347. };
  348. return new ApiResult<object>(data);
  349. }
  350. else
  351. {
  352. var data = new
  353. {
  354. tabName = new string[0],
  355. data = new PagesModel<object>(null, searchModel)
  356. };
  357. return new ApiResult<object>(data);
  358. }
  359. }
  360. catch (Exception ex)
  361. {
  362. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  363. }
  364. }
  365. private void IniInflux()
  366. {
  367. //连接InfluxDb的API地址、账号、密码
  368. var infuxUrl = _configuration["IniInflux:infuxUrl"]?.ToString(); //"http://60.204.212.71:8085/";
  369. var infuxUser = _configuration["IniInflux:infuxUser"]?.ToString(); //"admin";
  370. var infuxPwd = _configuration["IniInflux:infuxPwd"]?.ToString(); // "123456";
  371. //创建InfluxDbClient实例
  372. clientDb = new InfluxDbClient(infuxUrl, infuxUser, infuxPwd, InfluxDbVersion.Latest);
  373. }
  374. /// <summary>
  375. /// 发送邮件(附件为历史记录)-原方法
  376. /// </summary>
  377. /// <param name="searchModel"></param>
  378. /// <returns></returns>
  379. [HttpPost("SendSpotSeriesToEmail0")]
  380. [AllowAnonymous]
  381. public async Task<ApiResult> SendRecordsToEmail0(SendSpotSeriesEmailModel searchModel)
  382. {
  383. if (searchModel == null)
  384. {
  385. return new ApiResult(ReturnCode.ArgsError);
  386. }
  387. try
  388. {
  389. string strStart = searchModel.start.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  390. string strEnd = searchModel.end.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  391. string strId = searchModel.point[0];
  392. string strIds = string.Join('|', searchModel.point);
  393. IniInflux();
  394. //传入查询命令,支持多条
  395. var queries = new[]
  396. {
  397. "SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id =~/^"+strIds+"$/ order by time desc TZ('Asia/Shanghai')"
  398. };
  399. var dbName = "fanyidb";
  400. //从指定库中查询数据
  401. var response = await clientDb.Client.QueryAsync(queries, dbName);
  402. if (!response.Any())
  403. {
  404. string msg = searchModel.start + "到" + searchModel.end + "日期之间没有查找到数据!";
  405. return new ApiResult(ReturnCode.DataError, msg);
  406. }
  407. //得到Serie集合对象(返回执行多个查询的结果)
  408. var series = response.ToList();
  409. //取出第一条命令的查询结果,是一个集合
  410. var list = series[0].Values;
  411. var serie1s = list.Select(x => new Serie1
  412. {
  413. Time = x[0].ToString(),
  414. ID = x[1].ToString(),
  415. Value = Convert.ToDecimal(x[2]),
  416. Name = x[3].ToString()
  417. }).ToList();
  418. var dataTable = serie1s.ToPivotTable(x => x.Name, x => x.Time, x => x.Any() ? x.Sum(s => s.Value) : 0);
  419. IWorkbook workbook = new XSSFWorkbook();
  420. ISheet sheet = workbook.CreateSheet("sheet1");
  421. var headRow = sheet.CreateRow(0);
  422. headRow.CreateCell(0).SetCellValue("日期");
  423. for (int i = 1; i < dataTable.Columns.Count; i++)
  424. {
  425. headRow.CreateCell(i).SetCellValue(dataTable.Columns[i].ColumnName);
  426. }
  427. //第二行,列名
  428. IFont font1 = workbook.CreateFont();
  429. font1.IsBold = true;
  430. font1.FontHeightInPoints = 12;
  431. font1.FontName = "宋体";
  432. ICellStyle headCellStyle = workbook.CreateCellStyle();
  433. headCellStyle.SetFont(font1);
  434. //边框
  435. headCellStyle.BorderBottom = BorderStyle.Thin;
  436. headCellStyle.BorderLeft = BorderStyle.Thin;
  437. headCellStyle.BorderRight = BorderStyle.Thin;
  438. headCellStyle.BorderTop = BorderStyle.Thin;
  439. foreach (var item in headRow.Cells)
  440. {
  441. item.CellStyle = headCellStyle;
  442. }
  443. int start = 1;
  444. IFont font3 = workbook.CreateFont();
  445. font3.FontHeightInPoints = 9;
  446. font3.FontName = "宋体";
  447. ICellStyle contentCellStyle = workbook.CreateCellStyle();
  448. contentCellStyle.SetFont(font3);
  449. //边框
  450. contentCellStyle.BorderBottom = BorderStyle.Thin;
  451. contentCellStyle.BorderLeft = BorderStyle.Thin;
  452. contentCellStyle.BorderRight = BorderStyle.Thin;
  453. contentCellStyle.BorderTop = BorderStyle.Thin;
  454. for (int i = 0; i < dataTable.Rows.Count; i++)
  455. {
  456. var row = sheet.CreateRow(start);
  457. for (int j = 0; j < dataTable.Columns.Count; j++)
  458. {
  459. if (j==0)
  460. {
  461. row.CreateCell(j).SetCellValue(dataTable.Rows[i][j].ToString());
  462. }
  463. else
  464. {
  465. row.CreateCell(j).SetCellValue(Convert.ToDouble(dataTable.Rows[i][j]));
  466. }
  467. }
  468. start++;
  469. foreach (var cell in row.Cells)
  470. {
  471. cell.CellStyle = contentCellStyle;
  472. }
  473. }
  474. //foreach (var item in list)
  475. //{
  476. // var row = sheet.CreateRow(start);
  477. // row.CreateCell(0).SetCellValue(item[0].ToString());
  478. // row.CreateCell(1).SetCellValue(Convert.ToDouble(item[2]));
  479. // start++;
  480. // foreach (var cell in row.Cells)
  481. // {
  482. // cell.CellStyle = contentCellStyle;
  483. // }
  484. //}
  485. // 自适应单元格
  486. for (int i = 0; i < sheet.LastRowNum; i++)
  487. {
  488. sheet.AutoSizeRow(i);
  489. }
  490. for (int i = 0; i < 7; i++)
  491. {
  492. sheet.AutoSizeColumn(i, true);
  493. }
  494. using (var stream = new NpoiMemoryStream())
  495. {
  496. workbook.Write(stream);
  497. stream.Seek(0, SeekOrigin.Begin);
  498. await Task.Run(() =>
  499. {
  500. EmailHelper.SendEmail(searchModel.Mails, $"{searchModel.DevName}设备点历史记录{searchModel.start}-{searchModel.end}", "", "报表见附件", $"{searchModel.DevName}设备点历史记录{searchModel.start}-{searchModel.end}报表.xlsx", "application/vnd.ms-excel", stream);
  501. });
  502. }
  503. }
  504. catch (Exception ex)
  505. {
  506. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  507. }
  508. return new ApiResult(ReturnCode.Success);
  509. }
  510. /// <summary>
  511. /// 发送邮件(附件为历史记录)-速度优化
  512. /// </summary>
  513. /// <param name="searchModel"></param>
  514. /// <returns></returns>
  515. [HttpPost("SendSpotSeriesToEmail")]
  516. [AllowAnonymous]
  517. public async Task<ApiResult> SendRecordsToEmail(SendSpotSeriesEmailModel searchModel)
  518. {
  519. if (searchModel == null)
  520. {
  521. return new ApiResult(ReturnCode.ArgsError);
  522. }
  523. try
  524. {
  525. string strStart = searchModel.start.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  526. string strEnd = searchModel.end.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  527. string strId = searchModel.point[0];
  528. string strIds = string.Join('|', searchModel.point);
  529. IniInflux();
  530. //传入查询命令,支持多条
  531. var queries = new[]
  532. {
  533. "SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id =~/^"+strIds+"$/ order by time desc TZ('Asia/Shanghai')"
  534. };
  535. var dbName = "fanyidb";
  536. //从指定库中查询数据
  537. var response = await clientDb.Client.QueryAsync(queries, dbName);
  538. if (!response.Any())
  539. {
  540. string msg = searchModel.start + "到" + searchModel.end + "日期之间没有查找到数据!";
  541. return new ApiResult(ReturnCode.DataError, msg);
  542. }
  543. //得到Serie集合对象(返回执行多个查询的结果)
  544. var series = response.ToList();
  545. //取出第一条命令的查询结果,是一个集合
  546. var list = series[0].Values;
  547. var serie1s = list.Select(x => new Serie1
  548. {
  549. Time = x[0].ToString(),
  550. ID = x[1].ToString(),
  551. Value = Convert.ToDecimal(x[2]),
  552. Name = x[3].ToString()
  553. }).ToList();
  554. var tableColumns = serie1s.Select(x => x.Name).Distinct().ToList();
  555. var tabName1 = serie1s.GroupBy(x => new { x.ID, x.Name }).ToList();
  556. var rows = serie1s.GroupBy(item => item.Time).
  557. Select(rowGroup => new {
  558. keys = rowGroup.Key,
  559. values = tableColumns.GroupJoin(
  560. rowGroup,
  561. p => p,
  562. n => n.Name,
  563. (p, t) => t.Select(item => item.Value).First()
  564. )
  565. });
  566. IWorkbook workbook = new XSSFWorkbook();
  567. ISheet sheet = workbook.CreateSheet("sheet1");
  568. var headRow = sheet.CreateRow(0);
  569. headRow.CreateCell(0).SetCellValue("日期");
  570. for (int i = 1; i < tableColumns.Count + 1; i++)
  571. {
  572. int index = tabName1.FindIndex(t => t.Key.ID == searchModel.point[i - 1]);
  573. string vals = tabName1.Find(t => t.Key.ID == searchModel.point[i - 1]).Key.Name;
  574. headRow.CreateCell(i).SetCellValue(vals.ToString());
  575. //headRow.CreateCell(i).SetCellValue(tableColumns[i - 1].ToString());
  576. }
  577. #region 样式
  578. //第二行,列名
  579. IFont font1 = workbook.CreateFont();
  580. font1.IsBold = true;
  581. font1.FontHeightInPoints = 12;
  582. font1.FontName = "宋体";
  583. ICellStyle headCellStyle = workbook.CreateCellStyle();
  584. headCellStyle.SetFont(font1);
  585. //边框
  586. headCellStyle.BorderBottom = BorderStyle.Thin;
  587. headCellStyle.BorderLeft = BorderStyle.Thin;
  588. headCellStyle.BorderRight = BorderStyle.Thin;
  589. headCellStyle.BorderTop = BorderStyle.Thin;
  590. foreach (var item in headRow.Cells)
  591. {
  592. item.CellStyle = headCellStyle;
  593. }
  594. int start = 1;
  595. IFont font3 = workbook.CreateFont();
  596. font3.FontHeightInPoints = 9;
  597. font3.FontName = "宋体";
  598. ICellStyle contentCellStyle = workbook.CreateCellStyle();
  599. contentCellStyle.SetFont(font3);
  600. //边框
  601. contentCellStyle.BorderBottom = BorderStyle.Thin;
  602. contentCellStyle.BorderLeft = BorderStyle.Thin;
  603. contentCellStyle.BorderRight = BorderStyle.Thin;
  604. contentCellStyle.BorderTop = BorderStyle.Thin;
  605. #endregion
  606. foreach (var item in rows)
  607. {
  608. var items = item.values.Cast<object>().ToList();
  609. var row = sheet.CreateRow(start);
  610. row.CreateCell(0).SetCellValue(item.keys);
  611. int j = 1;
  612. foreach (var ite in items)
  613. {
  614. //string vals= EnumerableHelper.GetValues(ite.ToString());
  615. //row.CreateCell(j).SetCellValue(Convert.ToDouble(ite));
  616. int index = tabName1.FindIndex(t => t.Key.ID == searchModel.point[j-1]);
  617. double vals = Convert.ToDouble(items[index]);
  618. row.CreateCell(j).SetCellValue(vals);
  619. j++;
  620. }
  621. start++;
  622. foreach (var cell in row.Cells)
  623. {
  624. cell.CellStyle = contentCellStyle;
  625. }
  626. }
  627. // 自适应单元格
  628. for (int i = 0; i < sheet.LastRowNum; i++)
  629. {
  630. sheet.AutoSizeRow(i);
  631. }
  632. for (int i = 0; i < 7; i++)
  633. {
  634. sheet.AutoSizeColumn(i, true);
  635. }
  636. string emailName = $"{searchModel.DevName}设备点历史记录{searchModel.start.ToString("yyyy-MM-dd HH:mm:ss")}至{searchModel.end.ToString("yyyy-MM-dd HH:mm:ss")}";
  637. using (var stream = new NpoiMemoryStream()) {
  638. workbook.Write(stream);
  639. stream.Seek(0, SeekOrigin.Begin);
  640. await Task.Run(() =>
  641. {
  642. EmailHelper.SendEmail(searchModel.Mails, emailName, "", "报表见附件", $"{emailName}.xlsx", "application/vnd.ms-excel", stream);
  643. });
  644. }
  645. }
  646. catch (Exception ex)
  647. {
  648. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  649. }
  650. return new ApiResult(ReturnCode.Success);
  651. }
  652. /// <summary>
  653. /// 条件获取历史数据-折线图
  654. /// </summary>
  655. /// <param name="searchModel"></param>
  656. /// <returns></returns>
  657. [HttpPost("GetDevSpotSeriesLineChart")]
  658. [AllowAnonymous]
  659. public async Task<object> GetDevSpotSeriesLineChart(DevSpotSeriesSearchModel searchModel)
  660. {
  661. if (searchModel == null || searchModel.point.Length == 0)
  662. {
  663. return new ApiResult(ReturnCode.ArgsError);
  664. }
  665. try
  666. {
  667. string strStart = searchModel.start.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  668. string strEnd = searchModel.end.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  669. string strId = searchModel.point[0];
  670. string strIds = string.Join('|', searchModel.point);
  671. IniInflux();
  672. //传入查询命令,支持多条
  673. var queries = new[]
  674. {
  675. "SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id =~/^"+strIds+"$/ order by time desc TZ('Asia/Shanghai')"
  676. };
  677. var dbName = "fanyidb";
  678. //从指定库中查询数据
  679. var response = await clientDb.Client.QueryAsync(queries, dbName);
  680. if (!response.Any())
  681. {
  682. return new ApiResult<object>(new
  683. {
  684. x = new List<string>(),
  685. y = new List<YEntity>()
  686. });
  687. }
  688. //得到Serie集合对象(返回执行多个查询的结果)
  689. List<Serie> series = response.ToList();
  690. //取出第一条命令的查询结果,是一个集合
  691. var list = series[0].Values;
  692. var serie1s = list.Select(x => new Serie1
  693. {
  694. Time = x[0].ToString(),
  695. ID = x[1].ToString(),
  696. Value = Convert.ToDecimal(x[2]),
  697. Name = x[3].ToString()
  698. }).ToList();
  699. var tabName1 = serie1s.GroupBy(x => x.Name).ToList();
  700. var dateArry = (serie1s.OrderBy(x=>x.Time)).GroupBy(x => x.Time).ToList();
  701. List<string> tabName =new List<string>();
  702. foreach (var item in tabName1)
  703. {
  704. tabName.Add(item.Key);
  705. }
  706. List<string> x = new List<string>();
  707. foreach (var item in dateArry)
  708. {
  709. x.Add(item.Key);
  710. }
  711. List<YEntity> yEntities = new List<YEntity>();
  712. foreach (var item in x)
  713. {
  714. var ll= serie1s.Where(t => t.Time == item).ToList();
  715. if (yEntities.Count==0)
  716. {
  717. foreach (var index in tabName)
  718. {
  719. YEntity yEntity = new YEntity();
  720. yEntity.data = new List<decimal>();
  721. var aa = (ll==null?null:(ll.Find(t => t.Name == index)));
  722. yEntity.name = index;
  723. if (aa!=null)
  724. {
  725. yEntity.data.Add(aa.Value);
  726. }
  727. else
  728. {
  729. yEntity.data.Add(0);
  730. }
  731. yEntities.Add(yEntity);
  732. }
  733. }
  734. else
  735. {
  736. foreach (var index in tabName)
  737. {
  738. var yData= yEntities.Find(y => y.name == index);
  739. if (yData != null)
  740. {
  741. var aa = (ll == null ? null : (ll.Find(t => t.Name == index)));
  742. if (aa != null)
  743. {
  744. yData.data.Add(aa.Value);
  745. }
  746. else
  747. {
  748. yData.data.Add(0);
  749. }
  750. }
  751. else
  752. {
  753. YEntity yEntity = new YEntity();
  754. yEntity.data = new List<decimal>();
  755. var aa = (ll == null ? null : (ll.Find(t => t.Name == index)));
  756. yEntity.name = index;
  757. if (aa != null)
  758. {
  759. yEntity.data.Add(aa.Value);
  760. }
  761. else
  762. {
  763. yEntity.data.Add(0);
  764. }
  765. yEntities.Add(yEntity);
  766. }
  767. }
  768. }
  769. }
  770. var data = new
  771. {
  772. x,
  773. y=yEntities,
  774. };
  775. return new ApiResult<object>(data);
  776. }
  777. catch (Exception ex)
  778. {
  779. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  780. }
  781. }
  782. }
  783. public class Serie1
  784. {
  785. public string Time { get; set; }
  786. public string Name { get; set; }
  787. public decimal Value { get; set; }
  788. public string ID { get; set; }
  789. }
  790. public class YEntity
  791. {
  792. public string name { get; set; }
  793. public List<decimal> data { get; set; }
  794. }
  795. }