namespace SimpleAdmin.Application; /// /// 维护员工端动态字段、材料类型及公司岗位要求。 /// public class OnboardingEntryConfigService : IOnboardingEntryConfigService { private readonly SqlSugarScope _db; public OnboardingEntryConfigService() { _db = DbContext.DB; } /// /// 查询全部动态入职字段。 /// public Task> ListFormFields() { return _db.Queryable() .OrderBy(x => x.FieldCode) .ToListAsync(); } /// /// 新增或编辑动态入职字段。 /// public async Task SaveFormField(OnboardingFormFieldSaveInput input) { var fieldCodeQuery = _db.Queryable() .Where(x => x.FieldCode == input.FieldCode); if (input.Id.HasValue) fieldCodeQuery = fieldCodeQuery.Where(x => x.Id != input.Id.Value); var fieldCodeExists = await fieldCodeQuery.AnyAsync(); if (fieldCodeExists) throw Oops.Bah("字段编码已存在"); var entity = new ObFormField { Id = input.Id ?? global::SimpleAdmin.Core.Utils.CommonUtils.GetSingleId(), FieldCode = input.FieldCode, FieldName = input.FieldName, DataType = input.DataType, OptionsJson = NormalizeOptionsJson(input.OptionsJson), ValidationRule = input.ValidationRule, Placeholder = input.Placeholder, Status = input.Status }; if (input.Id.HasValue) { var exists = await _db.Queryable().AnyAsync(x => x.Id == input.Id.Value); if (!exists) throw Oops.Bah("字段不存在"); await _db.Updateable(entity).ExecuteCommandAsync(); return; } await _db.Insertable(entity).ExecuteCommandAsync(); } /// /// 将空白的可选项转换为 null,避免 MySQL JSON 字段写入空字符串时报错。 /// private static string NormalizeOptionsJson(string optionsJson) { if (string.IsNullOrWhiteSpace(optionsJson)) return null; var normalizedJson = optionsJson.Trim(); try { using var jsonDocument = global::System.Text.Json.JsonDocument.Parse(normalizedJson); return normalizedJson; } catch (global::System.Text.Json.JsonException) { throw Oops.Bah("可选项不是有效的 JSON 格式"); } } /// /// 删除未被填写要求引用的动态字段。 /// public async Task DeleteFormFields(BaseIdListInput input) { if (input.Ids.Count == 0) return; var isReferenced = await _db.Queryable() .AnyAsync(x => input.Ids.Contains(x.FieldId)); if (isReferenced) throw Oops.Bah("字段已被填写要求引用,不能删除"); await _db.Deleteable().In(input.Ids).ExecuteCommandAsync(); } /// /// 查询全部入职材料类型。 /// public Task> ListMaterialTypes() { return _db.Queryable() .OrderBy(x => x.MaterialCode) .ToListAsync(); } /// /// 新增或编辑入职材料类型。 /// public async Task SaveMaterialType(OnboardingMaterialTypeSaveInput input) { if (input.MaxFileCount <= 0) throw Oops.Bah("最大文件数量必须大于0"); var materialCodeExists = await _db.Queryable() .AnyAsync(x => x.MaterialCode == input.MaterialCode && x.Id != input.Id); if (materialCodeExists) throw Oops.Bah("资料编码已存在"); var entity = new ObMaterialType { Id = input.Id ?? global::SimpleAdmin.Core.Utils.CommonUtils.GetSingleId(), MaterialCode = input.MaterialCode, MaterialName = input.MaterialName, AllowedExtensions = input.AllowedExtensions, MaxFileCount = input.MaxFileCount, MaxFileSizeMb = input.MaxFileSizeMb, Status = input.Status }; if (input.Id.HasValue) { var exists = await _db.Queryable().AnyAsync(x => x.Id == input.Id.Value); if (!exists) throw Oops.Bah("资料类型不存在"); await _db.Updateable(entity).ExecuteCommandAsync(); return; } await _db.Insertable(entity).ExecuteCommandAsync(); } /// /// 删除未被要求或上传记录引用的材料类型。 /// public async Task DeleteMaterialTypes(BaseIdListInput input) { if (input.Ids.Count == 0) return; var isReferenced = await _db.Queryable() .AnyAsync(x => input.Ids.Contains(x.MaterialTypeId)); if (isReferenced) throw Oops.Bah("资料类型已被资料要求引用,不能删除"); var hasUploads = await _db.Queryable() .AnyAsync(x => input.Ids.Contains(x.MaterialTypeId)); if (hasUploads) throw Oops.Bah("资料类型已有上传记录,不能删除"); await _db.Deleteable().In(input.Ids).ExecuteCommandAsync(); } /// /// 查询指定公司的动态字段填写要求。 /// public Task> ListFormRequirements(long companyId) { return _db.Queryable() .Where(x => x.CompanyId == companyId) .OrderBy(x => x.SortCode) .ToListAsync(); } /// /// 新增或编辑公司岗位动态字段要求。 /// public async Task SaveFormRequirement(OnboardingFormRequirementSaveInput input) { await EnsureCompanyAndPosition(input.CompanyId, input.PositionId); var fieldExists = await _db.Queryable() .AnyAsync(x => x.Id == input.FieldId && x.Status == "enable"); if (!fieldExists) throw Oops.Bah("动态字段不存在或未启用"); var requirementExists = await _db.Queryable() .AnyAsync(x => x.CompanyId == input.CompanyId && x.PositionId == input.PositionId && x.FieldId == input.FieldId && x.Id != input.Id); if (requirementExists) throw Oops.Bah("该公司、岗位和字段的要求已存在"); var entity = new ObFormRequirement { Id = input.Id ?? global::SimpleAdmin.Core.Utils.CommonUtils.GetSingleId(), CompanyId = input.CompanyId, PositionId = input.PositionId, FieldId = input.FieldId, Required = input.Required, SortCode = input.SortCode }; if (input.Id.HasValue) { await _db.Updateable(entity).ExecuteCommandAsync(); return; } await _db.Insertable(entity).ExecuteCommandAsync(); } /// /// 删除动态字段填写要求。 /// public Task DeleteFormRequirements(BaseIdListInput input) { if (input.Ids.Count == 0) return Task.CompletedTask; return _db.Deleteable().In(input.Ids).ExecuteCommandAsync(); } /// /// 查询指定公司的材料上传要求。 /// public Task> ListMaterialRequirements(long companyId) { return _db.Queryable() .Where(x => x.CompanyId == companyId) .OrderBy(x => x.SortCode) .ToListAsync(); } /// /// 新增或编辑公司岗位材料要求。 /// public async Task SaveMaterialRequirement(OnboardingMaterialRequirementSaveInput input) { await EnsureCompanyAndPosition(input.CompanyId, input.PositionId); var materialTypeExists = await _db.Queryable() .AnyAsync(x => x.Id == input.MaterialTypeId && x.Status == "enable"); if (!materialTypeExists) throw Oops.Bah("资料类型不存在或未启用"); var requirementExists = await _db.Queryable() .AnyAsync(x => x.CompanyId == input.CompanyId && x.PositionId == input.PositionId && x.MaterialTypeId == input.MaterialTypeId && x.Id != input.Id); if (requirementExists) throw Oops.Bah("该公司、岗位和资料类型的要求已存在"); var entity = new ObMaterialRequirement { Id = input.Id ?? global::SimpleAdmin.Core.Utils.CommonUtils.GetSingleId(), CompanyId = input.CompanyId, PositionId = input.PositionId, MaterialTypeId = input.MaterialTypeId, Required = input.Required, SortCode = input.SortCode }; if (input.Id.HasValue) { await _db.Updateable(entity).ExecuteCommandAsync(); return; } await _db.Insertable(entity).ExecuteCommandAsync(); } /// /// 删除材料上传要求。 /// public Task DeleteMaterialRequirements(BaseIdListInput input) { if (input.Ids.Count == 0) return Task.CompletedTask; return _db.Deleteable().In(input.Ids).ExecuteCommandAsync(); } private async Task EnsureCompanyAndPosition(long companyId, long? positionId) { var companyExists = await _db.Queryable() .AnyAsync(x => x.Id == companyId && x.Status == "enable"); if (!companyExists) throw Oops.Bah("公司不存在或未启用"); if (!positionId.HasValue) return; var positionExists = await _db.Queryable() .AnyAsync(x => x.Id == positionId.Value && x.CompanyId == companyId && x.Status == "enable"); if (!positionExists) throw Oops.Bah("岗位不存在、未启用或不属于该公司"); } }