This commit is contained in:
zpc 2025-09-23 16:11:54 +08:00
parent 050c89e657
commit a9582f4fcd
11 changed files with 515 additions and 2 deletions

View File

@ -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
{
/// <summary>
/// App 更新表
/// </summary>
[Route("business/OdfAppUpdates")]
public class OdfAppUpdatesController : BaseController
{
/// <summary>
/// App 更新表接口
/// </summary>
private readonly IOdfAppUpdatesService _OdfAppUpdatesService;
public OdfAppUpdatesController(IOdfAppUpdatesService OdfAppUpdatesService)
{
_OdfAppUpdatesService = OdfAppUpdatesService;
}
/// <summary>
/// 查询App 更新表列表
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
[HttpGet("list")]
[ActionPermissionFilter(Permission = "odfappupdates:list")]
public IActionResult QueryOdfAppUpdates([FromQuery] OdfAppUpdatesQueryDto parm)
{
var response = _OdfAppUpdatesService.GetList(parm);
return SUCCESS(response);
}
/// <summary>
/// 查询App 更新表详情
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
[HttpGet("{Id}")]
[ActionPermissionFilter(Permission = "odfappupdates:query")]
public IActionResult GetOdfAppUpdates(int Id)
{
var response = _OdfAppUpdatesService.GetInfo(Id);
var info = response.Adapt<OdfAppUpdatesDto>();
return SUCCESS(info);
}
/// <summary>
/// 修改状态
/// </summary>
/// <returns></returns>
[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);
}
/// <summary>
/// 添加App 更新表
/// </summary>
/// <returns></returns>
[HttpPost("add")]
[ActionPermissionFilter(Permission = "odfappupdates:add")]
[Log(Title = "App 更新表", BusinessType = BusinessType.INSERT)]
public IActionResult AddOdfAppUpdates([FromBody] OdfAppUpdatesDto parm)
{
var modal = parm.Adapt<OdfAppUpdates>().ToCreate(HttpContext);
parm.CreateTime = DateTime.Now;
var response = _OdfAppUpdatesService.AddOdfAppUpdates(modal);
return SUCCESS(response);
}
/// <summary>
/// 更新App 更新表
/// </summary>
/// <returns></returns>
[HttpPut]
[ActionPermissionFilter(Permission = "odfappupdates:edit")]
[Log(Title = "App 更新表", BusinessType = BusinessType.UPDATE)]
public IActionResult UpdateOdfAppUpdates([FromBody] OdfAppUpdatesDto parm)
{
var modal = parm.Adapt<OdfAppUpdates>().ToUpdate(HttpContext);
var response = _OdfAppUpdatesService.UpdateOdfAppUpdates(modal);
return ToResponse(response);
}
/// <summary>
/// 删除App 更新表
/// </summary>
/// <returns></returns>
[HttpPost("delete/{ids}")]
[ActionPermissionFilter(Permission = "odfappupdates:delete")]
[Log(Title = "App 更新表", BusinessType = BusinessType.DELETE)]
public IActionResult DeleteOdfAppUpdates([FromRoute] string ids)
{
var idArr = Tools.SplitAndConvert<int>(ids);
return ToResponse(_OdfAppUpdatesService.Delete(idArr));
}
}
}

View File

@ -103,7 +103,7 @@ namespace ZR.Admin.WebApi.Controllers
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
[ActionPermissionFilter(Permission = "common")] [ActionPermissionFilter(Permission = "common")]
public async Task<IActionResult> UploadFile([FromForm] UploadDto uploadDto, IFormFile file, StoreType storeType = StoreType.ALIYUN) public async Task<IActionResult> UploadFile([FromForm] UploadDto uploadDto, IFormFile file, StoreType storeType = StoreType.LOCAL)
{ {
if (file == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空"); if (file == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空");
SysFile sysfile = new(); SysFile sysfile = new();

View File

@ -21,5 +21,44 @@ namespace ZR.Admin.WebApi.Controllers
public class WebApiController : BaseController public class WebApiController : BaseController
{ {
private readonly WechatApiClient _client; private readonly WechatApiClient _client;
private readonly IOdfAppUpdatesService _odfAppUpdatesService;
public WebApiController(WechatApiClient client, IOdfAppUpdatesService odfAppUpdatesService)
{
_client = client;
_odfAppUpdatesService = odfAppUpdatesService;
}
/// <summary>
/// 检查App版本更新
/// </summary>
/// <param name="version">版本</param>
/// <returns></returns>
[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}");
}
}
} }
} }

View File

