diff --git a/DMS.Application/DTOs/CreateEmailAccountRequest.cs b/DMS.Application/DTOs/CreateEmailAccountRequest.cs new file mode 100644 index 0000000..b45a6d3 --- /dev/null +++ b/DMS.Application/DTOs/CreateEmailAccountRequest.cs @@ -0,0 +1,63 @@ +namespace DMS.Application.DTOs +{ + /// + /// 创建邮件账户请求DTO + /// + public class CreateEmailAccountRequest + { + /// + /// 账户名称 + /// + public string Name { get; set; } + + /// + /// 邮箱地址 + /// + public string EmailAddress { get; set; } + + /// + /// SMTP服务器地址 + /// + public string SmtpServer { get; set; } + + /// + /// SMTP端口号 + /// + public int SmtpPort { get; set; } = 587; + + /// + /// 是否启用SSL + /// + public bool EnableSsl { get; set; } = true; + + /// + /// 用户名 + /// + public string Username { get; set; } + + /// + /// 密码 + /// + public string Password { get; set; } + + /// + /// IMAP服务器地址 + /// + public string? ImapServer { get; set; } + + /// + /// IMAP端口号 + /// + public int ImapPort { get; set; } = 993; + + /// + /// 是否为默认账户 + /// + public bool IsDefault { get; set; } + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } = true; + } +} \ No newline at end of file diff --git a/DMS.Application/DTOs/EmailAccountDto.cs b/DMS.Application/DTOs/EmailAccountDto.cs new file mode 100644 index 0000000..80a722c --- /dev/null +++ b/DMS.Application/DTOs/EmailAccountDto.cs @@ -0,0 +1,73 @@ +namespace DMS.Application.DTOs +{ + /// + /// 邮件账户DTO + /// + public class EmailAccountDto + { + /// + /// 账户ID + /// + public int Id { get; set; } + + /// + /// 账户名称 + /// + public string Name { get; set; } + + /// + /// 邮箱地址 + /// + public string EmailAddress { get; set; } + + /// + /// SMTP服务器地址 + /// + public string SmtpServer { get; set; } + + /// + /// SMTP端口号 + /// + public int SmtpPort { get; set; } + + /// + /// 是否启用SSL + /// + public bool EnableSsl { get; set; } + + /// + /// 用户名 + /// + public string Username { get; set; } + + /// + /// IMAP服务器地址 + /// + public string? ImapServer { get; set; } + + /// + /// IMAP端口号 + /// + public int ImapPort { get; set; } + + /// + /// 是否为默认账户 + /// + public bool IsDefault { get; set; } + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } + } +} \ No newline at end of file diff --git a/DMS.Application/DTOs/EmailLogDto.cs b/DMS.Application/DTOs/EmailLogDto.cs new file mode 100644 index 0000000..d0e322f --- /dev/null +++ b/DMS.Application/DTOs/EmailLogDto.cs @@ -0,0 +1,38 @@ +namespace DMS.Application.DTOs +{ + /// + /// 邮件日志DTO + /// + public class EmailLogDto + { + /// + /// 日志ID + /// + public int Id { get; set; } + + /// + /// 关联的邮件ID + /// + public int EmailMessageId { get; set; } + + /// + /// 日志级别 + /// + public string Level { get; set; } + + /// + /// 日志消息 + /// + public string Message { get; set; } + + /// + /// 异常详情 + /// + public string? Exception { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } + } +} \ No newline at end of file diff --git a/DMS.Application/DTOs/EmailMessageDto.cs b/DMS.Application/DTOs/EmailMessageDto.cs new file mode 100644 index 0000000..459cc3e --- /dev/null +++ b/DMS.Application/DTOs/EmailMessageDto.cs @@ -0,0 +1,73 @@ +namespace DMS.Application.DTOs +{ + /// + /// 邮件消息DTO + /// + public class EmailMessageDto + { + /// + /// 邮件ID + /// + public int Id { get; set; } + + /// + /// 关联的邮件账户ID + /// + public int EmailAccountId { get; set; } + + /// + /// 发件人邮箱地址 + /// + public string From { get; set; } + + /// + /// 收件人邮箱地址(多个用分号分隔) + /// + public string To { get; set; } + + /// + /// 抄送邮箱地址(多个用分号分隔) + /// + public string? Cc { get; set; } + + /// + /// 密送邮箱地址(多个用分号分隔) + /// + public string? Bcc { get; set; } + + /// + /// 邮件主题 + /// + public string Subject { get; set; } + + /// + /// 邮件正文 + /// + public string Body { get; set; } + + /// + /// 是否为HTML格式 + /// + public bool IsHtml { get; set; } + + /// + /// 邮件发送状态 + /// + public string Status { get; set; } + + /// + /// 发送时间 + /// + public DateTime? SentAt { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } + } +} \ No newline at end of file diff --git a/DMS.Application/DTOs/EmailTemplateDto.cs b/DMS.Application/DTOs/EmailTemplateDto.cs new file mode 100644 index 0000000..bf1ec9c --- /dev/null +++ b/DMS.Application/DTOs/EmailTemplateDto.cs @@ -0,0 +1,53 @@ +namespace DMS.Application.DTOs +{ + /// + /// 邮件模板DTO + /// + public class EmailTemplateDto + { + /// + /// 模板ID + /// + public int Id { get; set; } + + /// + /// 模板名称 + /// + public string Name { get; set; } + + /// + /// 模板代码(唯一标识) + /// + public string Code { get; set; } + + /// + /// 模板主题 + /// + public string Subject { get; set; } + + /// + /// 模板内容 + /// + public string Body { get; set; } + + /// + /// 是否为HTML格式 + /// + public bool IsHtml { get; set; } + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } + } +} \ No newline at end of file diff --git a/DMS.Application/DTOs/SendEmailRequest.cs b/DMS.Application/DTOs/SendEmailRequest.cs new file mode 100644 index 0000000..18f4ebc --- /dev/null +++ b/DMS.Application/DTOs/SendEmailRequest.cs @@ -0,0 +1,43 @@ +namespace DMS.Application.DTOs +{ + /// + /// 发送邮件请求DTO + /// + public class SendEmailRequest + { + /// + /// 关联的邮件账户ID + /// + public int EmailAccountId { get; set; } + + /// + /// 收件人邮箱地址(多个用分号分隔) + /// + public string To { get; set; } + + /// + /// 抄送邮箱地址(多个用分号分隔) + /// + public string? Cc { get; set; } + + /// + /// 密送邮箱地址(多个用分号分隔) + /// + public string? Bcc { get; set; } + + /// + /// 邮件主题 + /// + public string Subject { get; set; } + + /// + /// 邮件正文 + /// + public string Body { get; set; } + + /// + /// 是否为HTML格式 + /// + public bool IsHtml { get; set; } = true; + } +} \ No newline at end of file diff --git a/DMS.Application/Interfaces/IEmailAppService.cs b/DMS.Application/Interfaces/IEmailAppService.cs new file mode 100644 index 0000000..d8144d2 --- /dev/null +++ b/DMS.Application/Interfaces/IEmailAppService.cs @@ -0,0 +1,75 @@ +using DMS.Application.DTOs; + +namespace DMS.Application.Interfaces +{ + /// + /// 邮件应用服务接口 + /// + public interface IEmailAppService + { + /// + /// 获取所有邮件账户 + /// + Task> GetAllEmailAccountsAsync(); + + /// + /// 根据ID获取邮件账户 + /// + Task GetEmailAccountByIdAsync(int id); + + /// + /// 创建邮件账户 + /// + Task CreateEmailAccountAsync(CreateEmailAccountRequest request); + + /// + /// 更新邮件账户 + /// + Task UpdateEmailAccountAsync(int id, CreateEmailAccountRequest request); + + /// + /// 删除邮件账户 + /// + Task DeleteEmailAccountAsync(int id); + + /// + /// 测试邮件账户连接 + /// + Task TestEmailAccountAsync(int id); + + /// + /// 发送邮件 + /// + Task SendEmailAsync(SendEmailRequest request); + + /// + /// 获取所有邮件模板 + /// + Task> GetAllEmailTemplatesAsync(); + + /// + /// 根据ID获取邮件模板 + /// + Task GetEmailTemplateByIdAsync(int id); + + /// + /// 根据代码获取邮件模板 + /// + Task GetEmailTemplateByCodeAsync(string code); + + /// + /// 创建邮件模板 + /// + Task CreateEmailTemplateAsync(EmailTemplateDto template); + + /// + /// 更新邮件模板 + /// + Task UpdateEmailTemplateAsync(int id, EmailTemplateDto template); + + /// + /// 删除邮件模板 + /// + Task DeleteEmailTemplateAsync(int id); + } +} \ No newline at end of file diff --git a/DMS.Application/Profiles/MappingProfile.cs b/DMS.Application/Profiles/MappingProfile.cs index d42d71d..5501201 100644 --- a/DMS.Application/Profiles/MappingProfile.cs +++ b/DMS.Application/Profiles/MappingProfile.cs @@ -11,14 +11,9 @@ public class MappingProfile : Profile { public MappingProfile() { - - - CreateMap() .ReverseMap(); - - // VariableTable 映射 CreateMap().ReverseMap(); @@ -26,11 +21,9 @@ public class MappingProfile : Profile CreateMap() .ReverseMap(); - CreateMap() .ReverseMap(); - // MqttServer 映射 CreateMap().ReverseMap(); @@ -50,5 +43,18 @@ public class MappingProfile : Profile // User 映射 CreateMap().ReverseMap(); CreateMap().ReverseMap(); + + // 邮件相关映射 + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + + CreateMap().ReverseMap(); + CreateMap() + .ForMember(dest => dest.EmailAccountId, opt => opt.MapFrom(src => src.EmailAccountId)) + .ReverseMap(); + + CreateMap().ReverseMap(); + + CreateMap().ReverseMap(); } } diff --git a/DMS.Application/Services/EmailAppService.cs b/DMS.Application/Services/EmailAppService.cs new file mode 100644 index 0000000..2d7d34d --- /dev/null +++ b/DMS.Application/Services/EmailAppService.cs @@ -0,0 +1,185 @@ +using AutoMapper; +using DMS.Application.DTOs; +using DMS.Application.Interfaces; +using DMS.Core.Interfaces.Repositories; +using DMS.Core.Interfaces.Services; +using DMS.Core.Models; + +namespace DMS.Application.Services +{ + /// + /// 邮件应用服务实现 + /// + public class EmailAppService : IEmailAppService + { + private readonly IEmailAccountRepository _emailAccountRepository; + private readonly IEmailTemplateRepository _emailTemplateRepository; + private readonly IEmailMessageRepository _emailMessageRepository; + private readonly IEmailService _emailService; + private readonly IMapper _mapper; + + public EmailAppService( + IEmailAccountRepository emailAccountRepository, + IEmailTemplateRepository emailTemplateRepository, + IEmailMessageRepository emailMessageRepository, + IEmailService emailService, + IMapper mapper) + { + _emailAccountRepository = emailAccountRepository; + _emailTemplateRepository = emailTemplateRepository; + _emailMessageRepository = emailMessageRepository; + _emailService = emailService; + _mapper = mapper; + } + + /// + /// 获取所有邮件账户 + /// + public async Task> GetAllEmailAccountsAsync() + { + var accounts = await _emailAccountRepository.GetAllAsync(); + return _mapper.Map>(accounts); + } + + /// + /// 根据ID获取邮件账户 + /// + public async Task GetEmailAccountByIdAsync(int id) + { + var account = await _emailAccountRepository.GetByIdAsync(id); + return _mapper.Map(account); + } + + /// + /// 创建邮件账户 + /// + public async Task CreateEmailAccountAsync(CreateEmailAccountRequest request) + { + var account = _mapper.Map(request); + var createdAccount = await _emailAccountRepository.AddAsync(account); + return _mapper.Map(createdAccount); + } + + /// + /// 更新邮件账户 + /// + public async Task UpdateEmailAccountAsync(int id, CreateEmailAccountRequest request) + { + var existingAccount = await _emailAccountRepository.GetByIdAsync(id); + if (existingAccount == null) + throw new ArgumentException($"未找到ID为 {id} 的邮件账户"); + + _mapper.Map(request, existingAccount); + existingAccount.UpdatedAt = DateTime.Now; + + var updatedAccount = await _emailAccountRepository.UpdateAsync(existingAccount); + return _mapper.Map(existingAccount); + } + + /// + /// 删除邮件账户 + /// + public async Task DeleteEmailAccountAsync(int id) + { + var account = await _emailAccountRepository.GetByIdAsync(id); + if (account == null) + return false; + + await _emailAccountRepository.DeleteAsync(account); + return true; + } + + /// + /// 测试邮件账户连接 + /// + public async Task TestEmailAccountAsync(int id) + { + var account = await _emailAccountRepository.GetByIdAsync(id); + if (account == null) + return false; + + return await _emailService.TestConnectionAsync(account); + } + + /// + /// 发送邮件 + /// + public async Task SendEmailAsync(SendEmailRequest request) + { + var account = await _emailAccountRepository.GetByIdAsync(request.EmailAccountId); + if (account == null) + throw new ArgumentException($"未找到ID为 {request.EmailAccountId} 的邮件账户"); + + var message = _mapper.Map(request); + message.From = account.EmailAddress; + + return await _emailService.SendEmailAsync(message, account); + } + + /// + /// 获取所有邮件模板 + /// + public async Task> GetAllEmailTemplatesAsync() + { + var templates = await _emailTemplateRepository.GetAllAsync(); + return _mapper.Map>(templates); + } + + /// + /// 根据ID获取邮件模板 + /// + public async Task GetEmailTemplateByIdAsync(int id) + { + var template = await _emailTemplateRepository.GetByIdAsync(id); + return _mapper.Map(template); + } + + /// + /// 根据代码获取邮件模板 + /// + public async Task GetEmailTemplateByCodeAsync(string code) + { + var template = await _emailTemplateRepository.GetByCodeAsync(code); + return _mapper.Map(template); + } + + /// + /// 创建邮件模板 + /// + public async Task CreateEmailTemplateAsync(EmailTemplateDto templateDto) + { + var template = _mapper.Map(templateDto); + var createdTemplate = await _emailTemplateRepository.AddAsync(template); + return _mapper.Map(createdTemplate); + } + + /// + /// 更新邮件模板 + /// + public async Task UpdateEmailTemplateAsync(int id, EmailTemplateDto templateDto) + { + var existingTemplate = await _emailTemplateRepository.GetByIdAsync(id); + if (existingTemplate == null) + throw new ArgumentException($"未找到ID为 {id} 的邮件模板"); + + _mapper.Map(templateDto, existingTemplate); + existingTemplate.UpdatedAt = DateTime.Now; + + var updatedTemplate = await _emailTemplateRepository.UpdateAsync(existingTemplate); + return _mapper.Map(existingTemplate); + } + + /// + /// 删除邮件模板 + /// + public async Task DeleteEmailTemplateAsync(int id) + { + var template = await _emailTemplateRepository.GetByIdAsync(id); + if (template == null) + return false; + + await _emailTemplateRepository.DeleteAsync(template); + return true; + } + } +} \ No newline at end of file diff --git a/DMS.Core/Interfaces/Repositories/IEmailAccountRepository.cs b/DMS.Core/Interfaces/Repositories/IEmailAccountRepository.cs new file mode 100644 index 0000000..9943b4f --- /dev/null +++ b/DMS.Core/Interfaces/Repositories/IEmailAccountRepository.cs @@ -0,0 +1,20 @@ +using DMS.Core.Models; + +namespace DMS.Core.Interfaces.Repositories +{ + /// + /// 邮件账户仓储接口 + /// + public interface IEmailAccountRepository : IBaseRepository + { + /// + /// 获取默认邮件账户 + /// + Task GetDefaultAccountAsync(); + + /// + /// 获取所有启用的邮件账户 + /// + Task> GetActiveAccountsAsync(); + } +} \ No newline at end of file diff --git a/DMS.Core/Interfaces/Repositories/IEmailLogRepository.cs b/DMS.Core/Interfaces/Repositories/IEmailLogRepository.cs new file mode 100644 index 0000000..014e776 --- /dev/null +++ b/DMS.Core/Interfaces/Repositories/IEmailLogRepository.cs @@ -0,0 +1,20 @@ +using DMS.Core.Models; + +namespace DMS.Core.Interfaces.Repositories +{ + /// + /// 邮件日志仓储接口 + /// + public interface IEmailLogRepository : IBaseRepository + { + /// + /// 根据邮件消息ID获取日志 + /// + Task> GetByEmailMessageIdAsync(int emailMessageId); + + /// + /// 根据日期范围获取日志 + /// + Task> GetByDateRangeAsync(DateTime startDate, DateTime endDate); + } +} \ No newline at end of file diff --git a/DMS.Core/Interfaces/Repositories/IEmailMessageRepository.cs b/DMS.Core/Interfaces/Repositories/IEmailMessageRepository.cs new file mode 100644 index 0000000..fa2852b --- /dev/null +++ b/DMS.Core/Interfaces/Repositories/IEmailMessageRepository.cs @@ -0,0 +1,20 @@ +using DMS.Core.Models; + +namespace DMS.Core.Interfaces.Repositories +{ + /// + /// 邮件消息仓储接口 + /// + public interface IEmailMessageRepository : IBaseRepository + { + /// + /// 根据状态获取邮件消息 + /// + Task> GetByStatusAsync(EmailSendStatus status); + + /// + /// 获取指定时间范围内的邮件消息 + /// + Task> GetByDateRangeAsync(DateTime startDate, DateTime endDate); + } +} \ No newline at end of file diff --git a/DMS.Core/Interfaces/Repositories/IEmailTemplateRepository.cs b/DMS.Core/Interfaces/Repositories/IEmailTemplateRepository.cs new file mode 100644 index 0000000..4ee8a4b --- /dev/null +++ b/DMS.Core/Interfaces/Repositories/IEmailTemplateRepository.cs @@ -0,0 +1,20 @@ +using DMS.Core.Models; + +namespace DMS.Core.Interfaces.Repositories +{ + /// + /// 邮件模板仓储接口 + /// + public interface IEmailTemplateRepository : IBaseRepository + { + /// + /// 根据代码获取邮件模板 + /// + Task GetByCodeAsync(string code); + + /// + /// 获取所有启用的邮件模板 + /// + Task> GetActiveTemplatesAsync(); + } +} \ No newline at end of file diff --git a/DMS.Core/Interfaces/Services/IEmailService.cs b/DMS.Core/Interfaces/Services/IEmailService.cs new file mode 100644 index 0000000..49ba4d1 --- /dev/null +++ b/DMS.Core/Interfaces/Services/IEmailService.cs @@ -0,0 +1,33 @@ +using DMS.Core.Models; + +namespace DMS.Core.Interfaces.Services +{ + /// + /// 邮件服务接口 + /// + public interface IEmailService + { + /// + /// 异步发送邮件 + /// + /// 邮件消息 + /// 邮件账户 + /// 发送是否成功 + Task SendEmailAsync(EmailMessage message, EmailAccount account); + + /// + /// 异步接收邮件 + /// + /// 邮件账户 + /// 接收邮件数量 + /// 接收到的邮件列表 + Task> ReceiveEmailsAsync(EmailAccount account, int count = 10); + + /// + /// 测试邮件账户连接 + /// + /// 邮件账户 + /// 连接是否成功 + Task TestConnectionAsync(EmailAccount account); + } +} \ No newline at end of file diff --git a/DMS.Core/Models/EmailAccount.cs b/DMS.Core/Models/EmailAccount.cs new file mode 100644 index 0000000..659b1d6 --- /dev/null +++ b/DMS.Core/Models/EmailAccount.cs @@ -0,0 +1,91 @@ +using System.ComponentModel.DataAnnotations; + +namespace DMS.Core.Models +{ + /// + /// 邮件账户配置实体 + /// + public class EmailAccount + { + /// + /// 账户ID + /// + public int Id { get; set; } + + /// + /// 账户名称 + /// + [Required] + [MaxLength(100)] + public string Name { get; set; } + + /// + /// 邮箱地址 + /// + [Required] + [MaxLength(255)] + public string EmailAddress { get; set; } + + /// + /// SMTP服务器地址 + /// + [Required] + [MaxLength(100)] + public string SmtpServer { get; set; } + + /// + /// SMTP端口号 + /// + public int SmtpPort { get; set; } = 587; + + /// + /// 是否启用SSL + /// + public bool EnableSsl { get; set; } = true; + + /// + /// 用户名 + /// + [Required] + [MaxLength(100)] + public string Username { get; set; } + + /// + /// 密码 + /// + [Required] + [MaxLength(100)] + public string Password { get; set; } + + /// + /// IMAP服务器地址 + /// + [MaxLength(100)] + public string? ImapServer { get; set; } + + /// + /// IMAP端口号 + /// + public int ImapPort { get; set; } = 993; + + /// + /// 是否为默认账户 + /// + public bool IsDefault { get; set; } + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } = true; + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.Now; + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } = DateTime.Now; + } +} \ No newline at end of file diff --git a/DMS.Core/Models/EmailLog.cs b/DMS.Core/Models/EmailLog.cs new file mode 100644 index 0000000..91449e0 --- /dev/null +++ b/DMS.Core/Models/EmailLog.cs @@ -0,0 +1,43 @@ +using System.ComponentModel.DataAnnotations; + +namespace DMS.Core.Models +{ + /// + /// 邮件日志实体 + /// + public class EmailLog + { + /// + /// 日志ID + /// + public int Id { get; set; } + + /// + /// 关联的邮件ID + /// + public int EmailMessageId { get; set; } + + /// + /// 日志级别 + /// + [Required] + [MaxLength(20)] + public string Level { get; set; } + + /// + /// 日志消息 + /// + [Required] + public string Message { get; set; } + + /// + /// 异常详情 + /// + public string? Exception { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.Now; + } +} \ No newline at end of file diff --git a/DMS.Core/Models/EmailMessage.cs b/DMS.Core/Models/EmailMessage.cs new file mode 100644 index 0000000..e31817c --- /dev/null +++ b/DMS.Core/Models/EmailMessage.cs @@ -0,0 +1,105 @@ +using System.ComponentModel.DataAnnotations; + +namespace DMS.Core.Models +{ + /// + /// 邮件消息实体 + /// + public class EmailMessage + { + /// + /// 邮件ID + /// + public int Id { get; set; } + + /// + /// 关联的邮件账户ID + /// + public int EmailAccountId { get; set; } + + /// + /// 发件人邮箱地址 + /// + [Required] + [MaxLength(255)] + public string From { get; set; } + + /// + /// 收件人邮箱地址(多个用分号分隔) + /// + [Required] + [MaxLength(1000)] + public string To { get; set; } + + /// + /// 抄送邮箱地址(多个用分号分隔) + /// + [MaxLength(1000)] + public string? Cc { get; set; } + + /// + /// 密送邮箱地址(多个用分号分隔) + /// + [MaxLength(1000)] + public string? Bcc { get; set; } + + /// + /// 邮件主题 + /// + [Required] + [MaxLength(500)] + public string Subject { get; set; } + + /// + /// 邮件正文 + /// + [Required] + public string Body { get; set; } + + /// + /// 是否为HTML格式 + /// + public bool IsHtml { get; set; } = true; + + /// + /// 邮件发送状态 + /// + public EmailSendStatus Status { get; set; } = EmailSendStatus.Pending; + + /// + /// 发送时间 + /// + public DateTime? SentAt { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.Now; + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } = DateTime.Now; + } + + /// + /// 邮件发送状态枚举 + /// + public enum EmailSendStatus + { + /// + /// 待发送 + /// + Pending, + + /// + /// 发送成功 + /// + Sent, + + /// + /// 发送失败 + /// + Failed + } +} \ No newline at end of file diff --git a/DMS.Core/Models/EmailTemplate.cs b/DMS.Core/Models/EmailTemplate.cs new file mode 100644 index 0000000..bea6c43 --- /dev/null +++ b/DMS.Core/Models/EmailTemplate.cs @@ -0,0 +1,62 @@ +using System.ComponentModel.DataAnnotations; + +namespace DMS.Core.Models +{ + /// + /// 邮件模板实体 + /// + public class EmailTemplate + { + /// + /// 模板ID + /// + public int Id { get; set; } + + /// + /// 模板名称 + /// + [Required] + [MaxLength(100)] + public string Name { get; set; } + + /// + /// 模板代码(唯一标识) + /// + [Required] + [MaxLength(50)] + public string Code { get; set; } + + /// + /// 模板主题 + /// + [Required] + [MaxLength(500)] + public string Subject { get; set; } + + /// + /// 模板内容 + /// + [Required] + public string Body { get; set; } + + /// + /// 是否为HTML格式 + /// + public bool IsHtml { get; set; } = true; + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } = true; + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.Now; + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } = DateTime.Now; + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/DMS.Infrastructure.csproj b/DMS.Infrastructure/DMS.Infrastructure.csproj index c727733..aab12e8 100644 --- a/DMS.Infrastructure/DMS.Infrastructure.csproj +++ b/DMS.Infrastructure/DMS.Infrastructure.csproj @@ -7,6 +7,7 @@ + diff --git a/DMS.Infrastructure/Entities/DbEmailAccount.cs b/DMS.Infrastructure/Entities/DbEmailAccount.cs new file mode 100644 index 0000000..3e16347 --- /dev/null +++ b/DMS.Infrastructure/Entities/DbEmailAccount.cs @@ -0,0 +1,89 @@ +using SqlSugar; +using System.ComponentModel.DataAnnotations; + +namespace DMS.Infrastructure.Entities +{ + /// + /// 邮件账户数据库实体 + /// + [SugarTable("email_accounts")] + public class DbEmailAccount + { + /// + /// 账户ID + /// + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + /// + /// 账户名称 + /// + [SugarColumn(Length = 100)] + public string Name { get; set; } + + /// + /// 邮箱地址 + /// + [SugarColumn(Length = 255)] + public string EmailAddress { get; set; } + + /// + /// SMTP服务器地址 + /// + [SugarColumn(Length = 100)] + public string SmtpServer { get; set; } + + /// + /// SMTP端口号 + /// + public int SmtpPort { get; set; } = 587; + + /// + /// 是否启用SSL + /// + public bool EnableSsl { get; set; } = true; + + /// + /// 用户名 + /// + [SugarColumn(Length = 100)] + public string Username { get; set; } + + /// + /// 密码 + /// + [SugarColumn(Length = 100)] + public string Password { get; set; } + + /// + /// IMAP服务器地址 + /// + [SugarColumn(Length = 100, IsNullable = true)] + public string? ImapServer { get; set; } + + /// + /// IMAP端口号 + /// + public int ImapPort { get; set; } = 993; + + /// + /// 是否为默认账户 + /// + public bool IsDefault { get; set; } + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } = true; + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.Now; + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } = DateTime.Now; + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Entities/DbEmailLog.cs b/DMS.Infrastructure/Entities/DbEmailLog.cs new file mode 100644 index 0000000..75576b4 --- /dev/null +++ b/DMS.Infrastructure/Entities/DbEmailLog.cs @@ -0,0 +1,46 @@ +using SqlSugar; +using System.ComponentModel.DataAnnotations; + +namespace DMS.Infrastructure.Entities +{ + /// + /// 邮件日志数据库实体 + /// + [SugarTable("email_logs")] + public class DbEmailLog + { + /// + /// 日志ID + /// + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + /// + /// 关联的邮件ID + /// + public int EmailMessageId { get; set; } + + /// + /// 日志级别 + /// + [SugarColumn(Length = 20)] + public string Level { get; set; } + + /// + /// 日志消息 + /// + [SugarColumn(Length = 4000)] + public string Message { get; set; } + + /// + /// 异常详情 + /// + [SugarColumn(Length = 2000, IsNullable = true)] + public string? Exception { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.Now; + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Entities/DbEmailMessage.cs b/DMS.Infrastructure/Entities/DbEmailMessage.cs new file mode 100644 index 0000000..8a0ba1d --- /dev/null +++ b/DMS.Infrastructure/Entities/DbEmailMessage.cs @@ -0,0 +1,86 @@ +using SqlSugar; +using System.ComponentModel.DataAnnotations; + +namespace DMS.Infrastructure.Entities +{ + /// + /// 邮件消息数据库实体 + /// + [SugarTable("email_messages")] + public class DbEmailMessage + { + /// + /// 邮件ID + /// + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + /// + /// 关联的邮件账户ID + /// + public int EmailAccountId { get; set; } + + /// + /// 发件人邮箱地址 + /// + [SugarColumn(Length = 255)] + public string From { get; set; } + + /// + /// 收件人邮箱地址(多个用分号分隔) + /// + [SugarColumn(Length = 1000)] + public string To { get; set; } + + /// + /// 抄送邮箱地址(多个用分号分隔) + /// + [SugarColumn(Length = 1000, IsNullable = true)] + public string? Cc { get; set; } + + /// + /// 密送邮箱地址(多个用分号分隔) + /// + [SugarColumn(Length = 1000, IsNullable = true)] + public string? Bcc { get; set; } + + /// + /// 邮件主题 + /// + [SugarColumn(Length = 500)] + public string Subject { get; set; } + + /// + /// 邮件正文 + /// + [SugarColumn(Length = 4000)] + public string Body { get; set; } + + /// + /// 是否为HTML格式 + /// + public bool IsHtml { get; set; } = true; + + /// + /// 邮件发送状态 + /// + [SugarColumn(Length = 20)] + public string Status { get; set; } = "Pending"; + + /// + /// 发送时间 + /// + [SugarColumn(IsNullable = true)] + public DateTime? SentAt { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.Now; + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } = DateTime.Now; + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Entities/DbEmailTemplate.cs b/DMS.Infrastructure/Entities/DbEmailTemplate.cs new file mode 100644 index 0000000..8d5e97e --- /dev/null +++ b/DMS.Infrastructure/Entities/DbEmailTemplate.cs @@ -0,0 +1,62 @@ +using SqlSugar; +using System.ComponentModel.DataAnnotations; + +namespace DMS.Infrastructure.Entities +{ + /// + /// 邮件模板数据库实体 + /// + [SugarTable("email_templates")] + public class DbEmailTemplate + { + /// + /// 模板ID + /// + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + /// + /// 模板名称 + /// + [SugarColumn(Length = 100)] + public string Name { get; set; } + + /// + /// 模板代码(唯一标识) + /// + [SugarColumn(Length = 50)] + public string Code { get; set; } + + /// + /// 模板主题 + /// + [SugarColumn(Length = 500)] + public string Subject { get; set; } + + /// + /// 模板内容 + /// + [SugarColumn(Length = 4000)] + public string Body { get; set; } + + /// + /// 是否为HTML格式 + /// + public bool IsHtml { get; set; } = true; + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } = true; + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.Now; + + /// + /// 更新时间 + /// + public DateTime UpdatedAt { get; set; } = DateTime.Now; + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Profiles/MappingProfile.cs b/DMS.Infrastructure/Profiles/MappingProfile.cs index 9d313e1..84bbf91 100644 --- a/DMS.Infrastructure/Profiles/MappingProfile.cs +++ b/DMS.Infrastructure/Profiles/MappingProfile.cs @@ -37,5 +37,10 @@ public class MappingProfile : Profile CreateMap().ReverseMap(); CreateMap().ReverseMap(); + + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); } } diff --git a/DMS.Infrastructure/Repositories/EmailAccountRepository.cs b/DMS.Infrastructure/Repositories/EmailAccountRepository.cs new file mode 100644 index 0000000..d92801d --- /dev/null +++ b/DMS.Infrastructure/Repositories/EmailAccountRepository.cs @@ -0,0 +1,158 @@ +using AutoMapper; +using DMS.Core.Interfaces.Repositories; +using DMS.Core.Models; +using DMS.Infrastructure.Data; +using DMS.Infrastructure.Entities; +using Microsoft.Extensions.Logging; +using SqlSugar; + +namespace DMS.Infrastructure.Repositories +{ + /// + /// 邮件账户仓储实现 + /// + public class EmailAccountRepository : IEmailAccountRepository + { + private readonly SqlSugarDbContext _dbContext; + protected readonly ILogger _logger; + private readonly IMapper _mapper; + + public EmailAccountRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger) + { + _mapper = mapper; + _dbContext = dbContext; + _logger = logger; + } + + /// + /// 获取 SqlSugarClient 实例 + /// + protected SqlSugarClient Db + { + get { return _dbContext.GetInstance(); } + } + + /// + /// 获取默认邮件账户 + /// + public async Task GetDefaultAccountAsync() + { + var dbEntity = await Db.Queryable() + .Where(e => e.IsDefault && e.IsActive) + .FirstAsync(); + + return dbEntity != null ? _mapper.Map(dbEntity) : null; + } + + /// + /// 获取所有启用的邮件账户 + /// + public async Task> GetActiveAccountsAsync() + { + var dbEntities = await Db.Queryable() + .Where(e => e.IsActive) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步根据ID获取单个实体。 + /// + public async Task GetByIdAsync(int id) + { + var dbEntity = await Db.Queryable() + .In(id) + .FirstAsync(); + + return dbEntity != null ? _mapper.Map(dbEntity) : null; + } + + /// + /// 异步获取所有实体。 + /// + public async Task> GetAllAsync() + { + var dbEntities = await Db.Queryable() + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步添加一个新实体。 + /// + public async Task AddAsync(EmailAccount entity) + { + var dbEntity = _mapper.Map(entity); + var result = await Db.Insertable(dbEntity) + .ExecuteReturnEntityAsync(); + + return _mapper.Map(result); + } + + /// + /// 异步更新一个已存在的实体。 + /// + public async Task UpdateAsync(EmailAccount entity) + { + var dbEntity = _mapper.Map(entity); + return await Db.Updateable(dbEntity) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID删除一个实体。 + /// + public async Task DeleteAsync(EmailAccount entity) + { + var dbEntity = _mapper.Map(entity); + return await Db.Deleteable(dbEntity) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID删除一个实体。 + /// + public async Task DeleteByIdAsync(int id) + { + return await Db.Deleteable() + .In(id) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID列表批量删除实体。 + /// + public async Task DeleteByIdsAsync(List ids) + { + return await Db.Deleteable() + .In(ids) + .ExecuteCommandAsync(); + } + + /// + /// 从数据库获取数据。 + /// + public async Task> TakeAsync(int number) + { + var dbEntities = await Db.Queryable() + .Take(number) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步批量添加实体。 + /// + public async Task AddBatchAsync(List entities) + { + var dbEntities = _mapper.Map>(entities); + var result = await Db.Insertable(dbEntities) + .ExecuteCommandAsync(); + + return result > 0; + } + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Repositories/EmailLogRepository.cs b/DMS.Infrastructure/Repositories/EmailLogRepository.cs new file mode 100644 index 0000000..ad61c0b --- /dev/null +++ b/DMS.Infrastructure/Repositories/EmailLogRepository.cs @@ -0,0 +1,158 @@ +using AutoMapper; +using DMS.Core.Interfaces.Repositories; +using DMS.Core.Models; +using DMS.Infrastructure.Data; +using DMS.Infrastructure.Entities; +using Microsoft.Extensions.Logging; +using SqlSugar; + +namespace DMS.Infrastructure.Repositories +{ + /// + /// 邮件日志仓储实现 + /// + public class EmailLogRepository : IEmailLogRepository + { + private readonly SqlSugarDbContext _dbContext; + protected readonly ILogger _logger; + private readonly IMapper _mapper; + + public EmailLogRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger) + { + _mapper = mapper; + _dbContext = dbContext; + _logger = logger; + } + + /// + /// 获取 SqlSugarClient 实例 + /// + protected SqlSugarClient Db + { + get { return _dbContext.GetInstance(); } + } + + /// + /// 异步根据ID获取单个实体。 + /// + public async Task GetByIdAsync(int id) + { + var dbEntity = await Db.Queryable() + .In(id) + .FirstAsync(); + + return dbEntity != null ? _mapper.Map(dbEntity) : null; + } + + /// + /// 异步获取所有实体。 + /// + public async Task> GetAllAsync() + { + var dbEntities = await Db.Queryable() + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步添加一个新实体。 + /// + public async Task AddAsync(EmailLog entity) + { + var dbEntity = _mapper.Map(entity); + var result = await Db.Insertable(dbEntity) + .ExecuteReturnEntityAsync(); + + return _mapper.Map(result); + } + + /// + /// 异步更新一个已存在的实体。 + /// + public async Task UpdateAsync(EmailLog entity) + { + var dbEntity = _mapper.Map(entity); + return await Db.Updateable(dbEntity) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID删除一个实体。 + /// + public async Task DeleteAsync(EmailLog entity) + { + var dbEntity = _mapper.Map(entity); + return await Db.Deleteable(dbEntity) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID删除一个实体。 + /// + public async Task DeleteByIdAsync(int id) + { + return await Db.Deleteable() + .In(id) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID列表批量删除实体。 + /// + public async Task DeleteByIdsAsync(List ids) + { + return await Db.Deleteable() + .In(ids) + .ExecuteCommandAsync(); + } + + /// + /// 从数据库获取数据。 + /// + public async Task> TakeAsync(int number) + { + var dbEntities = await Db.Queryable() + .Take(number) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步批量添加实体。 + /// + public async Task AddBatchAsync(List entities) + { + var dbEntities = _mapper.Map>(entities); + var result = await Db.Insertable(dbEntities) + .ExecuteCommandAsync(); + + return result > 0; + } + + /// + /// 根据邮件消息ID获取日志 + /// + public async Task> GetByEmailMessageIdAsync(int emailMessageId) + { + var dbEntities = await Db.Queryable() + .Where(e => e.EmailMessageId == emailMessageId) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 根据日期范围获取日志 + /// + public async Task> GetByDateRangeAsync(DateTime startDate, DateTime endDate) + { + var dbEntities = await Db.Queryable() + .Where(e => e.CreatedAt >= startDate && e.CreatedAt <= endDate) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Repositories/EmailMessageRepository.cs b/DMS.Infrastructure/Repositories/EmailMessageRepository.cs new file mode 100644 index 0000000..4f98dbe --- /dev/null +++ b/DMS.Infrastructure/Repositories/EmailMessageRepository.cs @@ -0,0 +1,158 @@ +using AutoMapper; +using DMS.Core.Interfaces.Repositories; +using DMS.Core.Models; +using DMS.Infrastructure.Data; +using DMS.Infrastructure.Entities; +using Microsoft.Extensions.Logging; +using SqlSugar; + +namespace DMS.Infrastructure.Repositories +{ + /// + /// 邮件消息仓储实现 + /// + public class EmailMessageRepository : IEmailMessageRepository + { + private readonly SqlSugarDbContext _dbContext; + protected readonly ILogger _logger; + private readonly IMapper _mapper; + + public EmailMessageRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger) + { + _mapper = mapper; + _dbContext = dbContext; + _logger = logger; + } + + /// + /// 获取 SqlSugarClient 实例 + /// + protected SqlSugarClient Db + { + get { return _dbContext.GetInstance(); } + } + + /// + /// 异步根据ID获取单个实体。 + /// + public async Task GetByIdAsync(int id) + { + var dbEntity = await Db.Queryable() + .In(id) + .FirstAsync(); + + return dbEntity != null ? _mapper.Map(dbEntity) : null; + } + + /// + /// 异步获取所有实体。 + /// + public async Task> GetAllAsync() + { + var dbEntities = await Db.Queryable() + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步添加一个新实体。 + /// + public async Task AddAsync(EmailMessage entity) + { + var dbEntity = _mapper.Map(entity); + var result = await Db.Insertable(dbEntity) + .ExecuteReturnEntityAsync(); + + return _mapper.Map(result); + } + + /// + /// 异步更新一个已存在的实体。 + /// + public async Task UpdateAsync(EmailMessage entity) + { + var dbEntity = _mapper.Map(entity); + return await Db.Updateable(dbEntity) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID删除一个实体。 + /// + public async Task DeleteAsync(EmailMessage entity) + { + var dbEntity = _mapper.Map(entity); + return await Db.Deleteable(dbEntity) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID删除一个实体。 + /// + public async Task DeleteByIdAsync(int id) + { + return await Db.Deleteable() + .In(id) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID列表批量删除实体。 + /// + public async Task DeleteByIdsAsync(List ids) + { + return await Db.Deleteable() + .In(ids) + .ExecuteCommandAsync(); + } + + /// + /// 从数据库获取数据。 + /// + public async Task> TakeAsync(int number) + { + var dbEntities = await Db.Queryable() + .Take(number) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步批量添加实体。 + /// + public async Task AddBatchAsync(List entities) + { + var dbEntities = _mapper.Map>(entities); + var result = await Db.Insertable(dbEntities) + .ExecuteCommandAsync(); + + return result > 0; + } + + /// + /// 根据状态获取邮件消息 + /// + public async Task> GetByStatusAsync(EmailSendStatus status) + { + var dbEntities = await Db.Queryable() + .Where(e => e.Status == status.ToString()) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 获取指定时间范围内的邮件消息 + /// + public async Task> GetByDateRangeAsync(DateTime startDate, DateTime endDate) + { + var dbEntities = await Db.Queryable() + .Where(e => e.CreatedAt >= startDate && e.CreatedAt <= endDate) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Repositories/EmailTemplateRepository.cs b/DMS.Infrastructure/Repositories/EmailTemplateRepository.cs new file mode 100644 index 0000000..b96af4a --- /dev/null +++ b/DMS.Infrastructure/Repositories/EmailTemplateRepository.cs @@ -0,0 +1,158 @@ +using AutoMapper; +using DMS.Core.Interfaces.Repositories; +using DMS.Core.Models; +using DMS.Infrastructure.Data; +using DMS.Infrastructure.Entities; +using Microsoft.Extensions.Logging; +using SqlSugar; + +namespace DMS.Infrastructure.Repositories +{ + /// + /// 邮件模板仓储实现 + /// + public class EmailTemplateRepository : IEmailTemplateRepository + { + private readonly SqlSugarDbContext _dbContext; + protected readonly ILogger _logger; + private readonly IMapper _mapper; + + public EmailTemplateRepository(IMapper mapper, SqlSugarDbContext dbContext, ILogger logger) + { + _mapper = mapper; + _dbContext = dbContext; + _logger = logger; + } + + /// + /// 获取 SqlSugarClient 实例 + /// + protected SqlSugarClient Db + { + get { return _dbContext.GetInstance(); } + } + + /// + /// 异步根据ID获取单个实体。 + /// + public async Task GetByIdAsync(int id) + { + var dbEntity = await Db.Queryable() + .In(id) + .FirstAsync(); + + return dbEntity != null ? _mapper.Map(dbEntity) : null; + } + + /// + /// 异步获取所有实体。 + /// + public async Task> GetAllAsync() + { + var dbEntities = await Db.Queryable() + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步添加一个新实体。 + /// + public async Task AddAsync(EmailTemplate entity) + { + var dbEntity = _mapper.Map(entity); + var result = await Db.Insertable(dbEntity) + .ExecuteReturnEntityAsync(); + + return _mapper.Map(result); + } + + /// + /// 异步更新一个已存在的实体。 + /// + public async Task UpdateAsync(EmailTemplate entity) + { + var dbEntity = _mapper.Map(entity); + return await Db.Updateable(dbEntity) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID删除一个实体。 + /// + public async Task DeleteAsync(EmailTemplate entity) + { + var dbEntity = _mapper.Map(entity); + return await Db.Deleteable(dbEntity) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID删除一个实体。 + /// + public async Task DeleteByIdAsync(int id) + { + return await Db.Deleteable() + .In(id) + .ExecuteCommandAsync(); + } + + /// + /// 异步根据ID列表批量删除实体。 + /// + public async Task DeleteByIdsAsync(List ids) + { + return await Db.Deleteable() + .In(ids) + .ExecuteCommandAsync(); + } + + /// + /// 从数据库获取数据。 + /// + public async Task> TakeAsync(int number) + { + var dbEntities = await Db.Queryable() + .Take(number) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + + /// + /// 异步批量添加实体。 + /// + public async Task AddBatchAsync(List entities) + { + var dbEntities = _mapper.Map>(entities); + var result = await Db.Insertable(dbEntities) + .ExecuteCommandAsync(); + + return result > 0; + } + + /// + /// 根据代码获取邮件模板 + /// + public async Task GetByCodeAsync(string code) + { + var dbEntity = await Db.Queryable() + .Where(e => e.Code == code && e.IsActive) + .FirstAsync(); + + return dbEntity != null ? _mapper.Map(dbEntity) : null; + } + + /// + /// 获取所有启用的邮件模板 + /// + public async Task> GetActiveTemplatesAsync() + { + var dbEntities = await Db.Queryable() + .Where(e => e.IsActive) + .ToListAsync(); + + return _mapper.Map>(dbEntities); + } + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Repositories/InitializeRepository.cs b/DMS.Infrastructure/Repositories/InitializeRepository.cs index fa88cf3..a1d5c65 100644 --- a/DMS.Infrastructure/Repositories/InitializeRepository.cs +++ b/DMS.Infrastructure/Repositories/InitializeRepository.cs @@ -46,6 +46,11 @@ public class InitializeRepository : IInitializeRepository _db.CodeFirst.InitTables(); _db.CodeFirst.InitTables(); _db.CodeFirst.InitTables(); + _db.CodeFirst.InitTables(); + _db.CodeFirst.InitTables(); + _db.CodeFirst.InitTables(); + _db.CodeFirst.InitTables(); + _db.CodeFirst.InitTables(); } /// @@ -140,14 +145,20 @@ public class InitializeRepository : IInitializeRepository }, new DbMenu { - Id = 6, Header = "设置", Icon = "\uE713", ParentId = 0, - MenuType = MenuType.MainMenu, TargetViewKey = "SettingView", + Id = 6, Header = "邮件管理", Icon = "\uE715", ParentId = 0, + MenuType = MenuType.MainMenu, TargetViewKey = "EmailManagementView", DisplayOrder = 6 }, new DbMenu { - Id = 7, Header = "关于", Icon = "\uE946", ParentId = 0, - MenuType = MenuType.MainMenu, TargetViewKey = "", DisplayOrder = 7 + Id = 7, Header = "设置", Icon = "\uE713", ParentId = 0, + MenuType = MenuType.MainMenu, TargetViewKey = "SettingView", + DisplayOrder = 7 + }, + new DbMenu + { + Id = 8, Header = "关于", Icon = "\uE946", ParentId = 0, + MenuType = MenuType.MainMenu, TargetViewKey = "", DisplayOrder = 8 } // 假设有一个AboutView }; diff --git a/DMS.Infrastructure/Services/EmailService.cs b/DMS.Infrastructure/Services/EmailService.cs new file mode 100644 index 0000000..f8acf29 --- /dev/null +++ b/DMS.Infrastructure/Services/EmailService.cs @@ -0,0 +1,170 @@ +using DMS.Core.Interfaces.Services; +using DMS.Core.Models; +using MailKit.Net.Imap; +using MailKit.Net.Smtp; +using MailKit.Security; +using Microsoft.Extensions.Logging; +using MimeKit; + +namespace DMS.Infrastructure.Services +{ + /// + /// 邮件服务实现 + /// + public class EmailService : IEmailService + { + private readonly ILogger _logger; + + public EmailService(ILogger logger) + { + _logger = logger; + } + + /// + /// 异步发送邮件 + /// + public async Task SendEmailAsync(EmailMessage message, EmailAccount account) + { + try + { + var mimeMessage = new MimeMessage(); + mimeMessage.From.Add(new MailboxAddress(account.EmailAddress, account.EmailAddress)); + mimeMessage.To.AddRange(ParseAddresses(message.To)); + + if (!string.IsNullOrEmpty(message.Cc)) + mimeMessage.Cc.AddRange(ParseAddresses(message.Cc)); + + if (!string.IsNullOrEmpty(message.Bcc)) + mimeMessage.Bcc.AddRange(ParseAddresses(message.Bcc)); + + mimeMessage.Subject = message.Subject; + + var bodyBuilder = new BodyBuilder(); + if (message.IsHtml) + bodyBuilder.HtmlBody = message.Body; + else + bodyBuilder.TextBody = message.Body; + + mimeMessage.Body = bodyBuilder.ToMessageBody(); + + using var client = new SmtpClient(); + await client.ConnectAsync(account.SmtpServer, account.SmtpPort, account.EnableSsl ? SecureSocketOptions.SslOnConnect : SecureSocketOptions.None); + await client.AuthenticateAsync(account.Username, account.Password); + await client.SendAsync(mimeMessage); + await client.DisconnectAsync(true); + + message.Status = EmailSendStatus.Sent; + message.SentAt = DateTime.Now; + + _logger.LogInformation($"邮件发送成功: {message.Subject}"); + return true; + } + catch (Exception ex) + { + message.Status = EmailSendStatus.Failed; + _logger.LogError(ex, $"邮件发送失败: {message.Subject}"); + return false; + } + } + + /// + /// 异步接收邮件 + /// + public async Task> ReceiveEmailsAsync(EmailAccount account, int count = 10) + { + var emails = new List(); + + try + { + if (string.IsNullOrEmpty(account.ImapServer)) + { + _logger.LogWarning("未配置IMAP服务器,无法接收邮件"); + return emails; + } + + using var client = new ImapClient(); + await client.ConnectAsync(account.ImapServer, account.ImapPort, SecureSocketOptions.SslOnConnect); + await client.AuthenticateAsync(account.Username, account.Password); + + var inbox = client.Inbox; + await inbox.OpenAsync(MailKit.FolderAccess.ReadOnly); + + var endIndex = Math.Min(count, inbox.Count); + for (int i = 0; i < endIndex; i++) + { + var message = await inbox.GetMessageAsync(i); + var email = new EmailMessage + { + EmailAccountId = account.Id, + From = message.From.ToString(), + To = message.To.ToString(), + Subject = message.Subject, + Body = message.TextBody ?? message.HtmlBody ?? "", + IsHtml = !string.IsNullOrEmpty(message.HtmlBody), + SentAt = message.Date.DateTime, + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now + }; + emails.Add(email); + } + + await client.DisconnectAsync(true); + _logger.LogInformation($"成功接收 {emails.Count} 封邮件"); + } + catch (Exception ex) + { + _logger.LogError(ex, "接收邮件时发生错误"); + } + + return emails; + } + + /// + /// 测试邮件账户连接 + /// + public async Task TestConnectionAsync(EmailAccount account) + { + try + { + // 测试SMTP连接 + using var smtpClient = new SmtpClient(); + await smtpClient.ConnectAsync(account.SmtpServer, account.SmtpPort, account.EnableSsl ? SecureSocketOptions.SslOnConnect : SecureSocketOptions.None); + await smtpClient.AuthenticateAsync(account.Username, account.Password); + await smtpClient.DisconnectAsync(true); + + // 如果配置了IMAP服务器,也测试IMAP连接 + if (!string.IsNullOrEmpty(account.ImapServer)) + { + using var imapClient = new ImapClient(); + await imapClient.ConnectAsync(account.ImapServer, account.ImapPort, SecureSocketOptions.SslOnConnect); + await imapClient.AuthenticateAsync(account.Username, account.Password); + await imapClient.DisconnectAsync(true); + } + + _logger.LogInformation($"邮件账户 {account.EmailAddress} 连接测试成功"); + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, $"邮件账户 {account.EmailAddress} 连接测试失败"); + return false; + } + } + + /// + /// 解析邮箱地址字符串 + /// + private IEnumerable ParseAddresses(string addresses) + { + var addressList = addresses.Split(new[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var address in addressList) + { + var trimmedAddress = address.Trim(); + if (!string.IsNullOrEmpty(trimmedAddress)) + { + yield return MailboxAddress.Parse(trimmedAddress); + } + } + } + } +} \ No newline at end of file diff --git a/DMS.WPF/App.xaml.cs b/DMS.WPF/App.xaml.cs index c30663f..e205a05 100644 --- a/DMS.WPF/App.xaml.cs +++ b/DMS.WPF/App.xaml.cs @@ -216,11 +216,16 @@ public partial class App : System.Windows.Application services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); // 添加这行 + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); // 注册App服务\r\n services.AddSingleton(); @@ -267,6 +272,8 @@ public partial class App : System.Windows.Application // 注册主数据服务 services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); // 注册视图模型 @@ -283,6 +290,7 @@ public partial class App : System.Windows.Application services.AddSingleton(); services.AddScoped(); services.AddSingleton(); + services.AddSingleton(); // 注册对话框视图模型 services.AddTransient(); @@ -298,6 +306,8 @@ public partial class App : System.Windows.Application services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); // 注册View视图 services.AddSingleton(); @@ -310,6 +320,8 @@ public partial class App : System.Windows.Application services.AddSingleton(); services.AddScoped(); services.AddScoped(); + services.AddSingleton(); + } private void ConfigureLogging(ILoggingBuilder loggingBuilder) diff --git a/DMS.WPF/Interfaces/IDialogViewModel.cs b/DMS.WPF/Interfaces/IDialogViewModel.cs new file mode 100644 index 0000000..30df0fb --- /dev/null +++ b/DMS.WPF/Interfaces/IDialogViewModel.cs @@ -0,0 +1,13 @@ +namespace DMS.WPF.Interfaces +{ + /// + /// 对话框视图模型接口 + /// + public interface IDialogViewModel + { + /// + /// 关闭请求事件 + /// + event Action CloseRequested; + } +} \ No newline at end of file diff --git a/DMS.WPF/Services/DialogService.cs b/DMS.WPF/Services/DialogService.cs index bb49052..0d70457 100644 --- a/DMS.WPF/Services/DialogService.cs +++ b/DMS.WPF/Services/DialogService.cs @@ -27,7 +27,8 @@ namespace DMS.WPF.Services { typeof(MqttSelectionDialogViewModel), typeof(MqttSelectionDialog) }, { typeof(MqttAliasBatchEditDialogViewModel), typeof(MqttAliasBatchEditDialog) }, { typeof(HistorySettingsDialogViewModel), typeof(HistorySettingsDialog) }, - { typeof(AlarmSettingsDialogViewModel), typeof(AlarmSettingsDialog) } + { typeof(AlarmSettingsDialogViewModel), typeof(AlarmSettingsDialog) }, + { typeof(EmailAccountDialogViewModel), typeof(EmailAccountDialog) } // Add other mappings here // ... other dialogs }; diff --git a/DMS.WPF/Services/EmailFunctionalityTestService.cs b/DMS.WPF/Services/EmailFunctionalityTestService.cs new file mode 100644 index 0000000..c66c8b3 --- /dev/null +++ b/DMS.WPF/Services/EmailFunctionalityTestService.cs @@ -0,0 +1,89 @@ +using DMS.Application.DTOs; +using DMS.Application.Interfaces; +using DMS.Core.Interfaces.Repositories; +using DMS.Core.Interfaces.Services; +using DMS.Core.Models; +using Microsoft.Extensions.DependencyInjection; + +namespace DMS.WPF.Services +{ + /// + /// 邮件功能测试服务 + /// + public class EmailFunctionalityTestService + { + private readonly IEmailAppService _emailAppService; + private readonly IEmailAccountRepository _emailAccountRepository; + private readonly IEmailService _emailService; + + public EmailFunctionalityTestService( + IEmailAppService emailAppService, + IEmailAccountRepository emailAccountRepository, + IEmailService emailService) + { + _emailAppService = emailAppService; + _emailAccountRepository = emailAccountRepository; + _emailService = emailService; + } + + /// + /// 运行邮件功能测试 + /// + public async Task RunTestAsync() + { + try + { + // 1. 创建测试邮件账户 + var createRequest = new CreateEmailAccountRequest + { + Name = "测试邮件账户", + EmailAddress = "test@example.com", + SmtpServer = "smtp.example.com", + SmtpPort = 587, + EnableSsl = true, + Username = "test@example.com", + Password = "password", + ImapServer = "imap.example.com", + ImapPort = 993, + IsDefault = true, + IsActive = true + }; + + var createdAccount = await _emailAppService.CreateEmailAccountAsync(createRequest); + Console.WriteLine($"创建邮件账户成功,ID: {createdAccount.Id}"); + + // 2. 获取所有邮件账户 + var accounts = await _emailAppService.GetAllEmailAccountsAsync(); + Console.WriteLine($"获取到 {accounts.Count} 个邮件账户"); + + // 3. 测试连接(这会失败,因为我们使用的是假的服务器地址) + var connectionResult = await _emailAppService.TestEmailAccountAsync(createdAccount.Id); + Console.WriteLine($"邮件账户连接测试结果: {connectionResult}"); + + // 4. 创建测试邮件模板 + var templateDto = new EmailTemplateDto + { + Name = "测试模板", + Code = "TEST_TEMPLATE", + Subject = "测试邮件主题", + Body = "

测试邮件内容

这是一封测试邮件。

", + IsHtml = true, + IsActive = true + }; + + var createdTemplate = await _emailAppService.CreateEmailTemplateAsync(templateDto); + Console.WriteLine($"创建邮件模板成功,ID: {createdTemplate.Id}"); + + // 5. 获取所有邮件模板 + var templates = await _emailAppService.GetAllEmailTemplatesAsync(); + Console.WriteLine($"获取到 {templates.Count} 个邮件模板"); + + Console.WriteLine("邮件功能测试完成!"); + } + catch (Exception ex) + { + Console.WriteLine($"邮件功能测试过程中发生错误: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/DMS.WPF/Services/NavigationService.cs b/DMS.WPF/Services/NavigationService.cs index b616519..ef8ea54 100644 --- a/DMS.WPF/Services/NavigationService.cs +++ b/DMS.WPF/Services/NavigationService.cs @@ -94,6 +94,8 @@ public class NavigationService : INavigationService return App.Current.Services.GetRequiredService(); case "SettingView": return App.Current.Services.GetRequiredService(); + case "EmailManagementView": + return App.Current.Services.GetRequiredService(); default: return null; } diff --git a/DMS.WPF/ViewModels/Dialogs/EmailAccountDialogViewModel.cs b/DMS.WPF/ViewModels/Dialogs/EmailAccountDialogViewModel.cs new file mode 100644 index 0000000..5c3888e --- /dev/null +++ b/DMS.WPF/ViewModels/Dialogs/EmailAccountDialogViewModel.cs @@ -0,0 +1,161 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using DMS.Application.DTOs; +using DMS.Application.Interfaces; +using DMS.WPF.Interfaces; + +namespace DMS.WPF.ViewModels.Dialogs +{ + /// + /// 邮件账户对话框视图模型 + /// + public partial class EmailAccountDialogViewModel : DialogViewModelBase, IDialogViewModel + { + private readonly IEmailAppService _emailAppService; + private readonly INotificationService _notificationService; + private bool _isEditMode; + private int _accountId; + + [ObservableProperty] + private string _name = string.Empty; + + [ObservableProperty] + private string _emailAddress = string.Empty; + + [ObservableProperty] + private string _smtpServer = string.Empty; + + [ObservableProperty] + private int _smtpPort = 587; + + [ObservableProperty] + private bool _enableSsl = true; + + [ObservableProperty] + private string _username = string.Empty; + + [ObservableProperty] + private string _password = string.Empty; + + [ObservableProperty] + private string _imapServer = string.Empty; + + [ObservableProperty] + private int _imapPort = 993; + + [ObservableProperty] + private bool _isDefault; + + [ObservableProperty] + private bool _isActive = true; + + [ObservableProperty] + private string _dialogTitle = "添加邮件账户"; + + public event Action? CloseRequested; + + public EmailAccountDialogViewModel( + IEmailAppService emailAppService, + INotificationService notificationService) + { + _emailAppService = emailAppService; + _notificationService = notificationService; + PrimaryButText = "保存"; + } + + /// + /// 设置要编辑的邮件账户 + /// + public void SetEmailAccount(EmailAccountDto account) + { + _isEditMode = true; + _accountId = account.Id; + DialogTitle = "编辑邮件账户"; + + Name = account.Name; + EmailAddress = account.EmailAddress; + SmtpServer = account.SmtpServer; + SmtpPort = account.SmtpPort; + EnableSsl = account.EnableSsl; + Username = account.Username; + Password = ""; // 出于安全考虑,不显示密码 + ImapServer = account.ImapServer ?? ""; + ImapPort = account.ImapPort; + IsDefault = account.IsDefault; + IsActive = account.IsActive; + } + + /// + /// 保存命令 + /// + [RelayCommand] + private async Task Save() + { + if (!ValidateInput()) + return; + + var request = new CreateEmailAccountRequest + { + Name = Name, + EmailAddress = EmailAddress, + SmtpServer = SmtpServer, + SmtpPort = SmtpPort, + EnableSsl = EnableSsl, + Username = Username, + Password = Password, + ImapServer = string.IsNullOrEmpty(ImapServer) ? null : ImapServer, + ImapPort = ImapPort, + IsDefault = IsDefault, + IsActive = IsActive + }; + Close(request); + } + + /// + /// 取消命令 + /// + [RelayCommand] + private async Task Cancel() + { + Close(null); + } + + /// + /// 验证输入 + /// + private bool ValidateInput() + { + if (string.IsNullOrWhiteSpace(Name)) + { + _notificationService.ShowWarn("请输入账户名称"); + return false; + } + + if (string.IsNullOrWhiteSpace(EmailAddress)) + { + _notificationService.ShowWarn("请输入邮箱地址"); + return false; + } + + if (string.IsNullOrWhiteSpace(SmtpServer)) + { + _notificationService.ShowWarn("请输入SMTP服务器地址"); + return false; + } + + if (string.IsNullOrWhiteSpace(Username)) + { + _notificationService.ShowWarn("请输入用户名"); + return false; + } + + if (!_isEditMode && string.IsNullOrWhiteSpace(Password)) + { + _notificationService.ShowWarn("请输入密码"); + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/DMS.WPF/ViewModels/Dialogs/EmailTemplateDialogViewModel.cs b/DMS.WPF/ViewModels/Dialogs/EmailTemplateDialogViewModel.cs new file mode 100644 index 0000000..86d73f3 --- /dev/null +++ b/DMS.WPF/ViewModels/Dialogs/EmailTemplateDialogViewModel.cs @@ -0,0 +1,151 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using DMS.Application.DTOs; +using DMS.Application.Interfaces; +using DMS.WPF.Interfaces; + +namespace DMS.WPF.ViewModels.Dialogs +{ + /// + /// 邮件模板对话框视图模型 + /// + public partial class EmailTemplateDialogViewModel : DialogViewModelBase, IDialogViewModel + { + private readonly IEmailAppService _emailAppService; + private readonly INotificationService _notificationService; + private bool _isEditMode; + private int _templateId; + + [ObservableProperty] + private string _name = string.Empty; + + [ObservableProperty] + private string _code = string.Empty; + + [ObservableProperty] + private string _subject = string.Empty; + + [ObservableProperty] + private string _body = string.Empty; + + [ObservableProperty] + private bool _isHtml = true; + + [ObservableProperty] + private bool _isActive = true; + + [ObservableProperty] + private string _dialogTitle = "添加邮件模板"; + + public event Action? CloseRequested; + + public EmailTemplateDialogViewModel( + IEmailAppService emailAppService, + INotificationService notificationService) + { + _emailAppService = emailAppService; + _notificationService = notificationService; + PrimaryButText = "保存"; + } + + /// + /// 设置要编辑的邮件模板 + /// + public void SetEmailTemplate(EmailTemplateDto template) + { + _isEditMode = true; + _templateId = template.Id; + DialogTitle = "编辑邮件模板"; + + Name = template.Name; + Code = template.Code; + Subject = template.Subject; + Body = template.Body; + IsHtml = template.IsHtml; + IsActive = template.IsActive; + } + + /// + /// 保存命令 + /// + [RelayCommand] + private async Task Save() + { + if (!ValidateInput()) + return; + + try + { + var template = new EmailTemplateDto + { + Name = Name, + Code = Code, + Subject = Subject, + Body = Body, + IsHtml = IsHtml, + IsActive = IsActive + }; + + if (_isEditMode) + { + await _emailAppService.UpdateEmailTemplateAsync(_templateId, template); + _notificationService.ShowSuccess("邮件模板更新成功"); + } + else + { + await _emailAppService.CreateEmailTemplateAsync(template); + _notificationService.ShowSuccess("邮件模板创建成功"); + } + + CloseRequested?.Invoke(true); + await Close(new EmailTemplateDto()); + } + catch (Exception ex) + { + _notificationService.ShowError(_isEditMode ? "更新失败" : "创建失败", ex); + } + } + + /// + /// 取消命令 + /// + [RelayCommand] + private async Task Cancel() + { + CloseRequested?.Invoke(false); + await Close(null); + } + + /// + /// 验证输入 + /// + private bool ValidateInput() + { + if (string.IsNullOrWhiteSpace(Name)) + { + _notificationService.ShowWarn("请输入模板名称"); + return false; + } + + if (string.IsNullOrWhiteSpace(Code)) + { + _notificationService.ShowWarn("请输入模板代码"); + return false; + } + + if (string.IsNullOrWhiteSpace(Subject)) + { + _notificationService.ShowWarn("请输入邮件主题"); + return false; + } + + if (string.IsNullOrWhiteSpace(Body)) + { + _notificationService.ShowWarn("请输入邮件内容"); + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/DMS.WPF/ViewModels/EmailManagementViewModel.cs b/DMS.WPF/ViewModels/EmailManagementViewModel.cs new file mode 100644 index 0000000..8d009f5 --- /dev/null +++ b/DMS.WPF/ViewModels/EmailManagementViewModel.cs @@ -0,0 +1,237 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using DMS.Application.DTOs; +using DMS.Application.Interfaces; +using DMS.WPF.Interfaces; +using DMS.WPF.ViewModels.Dialogs; +using System.Collections.ObjectModel; +using Microsoft.Extensions.DependencyInjection; + +namespace DMS.WPF.ViewModels +{ + /// + /// 邮件管理视图模型 + /// + public partial class EmailManagementViewModel : ViewModelBase + { + private readonly IEmailAppService _emailAppService; + private readonly IDialogService _dialogService; + private readonly INotificationService _notificationService; + + [ObservableProperty] + private ObservableCollection _emailAccounts = new(); + + [ObservableProperty] + private EmailAccountDto? _selectedEmailAccount; + + [ObservableProperty] + private ObservableCollection _emailTemplates = new(); + + [ObservableProperty] + private EmailTemplateDto? _selectedEmailTemplate; + + public EmailManagementViewModel( + IEmailAppService emailAppService, + IDialogService dialogService, + INotificationService notificationService) + { + _emailAppService = emailAppService; + _dialogService = dialogService; + _notificationService = notificationService; + } + + /// + /// 加载数据命令 + /// + [RelayCommand] + private async Task LoadDataAsync() + { + try + { + // 加载邮件账户 + var accounts = await _emailAppService.GetAllEmailAccountsAsync(); + EmailAccounts = new ObservableCollection(accounts); + + // 加载邮件模板 + var templates = await _emailAppService.GetAllEmailTemplatesAsync(); + EmailTemplates = new ObservableCollection(templates); + } + catch (Exception ex) + { + _notificationService.ShowError("加载数据失败", ex); + } + } + + /// + /// 添加邮件账户命令 + /// + [RelayCommand] + private async Task AddEmailAccountAsync() + { + EmailAccountDialogViewModel viewModel = App.Current.Services.GetRequiredService(); + var emailAccountDto = await _dialogService.ShowDialogAsync(viewModel); + if (emailAccountDto==null) + { + return; + } + + } + + /// + /// 编辑邮件账户命令 + /// + [RelayCommand] + private async Task EditEmailAccountAsync() + { + if (SelectedEmailAccount == null) + { + _notificationService.ShowWarn("请选择要编辑的邮件账户"); + return; + } + EmailAccountDialogViewModel viewModel = App.Current.Services.GetRequiredService(); + viewModel.SetEmailAccount(SelectedEmailAccount); + var emailAccountDto = await _dialogService.ShowDialogAsync(viewModel); + if (emailAccountDto==null) + { + return; + } + + // var dialog = _dialogService.CreateDialog(); + // dialog.SetEmailAccount(SelectedEmailAccount); + // var result = await dialog.ShowAsync(); + // if (result == true) + // { + // await LoadDataAsync(); + // } + } + + /// + /// 删除邮件账户命令 + /// + [RelayCommand] + private async Task DeleteEmailAccountAsync() + { + if (SelectedEmailAccount == null) + { + _notificationService.ShowWarn("请选择要删除的邮件账户"); + return; + } + + ConfirmDialogViewModel confirmDialogViewModel = new ConfirmDialogViewModel( + "确认删除", + $"确定要删除邮件账户 {SelectedEmailAccount.Name} 吗?", "删除"); + + var confirmResult = await _dialogService.ShowDialogAsync(confirmDialogViewModel); + + if (confirmResult == true) + { + try + { + await _emailAppService.DeleteEmailAccountAsync(SelectedEmailAccount.Id); + _notificationService.ShowSuccess("删除成功"); + await LoadDataAsync(); + } + catch (Exception ex) + { + _notificationService.ShowError("删除失败", ex); + } + } + } + + /// + /// 测试邮件账户连接命令 + /// + [RelayCommand] + private async Task TestEmailAccountAsync() + { + if (SelectedEmailAccount == null) + { + _notificationService.ShowWarn("请选择要测试的邮件账户"); + return; + } + + try + { + var result = await _emailAppService.TestEmailAccountAsync(SelectedEmailAccount.Id); + if (result) + { + _notificationService.ShowSuccess("连接测试成功"); + } + else + { + _notificationService.ShowWarn("连接测试失败"); + } + } + catch (Exception ex) + { + _notificationService.ShowError("连接测试失败", ex); + } + } + + /// + /// 添加邮件模板命令 + /// + [RelayCommand] + private async Task AddEmailTemplateAsync() + { + // var dialog = _dialogService.CreateDialog(); + // var result = await dialog.ShowAsync(); + // if (result == true) + // { + // await LoadDataAsync(); + // } + } + + /// + /// 编辑邮件模板命令 + /// + [RelayCommand] + private async Task EditEmailTemplateAsync() + { + if (SelectedEmailTemplate == null) + { + _notificationService.ShowWarn("请选择要编辑的邮件模板"); + return; + } + + // var dialog = _dialogService.CreateDialog(); + // dialog.SetEmailTemplate(SelectedEmailTemplate); + // var result = await dialog.ShowAsync(); + // if (result == true) + // { + // await LoadDataAsync(); + // } + } + + /// + /// 删除邮件模板命令 + /// + [RelayCommand] + private async Task DeleteEmailTemplateAsync() + { + if (SelectedEmailTemplate == null) + { + _notificationService.ShowWarn("请选择要删除的邮件模板"); + return; + } + + // var confirmResult = await _dialogService.ShowConfirmDialogAsync( + // "确认删除", + // $"确定要删除邮件模板 {SelectedEmailTemplate.Name} 吗?"); + + // if (confirmResult == true) + // { + // try + // { + // await _emailAppService.DeleteEmailTemplateAsync(SelectedEmailTemplate.Id); + // _notificationService.ShowSuccess("删除成功"); + // await LoadDataAsync(); + // } + // catch (Exception ex) + // { + // _notificationService.ShowError("删除失败", ex); + // } + // } + } + } +} \ No newline at end of file diff --git a/DMS.WPF/Views/Dialogs/EmailAccountDialog.xaml b/DMS.WPF/Views/Dialogs/EmailAccountDialog.xaml new file mode 100644 index 0000000..9068e84 --- /dev/null +++ b/DMS.WPF/Views/Dialogs/EmailAccountDialog.xaml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DMS.WPF/Views/Dialogs/EmailAccountDialog.xaml.cs b/DMS.WPF/Views/Dialogs/EmailAccountDialog.xaml.cs new file mode 100644 index 0000000..167a8a2 --- /dev/null +++ b/DMS.WPF/Views/Dialogs/EmailAccountDialog.xaml.cs @@ -0,0 +1,48 @@ +using DMS.WPF.ViewModels.Dialogs; +using DMS.WPF.Helper; +using iNKORE.UI.WPF.Modern.Controls; +using System.Windows; +using System.Windows.Controls; + +namespace DMS.WPF.Views.Dialogs +{ + /// + /// EmailAccountDialog.xaml 的交互逻辑 + /// + public partial class EmailAccountDialog : ContentDialog + { + private const int ContentAreaMaxWidth = 1000; + private const int ContentAreaMaxHeight = 800; + + public EmailAccountDialog() + { + InitializeComponent(); + this.Opened += OnOpened; + DataContextChanged += EmailAccountDialog_DataContextChanged; + } + + private void OnOpened(ContentDialog sender, ContentDialogOpenedEventArgs args) + { + // 修改对话框内容区域的最大宽度和高度 + var backgroundElementBorder = VisualTreeFinder.FindVisualChildByName(this, "BackgroundElement"); + if (backgroundElementBorder != null) + { + backgroundElementBorder.MaxWidth = ContentAreaMaxWidth; + backgroundElementBorder.MaxHeight = ContentAreaMaxHeight; + } + } + + private void EmailAccountDialog_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (DataContext is EmailAccountDialogViewModel viewModel) + { + // 处理密码框 + PasswordBox.Password = viewModel.Password; + PasswordBox.PasswordChanged += (s, args) => + { + viewModel.Password = PasswordBox.Password; + }; + } + } + } +} \ No newline at end of file diff --git a/DMS.WPF/Views/Dialogs/EmailTemplateDialog.xaml b/DMS.WPF/Views/Dialogs/EmailTemplateDialog.xaml new file mode 100644 index 0000000..b889651 --- /dev/null +++ b/DMS.WPF/Views/Dialogs/EmailTemplateDialog.xaml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DMS.WPF/Views/Dialogs/EmailTemplateDialog.xaml.cs b/DMS.WPF/Views/Dialogs/EmailTemplateDialog.xaml.cs new file mode 100644 index 0000000..57a2e71 --- /dev/null +++ b/DMS.WPF/Views/Dialogs/EmailTemplateDialog.xaml.cs @@ -0,0 +1,33 @@ +using DMS.WPF.Helper; +using iNKORE.UI.WPF.Modern.Controls; +using System.Windows; +using System.Windows.Controls; + +namespace DMS.WPF.Views.Dialogs +{ + /// + /// EmailTemplateDialog.xaml 的交互逻辑 + /// + public partial class EmailTemplateDialog : ContentDialog + { + private const int ContentAreaMaxWidth = 1000; + private const int ContentAreaMaxHeight = 800; + + public EmailTemplateDialog() + { + InitializeComponent(); + this.Opened += OnOpened; + } + + private void OnOpened(ContentDialog sender, ContentDialogOpenedEventArgs args) + { + // 修改对话框内容区域的最大宽度和高度 + var backgroundElementBorder = VisualTreeFinder.FindVisualChildByName(this, "BackgroundElement"); + if (backgroundElementBorder != null) + { + backgroundElementBorder.MaxWidth = ContentAreaMaxWidth; + backgroundElementBorder.MaxHeight = ContentAreaMaxHeight; + } + } + } +} \ No newline at end of file diff --git a/DMS.WPF/Views/EmailManagementView.xaml b/DMS.WPF/Views/EmailManagementView.xaml new file mode 100644 index 0000000..8c0aa2e --- /dev/null +++ b/DMS.WPF/Views/EmailManagementView.xaml @@ -0,0 +1,68 @@ + + + + + + + + + +