diff --git a/web-api/src/main/java/com/jeesite/modules/apps/Module/TableTree.java b/web-api/src/main/java/com/jeesite/modules/apps/Module/TableTree.java new file mode 100644 index 0000000..7b8f4b3 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/apps/Module/TableTree.java @@ -0,0 +1,26 @@ +package com.jeesite.modules.apps.Module; + + + +import com.jeesite.modules.biz.entity.MyDataColumn; +import com.jeesite.modules.biz.entity.MyDataTable; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class TableTree implements Serializable { + + MyDataTable dataTable; + + List dataColumns; + + public TableTree() { + } + + public TableTree(MyDataTable dataTable, List dataColumns) { + this.dataTable = dataTable; + this.dataColumns = dataColumns; + } +} diff --git a/web-api/src/main/java/com/jeesite/modules/apps/Service/erpFlowService.java b/web-api/src/main/java/com/jeesite/modules/apps/Service/erpFlowService.java index c9b55aa..80ff0e1 100644 --- a/web-api/src/main/java/com/jeesite/modules/apps/Service/erpFlowService.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/Service/erpFlowService.java @@ -5,8 +5,8 @@ import com.jeesite.modules.erp.service.ErpAccountService; import com.jeesite.modules.erp.service.ErpCategoryService; import com.jeesite.modules.erp.service.ErpDebtsService; import com.jeesite.modules.erp.service.ErpTransactionFlowService; -import com.jeesite.modules.utils.BigDecimalUtils; -import com.jeesite.modules.utils.DateUtils; +import com.jeesite.modules.apps.utils.BigDecimalUtils; +import com.jeesite.modules.apps.utils.DateUtils; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -70,8 +70,8 @@ public class erpFlowService { erpIncome.getCategoryId(), // 分类ID erpIncome.getRemark(), // 备注 erpIncome.getIncomeId(), // 业务ID - com.jeesite.modules.utils.DateUtils.getCurrentYear(), // 年 - com.jeesite.modules.utils.DateUtils.getCurrentMonth() // 月 + DateUtils.getCurrentYear(), // 年 + DateUtils.getCurrentMonth() // 月 ); } diff --git a/web-api/src/main/java/com/jeesite/modules/utils/BigDecimalUtils.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/BigDecimalUtils.java similarity index 97% rename from web-api/src/main/java/com/jeesite/modules/utils/BigDecimalUtils.java rename to web-api/src/main/java/com/jeesite/modules/apps/utils/BigDecimalUtils.java index 72bda8d..38845d4 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/BigDecimalUtils.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/BigDecimalUtils.java @@ -1,4 +1,4 @@ -package com.jeesite.modules.utils; +package com.jeesite.modules.apps.utils; import java.math.BigDecimal; import java.math.RoundingMode; diff --git a/web-api/src/main/java/com/jeesite/modules/utils/DateUtils.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/DateUtils.java similarity index 89% rename from web-api/src/main/java/com/jeesite/modules/utils/DateUtils.java rename to web-api/src/main/java/com/jeesite/modules/apps/utils/DateUtils.java index 138c6b7..f487f1d 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/DateUtils.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/DateUtils.java @@ -1,7 +1,8 @@ -package com.jeesite.modules.utils; +package com.jeesite.modules.apps.utils; import java.text.SimpleDateFormat; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Date; @@ -14,6 +15,12 @@ public class DateUtils { private static final DateTimeFormatter SHORT_YEAR_MONTH_CN_FORMATTER = DateTimeFormatter.ofPattern("yy年MM月"); + private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + + public static String getCurrentDateTime() { + return LocalDateTime.now().format(DATETIME_FORMATTER); + } public static String dsValue() { LocalDate currentDate = LocalDate.now(); diff --git a/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/DockerUtil.java similarity index 99% rename from web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java rename to web-api/src/main/java/com/jeesite/modules/apps/utils/DockerUtil.java index cf14f4c..ce47556 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/DockerUtil.java @@ -1,4 +1,4 @@ -package com.jeesite.modules.utils; +package com.jeesite.modules.apps.utils; import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSch; diff --git a/web-api/src/main/java/com/jeesite/modules/utils/KeyUtil.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/KeyUtil.java similarity index 97% rename from web-api/src/main/java/com/jeesite/modules/utils/KeyUtil.java rename to web-api/src/main/java/com/jeesite/modules/apps/utils/KeyUtil.java index 19016a8..cc9c243 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/KeyUtil.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/KeyUtil.java @@ -1,4 +1,4 @@ -package com.jeesite.modules.utils; +package com.jeesite.modules.apps.utils; import java.awt.*; import java.util.concurrent.ThreadLocalRandom; diff --git a/web-api/src/main/java/com/jeesite/modules/utils/LoggerUtils.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/LoggerUtils.java similarity index 99% rename from web-api/src/main/java/com/jeesite/modules/utils/LoggerUtils.java rename to web-api/src/main/java/com/jeesite/modules/apps/utils/LoggerUtils.java index 841db57..6b264eb 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/LoggerUtils.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/LoggerUtils.java @@ -1,4 +1,4 @@ -package com.jeesite.modules.utils; +package com.jeesite.modules.apps.utils; import java.io.*; import java.nio.charset.StandardCharsets; diff --git a/web-api/src/main/java/com/jeesite/modules/apps/utils/MailReceiveUtils.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/MailReceiveUtils.java new file mode 100644 index 0000000..178cfe7 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/MailReceiveUtils.java @@ -0,0 +1,658 @@ +//package com.jeesite.modules.utils; +// +// +// +// +//import jakarta.activation.MimetypesFileTypeMap; +// +//import java.io.*; +//import java.nio.ByteBuffer; +//import java.nio.channels.FileChannel; +//import java.nio.charset.Charset; +//import java.nio.charset.StandardCharsets; +//import java.nio.file.Files; +//import java.nio.file.StandardOpenOption; +//import java.security.MessageDigest; +//import java.util.*; +// +//public class MailReceiveUtils { +// +// // 连接重试配置 +// private static final int CONNECT_RETRY_TIMES = 3; +// private static final long CONNECT_RETRY_INTERVAL = 1000L; +// private static final LoggerUtils logger = LoggerUtils.getInstance(); +// +// // 缓存ByteBuffer +// private static final ThreadLocal BUFFER_LOCAL = ThreadLocal.withInitial(() -> ByteBuffer.allocate(8192)); +// +// // MIME类型映射(修复附件FileType识别) +// private static final MimetypesFileTypeMap MIME_TYPE_MAP = new MimetypesFileTypeMap(); +// +// static { +// // 扩展MIME类型映射,解决常见文件类型识别错误 +// MIME_TYPE_MAP.addMimeTypes("application/pdf pdf"); +// MIME_TYPE_MAP.addMimeTypes("application/msword doc"); +// MIME_TYPE_MAP.addMimeTypes("application/vnd.openxmlformats-officedocument.wordprocessingml.document docx"); +// MIME_TYPE_MAP.addMimeTypes("application/vnd.ms-excel xls"); +// MIME_TYPE_MAP.addMimeTypes("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx"); +// MIME_TYPE_MAP.addMimeTypes("application/vnd.ms-powerpoint ppt"); +// MIME_TYPE_MAP.addMimeTypes("application/vnd.openxmlformats-officedocument.presentationml.presentation pptx"); +// MIME_TYPE_MAP.addMimeTypes("image/jpeg jpg jpeg"); +// MIME_TYPE_MAP.addMimeTypes("image/png png"); +// MIME_TYPE_MAP.addMimeTypes("image/gif gif"); +// MIME_TYPE_MAP.addMimeTypes("application/zip zip"); +// MIME_TYPE_MAP.addMimeTypes("application/x-rar-compressed rar"); +// MIME_TYPE_MAP.addMimeTypes("application/x-7z-compressed 7z"); +// } +// +// /** +// * 接收未读邮件(优化:优先解析HTML格式正文) +// */ +// public static List receiveUnreadMails(BizMailAccount mailAccount, String saveBasePath) throws Exception { +// List receivedMailList = new ArrayList<>(); +// Session session = createMailSession(mailAccount); +// Store store = null; +// Folder folder = null; +// +// try { +// // 1. 建立IMAP连接(带重试) +// store = session.getStore("imap"); +// boolean isConnected = false; +// int retryCount = 0; +// while (!isConnected) { +// try { +// store.connect(mailAccount.getHost(), mailAccount.getImapPort(), +// mailAccount.getUsername(), mailAccount.getPassword()); +// isConnected = store.isConnected(); +// if (isConnected) { +// logger.info("第" + (retryCount + 1) + "次连接IMAP成功:" + mailAccount.getHost(), mailAccount.getAccountName()); +// } +// } catch (AuthenticationFailedException e) { +// logger.error("账号/密码错误,直接返回", e); +// return receivedMailList; +// } catch (MessagingException e) { +// retryCount++; +// logger.error("第" + retryCount + "次连接失败:" + e.getMessage(), mailAccount.getAccountName()); +// if (retryCount >= CONNECT_RETRY_TIMES) { +// throw new IllegalStateException("IMAP连接失败(重试3次)", e); +// } +// Thread.sleep(CONNECT_RETRY_INTERVAL); +// } +// } +// +// // 2. 打开收件箱 +// folder = store.getFolder("INBOX"); +// if (folder == null || !folder.exists()) { +// logger.error("收件箱不存在"); +// return receivedMailList; +// } +// folder.open(Folder.READ_WRITE); +// logger.info("未读邮件数:" + folder.getUnreadMessageCount()); +// +// // 3. 筛选未读邮件 +// Message[] unreadMessages = folder.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false)); +// if (unreadMessages == null || unreadMessages.length == 0) { +// logger.warn("无未读邮件", mailAccount.getAccountName()); +// return receivedMailList; +// } +// +// // 4. 处理每封邮件 +// for (Message message : unreadMessages) { +// try { +// BizMailReceived bizMail = buildBizMailReceived(message, mailAccount); +// // 记录整封邮件附件下载开始时间 +// long mailAttachDownloadStart = System.currentTimeMillis(); +// logger.info("开始下载邮件[" + getMessageId(message) + "]的附件,开始时间:" + new Date(mailAttachDownloadStart)); +// +// List attachments = downloadExplicitAttachments(message, bizMail.getMessageId(), saveBasePath); +// +// // 记录整封邮件附件下载结束时间 +// long mailAttachDownloadEnd = System.currentTimeMillis(); +// logger.info("完成下载邮件[" + getMessageId(message) + "]的附件,结束时间:" + new Date(mailAttachDownloadEnd) + +// ",耗时:" + (mailAttachDownloadEnd - mailAttachDownloadStart) + "ms"); +// +// receivedMailList.add(new MailReceived(bizMail, attachments)); +// message.setFlag(Flags.Flag.SEEN, true); // 标记已读 +// } catch (Exception e) { +// logger.error("处理邮件失败(Message-ID:" + getMessageId(message) + "):" + e.getMessage(), e); +// continue; +// } +// } +// +// } finally { +// // 关闭资源 +// if (folder != null && folder.isOpen()) { +// try { +// folder.close(true); +// } catch (MessagingException e) { +// logger.error("关闭文件夹失败", e); +// } +// } +// if (store != null && store.isConnected()) { +// try { +// store.close(); +// } catch (MessagingException e) { +// logger.error("关闭连接失败", e); +// } +// } +// BUFFER_LOCAL.remove(); +// } +// +// return receivedMailList; +// } +// +// /** +// * 创建邮件会话(优化编码+IMAP配置) +// */ +// private static Session createMailSession(BizMailAccount mailAccount) { +// Properties props = new Properties(); +// boolean sslEnable = "true".equals(mailAccount.getSslEnable()); +// props.put("mail.imap.host", mailAccount.getHost()); +// props.put("mail.imap.port", mailAccount.getImapPort()); +// props.put("mail.imap.ssl.enable", sslEnable); +// props.put("mail.imap.ssl.protocols", "TLSv1.2"); // 强制TLS1.2,避免SSL漏洞 +// props.put("mail.imap.auth", "true"); +// props.put("mail.imap.connectiontimeout", "10000"); +// props.put("mail.imap.timeout", "30000"); +// props.put("mail.imap.partialfetch", "false"); // 禁用部分获取,避免内容截断 +// props.put("mail.mime.charset", "UTF-8"); +// props.put("mail.mime.base64.ignoreerrors", "true"); +// props.put("mail.mime.decodefilenamehandler", "com.sun.mail.imap.protocol.IMAPUTF8DecodeHandler"); +// // 关键:启用UTF-8文件名解码 +// System.setProperty("mail.mime.encodeparameters", "false"); +// +// return Session.getInstance(props, new Authenticator() { +// @Override +// protected PasswordAuthentication getPasswordAuthentication() { +// return new PasswordAuthentication(mailAccount.getUsername(), mailAccount.getPassword()); +// } +// }); +// } +// +// /** +// * 构建邮件实体(核心优化:优先解析HTML正文) +// */ +// private static BizMailReceived buildBizMailReceived(Message message, BizMailAccount mailAccount) throws Exception { +// BizMailReceived received = new BizMailReceived(); +// received.setCreateTime(new Date()); +// received.setMessageId(getMessageId(message)); +// received.setAccountId(mailAccount.getId()); +// received.setUstatus("1"); +// received.setMailbox("INBOX"); +// +// // 发件人(修复编码) +// Address[] from = message.getFrom(); +// if (from != null && from.length > 0) { +// InternetAddress fromAddr = (InternetAddress) from[0]; +// received.setFromAddress(fromAddr.getAddress()); +// // 优先解码发件人名称 +// String personal = fromAddr.getPersonal(); +// if (personal != null) { +// received.setFromName(decodeMimeText(personal)); +// } else { +// received.setFromName(fromAddr.getAddress()); +// } +// } +// +// // 收件人/抄送/密送(修复编码) +// received.setToAddresses(convertAddresses(message.getRecipients(Message.RecipientType.TO))); +// received.setCcAddresses(convertAddresses(message.getRecipients(Message.RecipientType.CC))); +// received.setBccAddresses(convertAddresses(message.getRecipients(Message.RecipientType.BCC))); +// +// // 主题(修复乱码) +// String subject = message.getSubject(); +// received.setSubject(subject == null ? "" : decodeMimeText(subject)); +// +// // 核心优化:优先解析HTML格式正文 +// String htmlContent = parseHtmlMailContent(message); +// // 最终空内容兜底 +// received.setMailContent(htmlContent.isEmpty() ? "

(无正文内容)

" : htmlContent); +// +// // 时间 +// received.setReceivedTime(new Date()); +// received.setSendTime(message.getSentDate() != null ? message.getSentDate() : new Date()); +// +// // 是否有显式附件 +// received.setHasAttachment(hasExplicitAttachment(message) ? "1" : "0"); +// +// return received; +// } +// +// /** +// * 核心优化:专门解析HTML格式正文(优先提取HTML,无则将纯文本转为HTML) +// */ +// private static String parseHtmlMailContent(Message message) throws Exception { +// Object content = message.getContent(); +// StringBuilder htmlSb = new StringBuilder(); +// +// // 递归提取HTML内容 +// extractHtmlContentRecursive(content, htmlSb); +// +// // 清理HTML内容,去除无效标签和空白 +// String rawHtml = htmlSb.toString().replaceAll("\\n+", "").replaceAll("\\s+", " ").trim(); +// // 如果没有提取到HTML内容,尝试提取纯文本并转为HTML格式 +// if (rawHtml.isEmpty()) { +// String plainText = extractPlainTextContent(message); +// if (!plainText.isEmpty()) { +// // 将纯文本转为基本HTML格式(换行转
,空格转 ) +// rawHtml = "