@ -49,7 +49,7 @@
"sqlExecutionTime": 5, //Sql "sqlExecutionTime": 5, //Sql
"Upload": { "Upload": {
"uploadUrl": "http://localhost:8888", //访 "uploadUrl": "http://localhost:8888", //访
"localSavePath": "", // wwwroot "localSavePath": "/file/", // wwwroot
"maxSize": 15, // 15M "maxSize": 15, // 15M
"notAllowedExt": [ ".bat", ".exe", ".jar", ".js" ], "notAllowedExt": [ ".bat", ".exe", ".jar", ".js" ],
"requestLimitSize": 50 //body "requestLimitSize": 50 //body

View File

@ -0,0 +1,93 @@
namespace ZR.Model.Business.Dto
{
/// <summary>
/// App 更新表查询对象
/// </summary>
public class OdfAppUpdatesQueryDto : PagerInfo
{
public int? VersionCode { get; set; }
}
/// <summary>
/// App 更新表输入输出对象
/// </summary>
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; }
}
/// <summary>
/// App 更新表输入输出对象
/// </summary>
public class OdfAppUpdatesStatusDto
{
public int? Id { get; set; }
[Required(ErrorMessage = "是否启用不能为空")]
public bool IsActive { get; set; }
}
/// <summary>
/// App版本检查请求对象
/// </summary>
public class AppVersionCheckRequestDto
{
/// <summary>
/// 当前App版本号 (如: 1.0.1)
/// </summary>
[Required(ErrorMessage = "版本号不能为空")]
public string Version { get; set; }
}
/// <summary>
/// App版本检查响应对象
/// </summary>
public class AppVersionCheckResponseDto
{
/// <summary>
/// 是否需要更新
/// </summary>
public bool NeedUpdate { get; set; }
/// <summary>
/// 是否强制更新
/// </summary>
public bool ForceUpdate { get; set; }
/// <summary>
/// 最新版本号
/// </summary>
public string LatestVersion { get; set; }
/// <summary>
/// 下载地址
/// </summary>
public string DownloadUrl { get; set; }
/// <summary>
/// 更新说明
/// </summary>
public string UpdateDescription { get; set; }
}
}

View File

@ -0,0 +1,42 @@
namespace ZR.Model.Business
{
/// <summary>
/// App 更新表
/// </summary>
[SugarTable("odf_app_updates")]
public class OdfAppUpdates
{
/// <summary>
/// Id
/// </summary>
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int? Id { get; set; }
/// <summary>
/// 版本号
/// </summary>
public int VersionCode { get; set; }
/// <summary>
/// 更新类型
/// </summary>
public string UpdateType { get; set; }
/// <summary>
/// 下载地址
/// </summary>
public string DownloadUrl { get; set; }
/// <summary>
/// 是否启用
/// </summary>
public bool IsActive { get; set; }
/// <summary>
/// 发布时间
/// </summary>
public DateTime? CreateTime { get; set; }
}
}

View File

@ -0,0 +1,33 @@
using ZR.Model.Business.Dto;
using ZR.Model.Business;
namespace ZR.Service.Business.IBusinessService
{
/// <summary>
/// App 更新表service接口
/// </summary>
public interface IOdfAppUpdatesService : IBaseService<OdfAppUpdates>
{
PagedInfo<OdfAppUpdatesDto> GetList(OdfAppUpdatesQueryDto parm);
OdfAppUpdates GetInfo(int Id);
OdfAppUpdates AddOdfAppUpdates(OdfAppUpdates parm);
int UpdateOdfAppUpdates(OdfAppUpdates parm);
/// <summary>
/// 批量更新所有激活状态为未激活
/// </summary>
/// <returns></returns>
int UpdateAllActiveToInactive();
/// <summary>
/// 检查App版本是否需要更新
/// </summary>
/// <param name="currentVersion">当前App版本号</param>
/// <returns></returns>
AppVersionCheckResponseDto CheckAppVersion(string currentVersion);
}
}

View File

@ -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
{
/// <summary>
/// App 更新表Service业务层处理
/// </summary>
[AppService(ServiceType = typeof(IOdfAppUpdatesService), ServiceLifetime = LifeTime.Transient)]
public class OdfAppUpdatesService : BaseService<OdfAppUpdates>, IOdfAppUpdatesService
{
/// <summary>
/// 查询App 更新表列表
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
public PagedInfo<OdfAppUpdatesDto> GetList(OdfAppUpdatesQueryDto parm)
{
var predicate = QueryExp(parm);
var response = Queryable()
//.OrderBy("IsActive desc")
.Where(predicate.ToExpression())
.ToPage<OdfAppUpdates, OdfAppUpdatesDto>(parm);
return response;
}
/// <summary>
/// 获取详情
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
public OdfAppUpdates GetInfo(int Id)
{
var response = Queryable()
.Where(x => x.Id == Id)
.First();
return response;
}
/// <summary>
/// 添加App 更新表
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public OdfAppUpdates AddOdfAppUpdates(OdfAppUpdates model)
{
return Insertable(model).ExecuteReturnEntity();
}
/// <summary>
/// 修改App 更新表
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public int UpdateOdfAppUpdates(OdfAppUpdates model)
{
return Update(model, true);
}
/// <summary>
/// 批量更新所有激活状态为未激活
/// </summary>
/// <returns></returns>
public int UpdateAllActiveToInactive()
{
return Update(x => x.IsActive == true, x => new OdfAppUpdates { IsActive = false });
}
/// <summary>
/// 检查App版本是否需要更新
/// </summary>
/// <param name="currentVersion">当前App版本号</param>
/// <returns></returns>
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;
}
/// <summary>
/// 将版本号字符串转换为数字代码 (如: 1.0.1 -> 1001)
/// </summary>
/// <param name="version">版本号字符串</param>
/// <returns></returns>
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;
}
/// <summary>
/// 将数字代码转换为版本号字符串 (如: 1001 -> 1.0.1)
/// </summary>
/// <param name="code">数字代码</param>
/// <returns></returns>
private string ConvertCodeToVersion(int code)
{
var major = code / 10000;
var minor = (code % 10000) / 100;
var patch = code % 100;
return $"{major}.{minor}.{patch}";
}
/// <summary>
/// 查询导出表达式
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
private static Expressionable<OdfAppUpdates> QueryExp(OdfAppUpdatesQueryDto parm)
{
var predicate = Expressionable.Create<OdfAppUpdates>();
predicate = predicate.AndIF(parm.VersionCode != null, it => it.VersionCode == parm.VersionCode);
return predicate;
}
}
}