diff --git a/Infrastructure/Utils/ShapeUtil.cs b/Infrastructure/Utils/ShapeUtil.cs index 906e0fc..aff39db 100644 --- a/Infrastructure/Utils/ShapeUtil.cs +++ b/Infrastructure/Utils/ShapeUtil.cs @@ -119,6 +119,11 @@ public class ShapeUtil // return NetTopologySuite.IO.Esri.Shapefile.ReadAllGeometries(shpPath); } + public static bool CheckTextByUtf8() + { + return false; + } + /// /// 判断是否乱码 /// diff --git a/OpenAuth.App/ServiceApp/LayerManagerApp/DataTableAttr.cs b/OpenAuth.App/ServiceApp/LayerManagerApp/DataTableAttr.cs new file mode 100644 index 0000000..79d8517 --- /dev/null +++ b/OpenAuth.App/ServiceApp/LayerManagerApp/DataTableAttr.cs @@ -0,0 +1,27 @@ +using NetTopologySuite.IO; + +namespace OpenAuth.Repository.Domain; + +public class DataTableAttr +{ + // 字段名称 + public string Name { get; set; } + + // 字段类型 + public string Type { get; set; } + + // 字段长度 + public int Length { get; set; } + + /// + /// 对应数据库列名 + /// + public string RefName { get; set; } + + /// + /// 可能是中文描述 + /// + public string InitName { get; set; } + + +} \ No newline at end of file diff --git a/OpenAuth.App/ServiceApp/LayerManagerApp/LayerApp.cs b/OpenAuth.App/ServiceApp/LayerManagerApp/LayerApp.cs new file mode 100644 index 0000000..5e266a0 --- /dev/null +++ b/OpenAuth.App/ServiceApp/LayerManagerApp/LayerApp.cs @@ -0,0 +1,260 @@ +using System.Data; +using Infrastructure; +using Infrastructure.Utils; +using Microsoft.Extensions.Options; +using NetTopologySuite; +using NetTopologySuite.Geometries; +using NPOI.HSSF.UserModel; +using NPOI.SS.UserModel; +using NPOI.XSSF.UserModel; +using OpenAuth.App.BaseApp.Base; +using OpenAuth.App.Interface; +using OpenAuth.App.ServiceApp.LayerManagerApp.Request; +using OpenAuth.Repository; +using OpenAuth.Repository.Domain; +using SqlSugar; + +namespace OpenAuth.App.ServiceApp.LayerManagerApp; + +public class LayerApp : SqlSugarBaseApp +{ + private readonly string _filePath; + private readonly ISqlSugarClient _client; + + public LayerApp(ISugarUnitOfWork unitWork, + ISimpleClient repository, IAuth auth, + IOptions setOptions, ISqlSugarClient client) : base(unitWork, repository, auth) + { + _client = client; + _filePath = setOptions.Value.UploadPath; + if (string.IsNullOrEmpty(_filePath)) + { + _filePath = AppContext.BaseDirectory; + } + } + + public async Task> UploadExcel(LayerReq req) + { + using var db = Repository.AsSugarClient(); + var excelPath = Path.Combine(_filePath, req.FilePath); + // excel名称 + var excelFileName = Path.GetFileNameWithoutExtension(excelPath); + // 使用NPOI读取Excel文件 + using (var fileStream = new FileStream(excelPath, FileMode.Open, FileAccess.Read)) + { + IWorkbook workbook; + if (Path.GetExtension(excelPath).Equals(".xls")) + { + workbook = new HSSFWorkbook(fileStream); + } + else + { + workbook = new XSSFWorkbook(fileStream); + } + + // + var sheet = workbook.GetSheetAt(0); + // 获取总行数 + var rowCount = sheet.LastRowNum; + if (rowCount < 3) + { + throw new Exception("只有两行表头"); + } + + // 获取总列数 + var columnCount = sheet.GetRow(0).LastCellNum; + var headers = new List(); + // 遍历表头 + var chineseRow = sheet.GetRow(0); + var englishRow = sheet.GetRow(1); + + for (var j = 0; j < columnCount; j++) + { + var header = new DataTableAttr + { + InitName = chineseRow.GetCell(j).ToString(), // 中文表头 + RefName = englishRow.GetCell(j).ToString()?.ToLower(), // 英文表头 + // 字段类型 + Type = "string", + // 原始字段名称 + Name = englishRow.GetCell(j).ToString(), + // 字段长度 + Length = 64 + }; + headers.Add(header); + } + + var keys = headers.Select(a => a.RefName).ToList(); + if (!keys.Contains("lng") || !keys.Contains("lat")) + { + throw new Exception("缺少经纬度字段"); + } + + var typeBuilder = db.DynamicBuilder().CreateClass(req.DataTable, + new SugarTable() { TableName = req.DataTable, TableDescription = req.ServerName + "图斑" }); + //添加主键 + typeBuilder.CreateProperty("id", typeof(string), new SugarColumn() + { + IsPrimaryKey = true, + IsIdentity = false, + ColumnDataType = "varchar", + Length = 36, + ColumnDescription = "主键", + }); + //添加主键 + typeBuilder.CreateProperty("geometry", typeof(string), new SugarColumn() + { + IsPrimaryKey = false, + IsIdentity = false, + // ColumnDataType = "geometry(GEOMETRY)", + ColumnDataType = string.Concat("geometry(GEOMETRY,", + req.SpatialRef.AsSpan(req.SpatialRef.LastIndexOf(":", StringComparison.Ordinal) + 1), + ")"), + ColumnDescription = "图斑", + }); + + headers.ForEach(u => + { + if (!u.RefName.Equals("lng") && !u.RefName.Equals("lat")) + { + typeBuilder.CreateProperty(u.RefName, typeof(string), new SugarColumn() + { + IsPrimaryKey = false, + IsIdentity = false, + IsNullable = true, + Length = u.Length, + ColumnDescription = u.InitName, + }); + } + }); + // 开启事务 + await db.Ado.BeginTranAsync(IsolationLevel.ReadCommitted); + // 创建表 + //db.CodeFirst.InitTables(typeBuilder.BuilderType()); + + var cols = new string[headers.Count]; + for (var i = 0; i < headers.Count; i++) + { + if (headers[i].RefName.Equals("lng")) + { + cols[i] = "geometry"; + } + else if (headers[i].RefName.Equals("lat")) + { + cols[i] = "id"; + } + else + { + cols[i] = headers[i].RefName; + } + } + + var objs = new List>(1001); + var num = 0; + // 遍历数据行 + for (var i = 2; i < rowCount; i++) + { + var row = sheet.GetRow(i); + if (row == null) + { + continue; + } + + var data = new Dictionary(); + // 遍历列 + string lat = null, lng = null; + for (var j = 0; j < columnCount; j++) + { + var cell = row.GetCell(j); + if (cell == null) + { + continue; + } + + var cellValue = cell.ToString(); + switch (headers[j].RefName) + { + case "lat": + lat = cellValue; + continue; + case "lng": + lng = cellValue; + continue; + default: + data[headers[j].RefName] = cellValue; + break; + } + } + + if (lat != null && lng != null) + { + var geography = + NtsGeometryServices.Instance.CreateGeometryFactory( + int.Parse(req.SpatialRef.Substring( + req.SpatialRef.IndexOf(":", StringComparison.Ordinal) + 1))); + var point = geography.CreatePoint(new Coordinate(double.Parse(lng), double.Parse(lat))); + data["geometry"] = point.AsText(); + } + + data["id"] = Guid.NewGuid().ToString(); + objs.Add(data); + if (num++ == 999) + { + await db.Insertable(objs) + .AS(req.DataTable) // 指定目标表名 + .InsertColumns(cols) // 指定要插入的列 + .ExecuteCommandAsync(); + num = 0; + objs.Clear(); + } + } + + await db.Insertable(objs) + .AS(req.DataTable) // 指定目标表名 + .InsertColumns(cols) // 指定要插入的列 + .ExecuteCommandAsync(); + await db.Ado.CommitTranAsync(); + workbook.Close(); + // 关于图层发布失败后,如何处理? + // excel 矢量点发布图层 + var response = await GeoUtil.CreateStoreAndLayer("", req.SpatialRef, req.DataTable, ""); + // todo 保存图层信息 + var dmLayer = new DmLayer() + { + Id = Guid.NewGuid().ToString(), + SeverName = req.ServerName, + SpatialRef = req.SpatialRef, + SeverType = req.SeverType, // 服务类型 + StoreType = "", //存储类型 + DataSourceType = req.DataSourceType, + TableRef = req.DataTable, + ShapeType = req.ShapeType, + StyleName = req.StyleName, // 样式名称 + Description = req.Description, // 描述 + Screenshot = req.Screenshot // 截图 + }; + await Repository.AsSugarClient().Insertable(dmLayer).ExecuteCommandAsync(); + } + + return new Response + { + Result = true + }; + } + + public async Task> UploadShape(LayerReq req) + { + try + { + } + catch (Exception ex) + { + throw new CommonException(ex.Message, 500); + } + + return new Response + { + Result = true + }; + } +} \ No newline at end of file diff --git a/OpenAuth.App/ServiceApp/LayerManagerApp/Request/LayerReq.cs b/OpenAuth.App/ServiceApp/LayerManagerApp/Request/LayerReq.cs new file mode 100644 index 0000000..51e7b2a --- /dev/null +++ b/OpenAuth.App/ServiceApp/LayerManagerApp/Request/LayerReq.cs @@ -0,0 +1,64 @@ +using OpenAuth.Repository.Domain; + +namespace OpenAuth.App.ServiceApp.LayerManagerApp.Request +{ + public class LayerReq + { + public LayerReq() + { + } + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + public string Id { get; set; } + + /// + /// Desc:服务名称 + /// Default: + /// Nullable:True + /// + public string ServerName { get; set; } + + + /// + /// 空间参考 + /// + public string SpatialRef { get; set; } + + public string SeverType { get; set; } + + /// + /// 数据源类型 + /// + public string DataSourceType { get; set; } + + /// + /// 数据表名 + /// + public string DataTable { get; set; } + + /// + /// 文件路径 + /// + public string FilePath { get; set; } + + /// + /// 点线面 + /// + public string ShapeType { get; set; } + + // 头部信息,目前为空 + public List Headers { get; set; } + + public string Style { get; set; } + + public string StyleName { get; set; } + + public string Description { get; set; } + + public string Screenshot { get; set; } + } +} \ No newline at end of file diff --git a/OpenAuth.Repository/Domain/DmLayer.cs b/OpenAuth.Repository/Domain/DmLayer.cs new file mode 100644 index 0000000..19cf823 --- /dev/null +++ b/OpenAuth.Repository/Domain/DmLayer.cs @@ -0,0 +1,57 @@ +namespace OpenAuth.Repository.Domain; + +public class DmLayer +{ + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 服务名 + /// + public string SeverName { get; set; } + /// + /// 空间参考 + /// + public string SpatialRef { get; set; } + /// + /// 服务类型 矢量 倾斜摄影 栅格 + /// + public string SeverType { get; set; } + /// + /// 存储类型 + /// + public string StoreType { get; set; } + /// + /// 数据源类型 + /// + public string DataSourceType { get; set; } + /// + /// 创建时间 + /// + public DateTime? CreateTime { get; set; } + /// + /// 数据表名 + /// + public string TableRef { get; set; } + /// + /// 是否发布 + /// + public bool IsDisplay { get; set; } + /// + /// 矢量类型 点线面 + /// + public string ShapeType { get; set; } + /// + /// 样式名称 + /// + public string StyleName { get; set; } + /// + /// 描述 + /// + public string Description { get; set; } + /// + /// 截图 + /// + public string Screenshot { get; set; } +} \ No newline at end of file diff --git a/OpenAuth.WebApi/Controllers/ServiceController/LayerController.cs b/OpenAuth.WebApi/Controllers/ServiceController/LayerController.cs new file mode 100644 index 0000000..f53090f --- /dev/null +++ b/OpenAuth.WebApi/Controllers/ServiceController/LayerController.cs @@ -0,0 +1,43 @@ +using Infrastructure; +using Microsoft.AspNetCore.Mvc; +using OpenAuth.App.ServiceApp.LayerManagerApp; +using OpenAuth.App.ServiceApp.LayerManagerApp.Request; + +namespace OpenAuth.WebApi.Controllers.ServiceController; + +/// +/// 图层 +/// +[Route("api/[controller]/[action]")] +[ApiController] +public class LayerController : ControllerBase +{ + private readonly LayerApp _app; + + public LayerController(LayerApp layerApp) + { + _app = layerApp; + } + + /// + /// excel 上传 + /// + /// + /// + [HttpPost] + public async Task> UploadExcel(LayerReq req) + { + return await _app.UploadExcel(req); + } + + /// + /// shape文件上传 + /// + /// + /// + [HttpPost] + public async Task> UploadShape(LayerReq req) + { + return await _app.UploadShape(req); + } +} \ No newline at end of file