" + plainText.replaceAll("\\n", "
").replaceAll(" ", " ") + "

"; +// } +// } +// +// // 标准化HTML结构 +// return standardizeHtml(rawHtml); +// } +// +// /** +// * 递归提取HTML内容(优先获取text/html类型) +// */ +// private static void extractHtmlContentRecursive(Object content, StringBuilder sb) throws Exception { +// if (content == null) { +// return; +// } +// +// // 1. 直接是HTML文本(极少情况) +// if (content instanceof String text) { +// if (text.contains("") || text.contains("") || text.contains("

") || text.contains("
")) { +// sb.append(text); +// } +// return; +// } +// +// // 2. MimeMultipart:优先提取text/html部分 +// if (content instanceof MimeMultipart multipart) { +// String multipartType = multipart.getContentType().split(";")[0].trim().toLowerCase(); +// +// // 处理multipart/alternative(多格式正文,优先取text/html) +// if ("multipart/alternative".equals(multipartType)) { +// for (int i = 0; i < multipart.getCount(); i++) { +// BodyPart part = multipart.getBodyPart(i); +// String partType = part.getContentType().split(";")[0].trim().toLowerCase(); +// if ("text/html".equals(partType)) { +// // 读取HTML内容并追加 +// sb.append(readBodyPartContent(part)); +// return; // 找到HTML后直接返回,不再处理其他部分 +// } +// } +// } +// +// // 处理其他multipart类型(递归提取所有HTML部分) +// for (int i = 0; i < multipart.getCount(); i++) { +// BodyPart bodyPart = multipart.getBodyPart(i); +// String disposition = bodyPart.getDisposition(); +// +// // 跳过显式附件 +// if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) { +// continue; +// } +// +// // 提取HTML内容 +// String partType = bodyPart.getContentType().split(";")[0].trim().toLowerCase(); +// if ("text/html".equals(partType)) { +// sb.append(readBodyPartContent(bodyPart)); +// } else { +// // 递归解析子内容 +// extractHtmlContentRecursive(bodyPart.getContent(), sb); +// } +// } +// return; +// } +// +// // 3. 单个MimeBodyPart:如果是HTML类型则读取 +// if (content instanceof MimeBodyPart bodyPart) { +// String disposition = bodyPart.getDisposition(); +// // 跳过显式附件 +// if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) { +// return; +// } +// +// String partType = bodyPart.getContentType().split(";")[0].trim().toLowerCase(); +// if ("text/html".equals(partType)) { +// sb.append(readBodyPartContent(bodyPart)); +// } +// } +// } +// +// /** +// * 提取纯文本内容(作为HTML的降级方案) +// */ +// private static String extractPlainTextContent(Message message) throws Exception { +// Object content = message.getContent(); +// StringBuilder plainSb = new StringBuilder(); +// +// extractPlainTextRecursive(content, plainSb); +// +// return plainSb.toString().replaceAll("^\\s+|\\s+$", "").replaceAll("\\n+", "\n"); +// } +// +// /** +// * 递归提取纯文本内容 +// */ +// private static void extractPlainTextRecursive(Object content, StringBuilder sb) throws Exception { +// if (content == null) { +// return; +// } +// +// // 纯文本直接追加 +// if (content instanceof String) { +// String text = ((String) content).trim(); +// if (!text.isEmpty()) { +// sb.append(text).append("\n"); +// } +// return; +// } +// +// // 处理MimeMultipart +// if (content instanceof MimeMultipart multipart) { +// for (int i = 0; i < multipart.getCount(); i++) { +// BodyPart bodyPart = multipart.getBodyPart(i); +// // 跳过附件 +// if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) { +// continue; +// } +// // 提取纯文本 +// extractPlainTextRecursive(bodyPart.getContent(), sb); +// } +// return; +// } +// +// // 处理单个BodyPart +// if (content instanceof MimeBodyPart bodyPart) { +// if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) { +// return; +// } +// // 读取纯文本内容 +// String partContent = readBodyPartContent(bodyPart); +// if (!partContent.isEmpty()) { +// sb.append(partContent).append("\n"); +// } +// } +// } +// +// /** +// * 标准化HTML结构(补全基本标签,确保格式合法) +// */ +// private static String standardizeHtml(String html) { +// if (html.isEmpty()) { +// return ""; +// } +// +// // 补全HTML基本结构 +// if (!html.startsWith("")) { +// html = "" + html + ""; +// } +// +// // 修复常见的HTML格式问题 +// html = html.replaceAll("
", "
") +// .replaceAll("


", "
") +// .replaceAll("&", "&") +// .replaceAll("

\\s*

