新增预警页面
@@ -0,0 +1,79 @@
|
||||
package com.jeesite.modules.app.Job;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.modules.app.dao.MailReceived;
|
||||
import com.jeesite.modules.app.utils.LoggerUtils;
|
||||
import com.jeesite.modules.app.utils.MailReceiveUtils;
|
||||
import com.jeesite.modules.biz.entity.BizMailAccount;
|
||||
import com.jeesite.modules.biz.entity.BizMailAttachments;
|
||||
import com.jeesite.modules.biz.entity.BizMailReceived;
|
||||
import com.jeesite.modules.biz.service.BizMailAccountService;
|
||||
import com.jeesite.modules.biz.service.BizMailAttachmentsService;
|
||||
import com.jeesite.modules.biz.service.BizMailReceivedService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Controller
|
||||
public class mailJob {
|
||||
|
||||
|
||||
@Resource
|
||||
private BizMailAccountService bizMailAccountService;
|
||||
|
||||
@Resource
|
||||
private BizMailReceivedService receivedService;
|
||||
|
||||
@Resource
|
||||
private BizMailAttachmentsService attachmentsService;
|
||||
|
||||
@Resource(name = "hostMonitorExecutor")
|
||||
private ThreadPoolTaskExecutor hostMonitorExecutor;
|
||||
|
||||
|
||||
private String MAIL_PATH = "/ogsapp/mail";
|
||||
|
||||
private static final LoggerUtils logger = LoggerUtils.getInstance();
|
||||
|
||||
private static final boolean CRON_JOB = Boolean.parseBoolean(Global.getConfig("biz.cron.MailJob", "false"));
|
||||
|
||||
@Scheduled(cron = "10 0/15 * * * ?")
|
||||
public void getMailReceived() {
|
||||
if (CRON_JOB) {
|
||||
List<BizMailAccount> accounts = bizMailAccountService.findList(new BizMailAccount());
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>(accounts.size());
|
||||
for (BizMailAccount account : accounts) {
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
List<MailReceived> receivedList = MailReceiveUtils.receiveUnreadMails(account, MAIL_PATH);
|
||||
for (MailReceived mailReceived : receivedList) {
|
||||
BizMailReceived received = mailReceived.getReceived();
|
||||
List<BizMailAttachments> attachments = mailReceived.getAttachments();
|
||||
for (BizMailAttachments mailAttachments : attachments) {
|
||||
attachmentsService.insert(mailAttachments);
|
||||
}
|
||||
receivedService.save(received);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
}
|
||||
}, hostMonitorExecutor); // 指定使用配置的线程池
|
||||
futures.add(future);
|
||||
}
|
||||
try {
|
||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
.get(60, TimeUnit.SECONDS); // 超时时间可根据业务调整
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.jeesite.modules.app.utils;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* 文件下载工具类
|
||||
* 支持两种方式:
|
||||
* 1. 基于HttpServletResponse直接输出(适用于传统Servlet/SSM)
|
||||
* 2. 返回ResponseEntity<byte[]>(适用于SpringBoot)
|
||||
* 修复点:解决文件名前后加下划线、中文乱码、浏览器兼容性问题
|
||||
*/
|
||||
public class FileDownloadUtils {
|
||||
|
||||
/**
|
||||
* 私有构造方法,禁止实例化
|
||||
*/
|
||||
private FileDownloadUtils() {
|
||||
throw new UnsupportedOperationException("工具类禁止实例化");
|
||||
}
|
||||
|
||||
/**
|
||||
* 方式1:通过HttpServletResponse下载文件(推荐SSM/Servlet使用)
|
||||
*
|
||||
* @param orgFileName 文件完整路径(例如:D:/files/test.pdf)
|
||||
* @param fileName 下载时显示的文件名(例如:测试文件.pdf)
|
||||
* @param response HttpServletResponse对象
|
||||
* @throws Exception 文件操作异常
|
||||
*/
|
||||
public static void downloadFile(String orgFileName, String fileName, HttpServletResponse response) throws Exception {
|
||||
// 1. 构建完整文件路径
|
||||
Path fullFilePath = Paths.get(orgFileName);
|
||||
File file = fullFilePath.toFile();
|
||||
|
||||
// 2. 校验文件合法性
|
||||
validateFile(file);
|
||||
|
||||
// 3. 清理并编码文件名(避免特殊字符导致的解析异常)
|
||||
String encodedFileName = encodeFileName(fileName);
|
||||
|
||||
// 4. 设置响应头(核心修复:解决下划线/乱码问题)
|
||||
setDownloadResponseHeader(response, encodedFileName, file.length());
|
||||
|
||||
// 5. 读取文件并写入响应输出流(try-with-resources自动关闭流)
|
||||
try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(fullFilePath));
|
||||
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
|
||||
FileCopyUtils.copy(inputStream, outputStream);
|
||||
outputStream.flush();
|
||||
} catch (IOException e) {
|
||||
throw new IOException("文件下载失败:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 方式2:返回ResponseEntity<byte[]>(推荐SpringBoot使用)
|
||||
*
|
||||
* @param orgFileName 文件完整路径(例如:D:/files/test.pdf)
|
||||
* @param fileName 下载时显示的文件名(例如:测试文件.pdf)
|
||||
* @return ResponseEntity<byte [ ]> 下载响应实体
|
||||
* @throws IOException 文件操作异常
|
||||
*/
|
||||
public static ResponseEntity<byte[]> downloadFile(String orgFileName, String fileName) throws IOException {
|
||||
// 1. 构建完整文件路径
|
||||
Path fullFilePath = Paths.get(orgFileName);
|
||||
File file = fullFilePath.toFile();
|
||||
|
||||
// 2. 校验文件合法性
|
||||
validateFile(file);
|
||||
|
||||
// 3. 读取文件字节数组
|
||||
byte[] fileBytes = Files.readAllBytes(fullFilePath);
|
||||
|
||||
// 4. 清理并编码文件名
|
||||
String encodedFileName = encodeFileName(fileName);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
// 核心修复:使用RFC 5987标准,移除多余双引号,避免下划线问题
|
||||
headers.set(HttpHeaders.CONTENT_DISPOSITION,
|
||||
String.format("attachment; filename=%s; filename*=UTF-8''%s",
|
||||
encodedFileName, encodedFileName));
|
||||
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||
headers.setContentLength(fileBytes.length);
|
||||
// 禁止缓存
|
||||
headers.setCacheControl("no-cache, no-store, must-revalidate");
|
||||
headers.setPragma("no-cache");
|
||||
headers.setExpires(0);
|
||||
|
||||
// 6. 返回响应实体
|
||||
return new ResponseEntity<>(fileBytes, headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验文件合法性(存在性、是否为文件、读取权限)
|
||||
*
|
||||
* @param file 待校验文件
|
||||
* @throws FileNotFoundException 文件不合法异常
|
||||
*/
|
||||
private static void validateFile(File file) throws FileNotFoundException {
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("文件不存在:" + file.getAbsolutePath());
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
throw new FileNotFoundException("路径指向目录,不是文件:" + file.getAbsolutePath());
|
||||
}
|
||||
if (!file.canRead()) {
|
||||
throw new FileNotFoundException("文件无读取权限:" + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载响应头(核心修复:解决下划线/乱码/浏览器兼容问题)
|
||||
*
|
||||
* @param response HttpServletResponse
|
||||
* @param encodedFileName 编码后的文件名
|
||||
* @param fileSize 文件大小
|
||||
*/
|
||||
private static void setDownloadResponseHeader(HttpServletResponse response, String encodedFileName, long fileSize) {
|
||||
// 设置响应内容类型为二进制流
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
// 设置字符编码
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
// 设置内容长度
|
||||
response.setContentLengthLong(fileSize);
|
||||
// 核心修复:使用RFC 5987标准,移除多余双引号,避免浏览器解析出下划线
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
|
||||
String.format("attachment; filename=%s; filename*=UTF-8''%s",
|
||||
encodedFileName, encodedFileName));
|
||||
// 禁止缓存
|
||||
response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
|
||||
response.setHeader(HttpHeaders.PRAGMA, "no-cache");
|
||||
response.setDateHeader(HttpHeaders.EXPIRES, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码文件名(解决中文乱码+空格转+号导致的下划线问题)
|
||||
*
|
||||
* @param fileName 清理后的文件名
|
||||
* @return 编码后的文件名
|
||||
*/
|
||||
private static String encodeFileName(String fileName) {
|
||||
try {
|
||||
// 修复:将空格编码为%20而非+,避免浏览器解析为下划线
|
||||
return URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
|
||||
.replace("+", "%20");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// 理论上UTF-8不会抛出此异常,兜底返回原文件名
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -598,11 +598,10 @@ public class MailReceiveUtils {
|
||||
attachment.setFileMd5(md5);
|
||||
attachment.setDownloadCount(0);
|
||||
attachment.setIsCompressed(isCompressedFile(originalFileName) ? "1" : "0");
|
||||
attachment.setIsEncrypted("N");
|
||||
attachment.setIsEncrypted("0");
|
||||
attachment.setDownloadStartTime(new Date(attachDownloadStartTime)); // 附件下载开始时间
|
||||
attachment.setDownloadEndTime(new Date(attachDownloadEndTime)); // 附件下载结束时间
|
||||
attachment.setDownloadCostTime(costTime); // 附件下载耗时(毫秒)
|
||||
|
||||
return attachment;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
package com.jeesite.modules.app.utils;
|
||||
|
||||
import com.jeesite.modules.biz.entity.BizMailAccount;
|
||||
import com.jeesite.modules.biz.entity.BizMailSent;
|
||||
import com.jeesite.modules.file.entity.FileUpload;
|
||||
|
||||
import javax.mail.*;
|
||||
import javax.mail.internet.*;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class MailSendUtils {
|
||||
private static final ExecutorService MAIL_EXECUTOR = Executors.newFixedThreadPool(5);
|
||||
|
||||
private static String FILE_PATH = "/ogsapp/files";
|
||||
|
||||
/**
|
||||
* 同步发送HTML格式邮件
|
||||
*
|
||||
* @param mailAccount 邮件账户配置
|
||||
* @param mailSent 邮件发送内容信息
|
||||
* @return BizMailSent 填充发送结果后的对象
|
||||
*/
|
||||
public static BizMailSent sendHtmlMail(BizMailAccount mailAccount, BizMailSent mailSent, List<FileUpload> fileUploads) {
|
||||
// 初始化发送结果对象
|
||||
mailSent.setId(mailSent.getId());
|
||||
mailSent.setCreateTime(new Date());
|
||||
mailSent.setSendStatus("0"); // 默认失败状态
|
||||
// 1. 参数校验
|
||||
if (!validateParams(mailAccount, mailSent)) {
|
||||
mailSent.setErrorMsg("参数校验失败:邮件账户或发送内容不完整");
|
||||
return mailSent;
|
||||
}
|
||||
|
||||
Properties props = new Properties();
|
||||
props.put("mail.smtp.host", mailAccount.getHost());
|
||||
props.put("mail.smtp.port", mailAccount.getSmtpPort().toString());
|
||||
props.put("mail.smtp.auth", "true"); // 开启认证
|
||||
props.put("mail.smtp.socketFactory.port", mailAccount.getSmtpPort().toString());
|
||||
|
||||
// SSL配置
|
||||
if (mailAccount.getSslEnable().equals("true")) {
|
||||
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
|
||||
props.put("mail.smtp.starttls.enable", "true");
|
||||
}
|
||||
|
||||
// 3. 创建认证器
|
||||
Authenticator authenticator = new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(mailAccount.getUsername(), mailAccount.getPassword());
|
||||
}
|
||||
};
|
||||
|
||||
// 4. 创建邮件会话
|
||||
Session session = Session.getInstance(props, authenticator);
|
||||
session.setDebug(false); // 生产环境关闭调试
|
||||
|
||||
try {
|
||||
// 5. 构建MIME邮件消息
|
||||
MimeMessage message = new MimeMessage(session);
|
||||
|
||||
// 设置发件人
|
||||
message.setFrom(new InternetAddress(mailAccount.getFromAddress()));
|
||||
|
||||
// 设置收件人
|
||||
if (mailSent.getToAddresses() != null && !mailSent.getToAddresses().isEmpty()) {
|
||||
String[] toArray = mailSent.getToAddresses().split(",");
|
||||
InternetAddress[] toAddresses = new InternetAddress[toArray.length];
|
||||
for (int i = 0; i < toArray.length; i++) {
|
||||
toAddresses[i] = new InternetAddress(toArray[i].trim());
|
||||
}
|
||||
message.setRecipients(Message.RecipientType.TO, toAddresses);
|
||||
}
|
||||
|
||||
// 设置抄送人
|
||||
if (mailSent.getCcAddresses() != null && !mailSent.getCcAddresses().isEmpty()) {
|
||||
String[] ccArray = mailSent.getCcAddresses().split(",");
|
||||
InternetAddress[] ccAddresses = new InternetAddress[ccArray.length];
|
||||
for (int i = 0; i < ccArray.length; i++) {
|
||||
ccAddresses[i] = new InternetAddress(ccArray[i].trim());
|
||||
}
|
||||
message.setRecipients(Message.RecipientType.CC, ccAddresses);
|
||||
}
|
||||
// 设置邮件主题
|
||||
message.setSubject(mailSent.getSubject(), "UTF-8");
|
||||
// 构建邮件内容(支持HTML和附件)
|
||||
MimeMultipart multipart = new MimeMultipart("mixed");
|
||||
// HTML内容部分
|
||||
MimeBodyPart contentPart = new MimeBodyPart();
|
||||
contentPart.setContent(mailSent.getContent(), "text/html;charset=UTF-8");
|
||||
multipart.addBodyPart(contentPart);
|
||||
if (fileUploads.size() > 0) {
|
||||
mailSent.setHasAttachment("1");
|
||||
for (FileUpload upload : fileUploads) {
|
||||
MimeBodyPart attachmentPart = new MimeBodyPart();
|
||||
File file = new File(FILE_PATH + upload.getFileUrl());
|
||||
attachmentPart.attachFile(file);
|
||||
attachmentPart.setFileName(MimeUtility.encodeText(file.getName(), "UTF-8", "B"));
|
||||
multipart.addBodyPart(attachmentPart);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置邮件内容
|
||||
message.setContent(multipart);
|
||||
// 设置发送时间
|
||||
message.setSentDate(new Date());
|
||||
// 6. 发送邮件
|
||||
Transport.send(message);
|
||||
// 7. 更新发送结果
|
||||
mailSent.setSendTime(new Date());
|
||||
mailSent.setSendStatus("1");
|
||||
mailSent.setErrorMsg("");
|
||||
mailSent.setMessageId(message.getMessageID()); // 邮件服务器消息ID
|
||||
} catch (Exception e) {
|
||||
// 捕获所有异常,记录错误信息
|
||||
mailSent.setErrorMsg("邮件发送失败:" + e.getMessage());
|
||||
mailSent.setSendTime(new Date());
|
||||
// 打印异常栈(生产环境建议日志记录)
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return mailSent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步发送HTML格式邮件
|
||||
*
|
||||
* @param mailAccount 邮件账户配置
|
||||
* @param mailSent 邮件发送内容信息
|
||||
*/
|
||||
public static void sendHtmlMailAsync(BizMailAccount mailAccount, BizMailSent mailSent, List<FileUpload> fileUploads) {
|
||||
MAIL_EXECUTOR.submit(() -> sendHtmlMail(mailAccount, mailSent, fileUploads));
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数校验
|
||||
*
|
||||
* @param mailAccount 邮件账户
|
||||
* @param mailSent 邮件内容
|
||||
* @return 校验结果
|
||||
*/
|
||||
private static boolean validateParams(BizMailAccount mailAccount, BizMailSent mailSent) {
|
||||
// 校验账户必填项
|
||||
if (mailAccount == null || mailAccount.getHost() == null || mailAccount.getSmtpPort() == null
|
||||
|| mailAccount.getUsername() == null || mailAccount.getPassword() == null
|
||||
|| mailAccount.getFromAddress() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 校验邮件内容必填项
|
||||
return mailSent != null && mailSent.getToAddresses() != null && !mailSent.getToAddresses().isEmpty()
|
||||
&& mailSent.getSubject() != null && mailSent.getContent() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭线程池(应用关闭时调用)
|
||||
*/
|
||||
public static void shutdownExecutor() {
|
||||
MAIL_EXECUTOR.shutdown();
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,6 @@ package com.jeesite.modules.biz.entity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable;
|
||||
import com.jeesite.common.mybatis.annotation.JoinTable.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
@@ -35,7 +26,7 @@ import java.io.Serial;
|
||||
@Column(name = "create_time", attrName = "createTime", label = "记录时间", isUpdate = false, isUpdateForce = true),
|
||||
@Column(name = "id", attrName = "tid", label = "附件标识", isPK = true),
|
||||
@Column(name = "mail_id", attrName = "mailId", label = "收件标识"),
|
||||
@Column(name = "message_id", attrName = "messageId", label = "消息标识", isQuery = false),
|
||||
@Column(name = "message_id", attrName = "messageId", label = "消息标识"),
|
||||
@Column(name = "file_name", attrName = "fileName", label = "附件名称", queryType = QueryType.LIKE),
|
||||
@Column(name = "file_size", attrName = "fileSize", label = "文件大小", isQuery = false),
|
||||
@Column(name = "file_type", attrName = "fileType", label = "文件类型", isQuery = false),
|
||||
|
||||
@@ -46,6 +46,12 @@ import java.io.Serial;
|
||||
@Column(name = "has_attachment", attrName = "hasAttachment", label = "是否有附件"),
|
||||
@Column(name = "mailbox", attrName = "mailbox", label = "mailbox", isQuery = false),
|
||||
@Column(name = "ustatus", attrName = "ustatus", label = "状态"),
|
||||
}, joinTable = {
|
||||
@JoinTable(type = Type.LEFT_JOIN, entity = BizMailAccount.class, attrName = "this", alias = "b",
|
||||
on = "a.account_id = b.id",
|
||||
columns = {
|
||||
@Column(name = "account_name", attrName = "accountName", label = "配置名称"),
|
||||
}),
|
||||
}, orderBy = "a.id DESC"
|
||||
)
|
||||
@Data
|
||||
@@ -69,11 +75,12 @@ public class BizMailReceived extends DataEntity<BizMailReceived> implements Seri
|
||||
private String mailbox; // mailbox
|
||||
private String ustatus; // 状态
|
||||
|
||||
private String accountName;
|
||||
|
||||
@ExcelFields({
|
||||
@ExcelField(title = "记录时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "主键ID", attrName = "id", align = Align.CENTER, sort = 20),
|
||||
@ExcelField(title = "邮件服务器消息ID", attrName = "messageId", align = Align.CENTER, sort = 30),
|
||||
@ExcelField(title = "邮件账户标识", attrName = "accountId", align = Align.CENTER, sort = 40),
|
||||
@ExcelField(title = "主键标识", attrName = "id", align = Align.CENTER, sort = 20),
|
||||
@ExcelField(title = "配置名称", attrName = "accountName", align = Align.CENTER, sort = 40),
|
||||
@ExcelField(title = "发件人地址", attrName = "fromAddress", align = Align.CENTER, sort = 50),
|
||||
@ExcelField(title = "发件人名称", attrName = "fromName", align = Align.CENTER, sort = 60),
|
||||
@ExcelField(title = "收件人地址", attrName = "toAddresses", align = Align.CENTER, sort = 70),
|
||||
|
||||
@@ -47,6 +47,12 @@ import java.io.Serial;
|
||||
@Column(name = "f_flow_id", attrName = "fflowId", label = "流程id", isUpdate = false, isQuery = false),
|
||||
@Column(name = "f_flow_task_id", attrName = "fflowTaskId", label = "流程任务主键", isUpdate = false, isQuery = false),
|
||||
@Column(name = "f_flow_state", attrName = "fflowState", label = "流程任务状态", isUpdate = false, isQuery = false, isUpdateForce = true),
|
||||
}, joinTable = {
|
||||
@JoinTable(type = Type.LEFT_JOIN, entity = BizMailAccount.class, attrName = "this", alias = "b",
|
||||
on = "a.account_id = b.id",
|
||||
columns = {
|
||||
@Column(name = "account_name", attrName = "accountName", label = "配置名称"),
|
||||
}),
|
||||
}, orderBy = "a.create_time DESC"
|
||||
)
|
||||
@Data
|
||||
@@ -72,11 +78,12 @@ public class BizMailSent extends DataEntity<BizMailSent> implements Serializable
|
||||
private String fflowTaskId; // 流程任务主键
|
||||
private Integer fflowState; // 流程任务状态
|
||||
|
||||
private String accountName;
|
||||
|
||||
@ExcelFields({
|
||||
@ExcelField(title = "记录时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"),
|
||||
@ExcelField(title = "主键标识", attrName = "id", align = Align.CENTER, sort = 20),
|
||||
@ExcelField(title = "件服务器消息标识", attrName = "messageId", align = Align.CENTER, sort = 30),
|
||||
@ExcelField(title = "邮件账户标识", attrName = "accountId", align = Align.CENTER, sort = 40),
|
||||
@ExcelField(title = "服务名称", attrName = "accountName", align = Align.CENTER, sort = 40),
|
||||
@ExcelField(title = "发件人地址", attrName = "fromAddress", align = Align.CENTER, sort = 50),
|
||||
@ExcelField(title = "收件人地址", attrName = "toAddresses", align = Align.CENTER, sort = 60),
|
||||
@ExcelField(title = "抄送人地址", attrName = "ccAddresses", align = Align.CENTER, sort = 70),
|
||||
@@ -95,6 +102,7 @@ public class BizMailSent extends DataEntity<BizMailSent> implements Serializable
|
||||
public BizMailSent(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public Date getCreateTime_gte() {
|
||||
return sqlMap.getWhere().getValue("create_time", QueryType.GTE);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package com.jeesite.modules.biz.web;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import com.jeesite.modules.app.utils.FileDownloadUtils;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
@@ -26,6 +27,7 @@ import com.jeesite.modules.biz.service.BizMailAttachmentsService;
|
||||
|
||||
/**
|
||||
* 邮件附件表Controller
|
||||
*
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@@ -33,114 +35,130 @@ import com.jeesite.modules.biz.service.BizMailAttachmentsService;
|
||||
@RequestMapping(value = "${adminPath}/biz/mailAttachments")
|
||||
public class BizMailAttachmentsController extends BaseController {
|
||||
|
||||
private final BizMailAttachmentsService bizMailAttachmentsService;
|
||||
private final BizMailAttachmentsService bizMailAttachmentsService;
|
||||
|
||||
public BizMailAttachmentsController(BizMailAttachmentsService bizMailAttachmentsService) {
|
||||
this.bizMailAttachmentsService = bizMailAttachmentsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailAttachments get(Long tid, boolean isNewRecord) {
|
||||
return bizMailAttachmentsService.get(tid, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailAttachments bizMailAttachments, Model model) {
|
||||
model.addAttribute("bizMailAttachments", bizMailAttachments);
|
||||
return "modules/biz/bizMailAttachmentsList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailAttachments> listData(BizMailAttachments bizMailAttachments, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailAttachments.setPage(new Page<>(request, response));
|
||||
Page<BizMailAttachments> page = bizMailAttachmentsService.findPage(bizMailAttachments);
|
||||
return page;
|
||||
}
|
||||
public BizMailAttachmentsController(BizMailAttachmentsService bizMailAttachmentsService) {
|
||||
this.bizMailAttachmentsService = bizMailAttachmentsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailAttachments bizMailAttachments, Model model) {
|
||||
model.addAttribute("bizMailAttachments", bizMailAttachments);
|
||||
return "modules/biz/bizMailAttachmentsForm";
|
||||
}
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailAttachments get(Long tid, boolean isNewRecord) {
|
||||
return bizMailAttachmentsService.get(tid, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailAttachments bizMailAttachments) {
|
||||
bizMailAttachmentsService.save(bizMailAttachments);
|
||||
return renderResult(Global.TRUE, text("保存邮件附件表成功!"));
|
||||
}
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailAttachments bizMailAttachments, Model model) {
|
||||
model.addAttribute("bizMailAttachments", bizMailAttachments);
|
||||
return "modules/biz/bizMailAttachmentsList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailAttachments bizMailAttachments, HttpServletResponse response) {
|
||||
List<BizMailAttachments> list = bizMailAttachmentsService.findList(bizMailAttachments);
|
||||
String fileName = "邮件附件表" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("邮件附件表", BizMailAttachments.class)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailAttachments> listData(BizMailAttachments bizMailAttachments, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailAttachments.setPage(new Page<>(request, response));
|
||||
Page<BizMailAttachments> page = bizMailAttachmentsService.findPage(bizMailAttachments);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailAttachments bizMailAttachments = new BizMailAttachments();
|
||||
List<BizMailAttachments> list = ListUtils.newArrayList(bizMailAttachments);
|
||||
String fileName = "邮件附件表模板.xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("邮件附件表", BizMailAttachments.class, Type.IMPORT)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailAttachments bizMailAttachments, Model model) {
|
||||
model.addAttribute("bizMailAttachments", bizMailAttachments);
|
||||
return "modules/biz/bizMailAttachmentsForm";
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailAttachmentsService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:"+message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:"+ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailAttachments bizMailAttachments) {
|
||||
bizMailAttachmentsService.delete(bizMailAttachments);
|
||||
return renderResult(Global.TRUE, text("删除邮件附件表成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailAttachments bizMailAttachments) {
|
||||
bizMailAttachmentsService.save(bizMailAttachments);
|
||||
return renderResult(Global.TRUE, text("保存邮件附件表成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailAttachments bizMailAttachments, HttpServletResponse response) {
|
||||
List<BizMailAttachments> list = bizMailAttachmentsService.findList(bizMailAttachments);
|
||||
String fileName = "邮件附件表" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try (ExcelExport ee = new ExcelExport("邮件附件表", BizMailAttachments.class)) {
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailAttachments bizMailAttachments = new BizMailAttachments();
|
||||
List<BizMailAttachments> list = ListUtils.newArrayList(bizMailAttachments);
|
||||
String fileName = "邮件附件表模板.xlsx";
|
||||
try (ExcelExport ee = new ExcelExport("邮件附件表", BizMailAttachments.class, Type.IMPORT)) {
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailAttachmentsService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:" + message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:" + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailAttachments:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailAttachments bizMailAttachments) {
|
||||
bizMailAttachmentsService.delete(bizMailAttachments);
|
||||
return renderResult(Global.TRUE, text("删除邮件附件表成功!"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "listAll")
|
||||
@ResponseBody
|
||||
public List<BizMailAttachments> listAll(BizMailAttachments bizMailAttachments) {
|
||||
return bizMailAttachmentsService.findList(bizMailAttachments);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "downloadFile")
|
||||
public void downloadFile(BizMailAttachments bizMailAttachments, HttpServletResponse response) {
|
||||
try {
|
||||
BizMailAttachments attachments = bizMailAttachmentsService.get(bizMailAttachments);
|
||||
FileDownloadUtils.downloadFile(attachments.getStoragePath(), attachments.getFileName(), response);
|
||||
} catch (Exception e) {
|
||||
System.out.print(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.jeesite.modules.biz.web;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -26,6 +27,7 @@ import com.jeesite.modules.biz.service.BizMailReceivedService;
|
||||
|
||||
/**
|
||||
* 收件Controller
|
||||
*
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@@ -33,114 +35,114 @@ import com.jeesite.modules.biz.service.BizMailReceivedService;
|
||||
@RequestMapping(value = "${adminPath}/biz/mailReceived")
|
||||
public class BizMailReceivedController extends BaseController {
|
||||
|
||||
private final BizMailReceivedService bizMailReceivedService;
|
||||
private final BizMailReceivedService bizMailReceivedService;
|
||||
|
||||
public BizMailReceivedController(BizMailReceivedService bizMailReceivedService) {
|
||||
this.bizMailReceivedService = bizMailReceivedService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailReceived get(String id, boolean isNewRecord) {
|
||||
return bizMailReceivedService.get(id, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailReceived bizMailReceived, Model model) {
|
||||
model.addAttribute("bizMailReceived", bizMailReceived);
|
||||
return "modules/biz/bizMailReceivedList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailReceived> listData(BizMailReceived bizMailReceived, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailReceived.setPage(new Page<>(request, response));
|
||||
Page<BizMailReceived> page = bizMailReceivedService.findPage(bizMailReceived);
|
||||
return page;
|
||||
}
|
||||
public BizMailReceivedController(BizMailReceivedService bizMailReceivedService) {
|
||||
this.bizMailReceivedService = bizMailReceivedService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailReceived bizMailReceived, Model model) {
|
||||
model.addAttribute("bizMailReceived", bizMailReceived);
|
||||
return "modules/biz/bizMailReceivedForm";
|
||||
}
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailReceived get(String id, boolean isNewRecord) {
|
||||
return bizMailReceivedService.get(id, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailReceived bizMailReceived) {
|
||||
bizMailReceivedService.save(bizMailReceived);
|
||||
return renderResult(Global.TRUE, text("保存收件成功!"));
|
||||
}
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailReceived bizMailReceived, Model model) {
|
||||
model.addAttribute("bizMailReceived", bizMailReceived);
|
||||
return "modules/biz/bizMailReceivedList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailReceived bizMailReceived, HttpServletResponse response) {
|
||||
List<BizMailReceived> list = bizMailReceivedService.findList(bizMailReceived);
|
||||
String fileName = "收件" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("收件", BizMailReceived.class)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailReceived> listData(BizMailReceived bizMailReceived, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailReceived.setPage(new Page<>(request, response));
|
||||
Page<BizMailReceived> page = bizMailReceivedService.findPage(bizMailReceived);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailReceived bizMailReceived = new BizMailReceived();
|
||||
List<BizMailReceived> list = ListUtils.newArrayList(bizMailReceived);
|
||||
String fileName = "收件模板.xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("收件", BizMailReceived.class, Type.IMPORT)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailReceived bizMailReceived, Model model) {
|
||||
model.addAttribute("bizMailReceived", bizMailReceived);
|
||||
return "modules/biz/bizMailReceivedForm";
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailReceived bizMailReceived) {
|
||||
bizMailReceivedService.save(bizMailReceived);
|
||||
return renderResult(Global.TRUE, text("保存收件成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailReceived bizMailReceived, HttpServletResponse response) {
|
||||
List<BizMailReceived> list = bizMailReceivedService.findList(bizMailReceived);
|
||||
String fileName = "收件" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try (ExcelExport ee = new ExcelExport("收件", BizMailReceived.class)) {
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailReceived bizMailReceived = new BizMailReceived();
|
||||
List<BizMailReceived> list = ListUtils.newArrayList(bizMailReceived);
|
||||
String fileName = "收件模板.xlsx";
|
||||
try (ExcelExport ee = new ExcelExport("收件", BizMailReceived.class, Type.IMPORT)) {
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailReceivedService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:" + message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:" + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailReceived bizMailReceived) {
|
||||
bizMailReceivedService.delete(bizMailReceived);
|
||||
return renderResult(Global.TRUE, text("删除收件成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailReceivedService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:"+message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:"+ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailReceived:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailReceived bizMailReceived) {
|
||||
bizMailReceivedService.delete(bizMailReceived);
|
||||
return renderResult(Global.TRUE, text("删除收件成功!"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,14 @@
|
||||
package com.jeesite.modules.biz.web;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.jeesite.modules.app.utils.MailSendUtils;
|
||||
import com.jeesite.modules.app.utils.vDate;
|
||||
import com.jeesite.modules.biz.entity.BizMailAccount;
|
||||
import com.jeesite.modules.biz.service.BizMailAccountService;
|
||||
import com.jeesite.modules.file.entity.FileUpload;
|
||||
import com.jeesite.modules.file.utils.FileUploadUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -26,6 +34,7 @@ import com.jeesite.modules.biz.service.BizMailSentService;
|
||||
|
||||
/**
|
||||
* 发件Controller
|
||||
*
|
||||
* @author gaoxq
|
||||
* @version 2025-12-14
|
||||
*/
|
||||
@@ -33,114 +42,132 @@ import com.jeesite.modules.biz.service.BizMailSentService;
|
||||
@RequestMapping(value = "${adminPath}/biz/mailSent")
|
||||
public class BizMailSentController extends BaseController {
|
||||
|
||||
private final BizMailSentService bizMailSentService;
|
||||
|
||||
public BizMailSentController(BizMailSentService bizMailSentService) {
|
||||
this.bizMailSentService = bizMailSentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailSent get(String id, boolean isNewRecord) {
|
||||
return bizMailSentService.get(id, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailSent bizMailSent, Model model) {
|
||||
model.addAttribute("bizMailSent", bizMailSent);
|
||||
return "modules/biz/bizMailSentList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailSent> listData(BizMailSent bizMailSent, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailSent.setPage(new Page<>(request, response));
|
||||
Page<BizMailSent> page = bizMailSentService.findPage(bizMailSent);
|
||||
return page;
|
||||
}
|
||||
@Resource
|
||||
private BizMailAccountService accountService;
|
||||
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailSent bizMailSent, Model model) {
|
||||
model.addAttribute("bizMailSent", bizMailSent);
|
||||
return "modules/biz/bizMailSentForm";
|
||||
}
|
||||
private final BizMailSentService bizMailSentService;
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailSent bizMailSent) {
|
||||
bizMailSentService.save(bizMailSent);
|
||||
return renderResult(Global.TRUE, text("保存发件成功!"));
|
||||
}
|
||||
public BizMailSentController(BizMailSentService bizMailSentService) {
|
||||
this.bizMailSentService = bizMailSentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailSent bizMailSent, HttpServletResponse response) {
|
||||
List<BizMailSent> list = bizMailSentService.findList(bizMailSent);
|
||||
String fileName = "发件" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("发件", BizMailSent.class)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
@ModelAttribute
|
||||
public BizMailSent get(String id, boolean isNewRecord) {
|
||||
return bizMailSentService.get(id, isNewRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailSent bizMailSent = new BizMailSent();
|
||||
List<BizMailSent> list = ListUtils.newArrayList(bizMailSent);
|
||||
String fileName = "发件模板.xlsx";
|
||||
try(ExcelExport ee = new ExcelExport("发件", BizMailSent.class, Type.IMPORT)){
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = {"list", ""})
|
||||
public String list(BizMailSent bizMailSent, Model model) {
|
||||
model.addAttribute("bizMailSent", bizMailSent);
|
||||
return "modules/biz/bizMailSentList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "listData")
|
||||
@ResponseBody
|
||||
public Page<BizMailSent> listData(BizMailSent bizMailSent, HttpServletRequest request, HttpServletResponse response) {
|
||||
bizMailSent.setPage(new Page<>(request, response));
|
||||
Page<BizMailSent> page = bizMailSentService.findPage(bizMailSent);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看编辑表单
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "form")
|
||||
public String form(BizMailSent bizMailSent, Model model) {
|
||||
model.addAttribute("bizMailSent", bizMailSent);
|
||||
return "modules/biz/bizMailSentForm";
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@PostMapping(value = "save")
|
||||
@ResponseBody
|
||||
public String save(@Validated BizMailSent bizMailSent) {
|
||||
BizMailAccount account = accountService.get(bizMailSent.getAccountId());
|
||||
bizMailSent.setFromAddress(account.getFromAddress());
|
||||
bizMailSent.setUpdateTime(vDate.getUpdateTime(bizMailSent.getIsNewRecord()));
|
||||
bizMailSentService.save(bizMailSent);
|
||||
return renderResult(Global.TRUE, text("保存发件成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "exportData")
|
||||
public void exportData(BizMailSent bizMailSent, HttpServletResponse response) {
|
||||
List<BizMailSent> list = bizMailSentService.findList(bizMailSent);
|
||||
String fileName = "发件" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||
try (ExcelExport ee = new ExcelExport("发件", BizMailSent.class)) {
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:view")
|
||||
@RequestMapping(value = "importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
BizMailSent bizMailSent = new BizMailSent();
|
||||
List<BizMailSent> list = ListUtils.newArrayList(bizMailSent);
|
||||
String fileName = "发件模板.xlsx";
|
||||
try (ExcelExport ee = new ExcelExport("发件", BizMailSent.class, Type.IMPORT)) {
|
||||
ee.setDataList(list).write(response, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailSentService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:" + message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:" + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailSent bizMailSent) {
|
||||
bizMailSentService.delete(bizMailSent);
|
||||
return renderResult(Global.TRUE, text("删除发件成功!"));
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping(value = "sent")
|
||||
@ResponseBody
|
||||
public String sent(BizMailSent bizMailSent) {
|
||||
BizMailAccount account = accountService.get(bizMailSent.getAccountId());
|
||||
List<FileUpload> fileUploads = FileUploadUtils.findFileUpload(bizMailSent.getId(), "bizMailSent_file");
|
||||
BizMailSent sent = MailSendUtils.sendHtmlMail(account, bizMailSent, fileUploads);
|
||||
bizMailSentService.save(sent);
|
||||
return renderResult(Global.TRUE, text("邮件发件成功!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@PostMapping(value = "importData")
|
||||
public String importData(MultipartFile file) {
|
||||
try {
|
||||
String message = bizMailSentService.importData(file);
|
||||
return renderResult(Global.TRUE, "posfull:"+message);
|
||||
} catch (Exception ex) {
|
||||
return renderResult(Global.FALSE, "posfull:"+ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
@RequiresPermissions("biz:mailSent:edit")
|
||||
@RequestMapping(value = "delete")
|
||||
@ResponseBody
|
||||
public String delete(BizMailSent bizMailSent) {
|
||||
bizMailSentService.delete(bizMailSent);
|
||||
return renderResult(Global.TRUE, text("删除发件成功!"));
|
||||
}
|
||||
|
||||
}
|
||||
BIN
web-vue/packages/assets/images/docx.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
web-vue/packages/assets/images/file.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
web-vue/packages/assets/images/gz.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
web-vue/packages/assets/images/login-brand.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
web-vue/packages/assets/images/pdf.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web-vue/packages/assets/images/pptx.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web-vue/packages/assets/images/py.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
web-vue/packages/assets/images/sql.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
web-vue/packages/assets/images/user.jpg
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
web-vue/packages/assets/images/wps.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web-vue/packages/assets/images/xlsx.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web-vue/packages/assets/images/zip.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
@@ -30,6 +30,9 @@ export interface BizMailAttachments extends BasicModel<BizMailAttachments> {
|
||||
export const bizMailAttachmentsList = (params?: BizMailAttachments | any) =>
|
||||
defHttp.get<BizMailAttachments>({ url: adminPath + '/biz/mailAttachments/list', params });
|
||||
|
||||
export const bizMailAttachmentsListAll = (params?: BizMailAttachments | any) =>
|
||||
defHttp.get<BizMailAttachments[]>({ url: adminPath + '/biz/mailAttachments/listAll', params });
|
||||
|
||||
export const bizMailAttachmentsListData = (params?: BizMailAttachments | any) =>
|
||||
defHttp.post<Page<BizMailAttachments>>({ url: adminPath + '/biz/mailAttachments/listData', params });
|
||||
|
||||
@@ -53,3 +56,4 @@ export const bizMailAttachmentsImportData = (
|
||||
|
||||
export const bizMailAttachmentsDelete = (params?: BizMailAttachments | any) =>
|
||||
defHttp.get<BizMailAttachments>({ url: adminPath + '/biz/mailAttachments/delete', params });
|
||||
|
||||
|
||||
@@ -58,3 +58,7 @@ export const bizMailSentImportData = (
|
||||
|
||||
export const bizMailSentDelete = (params?: BizMailSent | any) =>
|
||||
defHttp.get<BizMailSent>({ url: adminPath + '/biz/mailSent/delete', params });
|
||||
|
||||
|
||||
export const bizMailSent = (params?: BizMailSent | any) =>
|
||||
defHttp.get<BizMailSent>({ url: adminPath + '/biz/mailSent/sent', params });
|
||||
@@ -236,6 +236,7 @@
|
||||
confirm: handleDelete.bind(this, record),
|
||||
},
|
||||
auth: 'biz:mailAccount:edit',
|
||||
ifShow: record.ustatus == '0'
|
||||
},
|
||||
{
|
||||
icon: 'ant-design:undo-outlined',
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
import { useI18n } from '@jeesite/core/hooks/web/useI18n';
|
||||
import { BasicColumn, BasicTableProps, FormProps } from '@jeesite/core/components/Table';
|
||||
import { bizMailAccountListData } from '@jeesite/biz/api/biz/mailAccount';
|
||||
|
||||
const { t } = useI18n('biz.mailAccount');
|
||||
|
||||
const modalProps = {
|
||||
title: t('邮件信息选择'),
|
||||
};
|
||||
|
||||
const searchForm: FormProps<BizMailAccount> = {
|
||||
baseColProps: { md: 8, lg: 6 },
|
||||
labelWidth: 90,
|
||||
schemas: [
|
||||
{
|
||||
label: t('记录时间起'),
|
||||
field: 'createTime_gte',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD HH:mm',
|
||||
showTime: { format: 'HH:mm' },
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('记录时间止'),
|
||||
field: 'createTime_lte',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD HH:mm',
|
||||
showTime: { format: 'HH:mm' },
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('服务地址'),
|
||||
field: 'host',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('用户名称'),
|
||||
field: 'username',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('发件人地址'),
|
||||
field: 'fromAddress',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('是否启用SSL'),
|
||||
field: 'sslEnable',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: 'is_open',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('状态'),
|
||||
field: 'status',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: 'ustatus',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const tableColumns: BasicColumn<BizMailAccount>[] = [
|
||||
{
|
||||
title: t('记录时间'),
|
||||
dataIndex: 'createTime',
|
||||
key: 'a.create_time',
|
||||
sorter: true,
|
||||
width: 230,
|
||||
align: 'left',
|
||||
slot: 'firstColumn',
|
||||
},
|
||||
{
|
||||
title: t('服务地址'),
|
||||
dataIndex: 'host',
|
||||
key: 'a.host',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('SMTP端口'),
|
||||
dataIndex: 'smtpPort',
|
||||
key: 'a.smtp_port',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('IMAP端口'),
|
||||
dataIndex: 'imapPort',
|
||||
key: 'a.imap_port',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('用户名称'),
|
||||
dataIndex: 'username',
|
||||
key: 'a.username',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('用户密码'),
|
||||
dataIndex: 'password',
|
||||
key: 'a.password',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('发件人地址'),
|
||||
dataIndex: 'fromAddress',
|
||||
key: 'a.from_address',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('是否启用SSL'),
|
||||
dataIndex: 'sslEnable',
|
||||
key: 'a.ssl_enable',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
dictType: 'is_open',
|
||||
},
|
||||
{
|
||||
title: t('状态'),
|
||||
dataIndex: 'status',
|
||||
key: 'a.status',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
dictType: 'ustatus',
|
||||
},
|
||||
{
|
||||
title: t('备注'),
|
||||
dataIndex: 'remark',
|
||||
key: 'a.remark',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('更新时间'),
|
||||
dataIndex: 'updateTime',
|
||||
key: 'a.update_time',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const tableProps: BasicTableProps = {
|
||||
api: bizMailAccountListData,
|
||||
beforeFetch: (params) => {
|
||||
params['isAll'] = true;
|
||||
return params;
|
||||
},
|
||||
columns: tableColumns,
|
||||
formConfig: searchForm,
|
||||
rowKey: 'id',
|
||||
};
|
||||
|
||||
export default {
|
||||
modalProps,
|
||||
tableProps,
|
||||
itemCode: 'id',
|
||||
itemName: 'id',
|
||||
isShowCode: false,
|
||||
};
|
||||
@@ -68,31 +68,11 @@
|
||||
showTime: { format: 'HH:mm' },
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('收件标识'),
|
||||
field: 'mailId',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('附件名称'),
|
||||
field: 'fileName',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('文件扩展名'),
|
||||
field: 'fileExt',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('是否压缩'),
|
||||
field: 'isCompressed',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('是否加密'),
|
||||
field: 'isEncrypted',
|
||||
component: 'Input',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -104,15 +84,7 @@
|
||||
sorter: true,
|
||||
width: 180,
|
||||
align: 'left',
|
||||
slot: 'firstColumn',
|
||||
},
|
||||
{
|
||||
title: t('收件标识'),
|
||||
dataIndex: 'mailId',
|
||||
key: 'a.mail_id',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
fixed: 'left'
|
||||
},
|
||||
{
|
||||
title: t('附件名称'),
|
||||
@@ -146,14 +118,6 @@
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('存储路径'),
|
||||
dataIndex: 'storagePath',
|
||||
key: 'a.storage_path',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('文件MD5'),
|
||||
dataIndex: 'fileMd5',
|
||||
@@ -177,6 +141,7 @@
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
dictType: 'is_compressed',
|
||||
},
|
||||
{
|
||||
title: t('是否加密'),
|
||||
@@ -185,11 +150,13 @@
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
dictType: 'is_encrypted',
|
||||
},
|
||||
];
|
||||
|
||||
const actionColumn: BasicColumn<BizMailAttachments> = {
|
||||
width: 160,
|
||||
align: 'center',
|
||||
actions: (record: BizMailAttachments) => [
|
||||
{
|
||||
icon: 'i-ant-design:delete-outlined',
|
||||
|
||||
@@ -15,7 +15,13 @@
|
||||
<Icon icon="i-ant-design:download-outlined" /> {{ t('导出') }}
|
||||
</a-button>
|
||||
</template>
|
||||
<template #slotBizKey="{ record }">
|
||||
<a @click="openViewModal(true, record)" :title="record.subject">
|
||||
{{ record.subject }}
|
||||
</a>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<ViewModal @register="registerViewModal" @success="handleSuccess" />
|
||||
<FormImport @register="registerImportModal" @success="handleSuccess" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -34,6 +40,7 @@
|
||||
import { useModal } from '@jeesite/core/components/Modal';
|
||||
import { FormProps } from '@jeesite/core/components/Form';
|
||||
import FormImport from './formImport.vue';
|
||||
import ViewModal from './view.vue';
|
||||
|
||||
const { t } = useI18n('biz.mailReceived');
|
||||
const { showMessage } = useMessage();
|
||||
@@ -71,7 +78,11 @@
|
||||
{
|
||||
label: t('账号名称'),
|
||||
field: 'accountId',
|
||||
component: 'Input',
|
||||
fieldLabel: 'accountName',
|
||||
component: 'ListSelect',
|
||||
componentProps: {
|
||||
selectType: 'bizMailAccountSelect',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('发件人名称'),
|
||||
@@ -86,12 +97,20 @@
|
||||
{
|
||||
label: t('是否有附件'),
|
||||
field: 'hasAttachment',
|
||||
component: 'Input',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: 'has_attachment',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('状态'),
|
||||
field: 'ustatus',
|
||||
component: 'Input',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: 'send_status',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -107,9 +126,9 @@
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: t('账户标识'),
|
||||
dataIndex: 'accountId',
|
||||
key: 'a.account_id',
|
||||
title: t('服务名称'),
|
||||
dataIndex: 'accountName',
|
||||
key: 'b.account_name',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
@@ -122,21 +141,14 @@
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('发件人名称'),
|
||||
dataIndex: 'fromName',
|
||||
key: 'a.from_name',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('邮件主题'),
|
||||
dataIndex: 'subject',
|
||||
key: 'a.subject',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
width: 425,
|
||||
align: 'left',
|
||||
slot: 'slotBizKey',
|
||||
},
|
||||
{
|
||||
title: t('接收时间'),
|
||||
@@ -153,6 +165,7 @@
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
dictType: 'has_attachment',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -197,6 +210,8 @@
|
||||
function handleForm(record: Recordable) {
|
||||
openDrawer(true, record);
|
||||
}
|
||||
|
||||
const [registerViewModal, { openModal: openViewModal }] = useModal();
|
||||
|
||||
async function handleExport() {
|
||||
loading.value = true;
|
||||
|
||||
614
web-vue/packages/biz/views/biz/mailInfo/received/view.vue
Normal file
@@ -0,0 +1,614 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
@register="register"
|
||||
title="邮件详情"
|
||||
:showOkBtn="false"
|
||||
:showCancelBtn="false"
|
||||
width="70%"
|
||||
defaultFullscreen="true"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<div class="detail-container">
|
||||
<div class="detail-title">{{ ReceivedList?.subject || '无标题' }}</div>
|
||||
<div class="detail-info">
|
||||
<span class="info-item">接收时间:{{ ReceivedList?.createTime || '-' }}</span>
|
||||
<span class="info-item">发件邮箱:{{ ReceivedList?.fromAddress }}|{{ ReceivedList?.fromName }}</span>
|
||||
</div>
|
||||
<div class="detail-content">
|
||||
<div class="content-header">
|
||||
<span class="content-title">邮件内容</span>
|
||||
<span class="content-tip" v-if="!ReceivedList?.mailContent">暂无邮件内容</span>
|
||||
</div>
|
||||
<div class="db-content" v-html="ReceivedList?.mailContent || ''"></div>
|
||||
</div>
|
||||
|
||||
<!-- 附件列表区域 -->
|
||||
<div class="attachments-section" v-if="MailAttachments.length > 0">
|
||||
<div class="attachments-title">
|
||||
附件列表 ({{ MailAttachments.length }})
|
||||
</div>
|
||||
<div class="attachments-vertical-container">
|
||||
<div class="attachments-grid">
|
||||
<div class="attachment-card" v-for="(item, index) in MailAttachments" :key="index">
|
||||
<div class="attachment-icon-wrapper">
|
||||
<img
|
||||
class="attachment-icon"
|
||||
:src="getAttachmentIconUrl(item)"
|
||||
:alt="item.fileName + '图标'"
|
||||
@error="handleIconLoadError"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="attachment-info-wrapper">
|
||||
<div class="file-info-row">
|
||||
<span class="attachment-name">{{ item.fileName }}</span>
|
||||
<span class="attachment-size">({{ formatFileSize(item.fileSize) }})</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="attachment-action-wrapper">
|
||||
<button class="download-btn" @click="downloadAttachment(item)">
|
||||
下载
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, PropType } from 'vue';
|
||||
import { useMessage } from '@jeesite/core/hooks/web/useMessage';
|
||||
import { BasicModal, useModalInner } from '@jeesite/core/components/Modal';
|
||||
import { BizMailReceived } from '@jeesite/biz/api/biz/mailReceived';
|
||||
import { useGlobSetting } from '@jeesite/core/hooks/setting';
|
||||
import { downloadByUrl } from '@jeesite/core/utils/file/download';
|
||||
import { BizMailAttachments, bizMailAttachmentsListAll } from '@jeesite/biz/api/biz/mailAttachments';
|
||||
|
||||
import defaultIcon from '@jeesite/assets/images/file.png';
|
||||
import docxIcon from '@jeesite/assets/images/docx.png';
|
||||
import gzIcon from '@jeesite/assets/images/gz.png';
|
||||
import pdfIcon from '@jeesite/assets/images/pdf.png';
|
||||
import pptxIcon from '@jeesite/assets/images/pptx.png';
|
||||
import pyIcon from '@jeesite/assets/images/py.png';
|
||||
import sqlIcon from '@jeesite/assets/images/sql.png';
|
||||
import wpsIcon from '@jeesite/assets/images/wps.png';
|
||||
import xlsxIcon from '@jeesite/assets/images/xlsx.png';
|
||||
import zipIcon from '@jeesite/assets/images/zip.png';
|
||||
|
||||
// 定义自定义图标配置类型
|
||||
interface CustomIconConfig {
|
||||
default?: string;
|
||||
types?: Record<string, string>;
|
||||
exts?: Record<string, string>;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicModal },
|
||||
emits: ['modalClose'],
|
||||
props: {
|
||||
customIcons: {
|
||||
type: Object as PropType<CustomIconConfig>,
|
||||
default: () => ({
|
||||
default: 'default-file.png',
|
||||
types: {
|
||||
docx: 'docx.png',
|
||||
gz: 'gz.png',
|
||||
pdf: 'pdf.png',
|
||||
pptx: 'pptx.png',
|
||||
py: 'py.png',
|
||||
sql: 'sql.png',
|
||||
wps: 'wps.png',
|
||||
xlsx: 'xlsx.png',
|
||||
zip: 'zip.png',
|
||||
other: 'default-file.png'
|
||||
},
|
||||
exts: {}
|
||||
})
|
||||
},
|
||||
iconBasePath: {
|
||||
type: String,
|
||||
default: '@jeesite/assets/images/'
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const ReceivedList = ref<BizMailReceived>();
|
||||
const MailAttachments = ref<BizMailAttachments[]>([]);
|
||||
const { createMessage } = useMessage();
|
||||
const iconMap = {
|
||||
'default-file.png': defaultIcon,
|
||||
'docx.png': docxIcon,
|
||||
'gz.png': gzIcon,
|
||||
'pdf.png': pdfIcon,
|
||||
'pptx.png': pptxIcon,
|
||||
'py.png': pyIcon,
|
||||
'sql.png': sqlIcon,
|
||||
'wps.png': wpsIcon,
|
||||
'xlsx.png': xlsxIcon,
|
||||
'zip.png': zipIcon
|
||||
};
|
||||
|
||||
const [register, { closeModal }] = useModalInner(async (data: any) => {
|
||||
if (!data) return;
|
||||
if (data.messageId) {
|
||||
await getAttachments({ messageId: data.messageId });
|
||||
}
|
||||
ReceivedList.value = data;
|
||||
});
|
||||
|
||||
// 获取附件列表
|
||||
const getAttachments = async (params: { messageId: any }) => {
|
||||
try {
|
||||
const result = await bizMailAttachmentsListAll(params);
|
||||
MailAttachments.value = result;
|
||||
} catch (error) {
|
||||
console.error('获取附件信息失败:', error);
|
||||
MailAttachments.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
async function downloadAttachment(attachment: BizMailAttachments) {
|
||||
const { ctxAdminPath } = useGlobSetting();
|
||||
await downloadByUrl({
|
||||
url: ctxAdminPath + '/biz/mailAttachments/downloadFile',
|
||||
params: {
|
||||
id : attachment.id
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 格式化文件大小
|
||||
const formatFileSize = (size: number) => {
|
||||
if (!size) return '0 B';
|
||||
const units = ['B', 'KB', 'MB', 'GB'];
|
||||
let unitIndex = 0;
|
||||
let fileSize = size;
|
||||
while (fileSize >= 1024 && unitIndex < units.length - 1) {
|
||||
fileSize /= 1024;
|
||||
unitIndex++;
|
||||
}
|
||||
return `${fileSize.toFixed(1)} ${units[unitIndex]}`;
|
||||
};
|
||||
|
||||
// 第一步:根据文件扩展名获取图标文件名
|
||||
const getAttachmentIconName = (file: BizMailAttachments) => {
|
||||
const { customIcons } = props;
|
||||
const ext = file.fileExt?.toLowerCase() || ''; // 统一转小写,避免大小写问题
|
||||
|
||||
let iconName = '';
|
||||
// 1. 优先按扩展名配置匹配
|
||||
if (customIcons.exts?.[ext]) {
|
||||
iconName = customIcons.exts[ext];
|
||||
}
|
||||
// 2. 按文件类型映射匹配
|
||||
else if (customIcons.types) {
|
||||
// 扩展名 → 图标类型的映射(覆盖所有常见类型)
|
||||
const typeMap: Record<string, string> = {
|
||||
'doc': 'docx.png',
|
||||
'docx': 'docx.png',
|
||||
'gz': 'gz.png',
|
||||
'pdf': 'pdf.png',
|
||||
'ppt': 'pptx.png',
|
||||
'pptx': 'pptx.png',
|
||||
'py': 'py.png',
|
||||
'sql': 'sql.png',
|
||||
'wps': 'wps.png',
|
||||
'xls': 'xlsx.png',
|
||||
'xlsx': 'xlsx.png',
|
||||
'zip': 'zip.png',
|
||||
'rar': 'zip.png',
|
||||
'7z': 'zip.png',
|
||||
'tar': 'zip.png',
|
||||
'jpg': 'default-file.png',
|
||||
'png': 'default-file.png',
|
||||
'txt': 'default-file.png',
|
||||
'json': 'default-file.png'
|
||||
};
|
||||
// 匹配不到则用other类型
|
||||
iconName = typeMap[ext] || customIcons.types['other'] || 'default-file.png';
|
||||
}
|
||||
// 3. 兜底用默认图标
|
||||
iconName = iconName || customIcons.default || 'default-file.png';
|
||||
|
||||
return iconName;
|
||||
};
|
||||
|
||||
// 第二步:根据图标文件名获取打包后的真实URL(核心)
|
||||
const getAttachmentIconUrl = (file: BizMailAttachments) => {
|
||||
const iconName = getAttachmentIconName(file);
|
||||
// 从映射表获取,兜底用默认图标
|
||||
return iconMap[iconName] || iconMap['default-file.png'];
|
||||
};
|
||||
|
||||
// 处理图标加载失败
|
||||
const handleIconLoadError = (e: Event) => {
|
||||
const target = e.target as HTMLImageElement;
|
||||
// 避免无限循环
|
||||
if (target.src === iconMap['default-file.png']) return;
|
||||
target.src = iconMap['default-file.png'];
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('modalClose');
|
||||
closeModal();
|
||||
};
|
||||
|
||||
return {
|
||||
register,
|
||||
closeModal,
|
||||
handleCancel,
|
||||
ReceivedList,
|
||||
MailAttachments,
|
||||
downloadAttachment,
|
||||
formatFileSize,
|
||||
getAttachmentIconUrl,
|
||||
handleIconLoadError
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.detail-container {
|
||||
background-color: #f0f8ff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
color: #1f2937;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #d1e7ff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.detail-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
color: #4b5563;
|
||||
font-size: 13px;
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
background-color: #ffffff;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #d1e7ff;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.03);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: #374151;
|
||||
margin-bottom: 20px;
|
||||
padding: 0;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #d1e7ff;
|
||||
flex: 1;
|
||||
min-height: 100px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content-header {
|
||||
padding: 12px 14px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.content-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content-title::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 14px;
|
||||
background-color: #4096ff;
|
||||
border-radius: 2px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.content-tip {
|
||||
font-size: 12px;
|
||||
color: #9ca3af;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.db-content {
|
||||
padding: 14px;
|
||||
margin: 0;
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
.attachments-section {
|
||||
margin-top: auto;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.attachments-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.attachments-vertical-container {
|
||||
width: 100%;
|
||||
--card-height: 70px;
|
||||
--card-gap: 8px;
|
||||
--container-padding: 4px;
|
||||
max-height: calc(3 * var(--card-height) + 2 * var(--card-gap) + 2 * var(--container-padding));
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 0 var(--container-padding) var(--container-padding) var(--container-padding);
|
||||
box-sizing: border-box;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #d1e7ff #f8fbff;
|
||||
}
|
||||
|
||||
.attachments-vertical-container::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.attachments-vertical-container::-webkit-scrollbar-track {
|
||||
background: #f8fbff;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.attachments-vertical-container::-webkit-scrollbar-thumb {
|
||||
background: #d1e7ff;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.attachments-vertical-container::-webkit-scrollbar-thumb:hover {
|
||||
background: #4096ff;
|
||||
}
|
||||
|
||||
.attachments-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(min(100%/4, max(150px, 100%/6)), 1fr));
|
||||
gap: var(--card-gap);
|
||||
padding-bottom: var(--card-gap);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.attachment-card {
|
||||
width: 100%;
|
||||
height: var(--card-height);
|
||||
background: #ffffff;
|
||||
border: 1px solid #d1e7ff;
|
||||
border-radius: 6px;
|
||||
padding: 8px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.03);
|
||||
transition: all 0.2s ease;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.attachment-card:hover {
|
||||
box-shadow: 0 3px 8px rgba(64, 150, 255, 0.1);
|
||||
border-color: #4096ff;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.attachment-icon-wrapper {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background-color: #f8fbff;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.attachment-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
border-radius: 2px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.attachment-icon[src] {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.attachment-info-wrapper {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: calc(100% - 100px);
|
||||
}
|
||||
|
||||
.file-info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.attachment-name {
|
||||
font-size: 12px;
|
||||
color: #1f2937;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.attachment-size {
|
||||
font-size: 10px;
|
||||
color: #6b7280;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.attachment-action-wrapper {
|
||||
flex-shrink: 0;
|
||||
width: 60px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.download-btn {
|
||||
padding: 3px 8px;
|
||||
border: 1px solid #1890ff;
|
||||
border-radius: 4px;
|
||||
background-color: #ffffff;
|
||||
color: #1890ff;
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
transition: all 0.2s ease;
|
||||
white-space: nowrap;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.download-btn:hover {
|
||||
background-color: #e6f7ff;
|
||||
border-color: #40a9ff;
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
.download-btn:active {
|
||||
background-color: #1890ff;
|
||||
color: white;
|
||||
border-color: #1890ff;
|
||||
}
|
||||
|
||||
.db-content::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.db-content::-webkit-scrollbar-track {
|
||||
background: #f8fbff;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.db-content::-webkit-scrollbar-thumb {
|
||||
background: #d1e7ff;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.db-content::-webkit-scrollbar-thumb:hover {
|
||||
background: #4096ff;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.attachments-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(min(100%/4, max(120px, 100%/5)), 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.attachments-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(min(100%/3, max(100px, 100%/4)), 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.attachments-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(min(100%/2, max(150px, 100%/3)), 1fr));
|
||||
}
|
||||
.attachment-card {
|
||||
padding: 6px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.attachments-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.attachment-info-wrapper {
|
||||
width: calc(100% - 80px);
|
||||
}
|
||||
.detail-container {
|
||||
padding: 15px;
|
||||
}
|
||||
.detail-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
.content-header {
|
||||
padding: 10px 12px;
|
||||
}
|
||||
.content-title {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-modal-content) {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
:deep(.ant-modal-body) {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -54,18 +54,10 @@
|
||||
{
|
||||
label: t('账户名称'),
|
||||
field: 'accountId',
|
||||
component: 'Input',
|
||||
fieldLabel: 'accountName',
|
||||
component: 'ListSelect',
|
||||
componentProps: {
|
||||
maxlength: 52,
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: t('发件人地址'),
|
||||
field: 'fromAddress',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
maxlength: 255,
|
||||
selectType: 'bizMailAccountSelect',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
@@ -74,7 +66,14 @@
|
||||
field: 'toAddresses',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
colProps: { md: 24, lg: 24 },
|
||||
},
|
||||
{
|
||||
label: t('抄送人地址'),
|
||||
field: 'ccAddresses',
|
||||
component: 'Input',
|
||||
colProps: { md: 24, lg: 24 },
|
||||
},
|
||||
{
|
||||
label: t('邮件内容'),
|
||||
field: 'content',
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
import { Icon } from '@jeesite/core/components/Icon';
|
||||
import { BasicTable, BasicColumn, useTable } from '@jeesite/core/components/Table';
|
||||
import { BizMailSent, bizMailSentList } from '@jeesite/biz/api/biz/mailSent';
|
||||
import { bizMailSentDelete, bizMailSentListData } from '@jeesite/biz/api/biz/mailSent';
|
||||
import { bizMailSentDelete, bizMailSent, bizMailSentListData } from '@jeesite/biz/api/biz/mailSent';
|
||||
import { useModal } from '@jeesite/core/components/Modal';
|
||||
import { FormProps } from '@jeesite/core/components/Form';
|
||||
import InputForm from './form.vue';
|
||||
@@ -80,7 +80,11 @@
|
||||
{
|
||||
label: t('账号名称'),
|
||||
field: 'accountId',
|
||||
component: 'Input',
|
||||
fieldLabel: 'accountName',
|
||||
component: 'ListSelect',
|
||||
componentProps: {
|
||||
selectType: 'bizMailAccountSelect',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('发件地址'),
|
||||
@@ -97,7 +101,7 @@
|
||||
field: 'sendStatus',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: '',
|
||||
dictType: 'send_status',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
@@ -106,7 +110,7 @@
|
||||
field: 'hasAttachment',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: '',
|
||||
dictType: 'has_attachment',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
@@ -121,7 +125,7 @@
|
||||
sorter: true,
|
||||
width: 180,
|
||||
align: 'left',
|
||||
slot: 'firstColumn',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: t('发件人地址'),
|
||||
@@ -162,7 +166,7 @@
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
dictType: '',
|
||||
dictType: 'send_status',
|
||||
},
|
||||
{
|
||||
title: t('是否有附件'),
|
||||
@@ -171,7 +175,7 @@
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
dictType: '',
|
||||
dictType: 'has_attachment',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -184,7 +188,7 @@
|
||||
title: t('编辑'),
|
||||
onClick: handleForm.bind(this, { id: record.id }),
|
||||
auth: 'biz:mailSent:edit',
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'i-ant-design:delete-outlined',
|
||||
color: 'error',
|
||||
@@ -195,6 +199,15 @@
|
||||
},
|
||||
auth: 'biz:mailSent:edit',
|
||||
},
|
||||
{
|
||||
icon: 'simple-line-icons:action-redo',
|
||||
color: 'success',
|
||||
title: t('发送'),
|
||||
popConfirm: {
|
||||
title: t('是否确认发送邮件信息?'),
|
||||
confirm: handleSent.bind(this, record),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -245,6 +258,13 @@
|
||||
showMessage(res.message);
|
||||
await handleSuccess(record);
|
||||
}
|
||||
|
||||
async function handleSent(record: Recordable) {
|
||||
const params = { id: record.id };
|
||||
const res = await bizMailSent(params);
|
||||
showMessage(res.message);
|
||||
await handleSuccess(record);
|
||||
}
|
||||
|
||||
async function handleSuccess(record: Recordable) {
|
||||
await reload({ record });
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
import { useI18n } from '@jeesite/core/hooks/web/useI18n';
|
||||
import { BasicColumn, BasicTableProps, FormProps } from '@jeesite/core/components/Table';
|
||||
import { bizMailSentListData } from '@jeesite/biz/api/biz/mailSent';
|
||||
|
||||
const { t } = useI18n('biz.mailSent');
|
||||
|
||||
const modalProps = {
|
||||
title: t('发件选择'),
|
||||
};
|
||||
|
||||
const searchForm: FormProps<BizMailSent> = {
|
||||
baseColProps: { md: 8, lg: 6 },
|
||||
labelWidth: 90,
|
||||
schemas: [
|
||||
{
|
||||
label: t('记录时间起'),
|
||||
field: 'createTime_gte',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD HH:mm',
|
||||
showTime: { format: 'HH:mm' },
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('记录时间止'),
|
||||
field: 'createTime_lte',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD HH:mm',
|
||||
showTime: { format: 'HH:mm' },
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('邮件账户标识'),
|
||||
field: 'accountId',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('发件人地址'),
|
||||
field: 'fromAddress',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('邮件主题'),
|
||||
field: 'subject',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('发送状态'),
|
||||
field: 'sendStatus',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: '',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('是否有附件'),
|
||||
field: 'hasAttachment',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: '',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const tableColumns: BasicColumn<BizMailSent>[] = [
|
||||
{
|
||||
title: t('记录时间'),
|
||||
dataIndex: 'createTime',
|
||||
key: 'a.create_time',
|
||||
sorter: true,
|
||||
width: 230,
|
||||
align: 'left',
|
||||
slot: 'firstColumn',
|
||||
},
|
||||
{
|
||||
title: t('件服务器消息标识'),
|
||||
dataIndex: 'messageId',
|
||||
key: 'a.message_id',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('邮件账户标识'),
|
||||
dataIndex: 'accountId',
|
||||
key: 'a.account_id',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('发件人地址'),
|
||||
dataIndex: 'fromAddress',
|
||||
key: 'a.from_address',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('收件人地址'),
|
||||
dataIndex: 'toAddresses',
|
||||
key: 'a.to_addresses',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('抄送人地址'),
|
||||
dataIndex: 'ccAddresses',
|
||||
key: 'a.cc_addresses',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('邮件主题'),
|
||||
dataIndex: 'subject',
|
||||
key: 'a.subject',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('邮件内容'),
|
||||
dataIndex: 'content',
|
||||
key: 'a.content',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('发送时间'),
|
||||
dataIndex: 'sendTime',
|
||||
key: 'a.send_time',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('发送状态'),
|
||||
dataIndex: 'sendStatus',
|
||||
key: 'a.send_status',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
dictType: '',
|
||||
},
|
||||
{
|
||||
title: t('错误信息'),
|
||||
dataIndex: 'errorMsg',
|
||||
key: 'a.error_msg',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('是否有附件'),
|
||||
dataIndex: 'hasAttachment',
|
||||
key: 'a.has_attachment',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
dictType: '',
|
||||
},
|
||||
{
|
||||
title: t('更新时间'),
|
||||
dataIndex: 'updateTime',
|
||||
key: 'a.update_time',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const tableProps: BasicTableProps = {
|
||||
api: bizMailSentListData,
|
||||
beforeFetch: (params) => {
|
||||
params['isAll'] = true;
|
||||
return params;
|
||||
},
|
||||
columns: tableColumns,
|
||||
formConfig: searchForm,
|
||||
rowKey: 'id',
|
||||
};
|
||||
|
||||
export default {
|
||||
modalProps,
|
||||
tableProps,
|
||||
itemCode: 'id',
|
||||
itemName: 'id',
|
||||
isShowCode: false,
|
||||
};
|
||||
@@ -0,0 +1,181 @@
|
||||
import { useI18n } from '@jeesite/core/hooks/web/useI18n';
|
||||
import { BasicColumn, BasicTableProps, FormProps } from '@jeesite/core/components/Table';
|
||||
import { BizMailAccount, bizMailAccountListData } from '@jeesite/biz/api/biz/mailAccount';
|
||||
|
||||
const { t } = useI18n('biz.mailAccount');
|
||||
|
||||
const modalProps = {
|
||||
title: t('邮件账号选择'),
|
||||
};
|
||||
|
||||
const searchForm: FormProps<BizMailAccount> = {
|
||||
baseColProps: { md: 8, lg: 6 },
|
||||
labelWidth: 90,
|
||||
schemas: [
|
||||
{
|
||||
label: t('记录时间起'),
|
||||
field: 'createTime_gte',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD HH:mm',
|
||||
showTime: { format: 'HH:mm' },
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('记录时间止'),
|
||||
field: 'createTime_lte',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
format: 'YYYY-MM-DD HH:mm',
|
||||
showTime: { format: 'HH:mm' },
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('SMTP服务'),
|
||||
field: 'host',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('用户名称'),
|
||||
field: 'username',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('发件地址'),
|
||||
field: 'fromAddress',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: t('启用SSL'),
|
||||
field: 'sslEnable',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: 'is_open',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('状态'),
|
||||
field: 'ustatus',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: 'ustatus',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const tableColumns: BasicColumn<BizMailAccount>[] = [
|
||||
{
|
||||
title: t('记录时间'),
|
||||
dataIndex: 'createTime',
|
||||
key: 'a.create_time',
|
||||
sorter: true,
|
||||
width: 180,
|
||||
align: 'left',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: t('配置名称'),
|
||||
dataIndex: 'accountName',
|
||||
key: 'a.account_name',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
slot: 'slotBizKey',
|
||||
},
|
||||
{
|
||||
title: t('SMTP服务'),
|
||||
dataIndex: 'host',
|
||||
key: 'a.host',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('SMTP端口'),
|
||||
dataIndex: 'smtpPort',
|
||||
key: 'a.smtp_port',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('IMAP服务'),
|
||||
dataIndex: 'imapHost',
|
||||
key: 'a.imap_host',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('IMAP端口'),
|
||||
dataIndex: 'imapPort',
|
||||
key: 'a.imap_port',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('用户名称'),
|
||||
dataIndex: 'username',
|
||||
key: 'a.username',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('发件地址'),
|
||||
dataIndex: 'fromAddress',
|
||||
key: 'a.from_address',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('启用SSL'),
|
||||
dataIndex: 'sslEnable',
|
||||
key: 'a.ssl_enable',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
dictType: 'is_open',
|
||||
},
|
||||
{
|
||||
title: t('状态'),
|
||||
dataIndex: 'ustatus',
|
||||
key: 'a.ustatus',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'center',
|
||||
dictType: 'ustatus',
|
||||
},
|
||||
{
|
||||
title: t('备注'),
|
||||
dataIndex: 'remark',
|
||||
key: 'a.remark',
|
||||
sorter: true,
|
||||
width: 130,
|
||||
align: 'left',
|
||||
},
|
||||
];
|
||||
|
||||
const tableProps: BasicTableProps = {
|
||||
api: bizMailAccountListData,
|
||||
beforeFetch: (params) => {
|
||||
params['isAll'] = true;
|
||||
return params;
|
||||
},
|
||||
columns: tableColumns,
|
||||
formConfig: searchForm,
|
||||
rowKey: 'id',
|
||||
};
|
||||
|
||||
export default {
|
||||
modalProps,
|
||||
tableProps,
|
||||
itemCode: 'id',
|
||||
itemName: 'accountName',
|
||||
isShowCode: true,
|
||||
};
|
||||