diff --git a/ZR.Admin.WebApi/Controllers/Business/OdfAppUpdatesController.cs b/ZR.Admin.WebApi/Controllers/Business/OdfAppUpdatesController.cs new file mode 100644 index 0000000..c5c4c8a --- /dev/null +++ b/ZR.Admin.WebApi/Controllers/Business/OdfAppUpdatesController.cs @@ -0,0 +1,130 @@ +using Microsoft.AspNetCore.Mvc; + +using System.Linq.Expressions; +using System.Threading.Tasks; + +using ZR.Model.Business; +using ZR.Model.Business.Dto; +using ZR.Service.Business; +using ZR.Service.Business.IBusinessService; + +//创建时间:2025-09-23 +namespace ZR.Admin.WebApi.Controllers.Business +{ + /// + /// App 更新表 + /// + [Route("business/OdfAppUpdates")] + public class OdfAppUpdatesController : BaseController + { + /// + /// App 更新表接口 + /// + private readonly IOdfAppUpdatesService _OdfAppUpdatesService; + + public OdfAppUpdatesController(IOdfAppUpdatesService OdfAppUpdatesService) + { + _OdfAppUpdatesService = OdfAppUpdatesService; + } + + /// + /// 查询App 更新表列表 + /// + /// + /// + [HttpGet("list")] + [ActionPermissionFilter(Permission = "odfappupdates:list")] + public IActionResult QueryOdfAppUpdates([FromQuery] OdfAppUpdatesQueryDto parm) + { + var response = _OdfAppUpdatesService.GetList(parm); + return SUCCESS(response); + } + + + /// + /// 查询App 更新表详情 + /// + /// + /// + [HttpGet("{Id}")] + [ActionPermissionFilter(Permission = "odfappupdates:query")] + public IActionResult GetOdfAppUpdates(int Id) + { + var response = _OdfAppUpdatesService.GetInfo(Id); + + var info = response.Adapt(); + return SUCCESS(info); + } + + /// + /// 修改状态 + /// + /// + [HttpPost("status")] + [ActionPermissionFilter(Permission = "odfappupdates:add")] + [Log(Title = "App 更新表", BusinessType = BusinessType.INSERT)] + public IActionResult OdfAppStatus([FromBody] OdfAppUpdatesStatusDto parm) + { + var modal = _OdfAppUpdatesService.GetById(parm.Id); + if (modal != null) + { + if (parm.IsActive) + { + // 先将所有激活状态设置为未激活 + _OdfAppUpdatesService.UpdateAllActiveToInactive(); + } + modal.IsActive = parm.IsActive; + var response = _OdfAppUpdatesService.UpdateOdfAppUpdates(modal); + + return SUCCESS(response); + } + return SUCCESS(null); + } + + /// + /// 添加App 更新表 + /// + /// + [HttpPost("add")] + [ActionPermissionFilter(Permission = "odfappupdates:add")] + [Log(Title = "App 更新表", BusinessType = BusinessType.INSERT)] + public IActionResult AddOdfAppUpdates([FromBody] OdfAppUpdatesDto parm) + { + var modal = parm.Adapt().ToCreate(HttpContext); + parm.CreateTime = DateTime.Now; + var response = _OdfAppUpdatesService.AddOdfAppUpdates(modal); + + return SUCCESS(response); + } + + /// + /// 更新App 更新表 + /// + /// + [HttpPut] + [ActionPermissionFilter(Permission = "odfappupdates:edit")] + [Log(Title = "App 更新表", BusinessType = BusinessType.UPDATE)] + public IActionResult UpdateOdfAppUpdates([FromBody] OdfAppUpdatesDto parm) + { + var modal = parm.Adapt().ToUpdate(HttpContext); + var response = _OdfAppUpdatesService.UpdateOdfAppUpdates(modal); + + return ToResponse(response); + } + + /// + /// 删除App 更新表 + /// + /// + [HttpPost("delete/{ids}")] + [ActionPermissionFilter(Permission = "odfappupdates:delete")] + [Log(Title = "App 更新表", BusinessType = BusinessType.DELETE)] + public IActionResult DeleteOdfAppUpdates([FromRoute] string ids) + { + var idArr = Tools.SplitAndConvert(ids); + + return ToResponse(_OdfAppUpdatesService.Delete(idArr)); + } + + } +} \ No newline at end of file diff --git a/ZR.Admin.WebApi/Controllers/CommonController.cs b/ZR.Admin.WebApi/Controllers/CommonController.cs index ede239c..8b693d2 100644 --- a/ZR.Admin.WebApi/Controllers/CommonController.cs +++ b/ZR.Admin.WebApi/Controllers/CommonController.cs @@ -103,7 +103,7 @@ namespace ZR.Admin.WebApi.Controllers /// [HttpPost] [ActionPermissionFilter(Permission = "common")] - public async Task UploadFile([FromForm] UploadDto uploadDto, IFormFile file, StoreType storeType = StoreType.ALIYUN) + public async Task UploadFile([FromForm] UploadDto uploadDto, IFormFile file, StoreType storeType = StoreType.LOCAL) { if (file == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空"); SysFile sysfile = new(); diff --git a/ZR.Admin.WebApi/Controllers/WebApiController.cs b/ZR.Admin.WebApi/Controllers/WebApiController.cs index e30af06..0e2d1ec 100644 --- a/ZR.Admin.WebApi/Controllers/WebApiController.cs +++ b/ZR.Admin.WebApi/Controllers/WebApiController.cs @@ -21,5 +21,44 @@ namespace ZR.Admin.WebApi.Controllers public class WebApiController : BaseController { private readonly WechatApiClient _client; + private readonly IOdfAppUpdatesService _odfAppUpdatesService; + + public WebApiController(WechatApiClient client, IOdfAppUpdatesService odfAppUpdatesService) + { + _client = client; + _odfAppUpdatesService = odfAppUpdatesService; + } + + /// + /// 检查App版本更新 + /// + /// 版本 + /// + [HttpGet] + public IActionResult CheckAppVersion([FromQuery] string version) + { + if (version == null || string.IsNullOrEmpty(version)) + { + return ToResponse(ResultCode.CUSTOM_ERROR, "版本号不能为空"); + } + + try + { + var response = _odfAppUpdatesService.CheckAppVersion(version); + + if (response.NeedUpdate) + { + return SUCCESS(response, "发现新版本"); + } + else + { + return SUCCESS(new { }, "当前已是最新版本"); + } + } + catch (Exception ex) + { + return ToResponse(ResultCode.CUSTOM_ERROR, $"版本检查失败: {ex.Message}"); + } + } } } diff --git a/ZR.Admin.WebApi/appsettings.json b/ZR.Admin.WebApi/appsettings.json index 5b9fbf0..4d25b1d 100644 --- a/ZR.Admin.WebApi/appsettings.json +++ b/ZR.Admin.WebApi/appsettings.json @@ -49,7 +49,7 @@ "sqlExecutionTime": 5, //Sql执行时间超过多少秒记录日志并警报 "Upload": { "uploadUrl": "http://localhost:8888", //本地存储资源访问路径 - "localSavePath": "", //本地上传默认文件存储目录 wwwroot + "localSavePath": "/file/", //本地上传默认文件存储目录 wwwroot "maxSize": 15, //上传文件大小限制 15M "notAllowedExt": [ ".bat", ".exe", ".jar", ".js" ], "requestLimitSize": 50 //请求body大小限制 diff --git a/ZR.Admin.WebApi/wwwroot/2025/0923/341f5ae608caea22.xlsx b/ZR.Admin.WebApi/wwwroot/2025/0923/341f5ae608caea22.xlsx new file mode 100644 index 0000000..02aad15 Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/2025/0923/341f5ae608caea22.xlsx differ diff --git a/ZR.Admin.WebApi/wwwroot/2025/0923/603d60c6c874695e.xlsx b/ZR.Admin.WebApi/wwwroot/2025/0923/603d60c6c874695e.xlsx new file mode 100644 index 0000000..02aad15 Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/2025/0923/603d60c6c874695e.xlsx differ diff --git a/ZR.Admin.WebApi/wwwroot/2025/0923/efd4757512a8be29.xlsx b/ZR.Admin.WebApi/wwwroot/2025/0923/efd4757512a8be29.xlsx new file mode 100644 index 0000000..02aad15 Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/2025/0923/efd4757512a8be29.xlsx differ diff --git a/ZR.Model/Business/Dto/OdfAppUpdatesDto.cs b/ZR.Model/Business/Dto/OdfAppUpdatesDto.cs new file mode 100644 index 0000000..575b1ea --- /dev/null +++ b/ZR.Model/Business/Dto/OdfAppUpdatesDto.cs @@ -0,0 +1,93 @@ + +namespace ZR.Model.Business.Dto +{ + /// + /// App 更新表查询对象 + /// + public class OdfAppUpdatesQueryDto : PagerInfo + { + public int? VersionCode { get; set; } + } + + /// + /// App 更新表输入输出对象 + /// + public class OdfAppUpdatesDto + { + public int? Id { get; set; } + + [Required(ErrorMessage = "版本号不能为空")] + public int VersionCode { get; set; } + + [Required(ErrorMessage = "更新类型不能为空")] + public string UpdateType { get; set; } + + [Required(ErrorMessage = "下载地址不能为空")] + public string DownloadUrl { get; set; } + + [Required(ErrorMessage = "是否启用不能为空")] + public bool IsActive { get; set; } + + public DateTime? CreateTime { get; set; } + + + + [ExcelColumn(Name = "更新类型")] + public string UpdateTypeLabel { get; set; } + } + + /// + /// App 更新表输入输出对象 + /// + public class OdfAppUpdatesStatusDto + { + public int? Id { get; set; } + + [Required(ErrorMessage = "是否启用不能为空")] + public bool IsActive { get; set; } + + } + + /// + /// App版本检查请求对象 + /// + public class AppVersionCheckRequestDto + { + /// + /// 当前App版本号 (如: 1.0.1) + /// + [Required(ErrorMessage = "版本号不能为空")] + public string Version { get; set; } + } + + /// + /// App版本检查响应对象 + /// + public class AppVersionCheckResponseDto + { + /// + /// 是否需要更新 + /// + public bool NeedUpdate { get; set; } + + /// + /// 是否强制更新 + /// + public bool ForceUpdate { get; set; } + + /// + /// 最新版本号 + /// + public string LatestVersion { get; set; } + + /// + /// 下载地址 + /// + public string DownloadUrl { get; set; } + + /// + /// 更新说明 + /// + public string UpdateDescription { get; set; } + } +} \ No newline at end of file diff --git a/ZR.Model/Business/OdfAppUpdates.cs b/ZR.Model/Business/OdfAppUpdates.cs new file mode 100644 index 0000000..1e4d47d --- /dev/null +++ b/ZR.Model/Business/OdfAppUpdates.cs @@ -0,0 +1,42 @@ + +namespace ZR.Model.Business +{ + /// + /// App 更新表 + /// + [SugarTable("odf_app_updates")] + public class OdfAppUpdates + { + /// + /// Id + /// + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int? Id { get; set; } + + /// + /// 版本号 + /// + public int VersionCode { get; set; } + + /// + /// 更新类型 + /// + public string UpdateType { get; set; } + + /// + /// 下载地址 + /// + public string DownloadUrl { get; set; } + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } + + /// + /// 发布时间 + /// + public DateTime? CreateTime { get; set; } + + } +} \ No newline at end of file diff --git a/ZR.Service/Business/IBusinessService/IOdfAppUpdatesService.cs b/ZR.Service/Business/IBusinessService/IOdfAppUpdatesService.cs new file mode 100644 index 0000000..c07021a --- /dev/null +++ b/ZR.Service/Business/IBusinessService/IOdfAppUpdatesService.cs @@ -0,0 +1,33 @@ +using ZR.Model.Business.Dto; +using ZR.Model.Business; + +namespace ZR.Service.Business.IBusinessService +{ + /// + /// App 更新表service接口 + /// + public interface IOdfAppUpdatesService : IBaseService + { + PagedInfo GetList(OdfAppUpdatesQueryDto parm); + + OdfAppUpdates GetInfo(int Id); + + + OdfAppUpdates AddOdfAppUpdates(OdfAppUpdates parm); + int UpdateOdfAppUpdates(OdfAppUpdates parm); + + /// + /// 批量更新所有激活状态为未激活 + /// + /// + int UpdateAllActiveToInactive(); + + /// + /// 检查App版本是否需要更新 + /// + /// 当前App版本号 + /// + AppVersionCheckResponseDto CheckAppVersion(string currentVersion); + + } +} diff --git a/ZR.Service/Business/OdfAppUpdatesService.cs b/ZR.Service/Business/OdfAppUpdatesService.cs new file mode 100644 index 0000000..bea0e5c --- /dev/null +++ b/ZR.Service/Business/OdfAppUpdatesService.cs @@ -0,0 +1,176 @@ +using Infrastructure.Attribute; +using Infrastructure.Extensions; +using ZR.Model.Business.Dto; +using ZR.Model.Business; +using ZR.Repository; +using ZR.Service.Business.IBusinessService; + +namespace ZR.Service.Business +{ + /// + /// App 更新表Service业务层处理 + /// + [AppService(ServiceType = typeof(IOdfAppUpdatesService), ServiceLifetime = LifeTime.Transient)] + public class OdfAppUpdatesService : BaseService, IOdfAppUpdatesService + { + /// + /// 查询App 更新表列表 + /// + /// + /// + public PagedInfo GetList(OdfAppUpdatesQueryDto parm) + { + var predicate = QueryExp(parm); + + var response = Queryable() + //.OrderBy("IsActive desc") + .Where(predicate.ToExpression()) + .ToPage(parm); + + return response; + } + + + /// + /// 获取详情 + /// + /// + /// + public OdfAppUpdates GetInfo(int Id) + { + var response = Queryable() + .Where(x => x.Id == Id) + .First(); + + return response; + } + + /// + /// 添加App 更新表 + /// + /// + /// + public OdfAppUpdates AddOdfAppUpdates(OdfAppUpdates model) + { + return Insertable(model).ExecuteReturnEntity(); + } + + /// + /// 修改App 更新表 + /// + /// + /// + public int UpdateOdfAppUpdates(OdfAppUpdates model) + { + return Update(model, true); + } + + /// + /// 批量更新所有激活状态为未激活 + /// + /// + public int UpdateAllActiveToInactive() + { + return Update(x => x.IsActive == true, x => new OdfAppUpdates { IsActive = false }); + } + + /// + /// 检查App版本是否需要更新 + /// + /// 当前App版本号 + /// + public AppVersionCheckResponseDto CheckAppVersion(string currentVersion) + { + var response = new AppVersionCheckResponseDto + { + NeedUpdate = false, + ForceUpdate = false + }; + + // 获取当前启用的最新版本 + var latestUpdate = Queryable() + .Where(x => x.IsActive == true) + .OrderByDescending(x => x.VersionCode) + .First(); + + if (latestUpdate == null) + { + return response; // 没有启用的版本,不需要更新 + } + + // 将版本号转换为可比较的格式 (如: 1.0.1 -> 1001) + var currentVersionCode = ConvertVersionToCode(currentVersion); + var latestVersionCode = latestUpdate.VersionCode; + + // 如果数据库中的版本号大于当前版本号,则需要更新 + if (latestVersionCode > currentVersionCode) + { + response.NeedUpdate = true; + response.LatestVersion = latestVersionCode.ToString(); + response.DownloadUrl = latestUpdate.DownloadUrl; + response.ForceUpdate = latestUpdate.UpdateType == "1"; // 假设UpdateType为"force"表示强制更新 + response.UpdateDescription = $"发现新版本 {response.LatestVersion},请及时更新"; + } + + return response; + } + + /// + /// 将版本号字符串转换为数字代码 (如: 1.0.1 -> 1001) + /// + /// 版本号字符串 + /// + private int ConvertVersionToCode(string version) + { + if (string.IsNullOrEmpty(version)) + return 0; + var newCode = version.Replace(".", ""); + if (int.TryParse(newCode, out int result)) + { + return result; + } + return 100; + //var parts = version.Split('.'); + //var code = 0; + //var multiplier = 100; // 支持到百位 + + //foreach (var part in parts) + //{ + // if (int.TryParse(part, out int num)) + // { + // code += num * multiplier; + // multiplier /= 100; // 每段占2位 + // } + //} + + //return code; + } + + /// + /// 将数字代码转换为版本号字符串 (如: 1001 -> 1.0.1) + /// + /// 数字代码 + /// + private string ConvertCodeToVersion(int code) + { + var major = code / 10000; + var minor = (code % 10000) / 100; + var patch = code % 100; + + return $"{major}.{minor}.{patch}"; + } + + /// + /// 查询导出表达式 + /// + /// + /// + private static Expressionable QueryExp(OdfAppUpdatesQueryDto parm) + { + var predicate = Expressionable.Create(); + + predicate = predicate.AndIF(parm.VersionCode != null, it => it.VersionCode == parm.VersionCode); + return predicate; + } + } +} \ No newline at end of file