", "") // 移除空p标签 +// .replaceAll(">\\s+<", "><"); // 移除标签间多余空格 +// +// return html; +// } +// +// /** +// * 读取BodyPart内容(优先原始流,自动识别编码) +// */ +// private static String readBodyPartContent(BodyPart part) throws Exception { +// // 1. 获取ContentType和编码 +// String contentType = part.getContentType() == null ? "" : part.getContentType().toLowerCase(); +// Charset charset = getCharsetFromContentType(contentType); +// +// // 2. 优先读取原始输入流(避免getContent()的自动转换错误) +// try (InputStream is = part.getInputStream(); +// BufferedInputStream bis = new BufferedInputStream(is); +// BufferedReader reader = new BufferedReader(new InputStreamReader(bis, charset))) { +// +// StringBuilder sb = new StringBuilder(); +// char[] buffer = new char[4096]; +// int bytesRead; +// while ((bytesRead = reader.read(buffer)) != -1) { +// sb.append(buffer, 0, bytesRead); +// } +// // 清理无效字符 +// return sb.toString(); +// } catch (Exception e) { +// logger.warn("读取BodyPart流失败:" + e.getMessage()); +// Object fallbackContent = part.getContent(); +// return fallbackContent instanceof String ? ((String) fallbackContent).trim() : ""; +// } +// } +// +// /** +// * 获取邮件内容 +// */ +// private static Charset getCharsetFromContentType(String contentType) { +// if (contentType == null || contentType.isEmpty()) { +// return StandardCharsets.UTF_8; +// } +// +// // 提取charset参数(支持多种格式) +// String charsetStr = null; +// String[] parts = contentType.split(";"); +// for (String part : parts) { +// part = part.trim().toLowerCase(); +// if (part.startsWith("charset=")) { +// charsetStr = part.substring("charset=".length()).trim() +// .replace("\"", "").replace("'", ""); +// break; +// } +// } +// +// // 验证编码有效性 +// if (charsetStr != null && !charsetStr.isEmpty()) { +// try { +// return Charset.forName(charsetStr); +// } catch (Exception e) { +// logger.warn("不支持的编码:" + charsetStr + ",使用默认UTF-8"); +// } +// } +// +// // 兜底编码(优先GBK,兼容中文邮件) +// try { +// return Charset.forName("GBK"); +// } catch (Exception e) { +// return StandardCharsets.UTF_8; +// } +// } +// +// /** +// * 解码MIME编码的文本(主题/发件人名称等) +// */ +// private static String decodeMimeText(String text) { +// if (text == null || text.isEmpty()) { +// return ""; +// } +// try { +// return MimeUtility.decodeText(text); +// } catch (UnsupportedEncodingException e) { +// // 多级降级处理 +// try { +// return new String(text.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); +// } catch (Exception e1) { +// try { +// return new String(text.getBytes(StandardCharsets.ISO_8859_1), "GBK"); +// } catch (Exception e2) { +// try { +// return new String(text.getBytes(StandardCharsets.ISO_8859_1), "GB2312"); +// } catch (Exception e3) { +// return text; +// } +// } +// } +// } +// } +// +// /** +// * 下载显式附件(保持原有逻辑) +// */ +// private static List downloadExplicitAttachments(Message message, String messageId, String saveBasePath) throws Exception { +// List attachments = new ArrayList<>(); +// if (!message.isMimeType("multipart/*")) { +// return attachments; +// } +// +// MimeMultipart multipart = (MimeMultipart) message.getContent(); +// File saveDir = new File(saveBasePath); +// if (!saveDir.exists()) { +// Files.createDirectories(saveDir.toPath()); +// } +// +// // 遍历所有显式附件 +// for (int i = 0; i < multipart.getCount(); i++) { +// BodyPart part = multipart.getBodyPart(i); +// if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) { +// try { +// BizMailAttachments attach = downloadSingleAttachment(part, messageId, saveDir); +// attachments.add(attach); +// } catch (Exception e) { +// logger.error("单附件下载失败(文件名:" + part.getFileName() + "):" + e.getMessage(), e); +// } +// } +// } +// +// return attachments; +// } +// +// /** +// * 下载单个附件(保持原有逻辑) +// */ +// private static BizMailAttachments downloadSingleAttachment(BodyPart part, String messageId, File saveDir) throws Exception { +// BizMailAttachments attachment = new BizMailAttachments(); +// +// // 1. 记录单个附件下载开始时间 +// long attachDownloadStartTime = System.currentTimeMillis(); +// String originalFileName = part.getFileName(); +// String fileNameForLog = originalFileName == null ? "未知文件名" : decodeMimeText(originalFileName); +// logger.info("开始下载附件[" + fileNameForLog + "],开始时间:" + new Date(attachDownloadStartTime)); +// // 2. 修复:文件名解码(解决乱码) +// if (originalFileName != null) { +// originalFileName = decodeMimeText(originalFileName); +// } else { +// originalFileName = "unknown_" + System.currentTimeMillis(); +// } +// // 3. 修复:附件FileType(优先从文件扩展名识别,解决ContentType错误) +// String fileExt = getFileExtension(originalFileName); +// String fileType = MIME_TYPE_MAP.getContentType(originalFileName); +// // 降级处理:如果MIME类型为空,使用BodyPart的ContentType +// if (fileType == null || fileType.isEmpty() || fileType.equals("application/octet-stream")) { +// fileType = part.getContentType().split(";")[0].trim(); // 去除charset等参数 +// } +// +// // 4. 计算MD5+保存文件 +// MessageDigest md = MessageDigest.getInstance("MD5"); +// ByteBuffer buffer = BUFFER_LOCAL.get(); +// buffer.clear(); +// +// // 临时文件 +// File tempFile = new File(saveDir, UUID.randomUUID().toString()); +// try (InputStream is = part.getInputStream(); +// FileChannel channel = FileChannel.open(tempFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE)) { +// +// int bytesRead; +// while ((bytesRead = is.read(buffer.array())) != -1) { +// md.update(buffer.array(), 0, bytesRead); +// buffer.limit(bytesRead); +// channel.write(buffer); +// buffer.clear(); +// } +// } +// +// // MD5命名(避免重名) +// String md5 = bytesToHex(md.digest()); +// File finalFile = new File(saveDir, md5 + (fileExt.isEmpty() ? "" : "." + fileExt)); +// +// // 处理文件已存在 +// if (finalFile.exists()) { +// logger.warn("附件已存在(MD5:" + md5 + "),跳过重复保存"); +// } else { +// if (!tempFile.renameTo(finalFile)) { +// logger.warn("附件重命名失败,使用临时文件名:" + tempFile.getName()); +// finalFile = tempFile; +// } +// } +// +// // 5. 记录单个附件下载结束时间 +// long attachDownloadEndTime = System.currentTimeMillis(); +// long costTime = attachDownloadEndTime - attachDownloadStartTime; +// logger.info("完成下载附件[" + originalFileName + "],结束时间:" + new Date(attachDownloadEndTime) + +// ",耗时:" + costTime + "ms,文件路径:" + finalFile.getAbsolutePath()); +// // 6. 封装附件信息(修复FileType,增加下载时间字段) +// attachment.setStoragePath(finalFile.getAbsolutePath()); +// attachment.setFileSize(finalFile.length()); +// attachment.setCreateTime(new Date()); +// attachment.setMailId(System.currentTimeMillis()); +// attachment.setMessageId(messageId); +// attachment.setFileName(originalFileName); +// attachment.setFileType(fileType); // 修复后的MIME类型 +// attachment.setFileExt(fileExt); +// attachment.setFileMd5(md5); +// attachment.setDownloadCount(0); +// attachment.setIsCompressed(isCompressedFile(originalFileName) ? "1" : "0"); +// attachment.setIsEncrypted("0"); +// attachment.setDownloadStartTime(new Date(attachDownloadStartTime)); // 附件下载开始时间 +// attachment.setDownloadEndTime(new Date(attachDownloadEndTime)); // 附件下载结束时间 +// attachment.setDownloadCostTime(costTime); // 附件下载耗时(毫秒) +// attachment.setSvgIcon(MyFileUtils.getIcon(fileExt)); +// return attachment; +// } +// +// /** +// * 判断是否有显式附件 +// */ +// private static boolean hasExplicitAttachment(Message message) throws Exception { +// if (!message.isMimeType("multipart/*")) { +// return false; +// } +// MimeMultipart multipart = (MimeMultipart) message.getContent(); +// for (int i = 0; i < multipart.getCount(); i++) { +// if (Part.ATTACHMENT.equalsIgnoreCase(multipart.getBodyPart(i).getDisposition())) { +// return true; +// } +// } +// return false; +// } +// +// // ------------------------ 工具方法 ------------------------ +// private static String getMessageId(Message message) throws MessagingException { +// String[] ids = message.getHeader("Message-ID"); +// if (ids != null && ids.length > 0) { +// return ids[0].replace("<", "").replace(">", "").trim(); +// } +// return UUID.randomUUID().toString() + "@" + message.getSession().getProperty("mail.imap.host"); +// } +// +// private static String convertAddresses(Address[] addresses) throws Exception { +// if (addresses == null || addresses.length == 0) { +// return ""; +// } +// StringBuilder sb = new StringBuilder(); +// for (Address addr : addresses) { +// sb.append(decodeMimeText(addr.toString())).append(","); +// } +// return !sb.isEmpty() ? sb.substring(0, sb.length() - 1) : ""; +// } +// +// private static String getFileExtension(String fileName) { +// if (fileName == null || !fileName.contains(".")) { +// return ""; +// } +// return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); +// } +// +// private static boolean isCompressedFile(String fileName) { +// Set exts = new HashSet<>(Arrays.asList("zip", "rar", "7z", "tar", "gz", "bz2")); +// return exts.contains(getFileExtension(fileName)); +// } +// +// private static String bytesToHex(byte[] bytes) { +// char[] hex = new char[bytes.length * 2]; +// for (int i = 0; i < bytes.length; i++) { +// int v = bytes[i] & 0xFF; +// hex[i * 2] = Character.forDigit(v >>> 4, 16); +// hex[i * 2 + 1] = Character.forDigit(v & 0x0F, 16); +// } +// return new String(hex).toLowerCase(); +// } +//} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/apps/utils/MailSendUtils.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/MailSendUtils.java new file mode 100644 index 0000000..927cddd --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/MailSendUtils.java @@ -0,0 +1,162 @@ +//package com.jeesite.modules.utils; +// +// +//import com.jeesite.modules.file.entity.FileUpload; +// +// +//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 final String FILE_PATH = "/ogsapp/files"; +// +// /** +// * 同步发送HTML格式邮件 +// * +// * @param mailAccount 邮件账户配置 +// * @param mailSent 邮件发送内容信息 +// * @return BizMailSent 填充发送结果后的对象 +// */ +// public static BizMailSent sendHtmlMail(BizMailAccount mailAccount, BizMailSent mailSent, List 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(upload.getFileName(), "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 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(); +// } +//} diff --git a/web-api/src/main/java/com/jeesite/modules/utils/MonitorUtil.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/MonitorUtil.java similarity index 99% rename from web-api/src/main/java/com/jeesite/modules/utils/MonitorUtil.java rename to web-api/src/main/java/com/jeesite/modules/apps/utils/MonitorUtil.java index 205adfd..89f0f5e 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/MonitorUtil.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/MonitorUtil.java @@ -1,4 +1,4 @@ -package com.jeesite.modules.utils; +package com.jeesite.modules.apps.utils; import com.jcraft.jsch.*; import com.jeesite.modules.apps.Module.MonitorResult; diff --git a/web-api/src/main/java/com/jeesite/modules/apps/utils/MysqlUtils.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/MysqlUtils.java new file mode 100644 index 0000000..915c98d --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/MysqlUtils.java @@ -0,0 +1,206 @@ +package com.jeesite.modules.apps.utils; + +import com.jeesite.modules.apps.Module.TableTree; +import com.jeesite.modules.biz.entity.MyDataColumn; +import com.jeesite.modules.biz.entity.MyDataSource; +import com.jeesite.modules.biz.entity.MyDataTable; + + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.sql.*; +import java.util.*; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MysqlUtils { + + private static final LoggerUtils logger = LoggerUtils.getInstance(); + // 需要排除的系统数据库 + private static final List SYSTEM_DATABASES = Arrays.asList( + "information_schema", "mysql", "performance_schema", "sys", "test" + ); + + // 提取字段长度的正则表达式(如varchar(50) -> 50) + private static final Pattern LENGTH_PATTERN = Pattern.compile("\\((\\d+)\\)"); + + /** + * 封装:获取MySQL数据库连接 + */ + private static Connection getConnection(String ip, Integer port, String username, String password) throws Exception { + String driver = "com.mysql.cj.jdbc.Driver"; + String jdbcUrl = String.format( + "jdbc:mysql://%s:%d/information_schema?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true", + ip, port + ); + Class.forName(driver); // 加载驱动 + return DriverManager.getConnection(jdbcUrl, username, password); + } + + /** + * 获取指定MySQL连接的所有非系统库表结构信息 + * + * @return 数据库名 -> 表信息列表(包含字段)的映射 + * @throws Exception 连接或查询异常 + */ + public static Map> getMysqlSchemaInfo(Connection conn) throws Exception { + Map> result = new HashMap<>(); + // 1. 获取所有非系统数据库 + List databases = getNonSystemDatabases(conn); + logger.info("获取到非系统数据库数量:", databases.size()); + // 2. 遍历数据库,获取表和字段信息 + for (String dbName : databases) { + List tableInfos = getTablesByDatabase(conn, dbName); + result.put(dbName, tableInfos); + } + return result; + } + + /** + * 获取所有非系统数据库 + */ + private static List getNonSystemDatabases(Connection conn) throws SQLException { + List databases = new ArrayList<>(); + String sql = "SELECT SCHEMA_NAME FROM SCHEMATA WHERE SCHEMA_NAME NOT IN (" + + String.join(",", Collections.nCopies(SYSTEM_DATABASES.size(), "?")) + ")"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + for (int i = 0; i < SYSTEM_DATABASES.size(); i++) { + ps.setString(i + 1, SYSTEM_DATABASES.get(i)); + } + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + databases.add(rs.getString("SCHEMA_NAME")); + } + } + } + return databases; + } + + /** + * 获取指定数据库下的所有表信息(包含字段) + */ + private static List getTablesByDatabase(Connection conn, String dbName) throws SQLException { + List tableInfos = new ArrayList<>(); + String tableSql = "SELECT " + + "TABLE_NAME, TABLE_COMMENT, CREATE_TIME, UPDATE_TIME, " + + "DATA_LENGTH, INDEX_LENGTH, TABLE_ROWS " + + "FROM TABLES WHERE TABLE_SCHEMA = ?"; + try (PreparedStatement tablePs = conn.prepareStatement(tableSql)) { + tablePs.setString(1, dbName); + try (ResultSet tableRs = tablePs.executeQuery()) { + while (tableRs.next()) { + MyDataTable tableInfo = buildDataTableInfo(tableRs, dbName); + List fields = getFieldsByTable(conn, dbName, tableInfo.getTableName()); + fields.forEach(field -> field.setTableId(tableInfo.getTableId())); + tableInfos.add(tableInfo); + } + } + } + return tableInfos; + } + + /** + * 构建DataTableInfo实体 + */ + private static MyDataTable buildDataTableInfo(ResultSet tableRs, String dbName) throws SQLException { + MyDataTable dataTable = new MyDataTable(); + String runTime = DateUtils.getCurrentDateTime(); + String createDate = tableRs.getString("CREATE_TIME"); + String updateDate = tableRs.getString("UPDATE_TIME"); + long dataLength = tableRs.getLong("DATA_LENGTH"); + long indexLength = tableRs.getLong("INDEX_LENGTH"); + BigDecimal tableSize = BigDecimal.valueOf((dataLength + indexLength) / 1024.0 / 1024.0) + .setScale(2, RoundingMode.HALF_UP); + + dataTable.setTableId(KeyUtil.ObjKey(32, 0)); + dataTable.setTableRows(tableRs.getLong("TABLE_ROWS")); + dataTable.setTableName(tableRs.getString("TABLE_NAME")); + dataTable.setTableComment(tableRs.getString("TABLE_COMMENT")); + dataTable.setTableSize(tableSize); + dataTable.setDataSource(dbName); + dataTable.setCreateTime(createDate != null ? createDate : runTime); + dataTable.setUpdateTime(updateDate != null ? updateDate : runTime); + dataTable.setDs(DateUtils.dsValue()); + return dataTable; + } + + /** + * 获取指定表的字段信息 + */ + private static List getFieldsByTable(Connection conn, String dbName, String tableName) throws SQLException { + List columns = new ArrayList<>(); + String fieldSql = "SELECT " + + "TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,DATA_TYPE, COLUMN_TYPE, COLUMN_COMMENT, " + + "ORDINAL_POSITION, CHARACTER_MAXIMUM_LENGTH " + + "FROM COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? " + + "ORDER BY ORDINAL_POSITION"; + try (PreparedStatement fieldPs = conn.prepareStatement(fieldSql)) { + fieldPs.setString(1, dbName); + fieldPs.setString(2, tableName); + try (ResultSet fieldRs = fieldPs.executeQuery()) { + while (fieldRs.next()) { + columns.add(buildDataTableField(fieldRs)); + } + } + } + return columns; + } + + /** + * 构建DataTableField实体 + */ + private static MyDataColumn buildDataTableField(ResultSet fieldRs) throws SQLException { + MyDataColumn column = new MyDataColumn(); + column.setColumnId(KeyUtil.ObjKey(32, 0)); + column.setTableSchema(fieldRs.getString("TABLE_SCHEMA")); + column.setTableName(fieldRs.getString("TABLE_NAME")); + column.setColumnName(fieldRs.getString("COLUMN_NAME")); + column.setDataType(fieldRs.getString("DATA_TYPE")); + column.setSort(fieldRs.getInt("ORDINAL_POSITION")); + column.setColumnComment(fieldRs.getString("COLUMN_COMMENT")); + Long length = fieldRs.getLong("CHARACTER_MAXIMUM_LENGTH"); + if (length == 0 || fieldRs.wasNull()) { + length = extractLengthFromType(fieldRs.getString("COLUMN_TYPE")); + } + column.setMaxLength(length); + column.setCreateTime(new Date()); + column.setDs(DateUtils.dsValue()); + return column; + } + + /** + * 从字段类型中提取长度(如int(11) -> 11) + */ + private static Long extractLengthFromType(String fieldType) { + if (fieldType == null) return null; + Matcher matcher = LENGTH_PATTERN.matcher(fieldType); + if (matcher.find()) { + try { + return Long.parseLong(matcher.group(1)); + } catch (NumberFormatException e) { + logger.warn("提取字段长度失败,类型", fieldType, e); + } + } + return null; + } + + public static List getTableTrees(MyDataSource dbConfig) { + List tableTrees = new ArrayList<>(); + try { + Connection conn = getConnection(dbConfig.getDbHost(), dbConfig.getDbPort(), dbConfig.getUsername(), dbConfig.getPassword()); + Map> schemaInfo = MysqlUtils.getMysqlSchemaInfo(conn); + for (Map.Entry> entry : schemaInfo.entrySet()) { + for (MyDataTable dataTable : entry.getValue()) { + dataTable.setSourceId(dbConfig.getId()); + List dataTableFields = getFieldsByTable(conn, entry.getKey(), dataTable.getTableName()); + dataTableFields.stream().forEach(tableField -> tableField.setTableId(dataTable.getTableId())); + tableTrees.add(new TableTree(dataTable, dataTableFields)); + } + } + } catch (Exception e) { + logger.error(e.getMessage()); + } + return tableTrees; + } +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/utils/PageUtil.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/PageUtil.java similarity index 97% rename from web-api/src/main/java/com/jeesite/modules/utils/PageUtil.java rename to web-api/src/main/java/com/jeesite/modules/apps/utils/PageUtil.java index ac692f2..77af1a2 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/PageUtil.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/PageUtil.java @@ -1,4 +1,4 @@ -package com.jeesite.modules.utils; +package com.jeesite.modules.apps.utils; import lombok.Data; diff --git a/web-api/src/main/java/com/jeesite/modules/utils/SftpUtil.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/SftpUtil.java similarity index 99% rename from web-api/src/main/java/com/jeesite/modules/utils/SftpUtil.java rename to web-api/src/main/java/com/jeesite/modules/apps/utils/SftpUtil.java index 34917cb..a725b72 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/SftpUtil.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/SftpUtil.java @@ -1,4 +1,4 @@ -package com.jeesite.modules.utils; +package com.jeesite.modules.apps.utils; import com.jcraft.jsch.*; import com.jeesite.modules.apps.Module.SftpResult; diff --git a/web-api/src/main/java/com/jeesite/modules/apps/utils/SqlUtils.java b/web-api/src/main/java/com/jeesite/modules/apps/utils/SqlUtils.java new file mode 100644 index 0000000..e63dd54 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/apps/utils/SqlUtils.java @@ -0,0 +1,84 @@ +package com.jeesite.modules.apps.utils; + + +import com.jeesite.modules.biz.entity.MyDataColumn; +import com.jeesite.modules.biz.entity.MyDataTable; + +import java.util.List; + +public class SqlUtils { + + + /** + * 生成CREATE TABLE语句 + * + * @return CREATE TABLE语句 + */ + public static String CreateTableSql(MyDataTable dataTable, List dataColumns) { + StringBuilder sb = new StringBuilder(); + // 表定义开始 + sb.append("CREATE TABLE ").append(dataTable.getTableName()).append(" (\n"); + // 拼接字段定义 + for (int i = 0; i < dataColumns.size(); i++) { + MyDataColumn dataColumn = dataColumns.get(i); + sb.append(" ").append(dataColumn.getColumnName()).append(" "); + // 处理字段类型和长度 + if (dataColumn.getMaxLength() != null && dataColumn.getMaxLength() > 0) { + sb.append(dataColumn.getMaxLength()).append("(").append(dataColumn.getMaxLength()).append(") "); + } else { + sb.append(dataColumn.getMaxLength()).append(" "); + } + + // 字段注释 + if (dataColumn.getColumnComment() != null && !dataColumn.getColumnComment().isEmpty()) { + sb.append("COMMENT '").append(dataColumn.getColumnComment()).append("'"); + } + + // 最后一个字段不加逗号 + if (i != dataColumns.size() - 1) { + sb.append(","); + } + sb.append("\n"); + } + // 表引擎和字符集 + sb.append(") "); + // 表注释 + if (dataTable.getTableComment() != null && !dataTable.getTableComment().isEmpty()) { + sb.append("COMMENT\t'").append(dataTable.getTableComment()).append("'"); + } + sb.append(";"); + + return sb.toString(); + } + + /** + * 生成带注释的SELECT语句 + * + * @return 带注释的SELECT语句 + */ + public static String SelectSqlComments(MyDataTable dataTable, List dataColumns) { + StringBuilder sb = new StringBuilder(); + // 表注释 + sb.append("-- 表名:").append(dataTable.getTableName()).append("\n"); + sb.append("-- 描述:").append(dataTable.getTableComment() != null ? dataTable.getTableComment() : "无").append("\n"); + sb.append("-- 数据来源:").append(dataTable.getDataSource() != null ? dataTable.getDataSource() : "未知").append("\n"); + // SELECT语句开始 + sb.append("SELECT\n"); + // 拼接字段(带注释) + for (int i = 0; i < dataColumns.size(); i++) { + MyDataColumn dataColumn = dataColumns.get(i); + // 拼接字段名 + sb.append(" ").append(dataColumn.getColumnName()); + if (i != dataColumns.size() - 1) { + sb.append(","); + } + if (dataColumn.getColumnComment() != null && !dataColumn.getColumnComment().isEmpty()) { + sb.append(" -- ").append(dataColumn.getColumnComment()); + } + sb.append("\n"); + } + // 表名 + sb.append("FROM ").append(dataTable.getTableName()).append("\n;"); + return sb.toString(); + } +} diff --git a/web-api/src/main/java/com/jeesite/modules/apps/web/desktop/AnalysisController.java b/web-api/src/main/java/com/jeesite/modules/apps/web/desktop/AnalysisController.java index a1d8866..578b686 100644 --- a/web-api/src/main/java/com/jeesite/modules/apps/web/desktop/AnalysisController.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/web/desktop/AnalysisController.java @@ -6,7 +6,7 @@ import cn.hutool.system.oshi.OshiUtil; import com.jeesite.modules.apps.Module.ChartInfo; import com.jeesite.modules.biz.entity.MyMunicipalities; import com.jeesite.modules.biz.service.MyMunicipalitiesService; -import com.jeesite.modules.utils.KeyUtil; +import com.jeesite.modules.apps.utils.KeyUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/web-api/src/main/java/com/jeesite/modules/apps/web/desktop/WorkbenchController.java b/web-api/src/main/java/com/jeesite/modules/apps/web/desktop/WorkbenchController.java index 639b3f8..51e0e42 100644 --- a/web-api/src/main/java/com/jeesite/modules/apps/web/desktop/WorkbenchController.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/web/desktop/WorkbenchController.java @@ -8,7 +8,7 @@ import com.jeesite.modules.sys.entity.DictData; import com.jeesite.modules.sys.entity.User; import com.jeesite.modules.sys.utils.DictUtils; import com.jeesite.modules.sys.utils.UserUtils; -import com.jeesite.modules.utils.DateUtils; +import com.jeesite.modules.apps.utils.DateUtils; import jakarta.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/web-api/src/main/java/com/jeesite/modules/apps/web/docker/myContainerController.java b/web-api/src/main/java/com/jeesite/modules/apps/web/docker/myContainerController.java index 9446709..3ecfb7a 100644 --- a/web-api/src/main/java/com/jeesite/modules/apps/web/docker/myContainerController.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/web/docker/myContainerController.java @@ -5,7 +5,7 @@ import com.jeesite.modules.apps.Module.DockerResult; import com.jeesite.modules.apps.Module.SystemInfo; import com.jeesite.modules.biz.dao.MySftpAccountsDao; import com.jeesite.modules.biz.entity.MySftpAccounts; -import com.jeesite.modules.utils.DockerUtil; +import com.jeesite.modules.apps.utils.DockerUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/web-api/src/main/java/com/jeesite/modules/apps/web/docker/myServerController.java b/web-api/src/main/java/com/jeesite/modules/apps/web/docker/myServerController.java index 0c51fdd..311cb98 100644 --- a/web-api/src/main/java/com/jeesite/modules/apps/web/docker/myServerController.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/web/docker/myServerController.java @@ -1,10 +1,8 @@ package com.jeesite.modules.apps.web.docker; import com.jeesite.modules.apps.Module.ServerInfo; -import com.jeesite.modules.apps.Module.SystemInfo; import com.jeesite.modules.biz.dao.MySftpAccountsDao; import com.jeesite.modules.biz.entity.MySftpAccounts; -import com.jeesite.modules.utils.DockerUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/web-api/src/main/java/com/jeesite/modules/apps/web/erp/BigScreenController.java b/web-api/src/main/java/com/jeesite/modules/apps/web/erp/BigScreenController.java index 9d41f0d..a6ea137 100644 --- a/web-api/src/main/java/com/jeesite/modules/apps/web/erp/BigScreenController.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/web/erp/BigScreenController.java @@ -4,8 +4,8 @@ import com.jeesite.modules.apps.Module.ChartDataItem; import com.jeesite.modules.apps.Module.ScreenTop; import com.jeesite.modules.erp.entity.ErpTransactionFlow; import com.jeesite.modules.erp.service.ErpTransactionFlowService; -import com.jeesite.modules.utils.BigDecimalUtils; -import com.jeesite.modules.utils.DateUtils; +import com.jeesite.modules.apps.utils.BigDecimalUtils; +import com.jeesite.modules.apps.utils.DateUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; diff --git a/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataColumnDao.java b/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataColumnDao.java new file mode 100644 index 0000000..48cc73d --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataColumnDao.java @@ -0,0 +1,15 @@ +package com.jeesite.modules.biz.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.biz.entity.MyDataColumn; + +/** + * 数据字段信息表 DAO 接口 + * @author gaoxq + * @version 2026-04-19 + */ +@MyBatisDao(dataSourceName="work") +public interface MyDataColumnDao extends CrudDao { + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataSourceDao.java b/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataSourceDao.java new file mode 100644 index 0000000..4ec5118 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataSourceDao.java @@ -0,0 +1,15 @@ +package com.jeesite.modules.biz.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.biz.entity.MyDataSource; + +/** + * 数据库配置 DAO 接口 + * @author gaoxq + * @version 2026-04-19 + */ +@MyBatisDao(dataSourceName="work") +public interface MyDataSourceDao extends CrudDao { + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataTableDao.java b/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataTableDao.java new file mode 100644 index 0000000..77b2e70 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/dao/MyDataTableDao.java @@ -0,0 +1,15 @@ +package com.jeesite.modules.biz.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.biz.entity.MyDataTable; + +/** + * 数据表信息表 DAO 接口 + * @author gaoxq + * @version 2026-04-19 + */ +@MyBatisDao(dataSourceName="work") +public interface MyDataTableDao extends CrudDao { + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataColumn.java b/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataColumn.java new file mode 100644 index 0000000..578e612 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataColumn.java @@ -0,0 +1,91 @@ +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 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; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.common.utils.excel.annotation.ExcelField; +import com.jeesite.common.utils.excel.annotation.ExcelField.Align; +import com.jeesite.common.utils.excel.annotation.ExcelFields; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; + +/** + * 数据字段信息表 Entity + * + * @author gaoxq + * @version 2026-04-19 + */ +@EqualsAndHashCode(callSuper = true) +@Table(name = "my_data_column", alias = "a", label = "字段信息表信息", columns = { + @Column(name = "create_time", attrName = "createTime", label = "创建时间", isUpdateForce = true), + @Column(name = "column_id", attrName = "columnId", label = "字段ID", isPK = true), + @Column(name = "table_id", attrName = "tableId", label = "所属表ID"), + @Column(name = "table_schema", attrName = "tableSchema", label = "数据库名称"), + @Column(name = "table_name", attrName = "tableName", label = "所属表名称"), + @Column(name = "column_name", attrName = "columnName", label = "字段名", queryType = QueryType.LIKE), + @Column(name = "column_comment", attrName = "columnComment", label = "字段注释"), + @Column(name = "column_type", attrName = "columnType", label = "字段类型"), + @Column(name = "data_type", attrName = "dataType", label = "数据类型"), + @Column(name = "max_length", attrName = "maxLength", label = "长度", isUpdateForce = true), + @Column(name = "is_nullable", attrName = "isNullable", label = "0非空 1可为空"), + @Column(name = "is_primary_key", attrName = "isPrimaryKey", label = "0否 1是主键"), + @Column(name = "sort", attrName = "sort", label = "排序", isUpdateForce = true), + @Column(name = "update_time", attrName = "updateTime", label = "更新日期", isUpdateForce = true), + @Column(name = "ds", attrName = "ds", label = "日期分区"), +}, orderBy = "a.column_id DESC" +) +@Data +public class MyDataColumn extends DataEntity implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + private Date createTime; // 创建时间 + private String columnId; // 字段ID + private String tableId; // 所属表ID + private String tableSchema; + private String tableName; + private String columnName; // 字段名 + private String columnComment; // 字段注释 + private String columnType; // 字段类型 + private String dataType; // 数据类型 + private Long maxLength; // 长度 + private String isNullable; // 0非空 1可为空 + private String isPrimaryKey; // 0否 1是主键 + private Integer sort; // 排序 + private Date updateTime; // 更新日期 + private String ds; + + @ExcelFields({ + @ExcelField(title = "创建时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"), + @ExcelField(title = "字段ID", attrName = "columnId", align = Align.CENTER, sort = 20), + @ExcelField(title = "所属表ID", attrName = "tableId", align = Align.CENTER, sort = 30), + @ExcelField(title = "字段名", attrName = "columnName", align = Align.CENTER, sort = 40), + @ExcelField(title = "字段注释", attrName = "columnComment", align = Align.CENTER, sort = 50), + @ExcelField(title = "字段类型", attrName = "columnType", align = Align.CENTER, sort = 60), + @ExcelField(title = "数据类型", attrName = "dataType", align = Align.CENTER, sort = 70), + @ExcelField(title = "长度", attrName = "maxLength", align = Align.CENTER, sort = 80), + @ExcelField(title = "0非空 1可为空", attrName = "isNullable", align = Align.CENTER, sort = 90), + @ExcelField(title = "0否 1是主键", attrName = "isPrimaryKey", align = Align.CENTER, sort = 100), + @ExcelField(title = "排序", attrName = "sort", align = Align.CENTER, sort = 110), + @ExcelField(title = "update_time", attrName = "updateTime", align = Align.CENTER, sort = 120, dataFormat = "yyyy-MM-dd hh:mm"), + }) + public MyDataColumn() { + this(null); + } + + public MyDataColumn(String id) { + super(id); + } +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataSource.java b/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataSource.java new file mode 100644 index 0000000..2236e45 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataSource.java @@ -0,0 +1,106 @@ +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 jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import jakarta.validation.constraints.NotNull; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.common.utils.excel.annotation.ExcelField; +import com.jeesite.common.utils.excel.annotation.ExcelField.Align; +import com.jeesite.common.utils.excel.annotation.ExcelFields; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; + +/** + * 数据库配置 Entity + * + * @author gaoxq + * @version 2026-04-19 + */ +@EqualsAndHashCode(callSuper = true) +@Table(name = "my_data_source", alias = "a", label = "数据库连接信息", columns = { + @Column(name = "create_time", attrName = "createTime", label = "创建时间", isUpdate = false, isUpdateForce = true), + @Column(name = "source_id", attrName = "sourceId", label = "主键ID", isPK = true), + @Column(name = "source_name", attrName = "sourceName", label = "连接名称", queryType = QueryType.LIKE), + @Column(name = "db_type", attrName = "dbType", label = "数据库类型"), + @Column(name = "db_host", attrName = "dbHost", label = "数据库IP"), + @Column(name = "db_port", attrName = "dbPort", label = "数据库端口", isQuery = false), + @Column(name = "db_name", attrName = "dbName", label = "数据库名称", queryType = QueryType.LIKE), + @Column(name = "username", attrName = "username", label = "账号", isQuery = false), + @Column(name = "password", attrName = "password", label = "密码", isQuery = false), + @Column(name = "params", attrName = "params", label = "连接参数", isQuery = false), + @Column(name = "remark", attrName = "remark", label = "备注说明", isQuery = false), + @Column(name = "ustatus", attrName = "ustatus", label = "状态"), + @Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true), +}, orderBy = "a.create_time DESC" +) +@Data +public class MyDataSource extends DataEntity implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + private Date createTime; // 创建时间 + private String sourceId; // 主键ID + private String sourceName; // 连接名称 + private String dbType; // 数据库类型 + private String dbHost; // 数据库IP + private Integer dbPort; // 数据库端口 + private String dbName; // 数据库名称 + private String username; // 账号 + private String password; // 密码 + private String params; // 连接参数 + private String remark; // 备注说明 + private String ustatus; // 状态 + private Date updateTime; // 更新时间 + + @ExcelFields({ + @ExcelField(title = "创建时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"), + @ExcelField(title = "主键ID", attrName = "sourceId", align = Align.CENTER, sort = 20), + @ExcelField(title = "连接名称", attrName = "sourceName", align = Align.CENTER, sort = 30), + @ExcelField(title = "数据库类型", attrName = "dbType", align = Align.CENTER, sort = 40), + @ExcelField(title = "数据库IP", attrName = "dbHost", align = Align.CENTER, sort = 50), + @ExcelField(title = "数据库端口", attrName = "dbPort", align = Align.CENTER, sort = 60), + @ExcelField(title = "数据库名称", attrName = "dbName", align = Align.CENTER, sort = 70), + @ExcelField(title = "账号", attrName = "username", align = Align.CENTER, sort = 80), + @ExcelField(title = "密码", attrName = "password", align = Align.CENTER, sort = 90), + @ExcelField(title = "连接参数", attrName = "params", align = Align.CENTER, sort = 100), + @ExcelField(title = "备注说明", attrName = "remark", align = Align.CENTER, sort = 110), + @ExcelField(title = "状态", attrName = "ustatus", align = Align.CENTER, sort = 120), + @ExcelField(title = "更新时间", attrName = "updateTime", align = Align.CENTER, sort = 130, dataFormat = "yyyy-MM-dd hh:mm"), + }) + public MyDataSource() { + this(null); + } + + public MyDataSource(String id) { + super(id); + } + + public Date getCreateTime_gte() { + return sqlMap.getWhere().getValue("create_time", QueryType.GTE); + } + + public void setCreateTime_gte(Date createTime) { + sqlMap.getWhere().and("create_time", QueryType.GTE, createTime); + } + + public Date getCreateTime_lte() { + return sqlMap.getWhere().getValue("create_time", QueryType.LTE); + } + + public void setCreateTime_lte(Date createTime) { + sqlMap.getWhere().and("create_time", QueryType.LTE, createTime); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataTable.java b/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataTable.java new file mode 100644 index 0000000..8ef6035 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/entity/MyDataTable.java @@ -0,0 +1,76 @@ +package com.jeesite.modules.biz.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +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 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; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.common.utils.excel.annotation.ExcelField; +import com.jeesite.common.utils.excel.annotation.ExcelField.Align; +import com.jeesite.common.utils.excel.annotation.ExcelFields; +import lombok.Data; + +import java.io.Serial; + +/** + * 数据表信息表 Entity + * + * @author gaoxq + * @version 2026-04-19 + */ +@Table(name = "my_data_table", alias = "a", label = "数据表信息信息", columns = { + @Column(name = "create_time", attrName = "createTime", label = "创建时间", isUpdate = false, isUpdateForce = true), + @Column(name = "table_id", attrName = "tableId", label = "表ID", isPK = true), + @Column(name = "source_id", attrName = "sourceId", label = "数据源ID"), + @Column(name = "table_name", attrName = "tableName", label = "数据表名", queryType = QueryType.LIKE), + @Column(name = "table_comment", attrName = "tableComment", label = "表注释"), + @Column(name = "table_rows", attrName = "tableRows", label = "数据行数"), + @Column(name = "table_size", attrName = "tableSize", label = "数据表大小"), + @Column(name = "update_time", attrName = "updateTime", label = "更新日期"), + @Column(name = "data_source", attrName = "dataSource", label = "数据库名称"), + @Column(name = "ds", attrName = "ds", label = "日期分区"), +}, orderBy = "a.create_time DESC" +) +@Data +public class MyDataTable extends DataEntity implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + private String createTime; // 创建时间 + private String tableId; // 表ID + private String sourceId; // 数据源ID + private String tableName; // 数据表名 + private String tableComment; // 表注释 + private Long tableRows; // 数据行数 + private BigDecimal tableSize; + private String updateTime; // 更新日期 + private String dataSource; + private String ds; + + @ExcelFields({ + @ExcelField(title = "创建时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"), + @ExcelField(title = "表ID", attrName = "tableId", align = Align.CENTER, sort = 20), + @ExcelField(title = "数据源ID", attrName = "sourceId", align = Align.CENTER, sort = 30), + @ExcelField(title = "数据表名", attrName = "tableName", align = Align.CENTER, sort = 40), + @ExcelField(title = "表注释", attrName = "tableComment", align = Align.CENTER, sort = 50), + @ExcelField(title = "数据行数", attrName = "tableRows", align = Align.CENTER, sort = 60), + @ExcelField(title = "update_time", attrName = "updateTime", align = Align.CENTER, sort = 70, dataFormat = "yyyy-MM-dd hh:mm"), + }) + public MyDataTable() { + this(null); + } + + public MyDataTable(String id) { + super(id); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataColumnService.java b/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataColumnService.java new file mode 100644 index 0000000..07e05d4 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataColumnService.java @@ -0,0 +1,134 @@ +package com.jeesite.modules.biz.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.biz.entity.MyDataColumn; +import com.jeesite.modules.biz.dao.MyDataColumnDao; +import com.jeesite.common.service.ServiceException; +import com.jeesite.common.config.Global; +import com.jeesite.common.validator.ValidatorUtils; +import com.jeesite.common.utils.excel.ExcelImport; +import org.springframework.web.multipart.MultipartFile; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; + +/** + * 数据字段信息表 Service + * @author gaoxq + * @version 2026-04-19 + */ +@Service +public class MyDataColumnService extends CrudService { + + /** + * 获取单条数据 + * @param myDataColumn 主键 + */ + @Override + public MyDataColumn get(MyDataColumn myDataColumn) { + return super.get(myDataColumn); + } + + /** + * 查询分页数据 + * @param myDataColumn 查询条件 + * @param myDataColumn page 分页对象 + */ + @Override + public Page findPage(MyDataColumn myDataColumn) { + return super.findPage(myDataColumn); + } + + /** + * 查询列表数据 + * @param myDataColumn 查询条件 + */ + @Override + public List findList(MyDataColumn myDataColumn) { + return super.findList(myDataColumn); + } + + /** + * 保存数据(插入或更新) + * @param myDataColumn 数据对象 + */ + @Override + @Transactional + public void save(MyDataColumn myDataColumn) { + super.save(myDataColumn); + } + + /** + * 导入数据 + * @param file 导入的数据文件 + */ + @Transactional + public String importData(MultipartFile file) { + if (file == null){ + throw new ServiceException(text("请选择导入的数据文件!")); + } + int successNum = 0; int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + try(ExcelImport ei = new ExcelImport(file, 2, 0)){ + List list = ei.getDataList(MyDataColumn.class); + for (MyDataColumn myDataColumn : list) { + try{ + ValidatorUtils.validateWithException(myDataColumn); + this.save(myDataColumn); + successNum++; + successMsg.append("
" + successNum + "、编号 " + myDataColumn.getId() + " 导入成功"); + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、编号 " + myDataColumn.getId() + " 导入失败:"; + if (e instanceof ConstraintViolationException){ + ConstraintViolationException cve = (ConstraintViolationException)e; + for (ConstraintViolation violation : cve.getConstraintViolations()) { + msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")"; + } + }else{ + msg += e.getMessage(); + } + failureMsg.append(msg); + logger.error(msg, e); + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + failureMsg.append(e.getMessage()); + return failureMsg.toString(); + } + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + }else{ + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + /** + * 更新状态 + * @param myDataColumn 数据对象 + */ + @Override + @Transactional + public void updateStatus(MyDataColumn myDataColumn) { + super.updateStatus(myDataColumn); + } + + /** + * 删除数据 + * @param myDataColumn 数据对象 + */ + @Override + @Transactional + public void delete(MyDataColumn myDataColumn) { + super.delete(myDataColumn); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataSourceService.java b/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataSourceService.java new file mode 100644 index 0000000..8836295 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataSourceService.java @@ -0,0 +1,134 @@ +package com.jeesite.modules.biz.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.biz.entity.MyDataSource; +import com.jeesite.modules.biz.dao.MyDataSourceDao; +import com.jeesite.common.service.ServiceException; +import com.jeesite.common.config.Global; +import com.jeesite.common.validator.ValidatorUtils; +import com.jeesite.common.utils.excel.ExcelImport; +import org.springframework.web.multipart.MultipartFile; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; + +/** + * 数据库配置 Service + * @author gaoxq + * @version 2026-04-19 + */ +@Service +public class MyDataSourceService extends CrudService { + + /** + * 获取单条数据 + * @param myDataSource 主键 + */ + @Override + public MyDataSource get(MyDataSource myDataSource) { + return super.get(myDataSource); + } + + /** + * 查询分页数据 + * @param myDataSource 查询条件 + * @param myDataSource page 分页对象 + */ + @Override + public Page findPage(MyDataSource myDataSource) { + return super.findPage(myDataSource); + } + + /** + * 查询列表数据 + * @param myDataSource 查询条件 + */ + @Override + public List findList(MyDataSource myDataSource) { + return super.findList(myDataSource); + } + + /** + * 保存数据(插入或更新) + * @param myDataSource 数据对象 + */ + @Override + @Transactional + public void save(MyDataSource myDataSource) { + super.save(myDataSource); + } + + /** + * 导入数据 + * @param file 导入的数据文件 + */ + @Transactional + public String importData(MultipartFile file) { + if (file == null){ + throw new ServiceException(text("请选择导入的数据文件!")); + } + int successNum = 0; int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + try(ExcelImport ei = new ExcelImport(file, 2, 0)){ + List list = ei.getDataList(MyDataSource.class); + for (MyDataSource myDataSource : list) { + try{ + ValidatorUtils.validateWithException(myDataSource); + this.save(myDataSource); + successNum++; + successMsg.append("
" + successNum + "、编号 " + myDataSource.getId() + " 导入成功"); + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、编号 " + myDataSource.getId() + " 导入失败:"; + if (e instanceof ConstraintViolationException){ + ConstraintViolationException cve = (ConstraintViolationException)e; + for (ConstraintViolation violation : cve.getConstraintViolations()) { + msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")"; + } + }else{ + msg += e.getMessage(); + } + failureMsg.append(msg); + logger.error(msg, e); + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + failureMsg.append(e.getMessage()); + return failureMsg.toString(); + } + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + }else{ + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + /** + * 更新状态 + * @param myDataSource 数据对象 + */ + @Override + @Transactional + public void updateStatus(MyDataSource myDataSource) { + super.updateStatus(myDataSource); + } + + /** + * 删除数据 + * @param myDataSource 数据对象 + */ + @Override + @Transactional + public void delete(MyDataSource myDataSource) { + super.delete(myDataSource); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataTableService.java b/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataTableService.java new file mode 100644 index 0000000..a33c673 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/service/MyDataTableService.java @@ -0,0 +1,134 @@ +package com.jeesite.modules.biz.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.biz.entity.MyDataTable; +import com.jeesite.modules.biz.dao.MyDataTableDao; +import com.jeesite.common.service.ServiceException; +import com.jeesite.common.config.Global; +import com.jeesite.common.validator.ValidatorUtils; +import com.jeesite.common.utils.excel.ExcelImport; +import org.springframework.web.multipart.MultipartFile; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; + +/** + * 数据表信息表 Service + * @author gaoxq + * @version 2026-04-19 + */ +@Service +public class MyDataTableService extends CrudService { + + /** + * 获取单条数据 + * @param myDataTable 主键 + */ + @Override + public MyDataTable get(MyDataTable myDataTable) { + return super.get(myDataTable); + } + + /** + * 查询分页数据 + * @param myDataTable 查询条件 + * @param myDataTable page 分页对象 + */ + @Override + public Page findPage(MyDataTable myDataTable) { + return super.findPage(myDataTable); + } + + /** + * 查询列表数据 + * @param myDataTable 查询条件 + */ + @Override + public List findList(MyDataTable myDataTable) { + return super.findList(myDataTable); + } + + /** + * 保存数据(插入或更新) + * @param myDataTable 数据对象 + */ + @Override + @Transactional + public void save(MyDataTable myDataTable) { + super.save(myDataTable); + } + + /** + * 导入数据 + * @param file 导入的数据文件 + */ + @Transactional + public String importData(MultipartFile file) { + if (file == null){ + throw new ServiceException(text("请选择导入的数据文件!")); + } + int successNum = 0; int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + try(ExcelImport ei = new ExcelImport(file, 2, 0)){ + List list = ei.getDataList(MyDataTable.class); + for (MyDataTable myDataTable : list) { + try{ + ValidatorUtils.validateWithException(myDataTable); + this.save(myDataTable); + successNum++; + successMsg.append("
" + successNum + "、编号 " + myDataTable.getId() + " 导入成功"); + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、编号 " + myDataTable.getId() + " 导入失败:"; + if (e instanceof ConstraintViolationException){ + ConstraintViolationException cve = (ConstraintViolationException)e; + for (ConstraintViolation violation : cve.getConstraintViolations()) { + msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")"; + } + }else{ + msg += e.getMessage(); + } + failureMsg.append(msg); + logger.error(msg, e); + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + failureMsg.append(e.getMessage()); + return failureMsg.toString(); + } + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + }else{ + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + /** + * 更新状态 + * @param myDataTable 数据对象 + */ + @Override + @Transactional + public void updateStatus(MyDataTable myDataTable) { + super.updateStatus(myDataTable); + } + + /** + * 删除数据 + * @param myDataTable 数据对象 + */ + @Override + @Transactional + public void delete(MyDataTable myDataTable) { + super.delete(myDataTable); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataColumnController.java b/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataColumnController.java new file mode 100644 index 0000000..6dd404f --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataColumnController.java @@ -0,0 +1,146 @@ +package com.jeesite.modules.biz.web; + +import java.util.List; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +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 com.jeesite.common.config.Global; +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.DateUtils; +import com.jeesite.common.utils.excel.ExcelExport; +import com.jeesite.common.utils.excel.annotation.ExcelField.Type; +import org.springframework.web.multipart.MultipartFile; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.biz.entity.MyDataColumn; +import com.jeesite.modules.biz.service.MyDataColumnService; + +/** + * 数据字段信息表 Controller + * @author gaoxq + * @version 2026-04-19 + */ +@Controller +@RequestMapping(value = "${adminPath}/biz/myDataColumn") +public class MyDataColumnController extends BaseController { + + private final MyDataColumnService myDataColumnService; + + public MyDataColumnController(MyDataColumnService myDataColumnService) { + this.myDataColumnService = myDataColumnService; + } + + /** + * 获取数据 + */ + @ModelAttribute + public MyDataColumn get(String columnId, boolean isNewRecord) { + return myDataColumnService.get(columnId, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("biz:myDataColumn:view") + @RequestMapping(value = {"list", ""}) + public String list(MyDataColumn myDataColumn, Model model) { + model.addAttribute("myDataColumn", myDataColumn); + return "modules/biz/myDataColumnList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("biz:myDataColumn:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page listData(MyDataColumn myDataColumn, HttpServletRequest request, HttpServletResponse response) { + myDataColumn.setPage(new Page<>(request, response)); + Page page = myDataColumnService.findPage(myDataColumn); + return page; + } + + /** + * 查看编辑表单 + */ + @RequiresPermissions("biz:myDataColumn:view") + @RequestMapping(value = "form") + public String form(MyDataColumn myDataColumn, Model model) { + model.addAttribute("myDataColumn", myDataColumn); + return "modules/biz/myDataColumnForm"; + } + + /** + * 保存数据 + */ + @RequiresPermissions("biz:myDataColumn:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated MyDataColumn myDataColumn) { + myDataColumnService.save(myDataColumn); + return renderResult(Global.TRUE, text("保存字段信息表成功!")); + } + + /** + * 导出数据 + */ + @RequiresPermissions("biz:myDataColumn:view") + @RequestMapping(value = "exportData") + public void exportData(MyDataColumn myDataColumn, HttpServletResponse response) { + List list = myDataColumnService.findList(myDataColumn); + String fileName = "字段信息表" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx"; + try(ExcelExport ee = new ExcelExport("字段信息表", MyDataColumn.class)){ + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 下载模板 + */ + @RequiresPermissions("biz:myDataColumn:view") + @RequestMapping(value = "importTemplate") + public void importTemplate(HttpServletResponse response) { + MyDataColumn myDataColumn = new MyDataColumn(); + List list = ListUtils.newArrayList(myDataColumn); + String fileName = "字段信息表模板.xlsx"; + try(ExcelExport ee = new ExcelExport("字段信息表", MyDataColumn.class, Type.IMPORT)){ + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 导入数据 + */ + @ResponseBody + @RequiresPermissions("biz:myDataColumn:edit") + @PostMapping(value = "importData") + public String importData(MultipartFile file) { + try { + String message = myDataColumnService.importData(file); + return renderResult(Global.TRUE, "posfull:"+message); + } catch (Exception ex) { + return renderResult(Global.FALSE, "posfull:"+ex.getMessage()); + } + } + + /** + * 删除数据 + */ + @RequiresPermissions("biz:myDataColumn:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(MyDataColumn myDataColumn) { + myDataColumnService.delete(myDataColumn); + return renderResult(Global.TRUE, text("删除字段信息表成功!")); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataSourceController.java b/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataSourceController.java new file mode 100644 index 0000000..159e4a4 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataSourceController.java @@ -0,0 +1,146 @@ +package com.jeesite.modules.biz.web; + +import java.util.List; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +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 com.jeesite.common.config.Global; +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.DateUtils; +import com.jeesite.common.utils.excel.ExcelExport; +import com.jeesite.common.utils.excel.annotation.ExcelField.Type; +import org.springframework.web.multipart.MultipartFile; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.biz.entity.MyDataSource; +import com.jeesite.modules.biz.service.MyDataSourceService; + +/** + * 数据库配置 Controller + * @author gaoxq + * @version 2026-04-19 + */ +@Controller +@RequestMapping(value = "${adminPath}/biz/myDataSource") +public class MyDataSourceController extends BaseController { + + private final MyDataSourceService myDataSourceService; + + public MyDataSourceController(MyDataSourceService myDataSourceService) { + this.myDataSourceService = myDataSourceService; + } + + /** + * 获取数据 + */ + @ModelAttribute + public MyDataSource get(String sourceId, boolean isNewRecord) { + return myDataSourceService.get(sourceId, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("biz:myDataSource:view") + @RequestMapping(value = {"list", ""}) + public String list(MyDataSource myDataSource, Model model) { + model.addAttribute("myDataSource", myDataSource); + return "modules/biz/myDataSourceList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("biz:myDataSource:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page listData(MyDataSource myDataSource, HttpServletRequest request, HttpServletResponse response) { + myDataSource.setPage(new Page<>(request, response)); + Page page = myDataSourceService.findPage(myDataSource); + return page; + } + + /** + * 查看编辑表单 + */ + @RequiresPermissions("biz:myDataSource:view") + @RequestMapping(value = "form") + public String form(MyDataSource myDataSource, Model model) { + model.addAttribute("myDataSource", myDataSource); + return "modules/biz/myDataSourceForm"; + } + + /** + * 保存数据 + */ + @RequiresPermissions("biz:myDataSource:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated MyDataSource myDataSource) { + myDataSourceService.save(myDataSource); + return renderResult(Global.TRUE, text("保存数据库连接成功!")); + } + + /** + * 导出数据 + */ + @RequiresPermissions("biz:myDataSource:view") + @RequestMapping(value = "exportData") + public void exportData(MyDataSource myDataSource, HttpServletResponse response) { + List list = myDataSourceService.findList(myDataSource); + String fileName = "数据库连接" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx"; + try(ExcelExport ee = new ExcelExport("数据库连接", MyDataSource.class)){ + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 下载模板 + */ + @RequiresPermissions("biz:myDataSource:view") + @RequestMapping(value = "importTemplate") + public void importTemplate(HttpServletResponse response) { + MyDataSource myDataSource = new MyDataSource(); + List list = ListUtils.newArrayList(myDataSource); + String fileName = "数据库连接模板.xlsx"; + try(ExcelExport ee = new ExcelExport("数据库连接", MyDataSource.class, Type.IMPORT)){ + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 导入数据 + */ + @ResponseBody + @RequiresPermissions("biz:myDataSource:edit") + @PostMapping(value = "importData") + public String importData(MultipartFile file) { + try { + String message = myDataSourceService.importData(file); + return renderResult(Global.TRUE, "posfull:"+message); + } catch (Exception ex) { + return renderResult(Global.FALSE, "posfull:"+ex.getMessage()); + } + } + + /** + * 删除数据 + */ + @RequiresPermissions("biz:myDataSource:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(MyDataSource myDataSource) { + myDataSourceService.delete(myDataSource); + return renderResult(Global.TRUE, text("删除数据库连接成功!")); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataTableController.java b/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataTableController.java new file mode 100644 index 0000000..8c8286c --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/web/MyDataTableController.java @@ -0,0 +1,146 @@ +package com.jeesite.modules.biz.web; + +import java.util.List; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +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 com.jeesite.common.config.Global; +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.DateUtils; +import com.jeesite.common.utils.excel.ExcelExport; +import com.jeesite.common.utils.excel.annotation.ExcelField.Type; +import org.springframework.web.multipart.MultipartFile; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.biz.entity.MyDataTable; +import com.jeesite.modules.biz.service.MyDataTableService; + +/** + * 数据表信息表 Controller + * @author gaoxq + * @version 2026-04-19 + */ +@Controller +@RequestMapping(value = "${adminPath}/biz/myDataTable") +public class MyDataTableController extends BaseController { + + private final MyDataTableService myDataTableService; + + public MyDataTableController(MyDataTableService myDataTableService) { + this.myDataTableService = myDataTableService; + } + + /** + * 获取数据 + */ + @ModelAttribute + public MyDataTable get(String tableId, boolean isNewRecord) { + return myDataTableService.get(tableId, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("biz:myDataTable:view") + @RequestMapping(value = {"list", ""}) + public String list(MyDataTable myDataTable, Model model) { + model.addAttribute("myDataTable", myDataTable); + return "modules/biz/myDataTableList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("biz:myDataTable:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page listData(MyDataTable myDataTable, HttpServletRequest request, HttpServletResponse response) { + myDataTable.setPage(new Page<>(request, response)); + Page page = myDataTableService.findPage(myDataTable); + return page; + } + + /** + * 查看编辑表单 + */ + @RequiresPermissions("biz:myDataTable:view") + @RequestMapping(value = "form") + public String form(MyDataTable myDataTable, Model model) { + model.addAttribute("myDataTable", myDataTable); + return "modules/biz/myDataTableForm"; + } + + /** + * 保存数据 + */ + @RequiresPermissions("biz:myDataTable:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated MyDataTable myDataTable) { + myDataTableService.save(myDataTable); + return renderResult(Global.TRUE, text("保存数据表信息成功!")); + } + + /** + * 导出数据 + */ + @RequiresPermissions("biz:myDataTable:view") + @RequestMapping(value = "exportData") + public void exportData(MyDataTable myDataTable, HttpServletResponse response) { + List list = myDataTableService.findList(myDataTable); + String fileName = "数据表信息" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx"; + try(ExcelExport ee = new ExcelExport("数据表信息", MyDataTable.class)){ + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 下载模板 + */ + @RequiresPermissions("biz:myDataTable:view") + @RequestMapping(value = "importTemplate") + public void importTemplate(HttpServletResponse response) { + MyDataTable myDataTable = new MyDataTable(); + List list = ListUtils.newArrayList(myDataTable); + String fileName = "数据表信息模板.xlsx"; + try(ExcelExport ee = new ExcelExport("数据表信息", MyDataTable.class, Type.IMPORT)){ + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 导入数据 + */ + @ResponseBody + @RequiresPermissions("biz:myDataTable:edit") + @PostMapping(value = "importData") + public String importData(MultipartFile file) { + try { + String message = myDataTableService.importData(file); + return renderResult(Global.TRUE, "posfull:"+message); + } catch (Exception ex) { + return renderResult(Global.FALSE, "posfull:"+ex.getMessage()); + } + } + + /** + * 删除数据 + */ + @RequiresPermissions("biz:myDataTable:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(MyDataTable myDataTable) { + myDataTableService.delete(myDataTable); + return renderResult(Global.TRUE, text("删除数据表信息成功!")); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/web/MyProjectInfoController.java b/web-api/src/main/java/com/jeesite/modules/biz/web/MyProjectInfoController.java index 84f85ad..7ebbaf3 100644 --- a/web-api/src/main/java/com/jeesite/modules/biz/web/MyProjectInfoController.java +++ b/web-api/src/main/java/com/jeesite/modules/biz/web/MyProjectInfoController.java @@ -5,7 +5,7 @@ import java.util.List; import com.jeesite.modules.apps.Module.PageResult; import com.jeesite.modules.apps.Module.Table.MyProjectParams; -import com.jeesite.modules.utils.PageUtil; +import com.jeesite.modules.apps.utils.PageUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/web-api/src/main/java/com/jeesite/modules/erp/web/ErpTransactionFlowController.java b/web-api/src/main/java/com/jeesite/modules/erp/web/ErpTransactionFlowController.java index 96752c8..687eb67 100644 --- a/web-api/src/main/java/com/jeesite/modules/erp/web/ErpTransactionFlowController.java +++ b/web-api/src/main/java/com/jeesite/modules/erp/web/ErpTransactionFlowController.java @@ -4,7 +4,7 @@ import java.util.List; import com.jeesite.modules.apps.Module.Table.ErpFlowParams; import com.jeesite.modules.apps.Module.PageResult; -import com.jeesite.modules.utils.PageUtil; +import com.jeesite.modules.apps.utils.PageUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; diff --git a/web-api/src/main/resources/mappings/modules/biz/MyDataColumnDao.xml b/web-api/src/main/resources/mappings/modules/biz/MyDataColumnDao.xml new file mode 100644 index 0000000..af45635 --- /dev/null +++ b/web-api/src/main/resources/mappings/modules/biz/MyDataColumnDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/web-api/src/main/resources/mappings/modules/biz/MyDataSourceDao.xml b/web-api/src/main/resources/mappings/modules/biz/MyDataSourceDao.xml new file mode 100644 index 0000000..41d9106 --- /dev/null +++ b/web-api/src/main/resources/mappings/modules/biz/MyDataSourceDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/web-api/src/main/resources/mappings/modules/biz/MyDataTableDao.xml b/web-api/src/main/resources/mappings/modules/biz/MyDataTableDao.xml new file mode 100644 index 0000000..048565d --- /dev/null +++ b/web-api/src/main/resources/mappings/modules/biz/MyDataTableDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/web-vue/packages/biz/api/biz/myDataColumn.ts b/web-vue/packages/biz/api/biz/myDataColumn.ts new file mode 100644 index 0000000..ee69176 --- /dev/null +++ b/web-vue/packages/biz/api/biz/myDataColumn.ts @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2013-Now https://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + * @author gaoxq + */ +import { defHttp } from '@jeesite/core/utils/http/axios'; +import { useGlobSetting } from '@jeesite/core/hooks/setting'; +import { BasicModel, Page } from '@jeesite/core/api/model/baseModel'; +import { UploadApiResult } from '@jeesite/core/api/sys/upload'; +import { UploadFileParams } from '@jeesite/types/axios'; +import { AxiosProgressEvent } from 'axios'; + +const { ctxPath, adminPath } = useGlobSetting(); + +export interface MyDataColumn extends BasicModel { + createTime?: string; // 创建时间 + columnId?: string; // 字段ID + tableId: string; // 所属表ID + columnName: string; // 字段名 + columnComment?: string; // 字段注释 + columnType: string; // 字段类型 + dataType?: string; // 数据类型 + maxLength?: number; // 长度 + isNullable?: string; // 0非空 1可为空 + isPrimaryKey?: string; // 0否 1是主键 + sort?: number; // 排序 + updateTime?: string; // update_time +} + +export const myDataColumnList = (params?: MyDataColumn | any) => + defHttp.get({ url: adminPath + '/biz/myDataColumn/list', params }); + +export const myDataColumnListData = (params?: MyDataColumn | any) => + defHttp.post>({ url: adminPath + '/biz/myDataColumn/listData', params }); + +export const myDataColumnForm = (params?: MyDataColumn | any) => + defHttp.get({ url: adminPath + '/biz/myDataColumn/form', params }); + +export const myDataColumnSave = (params?: any, data?: MyDataColumn | any) => + defHttp.postJson({ url: adminPath + '/biz/myDataColumn/save', params, data }); + +export const myDataColumnImportData = ( + params: UploadFileParams, + onUploadProgress: (progressEvent: AxiosProgressEvent) => void, +) => + defHttp.uploadFile( + { + url: ctxPath + adminPath + '/biz/myDataColumn/importData', + onUploadProgress, + }, + params, + ); + +export const myDataColumnDelete = (params?: MyDataColumn | any) => + defHttp.get({ url: adminPath + '/biz/myDataColumn/delete', params }); diff --git a/web-vue/packages/biz/api/biz/myDataSource.ts b/web-vue/packages/biz/api/biz/myDataSource.ts new file mode 100644 index 0000000..db8577d --- /dev/null +++ b/web-vue/packages/biz/api/biz/myDataSource.ts @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2013-Now https://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + * @author gaoxq + */ +import { defHttp } from '@jeesite/core/utils/http/axios'; +import { useGlobSetting } from '@jeesite/core/hooks/setting'; +import { BasicModel, Page } from '@jeesite/core/api/model/baseModel'; +import { UploadApiResult } from '@jeesite/core/api/sys/upload'; +import { UploadFileParams } from '@jeesite/types/axios'; +import { AxiosProgressEvent } from 'axios'; + +const { ctxPath, adminPath } = useGlobSetting(); + +export interface MyDataSource extends BasicModel { + createTime?: string; // 创建时间 + sourceId?: string; // 主键ID + sourceName: string; // 连接名称 + dbType: string; // 数据库类型 + dbHost: string; // 数据库IP + dbPort: number; // 数据库端口 + dbName: string; // 数据库名称 + username: string; // 账号 + password?: string; // 密码 + params?: string; // 连接参数 + remark?: string; // 备注说明 + ustatus: string; // 状态 + updateTime?: string; // 更新时间 +} + +export const myDataSourceList = (params?: MyDataSource | any) => + defHttp.get({ url: adminPath + '/biz/myDataSource/list', params }); + +export const myDataSourceListData = (params?: MyDataSource | any) => + defHttp.post>({ url: adminPath + '/biz/myDataSource/listData', params }); + +export const myDataSourceForm = (params?: MyDataSource | any) => + defHttp.get({ url: adminPath + '/biz/myDataSource/form', params }); + +export const myDataSourceSave = (params?: any, data?: MyDataSource | any) => + defHttp.postJson({ url: adminPath + '/biz/myDataSource/save', params, data }); + +export const myDataSourceImportData = ( + params: UploadFileParams, + onUploadProgress: (progressEvent: AxiosProgressEvent) => void, +) => + defHttp.uploadFile( + { + url: ctxPath + adminPath + '/biz/myDataSource/importData', + onUploadProgress, + }, + params, + ); + +export const myDataSourceDelete = (params?: MyDataSource | any) => + defHttp.get({ url: adminPath + '/biz/myDataSource/delete', params }); diff --git a/web-vue/packages/biz/api/biz/myDataTable.ts b/web-vue/packages/biz/api/biz/myDataTable.ts new file mode 100644 index 0000000..538c1ce --- /dev/null +++ b/web-vue/packages/biz/api/biz/myDataTable.ts @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2013-Now https://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + * @author gaoxq + */ +import { defHttp } from '@jeesite/core/utils/http/axios'; +import { useGlobSetting } from '@jeesite/core/hooks/setting'; +import { BasicModel, Page } from '@jeesite/core/api/model/baseModel'; +import { UploadApiResult } from '@jeesite/core/api/sys/upload'; +import { UploadFileParams } from '@jeesite/types/axios'; +import { AxiosProgressEvent } from 'axios'; + +const { ctxPath, adminPath } = useGlobSetting(); + +export interface MyDataTable extends BasicModel { + createTime?: string; // 创建时间 + tableId?: string; // 表ID + sourceId: string; // 数据源ID + tableName: string; // 数据表名 + tableComment?: string; // 表注释 + tableRows?: number; // 数据行数 + updateTime?: string; // update_time +} + +export const myDataTableList = (params?: MyDataTable | any) => + defHttp.get({ url: adminPath + '/biz/myDataTable/list', params }); + +export const myDataTableListData = (params?: MyDataTable | any) => + defHttp.post>({ url: adminPath + '/biz/myDataTable/listData', params }); + +export const myDataTableForm = (params?: MyDataTable | any) => + defHttp.get({ url: adminPath + '/biz/myDataTable/form', params }); + +export const myDataTableSave = (params?: any, data?: MyDataTable | any) => + defHttp.postJson({ url: adminPath + '/biz/myDataTable/save', params, data }); + +export const myDataTableImportData = ( + params: UploadFileParams, + onUploadProgress: (progressEvent: AxiosProgressEvent) => void, +) => + defHttp.uploadFile( + { + url: ctxPath + adminPath + '/biz/myDataTable/importData', + onUploadProgress, + }, + params, + ); + +export const myDataTableDelete = (params?: MyDataTable | any) => + defHttp.get({ url: adminPath + '/biz/myDataTable/delete', params }); diff --git a/web-vue/packages/biz/views/biz/myScreen/components/ChartTop.vue b/web-vue/packages/biz/views/biz/myBizScreen/components/ChartTop.vue similarity index 100% rename from web-vue/packages/biz/views/biz/myScreen/components/ChartTop.vue rename to web-vue/packages/biz/views/biz/myBizScreen/components/ChartTop.vue diff --git a/web-vue/packages/biz/views/biz/myScreen/index.vue b/web-vue/packages/biz/views/biz/myBizScreen/index.vue similarity index 61% rename from web-vue/packages/biz/views/biz/myScreen/index.vue rename to web-vue/packages/biz/views/biz/myBizScreen/index.vue index 7970c60..ff5c278 100644 --- a/web-vue/packages/biz/views/biz/myScreen/index.vue +++ b/web-vue/packages/biz/views/biz/myBizScreen/index.vue @@ -3,27 +3,26 @@
-
- -
+
+ +
-
-
-
-
左上左区域
-
左上右区域
+
+
+
+
左上左区域
+
左上右区域
- -
-
左下左区域
-
左下右区域
+
+
左下左区域
+
左下右区域
-
@@ -32,9 +31,9 @@ - diff --git a/web-vue/packages/biz/views/biz/myDataColumn/form.vue b/web-vue/packages/biz/views/biz/myDataColumn/form.vue new file mode 100644 index 0000000..7d14158 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataColumn/form.vue @@ -0,0 +1,175 @@ + + + diff --git a/web-vue/packages/biz/views/biz/myDataColumn/formImport.vue b/web-vue/packages/biz/views/biz/myDataColumn/formImport.vue new file mode 100644 index 0000000..0245d36 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataColumn/formImport.vue @@ -0,0 +1,103 @@ + + + diff --git a/web-vue/packages/biz/views/biz/myDataColumn/list.vue b/web-vue/packages/biz/views/biz/myDataColumn/list.vue new file mode 100644 index 0000000..285461e --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataColumn/list.vue @@ -0,0 +1,297 @@ + + + diff --git a/web-vue/packages/biz/views/biz/myDataColumn/select.ts b/web-vue/packages/biz/views/biz/myDataColumn/select.ts new file mode 100644 index 0000000..9cdf2c3 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataColumn/select.ts @@ -0,0 +1,190 @@ +import { useI18n } from '@jeesite/core/hooks/web/useI18n'; +import { BasicColumn, BasicTableProps, FormProps } from '@jeesite/core/components/Table'; +import { myDataColumnListData } from '@jeesite/biz/api/biz/myDataColumn'; + +const { t } = useI18n('biz.myDataColumn'); + +const modalProps = { + title: t('字段信息表选择'), +}; + +const searchForm: FormProps = { + baseColProps: { md: 8, lg: 6 }, + labelWidth: 90, + schemas: [ + { + label: t('创建时间'), + field: 'createTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD HH:mm', + showTime: { format: 'HH:mm' }, + }, + }, + { + label: t('所属表ID'), + field: 'tableId', + component: 'Input', + }, + { + label: t('字段名'), + field: 'columnName', + component: 'Input', + }, + { + label: t('字段注释'), + field: 'columnComment', + component: 'Input', + }, + { + label: t('字段类型'), + field: 'columnType', + component: 'Input', + }, + { + label: t('数据类型'), + field: 'dataType', + component: 'Input', + }, + { + label: t('长度'), + field: 'maxLength', + component: 'Input', + }, + { + label: t('0非空 1可为空'), + field: 'isNullable', + component: 'Input', + }, + { + label: t('0否 1是主键'), + field: 'isPrimaryKey', + component: 'Input', + }, + { + label: t('排序'), + field: 'sort', + component: 'Input', + }, + { + label: t('update_time'), + field: 'updateTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD HH:mm', + showTime: { format: 'HH:mm' }, + }, + }, + ], +}; + +const tableColumns: BasicColumn[] = [ + { + title: t('创建时间'), + dataIndex: 'createTime', + key: 'a.create_time', + sorter: true, + width: 230, + align: 'left', + slot: 'firstColumn', + }, + { + title: t('所属表ID'), + dataIndex: 'tableId', + key: 'a.table_id', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('字段名'), + dataIndex: 'columnName', + key: 'a.column_name', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('字段注释'), + dataIndex: 'columnComment', + key: 'a.column_comment', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('字段类型'), + dataIndex: 'columnType', + key: 'a.column_type', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('数据类型'), + dataIndex: 'dataType', + key: 'a.data_type', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('长度'), + dataIndex: 'maxLength', + key: 'a.max_length', + sorter: true, + width: 130, + align: 'center', + }, + { + title: t('0非空 1可为空'), + dataIndex: 'isNullable', + key: 'a.is_nullable', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('0否 1是主键'), + dataIndex: 'isPrimaryKey', + key: 'a.is_primary_key', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('排序'), + dataIndex: 'sort', + key: 'a.sort', + sorter: true, + width: 130, + align: 'center', + }, + { + title: t('update_time'), + dataIndex: 'updateTime', + key: 'a.update_time', + sorter: true, + width: 130, + align: 'center', + }, +]; + +const tableProps: BasicTableProps = { + api: myDataColumnListData, + beforeFetch: (params) => { + params['isAll'] = true; + return params; + }, + columns: tableColumns, + formConfig: searchForm, + rowKey: 'columnId', +}; + +export default { + modalProps, + tableProps, + itemCode: 'columnId', + itemName: 'columnId', + isShowCode: false, +}; diff --git a/web-vue/packages/biz/views/biz/myDataSource/form.vue b/web-vue/packages/biz/views/biz/myDataSource/form.vue new file mode 100644 index 0000000..d184ff9 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataSource/form.vue @@ -0,0 +1,187 @@ + + + diff --git a/web-vue/packages/biz/views/biz/myDataSource/list.vue b/web-vue/packages/biz/views/biz/myDataSource/list.vue new file mode 100644 index 0000000..6d7b281 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataSource/list.vue @@ -0,0 +1,275 @@ + + + diff --git a/web-vue/packages/biz/views/biz/myDataSource/select.ts b/web-vue/packages/biz/views/biz/myDataSource/select.ts new file mode 100644 index 0000000..576fd32 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataSource/select.ts @@ -0,0 +1,178 @@ +import { useI18n } from '@jeesite/core/hooks/web/useI18n'; +import { BasicColumn, BasicTableProps, FormProps } from '@jeesite/core/components/Table'; +import { myDataSourceListData } from '@jeesite/biz/api/biz/myDataSource'; + +const { t } = useI18n('biz.myDataSource'); + +const modalProps = { + title: t('数据库连接选择'), +}; + +const searchForm: FormProps = { + 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: 'sourceName', + component: 'Input', + }, + { + label: t('数据库类型'), + field: 'dbType', + component: 'Input', + }, + { + label: t('数据库IP'), + field: 'dbHost', + component: 'Input', + }, + { + label: t('数据库名称'), + field: 'dbName', + component: 'Input', + }, + { + label: t('状态'), + field: 'ustatus', + component: 'Input', + }, + ], +}; + +const tableColumns: BasicColumn[] = [ + { + title: t('创建时间'), + dataIndex: 'createTime', + key: 'a.create_time', + sorter: true, + width: 230, + align: 'left', + slot: 'firstColumn', + }, + { + title: t('连接名称'), + dataIndex: 'sourceName', + key: 'a.source_name', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('数据库类型'), + dataIndex: 'dbType', + key: 'a.db_type', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('数据库IP'), + dataIndex: 'dbHost', + key: 'a.db_host', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('数据库端口'), + dataIndex: 'dbPort', + key: 'a.db_port', + sorter: true, + width: 130, + align: 'center', + }, + { + title: t('数据库名称'), + dataIndex: 'dbName', + key: 'a.db_name', + sorter: true, + width: 130, + align: 'left', + }, + { + 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: 'params', + key: 'a.params', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('备注说明'), + dataIndex: 'remark', + key: 'a.remark', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('状态'), + dataIndex: 'ustatus', + key: 'a.ustatus', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('更新时间'), + dataIndex: 'updateTime', + key: 'a.update_time', + sorter: true, + width: 130, + align: 'center', + }, +]; + +const tableProps: BasicTableProps = { + api: myDataSourceListData, + beforeFetch: (params) => { + params['isAll'] = true; + return params; + }, + columns: tableColumns, + formConfig: searchForm, + rowKey: 'sourceId', +}; + +export default { + modalProps, + tableProps, + itemCode: 'sourceId', + itemName: 'sourceId', + isShowCode: false, +}; diff --git a/web-vue/packages/biz/views/biz/myDataTable/form.vue b/web-vue/packages/biz/views/biz/myDataTable/form.vue new file mode 100644 index 0000000..ff41096 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataTable/form.vue @@ -0,0 +1,134 @@ + + + diff --git a/web-vue/packages/biz/views/biz/myDataTable/formImport.vue b/web-vue/packages/biz/views/biz/myDataTable/formImport.vue new file mode 100644 index 0000000..e813970 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataTable/formImport.vue @@ -0,0 +1,103 @@ + + + diff --git a/web-vue/packages/biz/views/biz/myDataTable/list.vue b/web-vue/packages/biz/views/biz/myDataTable/list.vue new file mode 100644 index 0000000..cc53b90 --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataTable/list.vue @@ -0,0 +1,232 @@ + + + diff --git a/web-vue/packages/biz/views/biz/myDataTable/select.ts b/web-vue/packages/biz/views/biz/myDataTable/select.ts new file mode 100644 index 0000000..163a17b --- /dev/null +++ b/web-vue/packages/biz/views/biz/myDataTable/select.ts @@ -0,0 +1,125 @@ +import { useI18n } from '@jeesite/core/hooks/web/useI18n'; +import { BasicColumn, BasicTableProps, FormProps } from '@jeesite/core/components/Table'; +import { myDataTableListData } from '@jeesite/biz/api/biz/myDataTable'; + +const { t } = useI18n('biz.myDataTable'); + +const modalProps = { + title: t('数据表信息选择'), +}; + +const searchForm: FormProps = { + baseColProps: { md: 8, lg: 6 }, + labelWidth: 90, + schemas: [ + { + label: t('创建时间'), + field: 'createTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD HH:mm', + showTime: { format: 'HH:mm' }, + }, + }, + { + label: t('数据源ID'), + field: 'sourceId', + component: 'Input', + }, + { + label: t('数据表名'), + field: 'tableName', + component: 'Input', + }, + { + label: t('表注释'), + field: 'tableComment', + component: 'Input', + }, + { + label: t('数据行数'), + field: 'tableRows', + component: 'Input', + }, + { + label: t('update_time'), + field: 'updateTime', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD HH:mm', + showTime: { format: 'HH:mm' }, + }, + }, + ], +}; + +const tableColumns: BasicColumn[] = [ + { + title: t('创建时间'), + dataIndex: 'createTime', + key: 'a.create_time', + sorter: true, + width: 230, + align: 'left', + slot: 'firstColumn', + }, + { + title: t('数据源ID'), + dataIndex: 'sourceId', + key: 'a.source_id', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('数据表名'), + dataIndex: 'tableName', + key: 'a.table_name', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('表注释'), + dataIndex: 'tableComment', + key: 'a.table_comment', + sorter: true, + width: 130, + align: 'left', + }, + { + title: t('数据行数'), + dataIndex: 'tableRows', + key: 'a.table_rows', + sorter: true, + width: 130, + align: 'center', + }, + { + title: t('update_time'), + dataIndex: 'updateTime', + key: 'a.update_time', + sorter: true, + width: 130, + align: 'center', + }, +]; + +const tableProps: BasicTableProps = { + api: myDataTableListData, + beforeFetch: (params) => { + params['isAll'] = true; + return params; + }, + columns: tableColumns, + formConfig: searchForm, + rowKey: 'tableId', +}; + +export default { + modalProps, + tableProps, + itemCode: 'tableId', + itemName: 'tableId', + isShowCode: false, +};