// ============================================================================ // 【文件说明】HwContactUsInfoService.cs - 联系我们信息服务类 // ============================================================================ // 这个服务类负责处理"联系我们"模块的业务逻辑,包括: // - 用户留言/咨询信息的 CRUD 操作 // - 用户信息(姓名、邮箱、电话、IP)管理 // // 【业务背景】 // "联系我们"是企业官网的常见模块,用于收集用户的咨询、反馈、合作意向等。 // 这个服务管理用户提交的联系信息。 // // 【与 Java Spring Boot 的对比】 // Java Spring Boot: // @Service // public class HwContactUsInfoServiceImpl implements HwContactUsInfoService { ... } // // ASP.NET Core + Furion: // public class HwContactUsInfoService : ITransient { ... } // ============================================================================ namespace Admin.NET.Plugin.HwPortal; /// /// 联系我们信息服务类。 /// /// 【服务职责】 /// 1. 管理用户联系信息的增删改查 /// 2. 处理用户信息字段(姓名、邮箱、电话、IP) /// 3. 数据规范化(空字符串处理) /// /// /// 【用户姓名字段特殊处理】 /// Why:用户姓名在原 XML 中空串不会入库,这里同步保持, /// 避免后台筛选出现空值脏数据。 /// /// public class HwContactUsInfoService : ITransient { /// /// MyBatis 映射器名称(保留用于回滚)。 /// private const string Mapper = "HwContactUsInfoMapper"; /// /// MyBatis 执行器(保留用于回滚)。 /// private readonly HwPortalMyBatisExecutor _executor; /// /// SqlSugar 数据访问对象。 /// private readonly ISqlSugarClient _db; /// /// 构造函数(依赖注入)。 /// /// MyBatis 执行器 /// SqlSugar 数据访问对象 public HwContactUsInfoService(HwPortalMyBatisExecutor executor, ISqlSugarClient db) { _executor = executor; _db = db; } /// /// 根据ID查询联系信息。 /// /// 联系信息ID /// 联系信息实体 public async Task SelectHwContactUsInfoByContactUsInfoId(long contactUsInfoId) { // 回滚到 XML 方案时可直接恢复: // return await _executor.QuerySingleAsync(Mapper, "selectHwContactUsInfoByContactUsInfoId", new { contactUsInfoId }); return await _db.Queryable() .Where(item => item.ContactUsInfoId == contactUsInfoId) .FirstAsync(); } /// /// 查询联系信息列表。 /// /// 【动态查询条件】 /// 支持按用户名、邮箱、电话、IP等条件模糊查询。 /// 所有条件都是可选的,有值时才添加到 WHERE 子句。 /// /// /// 查询条件 /// 联系信息列表 public async Task> SelectHwContactUsInfoList(HwContactUsInfo input) { HwContactUsInfo query = input ?? new HwContactUsInfo(); // 回滚到 XML 方案时可直接恢复: // return await _executor.QueryListAsync(Mapper, "selectHwContactUsInfoList", query); return await _db.Queryable() .WhereIF(!string.IsNullOrWhiteSpace(query.UserName), item => item.UserName.Contains(query.UserName)) .WhereIF(!string.IsNullOrWhiteSpace(query.UserEmail), item => item.UserEmail.Contains(query.UserEmail)) .WhereIF(!string.IsNullOrWhiteSpace(query.UserPhone), item => item.UserPhone.Contains(query.UserPhone)) .WhereIF(!string.IsNullOrWhiteSpace(query.UserIp), item => item.UserIp.Contains(query.UserIp)) .ToListAsync(); } /// /// 新增联系信息。 /// /// 【用户姓名字段特殊处理】 /// Why:用户姓名在原 XML 中空串不会入库,这里同步保持, /// 避免后台筛选出现空值脏数据。 /// /// 原 XML 中 MyBatis 的条件: /// <if test="userName != null and userName != ''"> /// user_name = #{userName}, /// </if> /// /// 当传入空字符串时,XML 不会插入该字段。 /// 为了保持行为一致,这里将空字符串转为 null。 /// /// /// 联系信息 /// 影响行数 public async Task InsertHwContactUsInfo(HwContactUsInfo input) { // 【数据规范化】 // 将用户姓名空字符串转为 null,与 XML 方案保持一致 // Why:用户姓名在原 XML 中空串不会入库,这里同步保持,避免后台筛选出现空值脏数据。 input.UserName = NormalizeEmptyToNull(input.UserName); // 【审计字段】 input.CreateTime = HwPortalContextHelper.Now(); // 回滚到 XML 方案时可直接恢复: // long identity = await _executor.InsertReturnIdentityAsync(Mapper, "insertHwContactUsInfo", input); HwContactUsInfo entity = await _db.Insertable(input).ExecuteReturnEntityAsync(); input.ContactUsInfoId = entity.ContactUsInfoId; return input.ContactUsInfoId > 0 ? 1 : 0; } /// /// 更新联系信息。 /// /// 【字段级更新策略】 /// 1. 先查询现有记录 /// 2. 对非空字段进行更新 /// 3. 空字符串也视为有效值 /// /// /// 更新的数据 /// 影响行数 public async Task UpdateHwContactUsInfo(HwContactUsInfo input) { input.UpdateTime = HwPortalContextHelper.Now(); // 回滚到 XML 方案时可直接恢复: // return await _executor.ExecuteAsync(Mapper, "updateHwContactUsInfo", input); HwContactUsInfo current = await SelectHwContactUsInfoByContactUsInfoId(input.ContactUsInfoId ?? 0); if (current == null) { return 0; } // 【用户姓名字段】 // 使用 string.IsNullOrWhiteSpace 判断,空字符串不更新 if (!string.IsNullOrWhiteSpace(input.UserName)) { current.UserName = input.UserName; } // 【邮箱字段】 // 使用 != null 判断,允许更新为空字符串 if (input.UserEmail != null) { current.UserEmail = input.UserEmail; } // 【电话字段】 if (input.UserPhone != null) { current.UserPhone = input.UserPhone; } // 【IP字段】 if (input.UserIp != null) { current.UserIp = input.UserIp; } // 【备注字段】 if (input.Remark != null) { current.Remark = input.Remark; } // 【审计字段】 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(); } /// /// 批量删除联系信息。 /// /// 联系信息ID数组 /// 影响行数 public async Task DeleteHwContactUsInfoByContactUsInfoIds(long[] contactUsInfoIds) { // 回滚到 XML 方案时可直接恢复: // return await _executor.ExecuteAsync(Mapper, "deleteHwContactUsInfoByContactUsInfoIds", new { array = contactUsInfoIds }); return await _db.Deleteable() .In(contactUsInfoIds) .ExecuteCommandAsync(); } /// /// 将空字符串规范化转为 null。 /// /// 【辅助方法】 /// 用于保持与 XML 方案的数据一致性。 /// 原 XML 中 <if> 标签会跳过空字符串, /// 这里主动将空字符串转为 null,达到同样效果。 /// /// /// 输入字符串 /// null 或原值 private static string NormalizeEmptyToNull(string value) { return string.IsNullOrWhiteSpace(value) ? null : value; } }