You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
10 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// ============================================================================
// 【文件说明】HwWeb1Service.cs - 网页内容服务类
// ============================================================================
// 这个服务类负责处理网页内容的业务逻辑,包括:
// - 网页内容的 CRUD 操作
// - 多维度查询网站代码、设备ID、类型ID
// - 搜索索引重建
//
// 【业务背景】
// 网页内容模块用于管理网站的页面内容,支持按网站代码、设备类型、页面类型等多维度管理。
//
// 【与 Java Spring Boot 的对比】
// Java Spring Boot:
// @Service
// public class HwWeb1ServiceImpl implements HwWeb1Service { ... }
//
// ASP.NET Core + Furion:
// public class HwWeb1Service : ITransient { ... }
// ============================================================================
namespace Admin.NET.Plugin.HwPortal;
/// <summary>
/// 网页内容服务类。
/// <para>
/// 【服务职责】
/// 1. 管理网页内容的增删改查
/// 2. 支持多维度查询网站代码、设备ID、类型ID
/// 3. 网页内容变更时自动重建搜索索引
/// </para>
/// <para>
/// 【更新策略】
/// 更新操作采用"先删除后插入"的策略:
/// 先删除符合条件的旧记录,然后插入新记录。
/// 这种策略简化了更新逻辑但会改变记录的ID。
/// </para>
/// </summary>
public class HwWeb1Service : ITransient
{
/// <summary>
/// MyBatis 映射器名称(保留用于回滚)。
/// </summary>
private const string Mapper = "HwWebMapper1";
/// <summary>
/// MyBatis 执行器(保留用于回滚)。
/// </summary>
private readonly HwPortalMyBatisExecutor _executor;
/// <summary>
/// SqlSugar 数据访问对象。
/// </summary>
private readonly ISqlSugarClient _db;
/// <summary>
/// 搜索索引重建服务。
/// </summary>
private readonly IHwSearchRebuildService _searchRebuildService;
/// <summary>
/// 日志记录器。
/// </summary>
private readonly ILogger<HwWeb1Service> _logger;
/// <summary>
/// 构造函数(依赖注入)。
/// </summary>
/// <param name="executor">MyBatis 执行器</param>
/// <param name="db">SqlSugar 数据访问对象</param>
/// <param name="searchRebuildService">搜索索引重建服务</param>
/// <param name="logger">日志记录器</param>
public HwWeb1Service(HwPortalMyBatisExecutor executor, ISqlSugarClient db, IHwSearchRebuildService searchRebuildService, ILogger<HwWeb1Service> logger)
{
_executor = executor;
_db = db;
_searchRebuildService = searchRebuildService;
_logger = logger;
}
/// <summary>
/// 根据网站代码查询网页内容。
/// <para>
/// 【软删除过滤】
/// 查询时自动过滤已删除的记录IsDelete == "0")。
/// </para>
/// </summary>
/// <param name="webCode">网站代码</param>
/// <returns>网页内容实体</returns>
public async Task<HwWeb1> SelectHwWebByWebcode(long webCode)
{
// 回滚到 XML 方案时可直接恢复:
// return await _executor.QuerySingleAsync<HwWeb1>(Mapper, "selectHwWebByWebcode", new { webCode });
return await _db.Queryable<HwWeb1>()
.Where(item => item.IsDelete == "0" && item.WebCode == webCode)
.FirstAsync();
}
/// <summary>
/// 查询单个网页内容(多维度匹配)。
/// <para>
/// 【多维度匹配】
/// 按网站代码、设备ID、类型ID三个维度精确匹配。
/// </para>
/// </summary>
/// <param name="input">查询条件</param>
/// <returns>网页内容实体</returns>
public async Task<HwWeb1> SelectHwWebOne(HwWeb1 input)
{
HwWeb1 query = input ?? new HwWeb1();
// 回滚到 XML 方案时可直接恢复:
// return await _executor.QuerySingleAsync<HwWeb1>(Mapper, "selectHwWebOne", query);
return await _db.Queryable<HwWeb1>()
.Where(item => item.IsDelete == "0" && item.WebCode == query.WebCode && item.DeviceId == query.DeviceId && item.TypeId == query.TypeId)
.FirstAsync();
}
/// <summary>
/// 查询网页内容列表。
/// <para>
/// 【动态查询条件】
/// 支持按网页ID、JSON内容、网站代码、设备ID、类型ID、英文JSON等条件筛选。
/// </para>
/// </summary>
/// <param name="input">查询条件</param>
/// <returns>网页内容列表</returns>
public async Task<List<HwWeb1>> SelectHwWebList(HwWeb1 input)
{
HwWeb1 query = input ?? new HwWeb1();
// 回滚到 XML 方案时可直接恢复:
// return await _executor.QueryListAsync<HwWeb1>(Mapper, "selectHwWebList", query);
return await _db.Queryable<HwWeb1>()
.Where(item => item.IsDelete == "0")
.WhereIF(query.WebId.HasValue, item => item.WebId == query.WebId)
.WhereIF(query.WebJson != null && query.WebJson != string.Empty, item => item.WebJson == query.WebJson)
.WhereIF(query.WebJsonString != null && query.WebJsonString != string.Empty, item => item.WebJsonString == query.WebJsonString)
.WhereIF(query.WebCode.HasValue, item => item.WebCode == query.WebCode)
.WhereIF(query.DeviceId.HasValue, item => item.DeviceId == query.DeviceId)
.WhereIF(query.TypeId.HasValue, item => item.TypeId == query.TypeId)
.WhereIF(query.WebJsonEnglish != null, item => item.WebJsonEnglish == query.WebJsonEnglish)
.ToListAsync();
}
/// <summary>
/// 新增网页内容。
/// <para>
/// 【搜索索引重建】
/// 网页内容新增后,自动触发搜索索引重建。
/// </para>
/// </summary>
/// <param name="input">网页内容数据</param>
/// <returns>影响行数</returns>
public async Task<int> InsertHwWeb(HwWeb1 input)
{
// 【软删除标记初始化】
input.IsDelete = string.IsNullOrWhiteSpace(input.IsDelete) ? "0" : input.IsDelete;
// 回滚到 XML 方案时可直接恢复:
// long identity = await _executor.InsertReturnIdentityAsync(Mapper, "insertHwWeb", input);
HwWeb1 entity = await _db.Insertable(input).ExecuteReturnEntityAsync();
input.WebId = entity.WebId;
// 【搜索索引重建】
if (input.WebId > 0)
{
await RebuildSearchIndexQuietly("hw_web1");
}
return input.WebId > 0 ? 1 : 0;
}
/// <summary>
/// 更新网页内容。
/// <para>
/// 【更新策略】
/// 采用"先删除后插入"的策略:
/// 1. 先查询并删除符合条件的旧记录(软删除)
/// 2. 设置新记录的 IsDelete = "0"
/// 3. 插入新记录
///
/// 这种策略简化了更新逻辑但会改变记录的ID。
/// </para>
/// <para>
/// 【搜索索引重建】
/// 网页内容更新后,自动触发搜索索引重建。
/// </para>
/// </summary>
/// <param name="input">更新的数据</param>
/// <returns>影响行数</returns>
public async Task<int> UpdateHwWeb(HwWeb1 input)
{
// 【查询旧记录】
HwWeb1 query = new()
{
WebCode = input.WebCode,
TypeId = input.TypeId,
DeviceId = input.DeviceId
};
List<HwWeb1> exists = await SelectHwWebList(query);
// 【删除旧记录】
if (exists.Count > 0)
{
await DeleteHwWebByWebIds(exists.Where(u => u.WebId.HasValue).Select(u => u.WebId!.Value).ToArray(), false);
}
// 【设置新记录】
input.IsDelete = "0";
// 回滚到 XML 方案时可直接恢复:
// long identity = await _executor.InsertReturnIdentityAsync(Mapper, "insertHwWeb", input);
HwWeb1 entity = await _db.Insertable(input).ExecuteReturnEntityAsync();
input.WebId = entity.WebId;
// 【搜索索引重建】
if (input.WebId > 0)
{
await RebuildSearchIndexQuietly("hw_web1");
}
return input.WebId > 0 ? 1 : 0;
}
/// <summary>
/// 批量删除网页内容(软删除)。
/// </summary>
/// <param name="webIds">网页ID数组</param>
/// <returns>影响行数</returns>
public Task<int> DeleteHwWebByWebIds(long[] webIds)
{
return DeleteHwWebByWebIds(webIds, true);
}
/// <summary>
/// 批量删除网页内容(软删除)。
/// <para>
/// 【软删除实现】
/// 将 IsDelete 字段更新为"1",而不是物理删除。
/// </para>
/// <para>
/// 【搜索索引重建】
/// 网页内容删除后,自动触发搜索索引重建。
/// </para>
/// </summary>
/// <param name="webIds">网页ID数组</param>
/// <param name="rebuild">是否重建搜索索引</param>
/// <returns>影响行数</returns>
private async Task<int> DeleteHwWebByWebIds(long[] webIds, bool rebuild)
{
// 回滚到 XML 方案时可直接恢复:
// int rows = await _executor.ExecuteAsync(Mapper, "deleteHwWebByWebIds", new { array = webIds });
// 【查询待删除的网页】
List<HwWeb1> pages = await _db.Queryable<HwWeb1>()
.Where(item => item.WebId.HasValue && webIds.Contains(item.WebId.Value))
.ToListAsync();
// 【软删除标记】
foreach (HwWeb1 page in pages)
{
page.IsDelete = "1";
}
// 【批量更新】
int rows = pages.Count == 0 ? 0 : await _db.Updateable(pages)
.UpdateColumns(item => new { item.IsDelete })
.ExecuteCommandAsync();
// 【搜索索引重建】
if (rows > 0 && rebuild)
{
await RebuildSearchIndexQuietly("hw_web1");
}
return rows;
}
/// <summary>
/// 静默重建搜索索引。
/// </summary>
/// <param name="source">数据来源</param>
private async Task RebuildSearchIndexQuietly(string source)
{
try
{
await _searchRebuildService.RebuildAllAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "rebuild portal search index failed after {Source} changed", source);
}
}
}