TdevWebScadaController.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  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. using Castle.Core.Internal;
  32. namespace Ropin.Inspection.Api
  33. {
  34. public class TdevWebScadaController : BaseController
  35. {
  36. public ILogger<TdevWebScadaController> _logger { get; }
  37. private readonly ITdevWebScadaService _TdevWebScadaService;
  38. private InfluxDbClient clientDb;
  39. private readonly IConfiguration _configuration;
  40. /// <summary>
  41. /// 构造函数
  42. /// </summary>
  43. /// <param name="TdevWebScadaService"></param>
  44. /// <param name="logger"></param>
  45. public TdevWebScadaController(ITdevWebScadaService TdevWebScadaService, ILogger<TdevWebScadaController> logger, IConfiguration configuration)
  46. {
  47. _TdevWebScadaService = TdevWebScadaService;
  48. _logger = logger;
  49. _configuration = configuration;
  50. }
  51. /// <summary>
  52. /// 通过id获取云组态信息
  53. /// </summary>
  54. /// <param name="id"></param>
  55. /// <returns></returns>
  56. [HttpGet("GetWebScadaAsync/{id}")]
  57. [AllowAnonymous]
  58. public async Task<ApiResult> GetWebScadaAsync(string id)
  59. {
  60. if (string.IsNullOrEmpty(id))
  61. {
  62. return new ApiResult(ReturnCode.GeneralError);
  63. }
  64. try
  65. {
  66. var content = await _TdevWebScadaService.GetConditionAsync(new TdevWebScadaSearchModel { C_ID = id });
  67. return new ApiResult<TdevWebScadaViewModel>(content.FirstOrDefault());
  68. }
  69. catch (Exception ex)
  70. {
  71. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  72. }
  73. }
  74. /// <summary>
  75. /// 获取所有云组态
  76. /// </summary>
  77. /// <returns></returns>
  78. [HttpGet("GetWebScadasAsync")]
  79. public async Task<ApiResult> GetWebScadasAsync()
  80. {
  81. try
  82. {
  83. var contentList = await _TdevWebScadaService.GetAllAsync();
  84. return new ApiResult<IEnumerable<TdevWebScadaViewModel>>(contentList);
  85. }
  86. catch (Exception ex)
  87. {
  88. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  89. }
  90. }
  91. /// <summary>
  92. /// 通过云组态名称条件查询
  93. /// </summary>
  94. /// <param name="searchModel"></param>
  95. /// <returns></returns>
  96. [HttpPost("GetWebScadasByAsync")]
  97. public async Task<ApiResult> GetWebScadasByAsync(TdevWebScadaSearchModel searchModel)
  98. {
  99. if (searchModel == null)
  100. {
  101. return new ApiResult(ReturnCode.ArgsError);
  102. }
  103. searchModel.IsPagination = false;
  104. try
  105. {
  106. var contentList = await _TdevWebScadaService.GetConditionAsync(searchModel);
  107. return new ApiResult<PagesModel<TdevWebScadaViewModel>>(new PagesModel<TdevWebScadaViewModel>(contentList, searchModel));
  108. }
  109. catch (Exception ex)
  110. {
  111. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  112. }
  113. }
  114. /// <summary>
  115. /// 创建云组态
  116. /// </summary>
  117. /// <param name="content"></param>
  118. /// <returns></returns>
  119. [HttpPost("CreateWebScadaAsync")]
  120. public async Task<ApiResult> CreateWebScadaAsync(TdevWebScadaViewModel content)
  121. {
  122. if (content == null)
  123. {
  124. return new ApiResult(ReturnCode.ArgsError);
  125. }
  126. try
  127. {
  128. await _TdevWebScadaService.CreateOneAsync(content);
  129. }
  130. catch (Exception ex)
  131. {
  132. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  133. }
  134. return new ApiResult(ReturnCode.Success);
  135. }
  136. /// <summary>
  137. /// 删除云组态
  138. /// </summary>
  139. /// <param name="id"></param>
  140. /// <returns></returns>
  141. [HttpDelete("DeleteWebScadaAsync/{id}")]
  142. public async Task<ApiResult> DeleteWebScadaAsync(string id)
  143. {
  144. if (string.IsNullOrEmpty(id))
  145. {
  146. return new ApiResult(ReturnCode.GeneralError);
  147. }
  148. try
  149. {
  150. await _TdevWebScadaService.DeleteAsync(id);
  151. }
  152. catch (Exception ex)
  153. {
  154. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  155. }
  156. return new ApiResult(ReturnCode.Success);
  157. }
  158. /// <summary>
  159. /// 更新云组态
  160. /// </summary>
  161. /// <param name="id"></param>
  162. /// <param name="updateModel"></param>
  163. /// <returns></returns>
  164. [HttpPut("UpdateWebScadaAsync/{id}")]
  165. public async Task<ApiResult> UpdateWebScadaAsync(string id, TdevWebScadaUpdateModel updateModel)
  166. {
  167. if (string.IsNullOrEmpty(id))
  168. {
  169. return new ApiResult(ReturnCode.GeneralError);
  170. }
  171. try
  172. {
  173. await _TdevWebScadaService.UpdateAsync(id, updateModel);
  174. }
  175. catch (Exception ex)
  176. {
  177. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  178. }
  179. return new ApiResult(ReturnCode.Success);
  180. }
  181. /// <summary>
  182. /// 取设备点历史数据
  183. /// </summary>
  184. /// <returns></returns>
  185. [HttpGet("GetDevSpotSeries")]
  186. [AllowAnonymous]
  187. public async Task<object> GetDevSpotSeries()
  188. {
  189. try
  190. {
  191. HttpClient httpClient = new HttpClient();
  192. var msgData = new TpushMsgModel
  193. {
  194. };
  195. var httpRequestMessage = new HttpRequestMessage
  196. {
  197. Method = HttpMethod.Get,
  198. RequestUri = new Uri("http://www.dgt.net.cn:94/Device/GetDevSpotSeries"),
  199. Content = new StringContent(JsonConvert.SerializeObject(msgData), Encoding.UTF8, "application/json")
  200. };
  201. var response = await httpClient.SendAsync(httpRequestMessage);
  202. string responseResult = await response.Content.ReadAsStringAsync();
  203. return responseResult;
  204. }
  205. catch (Exception ex)
  206. {
  207. return null;
  208. }
  209. }
  210. /// <summary>
  211. /// 发送命令到设备
  212. /// </summary>
  213. /// <param name="boxNo"></param>
  214. /// <param name="searchModel"></param>
  215. /// <returns></returns>
  216. [HttpPost("PublishDeviceCommandByAsync")]
  217. [AllowAnonymous]
  218. public async Task<object> GetDevicePointByAsync([FromQuery] string boxNo, [FromBody] DeviceCommandModel model)
  219. {
  220. try
  221. {
  222. HttpClient httpClient = new HttpClient();
  223. //var msgData = new TpushMsgModel
  224. //{
  225. //};
  226. var httpRequestMessage = new HttpRequestMessage
  227. {
  228. Method = HttpMethod.Post,
  229. RequestUri = new Uri("http://60.204.212.71:95/api/Value/PublishDeviceCommandByAsync?boxNo=" + boxNo),
  230. Content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json")
  231. };
  232. var response = await httpClient.SendAsync(httpRequestMessage);
  233. string responseResult = await response.Content.ReadAsStringAsync();
  234. return responseResult;
  235. }
  236. catch (Exception ex)
  237. {
  238. return null;
  239. }
  240. }
  241. /// <summary>
  242. /// 条件获取历史数据
  243. /// </summary>
  244. /// <param name="point"></param>
  245. /// <param name="start"></param>
  246. /// <param name="end"></param>
  247. /// <returns></returns>
  248. [HttpPost("GetDevSpotSeriesAsync")]
  249. [AllowAnonymous]
  250. public async Task<object> GetDevSpotSeriesAsync(DevSpotSeriesSearchModel searchModel)
  251. {
  252. if (searchModel == null || searchModel.point.Length == 0)
  253. {
  254. return new ApiResult(ReturnCode.ArgsError);
  255. }
  256. try
  257. {
  258. //var contentList = await _TdevWebScadaService.GetConditionAsync(searchModel);
  259. //return new ApiResult<PagesModel<TdevWebScadaViewModel>>(new PagesModel<TdevWebScadaViewModel>(contentList, searchModel));
  260. //string strStart = searchModel.start.ToString("yyyy-MM-ddTHH:mm:ssZ");
  261. //string strEnd = searchModel.end.ToString("yyyy-MM-ddTHH:mm:ssZ");
  262. string strStart = searchModel.start.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  263. string strEnd = searchModel.end.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  264. string strId = searchModel.point[0];
  265. string strIds = string.Join('|', searchModel.point);
  266. IniInflux();
  267. //传入查询命令,支持多条
  268. var queries = new[]
  269. {
  270. //"SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id = '"+strId+"' order by time desc TZ('Asia/Shanghai')"
  271. "SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id =~/^"+strIds+"$/ order by time desc TZ('Asia/Shanghai')"
  272. //"SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id = '"+strId+"' order by time desc"
  273. };
  274. var dbName = "fanyidb";
  275. //从指定库中查询数据
  276. var response = await clientDb.Client.QueryAsync(queries, dbName);
  277. if (!response.Any()) {
  278. var data = new
  279. {
  280. tabName=new string[0],
  281. data = new PagesModel<object>(null, searchModel)
  282. };
  283. return new ApiResult<object>(data);
  284. }
  285. //得到Serie集合对象(返回执行多个查询的结果)
  286. List<Serie> series = response.ToList();
  287. //取出第一条命令的查询结果,是一个集合
  288. var list = series[0].Values;
  289. var serie1s = list.Select(x => new Serie1
  290. {
  291. Time = x[0].ToString(),
  292. ID = x[1].ToString(),
  293. Value = Convert.ToDecimal(x[2]),
  294. Name = x[3].ToString()
  295. }).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.Select(s => s.Value).FirstOrDefault() : 0);
  298. //var sortedAndFilteredTabName1 = searchModel.point
  299. // .Select(point => tabName1.FirstOrDefault(g => g.Key.ID == point))
  300. // .Where(g => g != null)
  301. // .ToList();
  302. var sortedAndFilteredTabName1 = searchModel.point
  303. .Select(point => new
  304. {
  305. Group = tabName1.FirstOrDefault(g => g.Key.ID == point),
  306. Index = tabName1.FindIndex(g => g.Key.ID == point)
  307. })
  308. .Where(item => item.Group != null)
  309. .ToList();
  310. string[] tabName = new string[sortedAndFilteredTabName1.Count + 1];
  311. IList<IList<object>> tabVlue = new List<IList<object>>();
  312. tabName[0] = "记录时间";
  313. int num = 1;
  314. foreach (var item in sortedAndFilteredTabName1)
  315. {
  316. string valName = item.Group.Key.Name;
  317. tabName[num] = valName;
  318. num++;
  319. }
  320. for (int i = 0; i < dataTable.Rows.Count; i++)
  321. {
  322. string[] objects=new string[tabName.Length];
  323. for (int j = 0; j < dataTable.Columns.Count; j++)
  324. {
  325. if (j>0)
  326. {
  327. int index = sortedAndFilteredTabName1[j - 1].Index;
  328. var vals1 = dataTable.Rows[i][index+1].ToString();
  329. objects[j] = vals1;
  330. }
  331. else
  332. {
  333. var vals = dataTable.Rows[i][j].ToString();
  334. objects[j] = vals;
  335. }
  336. }
  337. tabVlue.Add(objects);
  338. }
  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).FirstOrDefault()
  564. )
  565. });
  566. var sortedAndFilteredTabName = searchModel.point
  567. .Select(point => new
  568. {
  569. Group = tabName1.FirstOrDefault(g => g.Key.ID == point),
  570. Index = tabName1.FindIndex(g => g.Key.ID == point)
  571. })
  572. .Where(item => item.Group != null)
  573. .ToList();
  574. IWorkbook workbook = new XSSFWorkbook();
  575. ISheet sheet = workbook.CreateSheet("sheet1");
  576. var headRow = sheet.CreateRow(0);
  577. headRow.CreateCell(0).SetCellValue("日期");
  578. for (int i = 1; i < tableColumns.Count + 1; i++)
  579. {
  580. string vals = sortedAndFilteredTabName[i - 1].Group.Key.Name.ToString();
  581. headRow.CreateCell(i).SetCellValue(vals);
  582. }
  583. #region 样式
  584. //第二行,列名
  585. IFont font1 = workbook.CreateFont();
  586. font1.IsBold = true;
  587. font1.FontHeightInPoints = 12;
  588. font1.FontName = "宋体";
  589. ICellStyle headCellStyle = workbook.CreateCellStyle();
  590. headCellStyle.SetFont(font1);
  591. //边框
  592. headCellStyle.BorderBottom = BorderStyle.Thin;
  593. headCellStyle.BorderLeft = BorderStyle.Thin;
  594. headCellStyle.BorderRight = BorderStyle.Thin;
  595. headCellStyle.BorderTop = BorderStyle.Thin;
  596. foreach (var item in headRow.Cells)
  597. {
  598. item.CellStyle = headCellStyle;
  599. }
  600. int start = 1;
  601. IFont font3 = workbook.CreateFont();
  602. font3.FontHeightInPoints = 9;
  603. font3.FontName = "宋体";
  604. ICellStyle contentCellStyle = workbook.CreateCellStyle();
  605. contentCellStyle.SetFont(font3);
  606. //边框
  607. contentCellStyle.BorderBottom = BorderStyle.Thin;
  608. contentCellStyle.BorderLeft = BorderStyle.Thin;
  609. contentCellStyle.BorderRight = BorderStyle.Thin;
  610. contentCellStyle.BorderTop = BorderStyle.Thin;
  611. #endregion
  612. foreach (var item in rows)
  613. {
  614. var items = item.values.Cast<object>().ToList();
  615. var row = sheet.CreateRow(start);
  616. row.CreateCell(0).SetCellValue(item.keys);
  617. int j = 1;
  618. foreach (var ite in items)
  619. {
  620. int index = sortedAndFilteredTabName[j - 1].Index; ;
  621. double vals = Convert.ToDouble(items[index]);
  622. row.CreateCell(j).SetCellValue(vals);
  623. j++;
  624. }
  625. start++;
  626. foreach (var cell in row.Cells)
  627. {
  628. cell.CellStyle = contentCellStyle;
  629. }
  630. }
  631. // 自适应单元格
  632. for (int i = 0; i < sheet.LastRowNum; i++)
  633. {
  634. sheet.AutoSizeRow(i);
  635. }
  636. for (int i = 0; i < 7; i++)
  637. {
  638. sheet.AutoSizeColumn(i, true);
  639. }
  640. string emailName = $"{searchModel.DevName}设备点历史记录{searchModel.start.ToString("yyyy-MM-dd HH:mm:ss")}{searchModel.end.ToString("yyyy-MM-dd HH:mm:ss")}";
  641. using (var stream = new NpoiMemoryStream()) {
  642. workbook.Write(stream);
  643. stream.Seek(0, SeekOrigin.Begin);
  644. await Task.Run(() =>
  645. {
  646. EmailHelper.SendEmail(searchModel.Mails, emailName, "", "报表见附件", $"{emailName}.xlsx", "application/vnd.ms-excel", stream);
  647. });
  648. }
  649. }
  650. catch (Exception ex)
  651. {
  652. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  653. }
  654. return new ApiResult(ReturnCode.Success);
  655. }
  656. /// <summary>
  657. /// 条件获取历史数据-折线图
  658. /// </summary>
  659. /// <param name="searchModel"></param>
  660. /// <returns></returns>
  661. [HttpPost("GetDevSpotSeriesLineChart")]
  662. [AllowAnonymous]
  663. public async Task<object> GetDevSpotSeriesLineChart(DevSpotSeriesSearchModel searchModel)
  664. {
  665. if (searchModel == null || searchModel.point.Length == 0)
  666. {
  667. return new ApiResult(ReturnCode.ArgsError);
  668. }
  669. try
  670. {
  671. string strStart = searchModel.start.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  672. string strEnd = searchModel.end.AddHours(-8).ToString("yyyy-MM-ddTHH:mm:ssZ");
  673. string strId = searchModel.point[0];
  674. string strIds = string.Join('|', searchModel.point);
  675. IniInflux();
  676. //传入查询命令,支持多条
  677. var queries = new[]
  678. {
  679. "SELECT * FROM fanyidev WHERE time>'"+strStart+"' and time< '"+strEnd + "' and Id =~/^"+strIds+"$/ order by time desc TZ('Asia/Shanghai')"
  680. };
  681. var dbName = "fanyidb";
  682. //从指定库中查询数据
  683. var response = await clientDb.Client.QueryAsync(queries, dbName);
  684. if (!response.Any())
  685. {
  686. return new ApiResult<object>(new
  687. {
  688. x = new List<string>(),
  689. y = new List<YEntity>()
  690. });
  691. }
  692. //得到Serie集合对象(返回执行多个查询的结果)
  693. List<Serie> series = response.ToList();
  694. //取出第一条命令的查询结果,是一个集合
  695. var list = series[0].Values;
  696. var serie1s = list.Select(x => new Serie1
  697. {
  698. Time = x[0].ToString(),
  699. ID = x[1].ToString(),
  700. Value = Convert.ToDecimal(x[2]),
  701. Name = x[3].ToString()
  702. }).ToList();
  703. var tabName1 = serie1s.GroupBy(x => x.Name).ToList();
  704. var dateArry = (serie1s.OrderBy(x=>x.Time)).GroupBy(x => x.Time).ToList();
  705. List<string> tabName =new List<string>();
  706. foreach (var item in tabName1)
  707. {
  708. tabName.Add(item.Key);
  709. }
  710. List<string> x = new List<string>();
  711. foreach (var item in dateArry)
  712. {
  713. x.Add(item.Key);
  714. }
  715. List<YEntity> yEntities = new List<YEntity>();
  716. foreach (var item in x)
  717. {
  718. var ll= serie1s.Where(t => t.Time == item).ToList();
  719. if (yEntities.Count==0)
  720. {
  721. foreach (var index in tabName)
  722. {
  723. YEntity yEntity = new YEntity();
  724. yEntity.data = new List<decimal>();
  725. var aa = (ll==null?null:(ll.Find(t => t.Name == index)));
  726. yEntity.name = index;
  727. if (aa!=null)
  728. {
  729. yEntity.data.Add(aa.Value);
  730. }
  731. else
  732. {
  733. yEntity.data.Add(0);
  734. }
  735. yEntities.Add(yEntity);
  736. }
  737. }
  738. else
  739. {
  740. foreach (var index in tabName)
  741. {
  742. var yData= yEntities.Find(y => y.name == index);
  743. if (yData != null)
  744. {
  745. var aa = (ll == null ? null : (ll.Find(t => t.Name == index)));
  746. if (aa != null)
  747. {
  748. yData.data.Add(aa.Value);
  749. }
  750. else
  751. {
  752. yData.data.Add(0);
  753. }
  754. }
  755. else
  756. {
  757. YEntity yEntity = new YEntity();
  758. yEntity.data = new List<decimal>();
  759. var aa = (ll == null ? null : (ll.Find(t => t.Name == index)));
  760. yEntity.name = index;
  761. if (aa != null)
  762. {
  763. yEntity.data.Add(aa.Value);
  764. }
  765. else
  766. {
  767. yEntity.data.Add(0);
  768. }
  769. yEntities.Add(yEntity);
  770. }
  771. }
  772. }
  773. }
  774. var data = new
  775. {
  776. x,
  777. y=yEntities,
  778. };
  779. return new ApiResult<object>(data);
  780. }
  781. catch (Exception ex)
  782. {
  783. return new ApiResult(ReturnCode.GeneralError, ex.Message);
  784. }
  785. }
  786. }
  787. public class Serie1
  788. {
  789. public string Time { get; set; }
  790. public string Name { get; set; }
  791. public decimal Value { get; set; }
  792. public string ID { get; set; }
  793. }
  794. public class YEntity
  795. {
  796. public string name { get; set; }
  797. public List<decimal> data { get; set; }
  798. }
  799. }