From e00c53439af65f41a22324d5ac2d47b8f6e20693 Mon Sep 17 00:00:00 2001 From: iioter <535915157@qq.com> Date: Fri, 15 Nov 2024 15:55:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=9A=84Api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BasicData/DeviceVMs/DeviceApiBatchVM.cs | 43 +++++ .../BasicData/DeviceVMs/DeviceApiImportVM.cs | 50 +++++ .../BasicData/DeviceVMs/DeviceApiListVM.cs | 66 +++++++ .../BasicData/DeviceVMs/DeviceApiSearcher.cs | 24 +++ .../BasicData/DeviceVMs/DeviceApiVM.cs | 41 ++++ .../Controllers/DeviceApiController.cs | 180 ++++++++++++++++++ IoTGateway/data/iotgateway.db | Bin 475136 -> 475136 bytes 7 files changed, 404 insertions(+) create mode 100644 IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiBatchVM.cs create mode 100644 IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiImportVM.cs create mode 100644 IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiListVM.cs create mode 100644 IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiSearcher.cs create mode 100644 IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiVM.cs create mode 100644 IoTGateway/Areas/BasicData/Controllers/DeviceApiController.cs diff --git a/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiBatchVM.cs b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiBatchVM.cs new file mode 100644 index 0000000..182e835 --- /dev/null +++ b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiBatchVM.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; +using WalkingTec.Mvvm.Core; +using WalkingTec.Mvvm.Core.Extensions; +using IoTGateway.Model; + + +namespace IoTGateway.ViewModel.BasicData.DeviceVMs +{ + public partial class DeviceApiBatchVM : BaseBatchVM + { + public DeviceApiBatchVM() + { + ListVM = new DeviceApiListVM(); + LinkedVM = new DeviceApi_BatchEdit(); + } + + } + + /// + /// Class to define batch edit fields + /// + public class DeviceApi_BatchEdit : BaseVM + { + [Display(Name = "AutoStart")] + public Boolean? AutoStart { get; set; } + [Display(Name = "ChangeUpload")] + public Boolean? CgUpload { get; set; } + [Display(Name = "EnforcePeriodms")] + public UInt32? EnforcePeriod { get; set; } + [Display(Name = "CmdPeriodms")] + public UInt32? CmdPeriod { get; set; } + + protected override void InitVM() + { + } + + } + +} diff --git a/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiImportVM.cs b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiImportVM.cs new file mode 100644 index 0000000..37984cf --- /dev/null +++ b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiImportVM.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; +using WalkingTec.Mvvm.Core; +using WalkingTec.Mvvm.Core.Extensions; +using IoTGateway.Model; + + +namespace IoTGateway.ViewModel.BasicData.DeviceVMs +{ + public partial class DeviceApiTemplateVM : BaseTemplateVM + { + [Display(Name = "DeviceName")] + public ExcelPropety DeviceName_Excel = ExcelPropety.CreateProperty(x => x.DeviceName); + [Display(Name = "Sort")] + public ExcelPropety Index_Excel = ExcelPropety.CreateProperty(x => x.Index); + [Display(Name = "Description")] + public ExcelPropety Description_Excel = ExcelPropety.CreateProperty(x => x.Description); + public ExcelPropety Driver_Excel = ExcelPropety.CreateProperty(x => x.DriverId); + [Display(Name = "AutoStart")] + public ExcelPropety AutoStart_Excel = ExcelPropety.CreateProperty(x => x.AutoStart); + [Display(Name = "ChangeUpload")] + public ExcelPropety CgUpload_Excel = ExcelPropety.CreateProperty(x => x.CgUpload); + [Display(Name = "EnforcePeriodms")] + public ExcelPropety EnforcePeriod_Excel = ExcelPropety.CreateProperty(x => x.EnforcePeriod); + [Display(Name = "CmdPeriodms")] + public ExcelPropety CmdPeriod_Excel = ExcelPropety.CreateProperty(x => x.CmdPeriod); + [Display(Name = "Type")] + public ExcelPropety DeviceTypeEnum_Excel = ExcelPropety.CreateProperty(x => x.DeviceTypeEnum); + [Display(Name = "_Admin.Parent")] + public ExcelPropety Parent_Excel = ExcelPropety.CreateProperty(x => x.ParentId); + + protected override void InitVM() + { + Driver_Excel.DataType = ColumnDataType.ComboBox; + Driver_Excel.ListItems = DC.Set().GetSelectListItems(Wtm, y => y.DriverName); + Parent_Excel.DataType = ColumnDataType.ComboBox; + Parent_Excel.ListItems = DC.Set().GetSelectListItems(Wtm, y => y.DeviceName); + } + + } + + public class DeviceApiImportVM : BaseImportVM + { + + } + +} diff --git a/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiListVM.cs b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiListVM.cs new file mode 100644 index 0000000..a072a6c --- /dev/null +++ b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiListVM.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using WalkingTec.Mvvm.Core; +using WalkingTec.Mvvm.Core.Extensions; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; +using IoTGateway.Model; + + +namespace IoTGateway.ViewModel.BasicData.DeviceVMs +{ + public partial class DeviceApiListVM : BasePagedListVM + { + + protected override IEnumerable> InitGridHeader() + { + return new List>{ + this.MakeGridHeader(x => x.DeviceName), + this.MakeGridHeader(x => x.Index), + this.MakeGridHeader(x => x.Description), + this.MakeGridHeader(x => x.DriverName_view), + this.MakeGridHeader(x => x.AutoStart), + this.MakeGridHeader(x => x.CgUpload), + this.MakeGridHeader(x => x.EnforcePeriod), + this.MakeGridHeader(x => x.CmdPeriod), + this.MakeGridHeader(x => x.DeviceTypeEnum), + this.MakeGridHeader(x => x.DeviceName_view), + this.MakeGridHeaderAction(width: 200) + }; + } + + public override IOrderedQueryable GetSearchQuery() + { + var query = DC.Set() + .CheckContain(Searcher.DeviceName, x=>x.DeviceName) + .CheckEqual(Searcher.DriverId, x=>x.DriverId) + .Select(x => new DeviceApi_View + { + ID = x.ID, + DeviceName = x.DeviceName, + Index = x.Index, + Description = x.Description, + DriverName_view = x.Driver.DriverName, + AutoStart = x.AutoStart, + CgUpload = x.CgUpload, + EnforcePeriod = x.EnforcePeriod, + CmdPeriod = x.CmdPeriod, + DeviceTypeEnum = x.DeviceTypeEnum, + DeviceName_view = x.Parent.DeviceName, + }) + .OrderBy(x => x.ID); + return query; + } + + } + + public class DeviceApi_View : Device{ + [Display(Name = "DriverName")] + public String DriverName_view { get; set; } + [Display(Name = "DeviceName")] + public String DeviceName_view { get; set; } + + } +} diff --git a/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiSearcher.cs b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiSearcher.cs new file mode 100644 index 0000000..35dc8c6 --- /dev/null +++ b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiSearcher.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; +using WalkingTec.Mvvm.Core; +using WalkingTec.Mvvm.Core.Extensions; +using IoTGateway.Model; + + +namespace IoTGateway.ViewModel.BasicData.DeviceVMs +{ + public partial class DeviceApiSearcher : BaseSearcher + { + [Display(Name = "DeviceName")] + public String DeviceName { get; set; } + public Guid? DriverId { get; set; } + + protected override void InitVM() + { + } + + } +} diff --git a/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiVM.cs b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiVM.cs new file mode 100644 index 0000000..5a25bb7 --- /dev/null +++ b/IoTGateway.ViewModel/BasicData/DeviceVMs/DeviceApiVM.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations; +using WalkingTec.Mvvm.Core; +using WalkingTec.Mvvm.Core.Extensions; +using IoTGateway.Model; + + +namespace IoTGateway.ViewModel.BasicData.DeviceVMs +{ + public partial class DeviceApiVM : BaseCRUDVM + { + + public DeviceApiVM() + { + SetInclude(x => x.Driver); + SetInclude(x => x.Parent); + } + + protected override void InitVM() + { + } + + public override void DoAdd() + { + base.DoAdd(); + } + + public override void DoEdit(bool updateAllFields = false) + { + base.DoEdit(updateAllFields); + } + + public override void DoDelete() + { + base.DoDelete(); + } + } +} diff --git a/IoTGateway/Areas/BasicData/Controllers/DeviceApiController.cs b/IoTGateway/Areas/BasicData/Controllers/DeviceApiController.cs new file mode 100644 index 0000000..ef39cec --- /dev/null +++ b/IoTGateway/Areas/BasicData/Controllers/DeviceApiController.cs @@ -0,0 +1,180 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using WalkingTec.Mvvm.Core; +using WalkingTec.Mvvm.Core.Extensions; +using WalkingTec.Mvvm.Mvc; +using IoTGateway.ViewModel.BasicData.DeviceVMs; +using IoTGateway.Model; + + +namespace IoTGateway.Controllers +{ + [Area("BasicData")] + [AuthorizeJwtWithCookie] + [ActionDescription("设备维护Api")] + [ApiController] + [Route("api/Device")] + public partial class DeviceApiController : BaseApiController + { + [ActionDescription("Sys.Search")] + [HttpPost("Search")] + public IActionResult Search(DeviceApiSearcher searcher) + { + if (ModelState.IsValid) + { + var vm = Wtm.CreateVM(passInit: true); + vm.Searcher = searcher; + return Content(vm.GetJson()); + } + else + { + return BadRequest(ModelState.GetErrorJson()); + } + } + + [ActionDescription("Sys.Get")] + [HttpGet("{id}")] + public DeviceApiVM Get(string id) + { + var vm = Wtm.CreateVM(id); + return vm; + } + + [ActionDescription("Sys.Create")] + [HttpPost("Add")] + public IActionResult Add(DeviceApiVM vm) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState.GetErrorJson()); + } + else + { + vm.DoAdd(); + if (!ModelState.IsValid) + { + return BadRequest(ModelState.GetErrorJson()); + } + else + { + return Ok(vm.Entity); + } + } + + } + + [ActionDescription("Sys.Edit")] + [HttpPut("Edit")] + public IActionResult Edit(DeviceApiVM vm) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState.GetErrorJson()); + } + else + { + vm.DoEdit(false); + if (!ModelState.IsValid) + { + return BadRequest(ModelState.GetErrorJson()); + } + else + { + return Ok(vm.Entity); + } + } + } + + [HttpPost("BatchDelete")] + [ActionDescription("Sys.Delete")] + public IActionResult BatchDelete(string[] ids) + { + var vm = Wtm.CreateVM(); + if (ids != null && ids.Count() > 0) + { + vm.Ids = ids; + } + else + { + return Ok(); + } + if (!ModelState.IsValid || !vm.DoBatchDelete()) + { + return BadRequest(ModelState.GetErrorJson()); + } + else + { + return Ok(ids.Count()); + } + } + + + [ActionDescription("Sys.Export")] + [HttpPost("ExportExcel")] + public IActionResult ExportExcel(DeviceApiSearcher searcher) + { + var vm = Wtm.CreateVM(); + vm.Searcher = searcher; + vm.SearcherMode = ListVMSearchModeEnum.Export; + return vm.GetExportData(); + } + + [ActionDescription("Sys.CheckExport")] + [HttpPost("ExportExcelByIds")] + public IActionResult ExportExcelByIds(string[] ids) + { + var vm = Wtm.CreateVM(); + if (ids != null && ids.Count() > 0) + { + vm.Ids = new List(ids); + vm.SearcherMode = ListVMSearchModeEnum.CheckExport; + } + return vm.GetExportData(); + } + + [ActionDescription("Sys.DownloadTemplate")] + [HttpGet("GetExcelTemplate")] + public IActionResult GetExcelTemplate() + { + var vm = Wtm.CreateVM(); + var qs = new Dictionary(); + foreach (var item in Request.Query.Keys) + { + qs.Add(item, Request.Query[item]); + } + vm.SetParms(qs); + var data = vm.GenerateTemplate(out string fileName); + return File(data, "application/vnd.ms-excel", fileName); + } + + [ActionDescription("Sys.Import")] + [HttpPost("Import")] + public ActionResult Import(DeviceApiImportVM vm) + { + if (vm!=null && (vm.ErrorListVM.EntityList.Count > 0 || !vm.BatchSaveData())) + { + return BadRequest(vm.GetErrorJson()); + } + else + { + return Ok(vm?.EntityList?.Count ?? 0); + } + } + + + [HttpGet("GetDrivers")] + public ActionResult GetDrivers() + { + return Ok(DC.Set().GetSelectListItems(Wtm, x => x.DriverName)); + } + + [HttpGet("GetDevices")] + public ActionResult GetDevices() + { + return Ok(DC.Set().GetSelectListItems(Wtm, x => x.DeviceName)); + } + + } +} diff --git a/IoTGateway/data/iotgateway.db b/IoTGateway/data/iotgateway.db index d538f510388ac0a7521542ce84e08ca845659ef4..efd69cd9f8b3811443799c6c13132aa431eeae91 100644 GIT binary patch delta 8453 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 delta 4810 zcmaJ_33wD$w(hEXZ&j~V2?1m=BtUmoDpd8}EK2ppYG@LI5K%x9#;_%Xz_2_60fjdp zn=Dsma99-|AcHKa0FnX5WkwbQDof0SMM=apjxvlR%R8MW%U6paIJ?5xZcT=ValSQv$A^y^#5$PJ4H179|1N$nel0eO*Tn|$ zf>_5jA4sj+C9d7lK$s^E)Lk(p(2)wV?Qg*gx8q2vhF3Ev!IB7zbKx8W=RmFf7N%u5 zV4j9M-IJ}DE#jBr=VGIHNjxu}HvL0OZDC#)xq#&Lt13NxpK)~%Khj~b3j-@giG##0 z;tp}PaQ#q6mKT}+bk7x(g+bJh*1dzWd7UmV6BV%ZYCcKR!}MdVcXgj3E3Fe*j*)1Y zfz7N=VDE2cN~`y=%)(?-mTn|FR3}~(-xL>%g`y(zLZfgO;rMs29s2 zx>81++T+LBzu=DO8}ui%5tX5VC>bRmP*OKC^f)G%R_sDnZKfS*`Y5d|TINMrbVfF| zYX8v}y@(f(o4PSfB?IR65-PsPtq{kG4$;V65w5ZS5Nh~)!YW}B3F2--fAj(W3129* zw|s?qSWfbaWg~kQzsJtAl;KU5ftGIOTjtZ|?aUqXJo5;11}-<<=Zd&$Jjisx^d`T@ z^n&RrG>jbAM@)8;!FZKSM?a!1{frvd*SHe57>l`f%z5SwV?Se(;Y-5_Hcg*yc!k}; zR2oXzh#_o9<`?UK)SuFC)6XScc|DqqX0KIJPe#2Y^x4h0rky)fG)Ya?6JK}BeZ%|HGQAdA3U`QG&Mk*@pL&q)g1N*-&peAh zq-73p@|}rj2Nm;B7Q@l>=TL@rv-ghsLv%5Om`9kK; zKGv$Yphp>c^cJerBHPegmIaWDr*%y_k_F8gbKNc)gsVa|>lRiBMM57T!P0E0wXCyD zwy3O`xo+uX{?7cad6T)^Jea9rR^mN)5z(1bO}9;FO|O~en?~rGklvJmFBtC|Kf$Ao zdyI>5jH~lRVEZBO}p1NW3+ccx4iSpj6XgBAZ43 zeh}r*bs9>eKOI3MY3bW&48590da_I*?Wcik^7|;8-h3bW&T#+=ruSi#v*9324L<}^ z+Yg~kdhi-Caetri=>)%KDwB4W4 zJZjnxqpx5ip`S)a{f+Dn+`7?}Uc*+Jdl0=zZHK_%yhE_>I81CF4OXMOwA*zIBn5gz z0}6R&mvT^sq7GN$oyq3+|rb<%O<3>)?uUN96I6oX#hs6V8CNk5UfruXR+ z_$EfNB4s-%e*AX?T!YG|3^@_!s@pxE}ArOYm6zIm2-5z(#Zp^+7dgB}za=!cw+L*eBGBqs1Kd zZ4rx$^!e;eb}+x2U&N2m@8s|Ey-mO4KVeh2e{$!Ho4GfPvrIFdh%gxwGjz)4PW4`sekTKzk>& zUi=SS%B0MEWF=Ethr8#&o;j5&h|P?J=tL^9(q|e`A-&#+av5&@2W%$8({9mvUw8?2 zR^F;hrM+(8M``+HDAIeEkuA1zA0&$Yz8-P(c0E+;uzHZbRu2_*oPph}wJMb+hl#2Fnu^otE1v?l zbAf25uBLmQ!#OnnJamceBPgbnkKqy-MtV|l8s_P`Y50MEcZWq`X3^RPSnRse=JtS} zFifY>Gw0#?-%9t}))^~pm=3`5IcU?$61A zr{XL|N2fE;X&*)dyX!LWV565&mth|mnjK~P1bre3aB?cPRbNFo0S(68DBpr?da{m8 z!GnlOy)Ech=m+$H_WKsp3(*<#$w;l+kEm%%A6btf;Ce?qyE;9e&y6 z^1Gyf$1a1#Ku}UuH;n8ax7QU=6|ZU+KyjnTACd!(fL{uQeSYx9>y^9?JB$>UH|$nI zE~ndP(dn2nkL*(v*(ooO0(Pfea{9dh>2QRlKsXro`t2TPz~eE4=1HH|?GF20c1dyh zz@h?ZK94&j1r&EwE3Z% zCW)1O!#K{GhoIL-0Aoj34*Dgp8V*1b+yTia`&?2G0wxE+agW!>rlSIb698o&fO^6K za8HFG`<%eq9dLtV?vTslcUG5SoSJIp6vlkmG|_m*m~0rM-^_m}4l}EKCr+`r_)dH$ zsAvnPDI4%9o@Mgry;pG_o!u4N>AM?nK37rIJF&n<2X4Z4bJO~b&2KDk+OV`~>vpxQVGYIWS)gz2mtV-$+ zCR36oKJaS*sJ73qC@u4sRLs0lwW;aNZJ!@oF?@P4b>;BcRIO#K!sLGD0$YmMhJLjt zZ|#^rb;9gowWz4Pc;?K{kFIRqy%F3}9_aUt(;sI21^rwI*R($7g07hleLD)2sIUw| z{XMJ{rupKe>9#g$E4LDF)SZWGEj(}S;GZz7C~rbVanpfq&A&O^ymG0}Ez4AmnwsT_ z3nP;TVAEH^i%{SQ(?hIEaf7Xt&cA*ToN<6g_b$XkV}2F6;G$0t&3fst$H@ zLFbeXB@cKF%HXX@kqPA`6?2=mY`wYbB}iFrDdcQ(2A>n-I!lRj^a`wq)ysP?L?bT8 z#dK6=ET&ys!yruS9Ve~S$E2MpS>8$}CyvZc5dQ+1)&xs&fOQW6qoplYiM^uH`gL1< z^~?TOv`U}GE_j;&$`i891&N6d`|(URZ!?z-jwp6djtqxFyN9qfp=xlJrJ%blsVeXw zR6`9w{_ql95zGJd%(%Y2)2pp-W2Kf6$MeH zM$W%0nbyiIvc6@}m_kcPGLBJ#57(cb!kw!dD+JoxM7ps-AsAb13e)}xFV^#5{n#}CM+ cRn8%cepP*(oE7QWQr5i`w-61taCe6PH{eD|X#fBK