|
|
// ============================================================================
|
|
|
// 【文件说明】HwPortalConfigService.cs - 门户配置服务类
|
|
|
// ============================================================================
|
|
|
// 这个服务类负责处理门户配置的业务逻辑,包括:
|
|
|
// - 门户配置的 CRUD 操作
|
|
|
// - 关联查询(配置 + 配置类型)
|
|
|
// - 空字符串规范化处理
|
|
|
//
|
|
|
// 【业务背景】
|
|
|
// 门户配置模块用于管理网站首页的各种配置项,如轮播图、推荐内容等。
|
|
|
// 支持关联查询配置类型信息。
|
|
|
//
|
|
|
// 【与 Java Spring Boot 的对比】
|
|
|
// Java Spring Boot:
|
|
|
// @Service
|
|
|
// public class HwPortalConfigServiceImpl implements HwPortalConfigService { ... }
|
|
|
//
|
|
|
// ASP.NET Core + Furion:
|
|
|
// public class HwPortalConfigService : ITransient { ... }
|
|
|
// ============================================================================
|
|
|
|
|
|
namespace Admin.NET.Plugin.HwPortal;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 门户配置服务类。
|
|
|
/// <para>
|
|
|
/// 【服务职责】
|
|
|
/// 1. 管理门户配置的增删改查
|
|
|
/// 2. 支持关联查询配置类型信息
|
|
|
/// 3. 处理空字符串规范化
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【特殊类型处理】
|
|
|
/// 当 PortalConfigType 为 "2" 时,使用 JOIN 查询关联 HwPortalConfigType 表,
|
|
|
/// 返回包含配置类型名称等附加信息的结果。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
public class HwPortalConfigService : ITransient
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// MyBatis 映射器名称(保留用于回滚)。
|
|
|
/// </summary>
|
|
|
private const string Mapper = "HwPortalConfigMapper";
|
|
|
|
|
|
/// <summary>
|
|
|
/// MyBatis 执行器(保留用于回滚)。
|
|
|
/// </summary>
|
|
|
private readonly HwPortalMyBatisExecutor _executor;
|
|
|
|
|
|
/// <summary>
|
|
|
/// SqlSugar 数据访问对象。
|
|
|
/// </summary>
|
|
|
private readonly ISqlSugarClient _db;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 构造函数(依赖注入)。
|
|
|
/// </summary>
|
|
|
/// <param name="executor">MyBatis 执行器</param>
|
|
|
/// <param name="db">SqlSugar 数据访问对象</param>
|
|
|
public HwPortalConfigService(HwPortalMyBatisExecutor executor, ISqlSugarClient db)
|
|
|
{
|
|
|
_executor = executor;
|
|
|
_db = db;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 根据配置ID查询门户配置。
|
|
|
/// </summary>
|
|
|
/// <param name="portalConfigId">配置ID</param>
|
|
|
/// <returns>门户配置实体</returns>
|
|
|
public async Task<HwPortalConfig> SelectHwPortalConfigByPortalConfigId(long portalConfigId)
|
|
|
{
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.QuerySingleAsync<HwPortalConfig>(Mapper, "selectHwPortalConfigByPortalConfigId", new { portalConfigId });
|
|
|
return await _db.Queryable<HwPortalConfig>()
|
|
|
.Where(item => item.PortalConfigId == portalConfigId)
|
|
|
.FirstAsync();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 查询门户配置列表。
|
|
|
/// <para>
|
|
|
/// 【特殊类型处理】
|
|
|
/// 当 PortalConfigType 为 "2"(HwPortalConstants.PortalConfigTypeTwo)时,
|
|
|
/// 使用 BuildPortalConfigJoinQuery 方法进行 JOIN 查询,
|
|
|
/// 返回包含配置类型名称等附加信息的结果。
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【动态查询条件】
|
|
|
/// 支持按配置类型、类型ID、标题、排序号、描述、按钮名、路由地址、图片等条件筛选。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="input">查询条件</param>
|
|
|
/// <returns>门户配置列表</returns>
|
|
|
public async Task<List<HwPortalConfig>> SelectHwPortalConfigList(HwPortalConfig input)
|
|
|
{
|
|
|
HwPortalConfig query = input ?? new HwPortalConfig();
|
|
|
|
|
|
// 【特殊类型处理】
|
|
|
// 当配置类型为 "2" 时,使用 JOIN 查询关联配置类型表
|
|
|
if (string.Equals(HwPortalConstants.PortalConfigTypeTwo, query.PortalConfigType, StringComparison.Ordinal))
|
|
|
{
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.QueryListAsync<HwPortalConfig>(Mapper, "selectHwPortalConfigList2", query);
|
|
|
return await BuildPortalConfigJoinQuery(query).ToListAsync();
|
|
|
}
|
|
|
|
|
|
// 【普通查询】
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.QueryListAsync<HwPortalConfig>(Mapper, "selectHwPortalConfigList", query);
|
|
|
return await _db.Queryable<HwPortalConfig>()
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.PortalConfigType), item => item.PortalConfigType == query.PortalConfigType)
|
|
|
.WhereIF(query.PortalConfigTypeId.HasValue, item => item.PortalConfigTypeId == query.PortalConfigTypeId)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.PortalConfigTitle), item => item.PortalConfigTitle.Contains(query.PortalConfigTitle))
|
|
|
.WhereIF(query.PortalConfigOrder.HasValue, item => item.PortalConfigOrder == query.PortalConfigOrder)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.PortalConfigDesc), item => item.PortalConfigDesc == query.PortalConfigDesc)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.ButtonName), item => item.ButtonName.Contains(query.ButtonName))
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.RouterAddress), item => item.RouterAddress == query.RouterAddress)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.PortalConfigPic), item => item.PortalConfigPic == query.PortalConfigPic)
|
|
|
.ToListAsync();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 新增门户配置。
|
|
|
/// <para>
|
|
|
/// 【空字符串规范化】
|
|
|
/// Why:这里只把原 XML 会忽略的空串字段转成 null,
|
|
|
/// 其它字段继续保留调用方原值,避免语义漂移。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="input">门户配置数据</param>
|
|
|
/// <returns>影响行数</returns>
|
|
|
public async Task<int> InsertHwPortalConfig(HwPortalConfig input)
|
|
|
{
|
|
|
// 【数据规范化】
|
|
|
// 将空字符串转为 null,与 XML 方案保持一致
|
|
|
input.PortalConfigType = NormalizeEmptyToNull(input.PortalConfigType);
|
|
|
input.PortalConfigTitle = NormalizeEmptyToNull(input.PortalConfigTitle);
|
|
|
input.PortalConfigPic = NormalizeEmptyToNull(input.PortalConfigPic);
|
|
|
|
|
|
// 【审计字段】
|
|
|
input.CreateTime = HwPortalContextHelper.Now();
|
|
|
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// long identity = await _executor.InsertReturnIdentityAsync(Mapper, "insertHwPortalConfig", input);
|
|
|
HwPortalConfig entity = await _db.Insertable(input).ExecuteReturnEntityAsync();
|
|
|
input.PortalConfigId = entity.PortalConfigId;
|
|
|
return input.PortalConfigId > 0 ? 1 : 0;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 更新门户配置。
|
|
|
/// <para>
|
|
|
/// 【字段级更新策略】
|
|
|
/// 只更新输入对象中不为 null 或不为空的字段。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="input">更新的数据</param>
|
|
|
/// <returns>影响行数</returns>
|
|
|
public async Task<int> UpdateHwPortalConfig(HwPortalConfig input)
|
|
|
{
|
|
|
// 【审计字段】
|
|
|
input.UpdateTime = HwPortalContextHelper.Now();
|
|
|
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.ExecuteAsync(Mapper, "updateHwPortalConfig", input);
|
|
|
HwPortalConfig current = await SelectHwPortalConfigByPortalConfigId(input.PortalConfigId ?? 0);
|
|
|
if (current == null)
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
// 【配置类型】
|
|
|
if (!string.IsNullOrWhiteSpace(input.PortalConfigType))
|
|
|
{
|
|
|
current.PortalConfigType = input.PortalConfigType;
|
|
|
}
|
|
|
|
|
|
// 【类型ID】
|
|
|
if (input.PortalConfigTypeId.HasValue)
|
|
|
{
|
|
|
current.PortalConfigTypeId = input.PortalConfigTypeId;
|
|
|
}
|
|
|
|
|
|
// 【标题】
|
|
|
if (!string.IsNullOrWhiteSpace(input.PortalConfigTitle))
|
|
|
{
|
|
|
current.PortalConfigTitle = input.PortalConfigTitle;
|
|
|
}
|
|
|
|
|
|
// 【排序号】
|
|
|
if (input.PortalConfigOrder.HasValue)
|
|
|
{
|
|
|
current.PortalConfigOrder = input.PortalConfigOrder;
|
|
|
}
|
|
|
|
|
|
// 【描述】
|
|
|
if (input.PortalConfigDesc != null)
|
|
|
{
|
|
|
current.PortalConfigDesc = input.PortalConfigDesc;
|
|
|
}
|
|
|
|
|
|
// 【按钮名】
|
|
|
if (input.ButtonName != null)
|
|
|
{
|
|
|
current.ButtonName = input.ButtonName;
|
|
|
}
|
|
|
|
|
|
// 【路由地址】
|
|
|
if (input.RouterAddress != null)
|
|
|
{
|
|
|
current.RouterAddress = input.RouterAddress;
|
|
|
}
|
|
|
|
|
|
// 【图片】
|
|
|
if (!string.IsNullOrWhiteSpace(input.PortalConfigPic))
|
|
|
{
|
|
|
current.PortalConfigPic = input.PortalConfigPic;
|
|
|
}
|
|
|
|
|
|
// 【审计字段】
|
|
|
if (input.CreateTime.HasValue)
|
|
|
{
|
|
|
current.CreateTime = input.CreateTime;
|
|
|
}
|
|
|
|
|
|
if (input.CreateBy != null)
|
|
|
{
|
|
|
current.CreateBy = input.CreateBy;
|
|
|
}
|
|
|
|
|
|
current.UpdateTime = input.UpdateTime;
|
|
|
if (input.UpdateBy != null)
|
|
|
{
|
|
|
current.UpdateBy = input.UpdateBy;
|
|
|
}
|
|
|
|
|
|
return await _db.Updateable(current).ExecuteCommandAsync();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 批量删除门户配置。
|
|
|
/// </summary>
|
|
|
/// <param name="portalConfigIds">配置ID数组</param>
|
|
|
/// <returns>影响行数</returns>
|
|
|
public async Task<int> DeleteHwPortalConfigByPortalConfigIds(long[] portalConfigIds)
|
|
|
{
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.ExecuteAsync(Mapper, "deleteHwPortalConfigByPortalConfigIds", new { array = portalConfigIds });
|
|
|
return await _db.Deleteable<HwPortalConfig>()
|
|
|
.In(portalConfigIds)
|
|
|
.ExecuteCommandAsync();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 查询门户配置关联列表(JOIN查询)。
|
|
|
/// <para>
|
|
|
/// 【关联查询】
|
|
|
/// 使用 BuildPortalConfigJoinQuery 方法进行 JOIN 查询,
|
|
|
/// 返回包含配置类型信息的完整结果。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="input">查询条件</param>
|
|
|
/// <returns>门户配置列表(含类型信息)</returns>
|
|
|
public async Task<List<HwPortalConfig>> SelectHwPortalConfigJoinList(HwPortalConfig input)
|
|
|
{
|
|
|
HwPortalConfig query = input ?? new HwPortalConfig();
|
|
|
// 回滚到 XML 方案时可直接恢复:
|
|
|
// return await _executor.QueryListAsync<HwPortalConfig>(Mapper, "selectHwPortalConfigJoinList", query);
|
|
|
return await BuildPortalConfigJoinQuery(query).ToListAsync();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 构建门户配置 JOIN 查询。
|
|
|
/// <para>
|
|
|
/// 【SqlSugar JOIN 查询】
|
|
|
/// 使用 SqlSugar 的 Queryable 进行左连接(Left Join)查询,
|
|
|
/// 关联 HwPortalConfigType 表获取配置类型信息。
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// 【字段投影】
|
|
|
/// Why:这里统一把关联侧字段一起投影出来,避免 provider 对条件投影翻译不稳定。
|
|
|
/// 对不需要这些字段的调用方来说,多出冗余属性不会改变行为,但能明显降低切换风险。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="query">查询条件</param>
|
|
|
/// <returns>JOIN 查询对象</returns>
|
|
|
private ISugarQueryable<HwPortalConfig> BuildPortalConfigJoinQuery(HwPortalConfig query)
|
|
|
{
|
|
|
return _db.Queryable<HwPortalConfig, HwPortalConfigType>((config, configType) =>
|
|
|
new JoinQueryInfos(JoinType.Left, config.PortalConfigTypeId == configType.ConfigTypeId))
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.PortalConfigType), (config, _) => config.PortalConfigType == query.PortalConfigType)
|
|
|
.WhereIF(query.PortalConfigTypeId.HasValue, (config, _) => config.PortalConfigTypeId == query.PortalConfigTypeId)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.PortalConfigTitle), (config, _) => config.PortalConfigTitle.Contains(query.PortalConfigTitle))
|
|
|
.WhereIF(query.PortalConfigOrder.HasValue, (config, _) => config.PortalConfigOrder == query.PortalConfigOrder)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.PortalConfigDesc), (config, _) => config.PortalConfigDesc == query.PortalConfigDesc)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.ButtonName), (config, _) => config.ButtonName.Contains(query.ButtonName))
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.RouterAddress), (config, _) => config.RouterAddress == query.RouterAddress)
|
|
|
.WhereIF(!string.IsNullOrWhiteSpace(query.PortalConfigPic), (config, _) => config.PortalConfigPic == query.PortalConfigPic)
|
|
|
.Select((config, configType) => new HwPortalConfig
|
|
|
{
|
|
|
// 【主表字段】
|
|
|
PortalConfigId = config.PortalConfigId,
|
|
|
PortalConfigType = config.PortalConfigType,
|
|
|
PortalConfigTypeId = config.PortalConfigTypeId,
|
|
|
PortalConfigTitle = config.PortalConfigTitle,
|
|
|
PortalConfigOrder = config.PortalConfigOrder,
|
|
|
PortalConfigDesc = config.PortalConfigDesc,
|
|
|
ButtonName = config.ButtonName,
|
|
|
RouterAddress = config.RouterAddress,
|
|
|
PortalConfigPic = config.PortalConfigPic,
|
|
|
CreateTime = config.CreateTime,
|
|
|
CreateBy = config.CreateBy,
|
|
|
UpdateTime = config.UpdateTime,
|
|
|
UpdateBy = config.UpdateBy,
|
|
|
|
|
|
// 【关联表字段】
|
|
|
ConfigTypeName = configType.ConfigTypeName,
|
|
|
|
|
|
// 【冗余字段】
|
|
|
// Why:这里统一把关联侧字段一起投影出来,避免 provider 对条件投影翻译不稳定。
|
|
|
// 对不需要这些字段的调用方来说,多出冗余属性不会改变行为,但能明显降低切换风险。
|
|
|
HomeConfigTypePic = configType.HomeConfigTypePic,
|
|
|
HomeConfigTypeIcon = configType.ConfigTypeIcon,
|
|
|
HomeConfigTypeName = configType.HomeConfigTypeName,
|
|
|
HomeConfigTypeClassfication = configType.ConfigTypeClassfication,
|
|
|
ParentId = configType.ParentId,
|
|
|
Ancestors = configType.Ancestors
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 将空字符串规范化转为 null。
|
|
|
/// <para>
|
|
|
/// 【辅助方法】
|
|
|
/// 用于保持与 XML 方案的数据一致性。
|
|
|
/// 原 XML 中 <if> 标签会跳过空字符串,
|
|
|
/// 这里主动将空字符串转为 null,达到同样效果。
|
|
|
/// </para>
|
|
|
/// </summary>
|
|
|
/// <param name="value">输入字符串</param>
|
|
|
/// <returns>null 或原值</returns>
|
|
|
private static string NormalizeEmptyToNull(string value)
|
|
|
{
|
|
|
return string.IsNullOrWhiteSpace(value) ? null : value;
|
|
|
}
|
|
|
}
|