diff --git a/download.md b/download.md index 96b32fc2..e1d42d80 100644 --- a/download.md +++ b/download.md @@ -3,6 +3,8 @@
Windows +[WePush-v3.5.0_190713-x64-Setup.exe](http://download.zhoubochina.com/exe/WePush-v3.5.0_190713-x64-Setup.exe) +[WePush-with-jre-v3.5.0_190713-x64-Setup.exe](http://download.zhoubochina.com/exe/WePush-with-jre-v3.5.0_190713-x64-Setup.exe) [WePush-v3.4.2_190630-x64-Setup.exe](http://download.zhoubochina.com/exe/WePush-v3.4.2_190630-x64-Setup.exe) [WePush-with-jre-v3.4.2_190630-x64-Setup.exe](http://download.zhoubochina.com/exe/WePush-with-jre-v3.4.2_190630-x64-Setup.exe) [WePush-v3.4.1_190624-x64-Setup.exe](http://download.zhoubochina.com/exe/WePush-v3.4.1_190624-x64-Setup.exe) @@ -59,6 +61,7 @@
Mac OS +[v_3.5.0_190713.app](http://download.zhoubochina.com/mac/3.5.0.zip) [v_3.4.1_190624.app](http://download.zhoubochina.com/mac/3.4.1.zip) [v_3.4.2_190630.app](http://download.zhoubochina.com/mac/3.4.2.zip) [v_3.4.0_190619.app](http://download.zhoubochina.com/mac/3.4.0.zip) @@ -95,6 +98,7 @@
Linux +[v3.5.0_190713](http://download.zhoubochina.com/linux/WePush-3.5.0.zip) [v3.4.2_190630](http://download.zhoubochina.com/linux/WePush-3.4.2.zip) [v3.4.1_190624](http://download.zhoubochina.com/linux/WePush-3.4.1.zip) [v3.4.0_190619](http://download.zhoubochina.com/linux/WePush-3.4.0.zip) diff --git a/src/main/java/com/fangxuele/tool/push/bean/MailMsg.java b/src/main/java/com/fangxuele/tool/push/bean/MailMsg.java index ebd40946..5d3a3ecc 100644 --- a/src/main/java/com/fangxuele/tool/push/bean/MailMsg.java +++ b/src/main/java/com/fangxuele/tool/push/bean/MailMsg.java @@ -24,6 +24,11 @@ public class MailMsg implements Serializable { */ private String mailTitle; + /** + * 抄送 + */ + private String mailCc; + /** * 附件 */ diff --git a/src/main/java/com/fangxuele/tool/push/domain/TMsgMail.java b/src/main/java/com/fangxuele/tool/push/domain/TMsgMail.java index 625516f3..8fed4bf5 100644 --- a/src/main/java/com/fangxuele/tool/push/domain/TMsgMail.java +++ b/src/main/java/com/fangxuele/tool/push/domain/TMsgMail.java @@ -19,6 +19,8 @@ public class TMsgMail implements Serializable { private String modifiedTime; + private String cc; + private static final long serialVersionUID = 1L; public Integer getId() { @@ -84,4 +86,12 @@ public String getModifiedTime() { public void setModifiedTime(String modifiedTime) { this.modifiedTime = modifiedTime == null ? null : modifiedTime.trim(); } + + public String getCc() { + return cc; + } + + public void setCc(String cc) { + this.cc = cc == null ? null : cc.trim(); + } } \ No newline at end of file diff --git a/src/main/java/com/fangxuele/tool/push/domain/TMsgWxCp.java b/src/main/java/com/fangxuele/tool/push/domain/TMsgWxCp.java index ee86a317..378fb471 100644 --- a/src/main/java/com/fangxuele/tool/push/domain/TMsgWxCp.java +++ b/src/main/java/com/fangxuele/tool/push/domain/TMsgWxCp.java @@ -27,6 +27,8 @@ public class TMsgWxCp implements Serializable { private String modifiedTime; + private String btnTxt; + private static final long serialVersionUID = 1L; public Integer getId() { @@ -124,4 +126,12 @@ public String getModifiedTime() { public void setModifiedTime(String modifiedTime) { this.modifiedTime = modifiedTime == null ? null : modifiedTime.trim(); } + + public String getBtnTxt() { + return btnTxt; + } + + public void setBtnTxt(String btnTxt) { + this.btnTxt = btnTxt == null ? null : btnTxt.trim(); + } } \ No newline at end of file diff --git a/src/main/java/com/fangxuele/tool/push/logic/BoostPushRunThread.java b/src/main/java/com/fangxuele/tool/push/logic/BoostPushRunThread.java new file mode 100644 index 00000000..55acdd71 --- /dev/null +++ b/src/main/java/com/fangxuele/tool/push/logic/BoostPushRunThread.java @@ -0,0 +1,178 @@ +package com.fangxuele.tool.push.logic; + +import cn.hutool.core.date.BetweenFormater; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.cron.pattern.CronPattern; +import cn.hutool.cron.pattern.CronPatternUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.fangxuele.tool.push.App; +import com.fangxuele.tool.push.logic.msgsender.IMsgSender; +import com.fangxuele.tool.push.logic.msgsender.MsgSenderFactory; +import com.fangxuele.tool.push.logic.msgthread.MsgAsyncSendThread; +import com.fangxuele.tool.push.ui.form.BoostForm; +import com.fangxuele.tool.push.util.ConsoleUtil; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.http.HttpResponse; + +import javax.swing.*; +import java.io.IOException; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Future; + +/** + *
+ * 性能模式推送执行控制线程
+ * 
+ * + * @author RememBerBer + * @since 2019/7/7. + */ +public class BoostPushRunThread extends Thread { + + private static final Log logger = LogFactory.get(); + + public static List> futureList = Lists.newArrayList(); + + @Override + public void run() { + BoostForm.boostForm.getProcessedProgressBar().setIndeterminate(true); + BoostForm.boostForm.getCompletedProgressBar().setIndeterminate(true); + // 准备推送 + preparePushRun(); + BoostForm.boostForm.getProcessedProgressBar().setIndeterminate(false); + BoostForm.boostForm.getCompletedProgressBar().setIndeterminate(false); + ConsoleUtil.boostConsoleWithLog("推送开始……"); + // 消息数据分片以及线程纷发 + shardingAndMsgThread(); + // 时间监控 + timeMonitor(); + } + + /** + * 准备推送 + */ + private void preparePushRun() { + // 按钮状态 + BoostForm.boostForm.getScheduledRunButton().setEnabled(false); + BoostForm.boostForm.getStartButton().setEnabled(false); + BoostForm.boostForm.getStopButton().setEnabled(true); + + BoostForm.boostForm.getStopButton().setText("停止"); + // 初始化 + BoostForm.boostForm.getProcessedCountLabel().setText("0"); + BoostForm.boostForm.getSuccessCountLabel().setText("0"); + BoostForm.boostForm.getFailCountLabel().setText("0"); + + // 设置是否空跑 + PushControl.dryRun = BoostForm.boostForm.getDryRunCheckBox().isSelected(); + + // 执行前重新导入目标用户 + PushControl.reimportMembers(); + + // 重置推送数据 + PushData.reset(); + PushData.startTime = System.currentTimeMillis(); + + // 拷贝准备的目标用户 + PushData.toSendList.addAll(PushData.allUser); + PushData.toSendCount.set(PushData.allUser.size()); + // 总记录数 + PushData.totalRecords = PushData.toSendList.size(); + + BoostForm.boostForm.getMemberCountLabel().setText("消息总数:" + PushData.totalRecords); + BoostForm.boostForm.getProcessedProgressBar().setMaximum((int) PushData.totalRecords); + BoostForm.boostForm.getCompletedProgressBar().setMaximum((int) PushData.totalRecords); + ConsoleUtil.boostConsoleWithLog("消息总数:" + PushData.totalRecords); + // 可用处理器核心数量 + BoostForm.boostForm.getProcessorCountLabel().setText("可用处理器核心:" + Runtime.getRuntime().availableProcessors()); + ConsoleUtil.boostConsoleWithLog("可用处理器核心:" + Runtime.getRuntime().availableProcessors()); + + // 准备消息构造器 + PushControl.prepareMsgMaker(); + } + + /** + * 消息数据分片以及线程纷发 + */ + private static void shardingAndMsgThread() { + + MsgAsyncSendThread msgAsyncSendThread; + + IMsgSender msgSender = MsgSenderFactory.getMsgSender(); + msgAsyncSendThread = new MsgAsyncSendThread(msgSender); + + ThreadUtil.execute(msgAsyncSendThread); + ConsoleUtil.boostConsoleWithLog("线程启动完毕……"); + } + + /** + * 时间监控 + */ + private void timeMonitor() { + long startTimeMillis = System.currentTimeMillis(); + // 计时 + while (true) { + if (PushData.toSendCount.get() <= PushData.successRecords.longValue() + PushData.failRecords.longValue()) { + if (!PushData.fixRateScheduling) { + BoostForm.boostForm.getStopButton().setEnabled(false); + BoostForm.boostForm.getStopButton().updateUI(); + BoostForm.boostForm.getStartButton().setEnabled(true); + BoostForm.boostForm.getStartButton().updateUI(); + BoostForm.boostForm.getScheduledRunButton().setEnabled(true); + BoostForm.boostForm.getScheduledRunButton().updateUI(); + BoostForm.boostForm.getScheduledTaskLabel().setText(""); + String finishTip = "发送完毕!\n"; + JOptionPane.showMessageDialog(BoostForm.boostForm.getBoostPanel(), finishTip, "提示", + JOptionPane.INFORMATION_MESSAGE); + BoostForm.boostForm.getScheduledTaskLabel().setVisible(false); + } else { + if (App.config.isRadioCron()) { + Date nextDate = CronPatternUtil.nextDateAfter(new CronPattern(App.config.getTextCron()), new Date(), true); + BoostForm.boostForm.getScheduledTaskLabel().setText("计划任务执行中,下一次执行时间:" + DateFormatUtils.format(nextDate, "yyyy-MM-dd HH:mm:ss")); + } + BoostForm.boostForm.getStopButton().setText("停止计划任务"); + } + + PushData.endTime = System.currentTimeMillis(); + + // 保存停止前的数据 + try { + // 空跑控制 + if (!BoostForm.boostForm.getDryRunCheckBox().isSelected()) { + ConsoleUtil.boostConsoleWithLog("正在保存结果数据……"); + BoostForm.boostForm.getCompletedProgressBar().setIndeterminate(true); + PushControl.savePushData(); + ConsoleUtil.boostConsoleWithLog("结果数据保存完毕!"); + } + } catch (IOException e) { + logger.error(e); + } finally { + BoostForm.boostForm.getCompletedProgressBar().setIndeterminate(false); + } + break; + } + + long currentTimeMillis = System.currentTimeMillis(); + long lastTimeMillis = currentTimeMillis - startTimeMillis; + long leftTimeMillis = (long) ((double) lastTimeMillis / (PushData.sendSuccessList.size() + PushData.sendFailList.size()) * (PushData.allUser.size() - PushData.sendSuccessList.size() - PushData.sendFailList.size())); + + // 耗时 + String formatBetweenLast = DateUtil.formatBetween(lastTimeMillis, BetweenFormater.Level.SECOND); + BoostForm.boostForm.getLastTimeLabel().setText("".equals(formatBetweenLast) ? "0s" : formatBetweenLast); + + // 预计剩余 + String formatBetweenLeft = DateUtil.formatBetween(leftTimeMillis, BetweenFormater.Level.SECOND); + BoostForm.boostForm.getLeftTimeLabel().setText("".equals(formatBetweenLeft) ? "0s" : formatBetweenLeft); + + BoostForm.boostForm.getJvmMemoryLabel().setText("JVM内存占用:" + FileUtil.readableFileSize(Runtime.getRuntime().totalMemory()) + "/" + FileUtil.readableFileSize(Runtime.getRuntime().maxMemory())); + + ThreadUtil.safeSleep(100); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/fangxuele/tool/push/logic/PushControl.java b/src/main/java/com/fangxuele/tool/push/logic/PushControl.java index ce556404..57af3c8d 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/PushControl.java +++ b/src/main/java/com/fangxuele/tool/push/logic/PushControl.java @@ -19,7 +19,10 @@ import com.fangxuele.tool.push.logic.msgsender.MailMsgSender; import com.fangxuele.tool.push.logic.msgsender.MsgSenderFactory; import com.fangxuele.tool.push.logic.msgsender.SendResult; +import com.fangxuele.tool.push.ui.UiConsts; +import com.fangxuele.tool.push.ui.form.MainWindow; import com.fangxuele.tool.push.ui.form.MessageEditForm; +import com.fangxuele.tool.push.ui.form.PushForm; import com.fangxuele.tool.push.ui.form.PushHisForm; import com.fangxuele.tool.push.ui.form.ScheduleForm; import com.fangxuele.tool.push.ui.form.SettingForm; @@ -68,7 +71,7 @@ public class PushControl { */ public static List preview() { List sendResultList = new ArrayList<>(); - if (!pushCheck()) { + if (!configCheck()) { return null; } List msgDataList = new ArrayList<>(); @@ -97,7 +100,44 @@ public static List preview() { * * @return boolean */ - static boolean pushCheck() { + public static boolean pushCheck() { + if (StringUtils.isEmpty(MessageEditForm.messageEditForm.getMsgNameField().getText())) { + JOptionPane.showMessageDialog(MainWindow.mainWindow.getMainPanel(), "请先选择一条消息!", "提示", + JOptionPane.INFORMATION_MESSAGE); + MainWindow.mainWindow.getTabbedPane().setSelectedIndex(2); + + return false; + } + if (PushData.allUser == null || PushData.allUser.size() == 0) { + JOptionPane.showMessageDialog(MainWindow.mainWindow.getMainPanel(), "请先准备目标用户!", "提示", + JOptionPane.INFORMATION_MESSAGE); + + return false; + } + if (!PushData.boostMode) { + if ("0".equals(PushForm.pushForm.getMaxThreadPoolTextField().getText()) || StringUtils.isEmpty(PushForm.pushForm.getMaxThreadPoolTextField().getText())) { + JOptionPane.showMessageDialog(PushForm.pushForm.getPushPanel(), "请设置每页分配用户数!", "提示", + JOptionPane.INFORMATION_MESSAGE); + + return false; + } + if ("0".equals(PushForm.pushForm.getThreadCountTextField().getText()) || StringUtils.isEmpty(PushForm.pushForm.getThreadCountTextField().getText())) { + JOptionPane.showMessageDialog(PushForm.pushForm.getPushPanel(), "请设置每个线程分配的页数!", "提示", + JOptionPane.INFORMATION_MESSAGE); + + return false; + } + } + + return configCheck(); + } + + /** + * 配置检查 + * + * @return + */ + public static boolean configCheck() { int msgType = App.config.getMsgType(); switch (msgType) { case MessageTypeEnum.MP_TEMPLATE_CODE: @@ -293,7 +333,7 @@ static void savePushData() throws IOException { contentBuilder.append("
"); contentBuilder.append("
"); contentBuilder.append("

来自WePush,一款专注于批量推送的小而美的工具

"); - contentBuilder.append("\"WePush\""); + contentBuilder.append("\"WePush\""); File[] files = new File[fileList.size()]; fileList.toArray(files); @@ -363,4 +403,27 @@ static void prepareMsgMaker() { } } + /** + * 重新导入目标用户(定时任务) + */ + public static void reimportMembers() { + if (PushData.fixRateScheduling && ScheduleForm.scheduleForm.getReimportCheckBox().isSelected()) { + switch ((String) ScheduleForm.scheduleForm.getReimportComboBox().getSelectedItem()) { + case "通过SQL导入": + MemberListener.importFromSql(); + break; + case "通过文件导入": + MemberListener.importFromFile(); + break; + case "导入所有关注公众号的用户": + MemberListener.importWxAll(); + break; + case "导入企业通讯录中所有用户": + MemberListener.importWxCpAll(); + break; + default: + } + } + } + } \ No newline at end of file diff --git a/src/main/java/com/fangxuele/tool/push/logic/PushData.java b/src/main/java/com/fangxuele/tool/push/logic/PushData.java index 03d06056..75000343 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/PushData.java +++ b/src/main/java/com/fangxuele/tool/push/logic/PushData.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.LongAdder; /** @@ -26,6 +27,11 @@ public class PushData { */ static long totalRecords; + /** + * (异步发送)已处理数 + */ + public static LongAdder processedRecords = new LongAdder(); + /** * 发送成功数 */ @@ -41,6 +47,11 @@ public class PushData { */ public static List toSendList; + /** + * 准备发送的数量 + */ + public static final AtomicInteger toSendCount = new AtomicInteger(); + /** * 发送成功的列表 */ @@ -76,6 +87,13 @@ public class PushData { */ static LongAdder stopedThreadCount = new LongAdder(); + /** + * 已处理数+1 + */ + public static void increaseProcessed() { + processedRecords.add(1); + } + /** * 成功数+1 */ @@ -107,11 +125,17 @@ public static void increaseStopedThread() { */ public static long endTime = 0; + /** + * 是否为性能模式 + */ + public static boolean boostMode = false; + /** * 重置推送数据 */ static void reset() { running = true; + processedRecords.reset(); successRecords.reset(); failRecords.reset(); stopedThreadCount.reset(); diff --git a/src/main/java/com/fangxuele/tool/push/logic/PushRunThread.java b/src/main/java/com/fangxuele/tool/push/logic/PushRunThread.java index f4dcc7f9..906b5ffa 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/PushRunThread.java +++ b/src/main/java/com/fangxuele/tool/push/logic/PushRunThread.java @@ -14,8 +14,6 @@ import com.fangxuele.tool.push.logic.msgthread.MsgSendThread; import com.fangxuele.tool.push.ui.component.TableInCellProgressBarRenderer; import com.fangxuele.tool.push.ui.form.PushForm; -import com.fangxuele.tool.push.ui.form.ScheduleForm; -import com.fangxuele.tool.push.ui.listener.MemberListener; import com.fangxuele.tool.push.util.ConsoleUtil; import org.apache.commons.lang3.time.DateFormatUtils; @@ -40,17 +38,15 @@ public class PushRunThread extends Thread { @Override public void run() { - if (PushControl.pushCheck()) { - PushForm.pushForm.getPushTotalProgressBar().setIndeterminate(true); - // 准备推送 - preparePushRun(); - PushForm.pushForm.getPushTotalProgressBar().setIndeterminate(false); - ConsoleUtil.consoleWithLog("推送开始……"); - // 消息数据分片以及线程纷发 - shardingAndMsgThread(); - // 时间监控 - timeMonitor(); - } + PushForm.pushForm.getPushTotalProgressBar().setIndeterminate(true); + // 准备推送 + preparePushRun(); + PushForm.pushForm.getPushTotalProgressBar().setIndeterminate(false); + ConsoleUtil.consoleWithLog("推送开始……"); + // 消息数据分片以及线程纷发 + shardingAndMsgThread(); + // 时间监控 + timeMonitor(); } /** @@ -71,7 +67,7 @@ private void preparePushRun() { PushControl.dryRun = PushForm.pushForm.getDryRunCheckBox().isSelected(); // 执行前重新导入目标用户 - reimportMembers(); + PushControl.reimportMembers(); // 重置推送数据 PushData.reset(); @@ -177,6 +173,7 @@ private void timeMonitor() { String finishTip = "发送完毕!\n"; JOptionPane.showMessageDialog(PushForm.pushForm.getPushPanel(), finishTip, "提示", JOptionPane.INFORMATION_MESSAGE); + PushForm.pushForm.getScheduleDetailLabel().setVisible(false); } else { if (App.config.isRadioCron()) { Date nextDate = CronPatternUtil.nextDateAfter(new CronPattern(App.config.getTextCron()), new Date(), true); @@ -189,13 +186,13 @@ private void timeMonitor() { // 保存停止前的数据 try { - ConsoleUtil.consoleWithLog("正在保存结果数据……"); - PushForm.pushForm.getPushTotalProgressBar().setIndeterminate(true); // 空跑控制 if (!PushForm.pushForm.getDryRunCheckBox().isSelected()) { + ConsoleUtil.consoleWithLog("正在保存结果数据……"); + PushForm.pushForm.getPushTotalProgressBar().setIndeterminate(true); PushControl.savePushData(); + ConsoleUtil.consoleWithLog("结果数据保存完毕!"); } - ConsoleUtil.consoleWithLog("结果数据保存完毕!"); } catch (IOException e) { logger.error(e); } finally { @@ -222,27 +219,4 @@ private void timeMonitor() { } } - /** - * 重新导入目标用户(定时任务) - */ - private void reimportMembers() { - if (PushData.fixRateScheduling && ScheduleForm.scheduleForm.getReimportCheckBox().isSelected()) { - switch ((String) ScheduleForm.scheduleForm.getReimportComboBox().getSelectedItem()) { - case "通过SQL导入": - MemberListener.importFromSql(); - break; - case "通过文件导入": - MemberListener.importFromFile(); - break; - case "导入所有关注公众号的用户": - MemberListener.importWxAll(); - break; - case "导入企业通讯录中所有用户": - MemberListener.importWxCpAll(); - break; - default: - } - } - } - } \ No newline at end of file diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgmaker/MailMsgMaker.java b/src/main/java/com/fangxuele/tool/push/logic/msgmaker/MailMsgMaker.java index 77a554d0..913519b3 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgmaker/MailMsgMaker.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgmaker/MailMsgMaker.java @@ -16,6 +16,7 @@ public class MailMsgMaker extends BaseMsgMaker implements IMsgMaker { public static String mailTitle; + public static String mailCc; public static String mailFiles; public static String mailContent; @@ -24,6 +25,7 @@ public class MailMsgMaker extends BaseMsgMaker implements IMsgMaker { */ public static void prepare() { mailTitle = MailMsgForm.mailMsgForm.getMailTitleTextField().getText(); + mailCc = MailMsgForm.mailMsgForm.getMailCcTextField().getText(); mailFiles = MailMsgForm.mailMsgForm.getMailFilesTextField().getText(); mailContent = MailMsgForm.mailMsgForm.getMailContentPane().getText(); } @@ -39,9 +41,11 @@ public MailMsg makeMsg(String[] msgData) { MailMsg mailMsg = new MailMsg(); VelocityContext velocityContext = getVelocityContext(msgData); String title = TemplateUtil.evaluate(mailTitle, velocityContext); + String cc = TemplateUtil.evaluate(mailCc, velocityContext); String files = TemplateUtil.evaluate(mailFiles, velocityContext); String content = TemplateUtil.evaluate(mailContent, velocityContext); mailMsg.setMailTitle(title); + mailMsg.setMailCc(cc); mailMsg.setMailFiles(files); mailMsg.setMailContent(content); return mailMsg; diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgmaker/WxCpMsgMaker.java b/src/main/java/com/fangxuele/tool/push/logic/msgmaker/WxCpMsgMaker.java index 3a2633a0..f8697bb2 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgmaker/WxCpMsgMaker.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgmaker/WxCpMsgMaker.java @@ -29,6 +29,8 @@ public class WxCpMsgMaker extends BaseMsgMaker implements IMsgMaker { public static String url; + public static String btnTxt; + public static String msgContent; /** @@ -40,7 +42,8 @@ public static void prepare() { msgTitle = WxCpMsgForm.wxCpMsgForm.getTitleTextField().getText(); picUrl = WxCpMsgForm.wxCpMsgForm.getPicUrlTextField().getText().trim(); desc = WxCpMsgForm.wxCpMsgForm.getDescTextField().getText(); - url = WxCpMsgForm.wxCpMsgForm.getPicUrlTextField().getText().trim(); + url = WxCpMsgForm.wxCpMsgForm.getUrlTextField().getText().trim(); + btnTxt = WxCpMsgForm.wxCpMsgForm.getBtnTxtTextField().getText().trim(); msgContent = WxCpMsgForm.wxCpMsgForm.getContentTextArea().getText(); WxCpMsgSender.wxCpConfigStorage = null; WxCpMsgSender.wxCpService = null; @@ -78,6 +81,18 @@ public WxCpMessage makeMsg(String[] msgData) { } else if ("文本消息".equals(msgType)) { String content = TemplateUtil.evaluate(msgContent, velocityContext); wxCpMessage = WxCpMessage.TEXT().agentId(Integer.valueOf(agentId)).toUser(msgData[0]).content(content).build(); + } else if ("markdown消息".equals(msgType)) { + String content = TemplateUtil.evaluate(msgContent, velocityContext); + wxCpMessage = WxCpMessage.MARKDOWN().agentId(Integer.valueOf(agentId)).toUser(msgData[0]).content(content).build(); + } else if ("文本卡片消息".equals(msgType)) { + // 标题 + String title = TemplateUtil.evaluate(msgTitle, velocityContext); + // 描述 + String description = TemplateUtil.evaluate(desc, velocityContext); + // 跳转url + String urlLink = TemplateUtil.evaluate(url, velocityContext); + wxCpMessage = WxCpMessage.TEXTCARD().agentId(Integer.valueOf(agentId)).toUser(msgData[0]).title(title) + .description(description).url(urlLink).btnTxt(btnTxt).build(); } return wxCpMessage; diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/AliDayuTemplateMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/AliDayuTemplateMsgSender.java index 7b2c93d8..3960322d 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/AliDayuTemplateMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/AliDayuTemplateMsgSender.java @@ -58,6 +58,11 @@ public SendResult send(String[] msgData) { return result; } + @Override + public SendResult asyncSend(String[] msgData) { + return null; + } + /** * 获取阿里大于短信发送客户端 * diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/AliYunMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/AliYunMsgSender.java index 0d79b9af..c4bfbbb6 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/AliYunMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/AliYunMsgSender.java @@ -61,6 +61,11 @@ public SendResult send(String[] msgData) { return sendResult; } + @Override + public SendResult asyncSend(String[] msgData) { + return null; + } + /** * 获取阿里云短信发送客户端 * diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/IMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/IMsgSender.java index 0d2252bb..e57675cd 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/IMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/IMsgSender.java @@ -16,4 +16,11 @@ public interface IMsgSender { * @param msgData 消息数据 */ SendResult send(String[] msgData); + + /** + * 异步发送消息 + * + * @param msgData 消息数据 + */ + SendResult asyncSend(String[] msgData); } diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/MailMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/MailMsgSender.java index 376b0f12..9e5e70f1 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/MailMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/MailMsgSender.java @@ -8,6 +8,7 @@ import com.fangxuele.tool.push.logic.PushControl; import com.fangxuele.tool.push.logic.msgmaker.MailMsgMaker; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.compress.utils.Lists; import org.apache.commons.lang3.StringUtils; import java.io.File; @@ -39,15 +40,21 @@ public SendResult send(String[] msgData) { try { MailMsg mailMsg = mailMsgMaker.makeMsg(msgData); - String tos = msgData[0]; + List tos = Lists.newArrayList(); + tos.add(msgData[0]); if (PushControl.dryRun) { sendResult.setSuccess(true); return sendResult; } else { + List ccList = null; + if (StringUtils.isNotBlank(mailMsg.getMailCc())) { + ccList = Lists.newArrayList(); + ccList.add(mailMsg.getMailCc()); + } if (StringUtils.isEmpty(mailMsg.getMailFiles())) { - MailUtil.send(mailAccount, tos, mailMsg.getMailTitle(), mailMsg.getMailContent(), true); + MailUtil.send(mailAccount, tos, ccList, null, mailMsg.getMailTitle(), mailMsg.getMailContent(), true); } else { - MailUtil.send(mailAccount, tos, mailMsg.getMailTitle(), mailMsg.getMailContent(), true, FileUtil.file(mailMsg.getMailFiles())); + MailUtil.send(mailAccount, tos, ccList, null, mailMsg.getMailTitle(), mailMsg.getMailContent(), true, FileUtil.file(mailMsg.getMailFiles())); } sendResult.setSuccess(true); } @@ -60,6 +67,11 @@ public SendResult send(String[] msgData) { return sendResult; } + @Override + public SendResult asyncSend(String[] msgData) { + return null; + } + public SendResult sendTestMail(String tos) { SendResult sendResult = new SendResult(); diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/TxYunMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/TxYunMsgSender.java index 1b6980d6..0fbefccf 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/TxYunMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/TxYunMsgSender.java @@ -60,6 +60,11 @@ public SendResult send(String[] msgData) { return sendResult; } + @Override + public SendResult asyncSend(String[] msgData) { + return null; + } + /** * 获取腾讯云短信发送客户端 * diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxCpMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxCpMsgSender.java index 628056db..662b7d46 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxCpMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxCpMsgSender.java @@ -70,6 +70,11 @@ public SendResult send(String[] msgData) { return sendResult; } + @Override + public SendResult asyncSend(String[] msgData) { + return null; + } + /** * 微信企业号配置 * diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxKefuMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxKefuMsgSender.java index bc77a313..2a30f46f 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxKefuMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxKefuMsgSender.java @@ -48,4 +48,9 @@ public SendResult send(String[] msgData) { sendResult.setSuccess(true); return sendResult; } + + @Override + public SendResult asyncSend(String[] msgData) { + return null; + } } diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxKefuPriorMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxKefuPriorMsgSender.java index 12f34e39..0f2c3a6c 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxKefuPriorMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxKefuPriorMsgSender.java @@ -33,4 +33,9 @@ public SendResult send(String[] msgData) { sendResult.setSuccess(true); return sendResult; } + + @Override + public SendResult asyncSend(String[] msgData) { + return null; + } } diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMaTemplateMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMaTemplateMsgSender.java index b8d983c9..5aee73e7 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMaTemplateMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMaTemplateMsgSender.java @@ -57,6 +57,11 @@ public SendResult send(String[] msgData) { return sendResult; } + @Override + public SendResult asyncSend(String[] msgData) { + return null; + } + /** * 微信小程序配置 * diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMpTemplateMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMpTemplateMsgSender.java index d6180ce7..44c6efdb 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMpTemplateMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMpTemplateMsgSender.java @@ -1,14 +1,37 @@ package com.fangxuele.tool.push.logic.msgsender; +import cn.hutool.json.JSONUtil; import com.fangxuele.tool.push.App; +import com.fangxuele.tool.push.logic.BoostPushRunThread; import com.fangxuele.tool.push.logic.PushControl; +import com.fangxuele.tool.push.logic.PushData; import com.fangxuele.tool.push.logic.msgmaker.WxMpTemplateMsgMaker; +import com.fangxuele.tool.push.ui.form.BoostForm; +import com.fangxuele.tool.push.util.ConsoleUtil; import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; +import org.apache.http.Consts; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.concurrent.FutureCallback; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.impl.nio.client.HttpAsyncClients; +import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager; +import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor; +import org.apache.http.impl.nio.reactor.IOReactorConfig; +import org.apache.http.nio.reactor.ConnectingIOReactor; +import org.apache.http.nio.reactor.IOReactorException; +import org.apache.http.util.EntityUtils; + +import java.util.concurrent.Future; /** *
@@ -22,6 +45,7 @@
 public class WxMpTemplateMsgSender implements IMsgSender {
     public volatile static WxMpInMemoryConfigStorage wxMpConfigStorage;
     public volatile static WxMpService wxMpService;
+    public volatile static CloseableHttpAsyncClient closeableHttpAsyncClient;
     private WxMpTemplateMsgMaker wxMpTemplateMsgMaker;
 
     public WxMpTemplateMsgSender() {
@@ -54,6 +78,59 @@ public SendResult send(String[] msgData) {
         return sendResult;
     }
 
+    @Override
+    public SendResult asyncSend(String[] msgData) {
+        SendResult sendResult = new SendResult();
+
+        try {
+            if (PushControl.dryRun) {
+                // 已成功+1
+                PushData.increaseSuccess();
+                BoostForm.boostForm.getSuccessCountLabel().setText(String.valueOf(PushData.successRecords));
+                // 保存发送成功
+                PushData.sendSuccessList.add(msgData);
+                // 总进度条
+                BoostForm.boostForm.getCompletedProgressBar().setValue(PushData.successRecords.intValue() + PushData.failRecords.intValue());
+                sendResult.setSuccess(true);
+                return sendResult;
+            } else {
+                String openId = msgData[0];
+                WxMpTemplateMessage wxMessageTemplate = wxMpTemplateMsgMaker.makeMsg(msgData);
+                wxMessageTemplate.setToUser(openId);
+
+                String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + wxMpService.getAccessToken();
+                HttpPost httpPost = new HttpPost(url);
+                StringEntity entity = new StringEntity(wxMessageTemplate.toJson(), Consts.UTF_8);
+                httpPost.setEntity(entity);
+                if (wxMpService.getRequestHttp().getRequestHttpProxy() != null) {
+                    RequestConfig config = RequestConfig.custom().setProxy((HttpHost) wxMpService.getRequestHttp().getRequestHttpProxy()).build();
+                    httpPost.setConfig(config);
+                }
+                Future httpResponseFuture = getCloseableHttpAsyncClient().execute(httpPost, new CallBack(msgData));
+                BoostPushRunThread.futureList.add(httpResponseFuture);
+            }
+        } catch (Exception e) {
+            // 总发送失败+1
+            PushData.increaseFail();
+            BoostForm.boostForm.getFailCountLabel().setText(String.valueOf(PushData.failRecords));
+
+            // 保存发送失败
+            PushData.sendFailList.add(msgData);
+
+            // 失败异常信息输出控制台
+            ConsoleUtil.boostConsoleOnly("发送失败:" + e.toString() + ";msgData:" + JSONUtil.toJsonPrettyStr(msgData));
+            // 总进度条
+            BoostForm.boostForm.getCompletedProgressBar().setValue(PushData.successRecords.intValue() + PushData.failRecords.intValue());
+
+            sendResult.setSuccess(false);
+            sendResult.setInfo(e.getMessage());
+            log.error(e.toString());
+            return sendResult;
+        }
+
+        return sendResult;
+    }
+
     /**
      * 微信公众号配置
      *
@@ -115,4 +192,114 @@ public static WxMpService getWxMpService() {
         }
         return wxMpService;
     }
+
+    public static CloseableHttpAsyncClient getCloseableHttpAsyncClient() throws IOReactorException {
+        if (closeableHttpAsyncClient == null) {
+            synchronized (WxMpTemplateMsgSender.class) {
+                if (closeableHttpAsyncClient == null) {
+                    RequestConfig requestConfig = RequestConfig.custom()
+                            .setConnectTimeout(-1)
+                            .setSocketTimeout(-1)
+                            .setConnectionRequestTimeout(-1)
+                            .build();
+
+                    //配置io线程
+                    IOReactorConfig ioReactorConfig = IOReactorConfig.custom().
+                            setIoThreadCount(Runtime.getRuntime().availableProcessors())
+                            .setSoKeepAlive(true).setConnectTimeout(-1).setSoTimeout(-1)
+                            .build();
+                    //设置连接池大小
+                    ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(ioReactorConfig);
+                    PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager(ioReactor);
+                    //最大连接数
+                    connManager.setMaxTotal(5000);
+                    //per route最大连接数
+                    connManager.setDefaultMaxPerRoute(5000);
+
+                    closeableHttpAsyncClient = HttpAsyncClients.custom().
+                            setConnectionManager(connManager)
+                            .setDefaultRequestConfig(requestConfig)
+                            .build();
+
+                    closeableHttpAsyncClient.start();
+                }
+            }
+        }
+        return closeableHttpAsyncClient;
+    }
+
+    static class CallBack implements FutureCallback {
+
+        String[] msgData;
+
+        CallBack(String[] msgData) {
+            this.msgData = msgData;
+        }
+
+        @Override
+        public void completed(HttpResponse httpResponse) {
+            try {
+                String response = EntityUtils.toString(httpResponse.getEntity(), Consts.UTF_8);
+                if (response.isEmpty()) {
+                    // 总发送失败+1
+                    PushData.increaseFail();
+                    BoostForm.boostForm.getFailCountLabel().setText(String.valueOf(PushData.failRecords));
+
+                    // 保存发送失败
+                    PushData.sendFailList.add(msgData);
+
+                    // 失败异常信息输出控制台
+                    ConsoleUtil.boostConsoleOnly("发送失败:" + WxError.builder().errorCode(9999).errorMsg("无响应内容").build() + ";msgData:" + JSONUtil.toJsonPrettyStr(msgData));
+                    // 总进度条
+                    BoostForm.boostForm.getCompletedProgressBar().setValue(PushData.successRecords.intValue() + PushData.failRecords.intValue());
+                } else {
+                    WxError error = WxError.fromJson(response);
+                    if (error.getErrorCode() != 0) {
+                        // 总发送失败+1
+                        PushData.increaseFail();
+                        BoostForm.boostForm.getFailCountLabel().setText(String.valueOf(PushData.failRecords));
+
+                        // 保存发送失败
+                        PushData.sendFailList.add(msgData);
+
+                        // 失败异常信息输出控制台
+                        ConsoleUtil.boostConsoleOnly("发送失败:" + error + ";msgData:" + JSONUtil.toJsonPrettyStr(msgData));
+                        // 总进度条
+                        BoostForm.boostForm.getCompletedProgressBar().setValue(PushData.successRecords.intValue() + PushData.failRecords.intValue());
+                    } else {
+                        // 已成功+1
+                        PushData.increaseSuccess();
+                        BoostForm.boostForm.getSuccessCountLabel().setText(String.valueOf(PushData.successRecords));
+
+                        // 保存发送成功
+                        PushData.sendSuccessList.add(msgData);
+                        // 总进度条
+                        BoostForm.boostForm.getCompletedProgressBar().setValue(PushData.successRecords.intValue() + PushData.failRecords.intValue());
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        @Override
+        public void failed(Exception e) {
+            // 总发送失败+1
+            PushData.increaseFail();
+            BoostForm.boostForm.getFailCountLabel().setText(String.valueOf(PushData.failRecords));
+
+            // 保存发送失败
+            PushData.sendFailList.add(msgData);
+
+            // 失败异常信息输出控制台
+            ConsoleUtil.boostConsoleOnly("发送失败:" + e.toString() + ";msgData:" + JSONUtil.toJsonPrettyStr(msgData));
+            // 总进度条
+            BoostForm.boostForm.getCompletedProgressBar().setValue(PushData.successRecords.intValue() + PushData.failRecords.intValue());
+        }
+
+        @Override
+        public void cancelled() {
+            PushData.toSendCount.getAndDecrement();
+        }
+    }
 }
diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/YunPianMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/YunPianMsgSender.java
index 143f8811..2f601697 100644
--- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/YunPianMsgSender.java
+++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/YunPianMsgSender.java
@@ -61,6 +61,11 @@ public SendResult send(String[] msgData) {
         return sendResult;
     }
 
+    @Override
+    public SendResult asyncSend(String[] msgData) {
+        return null;
+    }
+
     /**
      * 获取云片网短信发送客户端
      *
diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgthread/BaseMsgThread.java b/src/main/java/com/fangxuele/tool/push/logic/msgthread/BaseMsgThread.java
index 8ce30ce1..87c443f8 100644
--- a/src/main/java/com/fangxuele/tool/push/logic/msgthread/BaseMsgThread.java
+++ b/src/main/java/com/fangxuele/tool/push/logic/msgthread/BaseMsgThread.java
@@ -88,7 +88,7 @@ public void run() {
      */
     public void initCurrentThread() {
         ConsoleUtil.consoleWithLog("线程" + this.getName() + "负责处理第:" + startIndex + "-" +
-                endIndex + "条的数据");
+                endIndex + "条数据");
 
         list = PushData.toSendList.subList(startIndex, endIndex);
 
diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgthread/MsgAsyncSendThread.java b/src/main/java/com/fangxuele/tool/push/logic/msgthread/MsgAsyncSendThread.java
new file mode 100644
index 00000000..a3dd0041
--- /dev/null
+++ b/src/main/java/com/fangxuele/tool/push/logic/msgthread/MsgAsyncSendThread.java
@@ -0,0 +1,43 @@
+package com.fangxuele.tool.push.logic.msgthread;
+
+import com.fangxuele.tool.push.logic.PushData;
+import com.fangxuele.tool.push.logic.msgsender.IMsgSender;
+import com.fangxuele.tool.push.ui.form.BoostForm;
+
+/**
+ * 
+ * 消息异步发送服务线程
+ * 
+ * + * @author RememBerBer + * @since 2019/7/7. + */ +public class MsgAsyncSendThread extends Thread { + + private IMsgSender iMsgSender; + + public MsgAsyncSendThread(IMsgSender msgSender) { + this.iMsgSender = msgSender; + } + + @Override + public void run() { + + for (int i = 0; i < PushData.toSendList.size(); i++) { + if (!PushData.running) { + PushData.toSendCount.set(i); + return; + } + // 本条消息所需的数据 + String[] msgData = PushData.toSendList.get(i); + iMsgSender.asyncSend(msgData); + // 已处理+1 + PushData.increaseProcessed(); + BoostForm.boostForm.getProcessedCountLabel().setText(String.valueOf(PushData.processedRecords)); + + // 总进度条 + BoostForm.boostForm.getProcessedProgressBar().setValue(PushData.processedRecords.intValue()); + } + + } +} diff --git a/src/main/java/com/fangxuele/tool/push/ui/Init.java b/src/main/java/com/fangxuele/tool/push/ui/Init.java index 6cf27352..84a4a4f9 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/Init.java +++ b/src/main/java/com/fangxuele/tool/push/ui/Init.java @@ -6,6 +6,7 @@ import com.fangxuele.tool.push.App; import com.fangxuele.tool.push.ui.dialog.FontSizeAdjustDialog; import com.fangxuele.tool.push.ui.form.AboutForm; +import com.fangxuele.tool.push.ui.form.BoostForm; import com.fangxuele.tool.push.ui.form.HelpForm; import com.fangxuele.tool.push.ui.form.MemberForm; import com.fangxuele.tool.push.ui.form.MessageEditForm; @@ -139,6 +140,7 @@ public static void initAllTab() { MessageManageForm.init(); MemberForm.init(); PushForm.init(); + BoostForm.init(); ScheduleForm.init(); SettingForm.init(); PushHisForm.init(); diff --git a/src/main/java/com/fangxuele/tool/push/ui/UiConsts.java b/src/main/java/com/fangxuele/tool/push/ui/UiConsts.java index 1cf6fd37..a8986c25 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/UiConsts.java +++ b/src/main/java/com/fangxuele/tool/push/ui/UiConsts.java @@ -16,7 +16,7 @@ public class UiConsts { * 软件名称,版本 */ public final static String APP_NAME = "WePush"; - public final static String APP_VERSION = "v_3.4.2_190630"; + public final static String APP_VERSION = "v_3.5.0_190713"; /** * 主窗口图标-大 @@ -69,4 +69,9 @@ public class UiConsts { */ public final static String QR_CODE_URL = "http://download.zhoubochina.com/file/wepush_qrcode.json"; + /** + * 介绍二维码URL + */ + public final static String INTRODUCE_QRCODE_URL = "http://download.zhoubochina.com/qrcode/introduce-wepush-qrcode.png"; + } diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/BoostForm.form b/src/main/java/com/fangxuele/tool/push/ui/form/BoostForm.form index a1e9c5a7..495be453 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/BoostForm.form +++ b/src/main/java/com/fangxuele/tool/push/ui/form/BoostForm.form @@ -24,14 +24,14 @@ - + - + @@ -42,14 +42,14 @@ - + - + @@ -60,7 +60,7 @@ - + @@ -75,19 +75,19 @@ - + - + - + @@ -106,20 +106,20 @@ - + - + - + - + @@ -138,22 +138,22 @@ - + - + - + - + @@ -182,31 +182,32 @@ - + - + - + - + - + + @@ -226,7 +227,7 @@ - + @@ -242,11 +243,12 @@ - + + @@ -255,23 +257,25 @@ - + + - + + - + diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/BoostForm.java b/src/main/java/com/fangxuele/tool/push/ui/form/BoostForm.java index ff84f8d6..cfd47970 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/BoostForm.java +++ b/src/main/java/com/fangxuele/tool/push/ui/form/BoostForm.java @@ -1,5 +1,6 @@ package com.fangxuele.tool.push.ui.form; +import com.fangxuele.tool.push.App; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.core.GridLayoutManager; import com.intellij.uiDesigner.core.Spacer; @@ -19,17 +20,32 @@ @Getter public class BoostForm { private JPanel boostPanel; - private JTextArea textArea1; - private JButton 开始Button; - private JButton 停止Button; - private JButton 按计划执行Button; - private JCheckBox 空跑CheckBox; - private JProgressBar progressBar1; - private JProgressBar progressBar2; + private JTextArea consoleTextArea; + private JButton startButton; + private JButton stopButton; + private JButton scheduledRunButton; + private JCheckBox dryRunCheckBox; + private JProgressBar processedProgressBar; + private JProgressBar completedProgressBar; private JLabel boostModeHelpLabel; + private JLabel processedCountLabel; + private JLabel successCountLabel; + private JLabel failCountLabel; + private JLabel lastTimeLabel; + private JLabel leftTimeLabel; + private JLabel msgNameLabel; + private JLabel memberCountLabel; + private JLabel processorCountLabel; + private JLabel jvmMemoryLabel; + private JLabel scheduledTaskLabel; public static BoostForm boostForm = new BoostForm(); + public static void init() { + boostForm.getDryRunCheckBox().setSelected(App.config.isDryRun()); + boostForm.getScheduledTaskLabel().setVisible(false); + } + { // GUI initializer generated by IntelliJ IDEA GUI Designer // >>> IMPORTANT!! <<< @@ -53,65 +69,65 @@ public class BoostForm { final JSeparator separator1 = new JSeparator(); separator1.setOrientation(1); panel1.add(separator1, new GridConstraints(0, 3, 5, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + successCountLabel = new JLabel(); + Font successCountLabelFont = this.$$$getFont$$$(null, -1, 72, successCountLabel.getFont()); + if (successCountLabelFont != null) successCountLabel.setFont(successCountLabelFont); + successCountLabel.setForeground(new Color(-13587376)); + successCountLabel.setText("0"); + panel1.add(successCountLabel, new GridConstraints(0, 5, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label1 = new JLabel(); - Font label1Font = this.$$$getFont$$$(null, -1, 72, label1.getFont()); - if (label1Font != null) label1.setFont(label1Font); - label1.setForeground(new Color(-13587376)); - label1.setText("1230"); - panel1.add(label1, new GridConstraints(0, 5, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + label1.setText("成功"); + panel1.add(label1, new GridConstraints(0, 6, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + failCountLabel = new JLabel(); + Font failCountLabelFont = this.$$$getFont$$$(null, -1, 72, failCountLabel.getFont()); + if (failCountLabelFont != null) failCountLabel.setFont(failCountLabelFont); + failCountLabel.setForeground(new Color(-2200483)); + failCountLabel.setText("0"); + panel1.add(failCountLabel, new GridConstraints(2, 5, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label2 = new JLabel(); - label2.setText("成功"); - panel1.add(label2, new GridConstraints(0, 6, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label3 = new JLabel(); - Font label3Font = this.$$$getFont$$$(null, -1, 72, label3.getFont()); - if (label3Font != null) label3.setFont(label3Font); - label3.setForeground(new Color(-2200483)); - label3.setText("43"); - panel1.add(label3, new GridConstraints(2, 5, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label4 = new JLabel(); - label4.setText("失败"); - panel1.add(label4, new GridConstraints(2, 6, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - progressBar2 = new JProgressBar(); - panel1.add(progressBar2, new GridConstraints(4, 4, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + label2.setText("失败"); + panel1.add(label2, new GridConstraints(2, 6, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + completedProgressBar = new JProgressBar(); + panel1.add(completedProgressBar, new GridConstraints(4, 4, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JSeparator separator2 = new JSeparator(); separator2.setEnabled(true); separator2.setOrientation(1); panel1.add(separator2, new GridConstraints(0, 7, 5, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - progressBar1 = new JProgressBar(); - panel1.add(progressBar1, new GridConstraints(4, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label5 = new JLabel(); - Font label5Font = this.$$$getFont$$$(null, -1, 72, label5.getFont()); - if (label5Font != null) label5.setFont(label5Font); - label5.setText("1273"); - panel1.add(label5, new GridConstraints(2, 1, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label6 = new JLabel(); - label6.setText("已处理"); - panel1.add(label6, new GridConstraints(2, 2, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + processedProgressBar = new JProgressBar(); + panel1.add(processedProgressBar, new GridConstraints(4, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + processedCountLabel = new JLabel(); + Font processedCountLabelFont = this.$$$getFont$$$(null, -1, 72, processedCountLabel.getFont()); + if (processedCountLabelFont != null) processedCountLabel.setFont(processedCountLabelFont); + processedCountLabel.setText("0"); + panel1.add(processedCountLabel, new GridConstraints(2, 1, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label3 = new JLabel(); + label3.setText("已处理"); + panel1.add(label3, new GridConstraints(2, 2, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JSeparator separator3 = new JSeparator(); separator3.setOrientation(1); panel1.add(separator3, new GridConstraints(0, 11, 5, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - final JLabel label7 = new JLabel(); - label7.setText("消息总数:1273"); - panel1.add(label7, new GridConstraints(1, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label8 = new JLabel(); - label8.setText("可用处理器核心:4"); - panel1.add(label8, new GridConstraints(2, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label9 = new JLabel(); - label9.setText("耗时"); - panel1.add(label9, new GridConstraints(0, 9, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label10 = new JLabel(); - label10.setText("预计剩余"); - panel1.add(label10, new GridConstraints(2, 9, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label11 = new JLabel(); - Font label11Font = this.$$$getFont$$$(null, -1, 36, label11.getFont()); - if (label11Font != null) label11.setFont(label11Font); - label11.setText("13s"); - panel1.add(label11, new GridConstraints(0, 10, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label12 = new JLabel(); - Font label12Font = this.$$$getFont$$$(null, -1, 36, label12.getFont()); - if (label12Font != null) label12.setFont(label12Font); - label12.setText("15s"); - panel1.add(label12, new GridConstraints(2, 10, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + memberCountLabel = new JLabel(); + memberCountLabel.setText("消息总数:0"); + panel1.add(memberCountLabel, new GridConstraints(1, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + processorCountLabel = new JLabel(); + processorCountLabel.setText("可用处理器核心:-"); + panel1.add(processorCountLabel, new GridConstraints(2, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label4 = new JLabel(); + label4.setText("耗时"); + panel1.add(label4, new GridConstraints(0, 9, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label5 = new JLabel(); + label5.setText("预计剩余"); + panel1.add(label5, new GridConstraints(2, 9, 2, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + lastTimeLabel = new JLabel(); + Font lastTimeLabelFont = this.$$$getFont$$$(null, -1, 36, lastTimeLabel.getFont()); + if (lastTimeLabelFont != null) lastTimeLabel.setFont(lastTimeLabelFont); + lastTimeLabel.setText("0s"); + panel1.add(lastTimeLabel, new GridConstraints(0, 10, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + leftTimeLabel = new JLabel(); + Font leftTimeLabelFont = this.$$$getFont$$$(null, -1, 36, leftTimeLabel.getFont()); + if (leftTimeLabelFont != null) leftTimeLabel.setFont(leftTimeLabelFont); + leftTimeLabel.setText("0s"); + panel1.add(leftTimeLabel, new GridConstraints(2, 10, 2, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final Spacer spacer1 = new Spacer(); panel1.add(spacer1, new GridConstraints(2, 0, 2, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); final Spacer spacer2 = new Spacer(); @@ -125,43 +141,47 @@ public class BoostForm { boostModeHelpLabel.setIcon(new ImageIcon(getClass().getResource("/icon/helpButton.png"))); boostModeHelpLabel.setText("性能模式"); panel1.add(boostModeHelpLabel, new GridConstraints(0, 0, 2, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label13 = new JLabel(); - Font label13Font = this.$$$getFont$$$(null, -1, 24, label13.getFont()); - if (label13Font != null) label13.setFont(label13Font); - label13.setForeground(new Color(-276358)); - label13.setText("消息名称:"); - panel1.add(label13, new GridConstraints(0, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label14 = new JLabel(); - label14.setText("JVM内存占用:"); - panel1.add(label14, new GridConstraints(3, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label15 = new JLabel(); - label15.setForeground(new Color(-276358)); - label15.setText("计划任务执行中"); - panel1.add(label15, new GridConstraints(4, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + msgNameLabel = new JLabel(); + Font msgNameLabelFont = this.$$$getFont$$$(null, -1, 24, msgNameLabel.getFont()); + if (msgNameLabelFont != null) msgNameLabel.setFont(msgNameLabelFont); + msgNameLabel.setForeground(new Color(-276358)); + msgNameLabel.setText("消息名称:-"); + panel1.add(msgNameLabel, new GridConstraints(0, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + jvmMemoryLabel = new JLabel(); + jvmMemoryLabel.setText("JVM内存占用:-"); + panel1.add(jvmMemoryLabel, new GridConstraints(3, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + scheduledTaskLabel = new JLabel(); + scheduledTaskLabel.setForeground(new Color(-276358)); + scheduledTaskLabel.setText("计划任务执行中"); + scheduledTaskLabel.setVisible(true); + panel1.add(scheduledTaskLabel, new GridConstraints(4, 12, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JPanel panel2 = new JPanel(); panel2.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); boostPanel.add(panel2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); final JScrollPane scrollPane1 = new JScrollPane(); panel2.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - textArea1 = new JTextArea(); - scrollPane1.setViewportView(textArea1); + consoleTextArea = new JTextArea(); + scrollPane1.setViewportView(consoleTextArea); final JPanel panel3 = new JPanel(); panel3.setLayout(new GridLayoutManager(1, 5, new Insets(0, 5, 5, 5), -1, -1)); boostPanel.add(panel3, new GridConstraints(2, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); - 开始Button = new JButton(); - 开始Button.setText("开始"); - panel3.add(开始Button, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + startButton = new JButton(); + startButton.setIcon(new ImageIcon(getClass().getResource("/icon/run@2x.png"))); + startButton.setText("开始"); + panel3.add(startButton, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final Spacer spacer4 = new Spacer(); panel3.add(spacer4, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); - 停止Button = new JButton(); - 停止Button.setText("停止"); - panel3.add(停止Button, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - 按计划执行Button = new JButton(); - 按计划执行Button.setText("按计划执行"); - panel3.add(按计划执行Button, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - 空跑CheckBox = new JCheckBox(); - 空跑CheckBox.setText("空跑"); - panel3.add(空跑CheckBox, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + stopButton = new JButton(); + stopButton.setIcon(new ImageIcon(getClass().getResource("/icon/suspend.png"))); + stopButton.setText("停止"); + panel3.add(stopButton, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + scheduledRunButton = new JButton(); + scheduledRunButton.setIcon(new ImageIcon(getClass().getResource("/icon/clock.png"))); + scheduledRunButton.setText("按计划执行"); + panel3.add(scheduledRunButton, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + dryRunCheckBox = new JCheckBox(); + dryRunCheckBox.setText("空跑"); + panel3.add(dryRunCheckBox, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final Spacer spacer5 = new Spacer(); boostPanel.add(spacer5, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); } diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/ScheduleForm.java b/src/main/java/com/fangxuele/tool/push/ui/form/ScheduleForm.java index dc03657d..4813fe8c 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/ScheduleForm.java +++ b/src/main/java/com/fangxuele/tool/push/ui/form/ScheduleForm.java @@ -85,6 +85,36 @@ public static void fillReimportComboBox() { } } + public static int getDayOfWeek(String week) { + int dayOfWeek; + switch (week) { + case "一": + dayOfWeek = 2; + break; + case "二": + dayOfWeek = 3; + break; + case "三": + dayOfWeek = 4; + break; + case "四": + dayOfWeek = 5; + break; + case "五": + dayOfWeek = 6; + break; + case "六": + dayOfWeek = 7; + break; + case "日": + dayOfWeek = 1; + break; + default: + dayOfWeek = 0; + } + return dayOfWeek; + } + { // GUI initializer generated by IntelliJ IDEA GUI Designer // >>> IMPORTANT!! <<< diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/msg/MailMsgForm.form b/src/main/java/com/fangxuele/tool/push/ui/form/msg/MailMsgForm.form index 60dbfdf5..90f60202 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/msg/MailMsgForm.form +++ b/src/main/java/com/fangxuele/tool/push/ui/form/msg/MailMsgForm.form @@ -1,6 +1,6 @@
- + @@ -20,7 +20,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -48,7 +48,7 @@ - + @@ -56,7 +56,7 @@ - + @@ -64,7 +64,7 @@ - + @@ -73,12 +73,28 @@ - + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/msg/MailMsgForm.java b/src/main/java/com/fangxuele/tool/push/ui/form/msg/MailMsgForm.java index 7de6c553..26c3ddc0 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/msg/MailMsgForm.java +++ b/src/main/java/com/fangxuele/tool/push/ui/form/msg/MailMsgForm.java @@ -39,6 +39,7 @@ public class MailMsgForm { private JEditorPane mailContentPane; private JButton fileExploreButton; private JLabel uEditorLabel; + private JTextField mailCcTextField; private static TMsgMailMapper msgMailMapper = MybatisUtil.getSqlSession().getMapper(TMsgMailMapper.class); @@ -84,6 +85,7 @@ public static void init(String msgName) { if (tMsgMailList.size() > 0) { TMsgMail tMsgMail = tMsgMailList.get(0); mailMsgForm.getMailTitleTextField().setText(tMsgMail.getTitle()); + mailMsgForm.getMailCcTextField().setText(tMsgMail.getCc()); mailMsgForm.getMailFilesTextField().setText(tMsgMail.getFiles()); mailMsgForm.getMailContentPane().setText(tMsgMail.getContent()); } @@ -94,6 +96,7 @@ public static void init(String msgName) { */ public static void clearAllField() { mailMsgForm.getMailTitleTextField().setText(""); + mailMsgForm.getMailCcTextField().setText(""); mailMsgForm.getMailFilesTextField().setText(""); mailMsgForm.getMailContentPane().setText(""); } @@ -114,6 +117,7 @@ public static void save(String msgName) { } if (!existSameMsg || isCover == JOptionPane.YES_OPTION) { String mailTitle = mailMsgForm.getMailTitleTextField().getText(); + String mailCc = mailMsgForm.getMailCcTextField().getText(); String mailFiles = mailMsgForm.getMailFilesTextField().getText(); String mailContent = mailMsgForm.getMailContentPane().getText(); @@ -123,6 +127,7 @@ public static void save(String msgName) { tMsgMail.setMsgType(MessageTypeEnum.EMAIL_CODE); tMsgMail.setMsgName(msgName); tMsgMail.setTitle(mailTitle); + tMsgMail.setCc(mailCc); tMsgMail.setFiles(mailFiles); tMsgMail.setContent(mailContent); tMsgMail.setCreateTime(now); @@ -155,33 +160,38 @@ public static void save(String msgName) { */ private void $$$setupUI$$$() { mailPanel = new JPanel(); - mailPanel.setLayout(new GridLayoutManager(4, 4, new Insets(8, 8, 8, 8), -1, -1)); + mailPanel.setLayout(new GridLayoutManager(5, 4, new Insets(8, 8, 8, 8), -1, -1)); mailPanel.setMinimumSize(new Dimension(-1, -1)); final JLabel label1 = new JLabel(); label1.setText("邮件标题"); mailPanel.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final JLabel label2 = new JLabel(); label2.setText("附件"); - mailPanel.add(label2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + mailPanel.add(label2, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); mailTitleTextField = new JTextField(); mailPanel.add(mailTitleTextField, new GridConstraints(0, 1, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); mailContentPane = new JEditorPane(); mailContentPane.setBackground(new Color(-12236470)); mailContentPane.setContentType("text/html"); mailContentPane.setText("\r\n \r\n \r\n \r\n \r\n \r\n\r\n"); - mailPanel.add(mailContentPane, new GridConstraints(3, 0, 1, 4, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false)); + mailPanel.add(mailContentPane, new GridConstraints(4, 0, 1, 4, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false)); final JLabel label3 = new JLabel(); label3.setText("邮件正文(HTML)"); - mailPanel.add(label3, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + mailPanel.add(label3, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); uEditorLabel = new JLabel(); uEditorLabel.setText("使用UEditor编辑HTML"); - mailPanel.add(uEditorLabel, new GridConstraints(2, 1, 1, 3, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + mailPanel.add(uEditorLabel, new GridConstraints(3, 1, 1, 3, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); fileExploreButton = new JButton(); fileExploreButton.setHorizontalAlignment(0); fileExploreButton.setText("浏览"); - mailPanel.add(fileExploreButton, new GridConstraints(1, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, 1, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + mailPanel.add(fileExploreButton, new GridConstraints(2, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, 1, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); mailFilesTextField = new JTextField(); - mailPanel.add(mailFilesTextField, new GridConstraints(1, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); + mailPanel.add(mailFilesTextField, new GridConstraints(2, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); + mailCcTextField = new JTextField(); + mailPanel.add(mailCcTextField, new GridConstraints(1, 1, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); + final JLabel label4 = new JLabel(); + label4.setText("抄送"); + mailPanel.add(label4, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); } /** diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/msg/WxCpMsgForm.form b/src/main/java/com/fangxuele/tool/push/ui/form/msg/WxCpMsgForm.form index 9bd34592..e894c81b 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/msg/WxCpMsgForm.form +++ b/src/main/java/com/fangxuele/tool/push/ui/form/msg/WxCpMsgForm.form @@ -8,7 +8,7 @@ - + @@ -29,7 +29,7 @@
- + @@ -40,6 +40,8 @@ + +
@@ -150,6 +152,25 @@
+ + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/msg/WxCpMsgForm.java b/src/main/java/com/fangxuele/tool/push/ui/form/msg/WxCpMsgForm.java index 7e111e13..ed107a1e 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/msg/WxCpMsgForm.java +++ b/src/main/java/com/fangxuele/tool/push/ui/form/msg/WxCpMsgForm.java @@ -48,6 +48,8 @@ public class WxCpMsgForm { private JComboBox appNameComboBox; private JButton appManageButton; private JTextArea contentTextArea; + private JTextField btnTxtTextField; + private JLabel btnTxtLabel; public static WxCpMsgForm wxCpMsgForm = new WxCpMsgForm(); @@ -82,14 +84,12 @@ public static void init(String msgName) { String cpMsgType = tMsgWxCp.getCpMsgType(); wxCpMsgForm.getAppNameComboBox().setSelectedItem(agentIdToAppNameMap.get(tMsgWxCp.getAgentId())); wxCpMsgForm.getMsgTypeComboBox().setSelectedItem(cpMsgType); - if ("文本消息".equals(cpMsgType)) { - wxCpMsgForm.getContentTextArea().setText(tMsgWxCp.getContent()); - } else if ("图文消息".equals(cpMsgType)) { - wxCpMsgForm.getTitleTextField().setText(tMsgWxCp.getTitle()); - } + wxCpMsgForm.getContentTextArea().setText(tMsgWxCp.getContent()); + wxCpMsgForm.getTitleTextField().setText(tMsgWxCp.getTitle()); wxCpMsgForm.getPicUrlTextField().setText(tMsgWxCp.getImgUrl()); wxCpMsgForm.getDescTextField().setText(tMsgWxCp.getDescribe()); wxCpMsgForm.getUrlTextField().setText(tMsgWxCp.getUrl()); + wxCpMsgForm.getBtnTxtTextField().setText(tMsgWxCp.getBtnTxt()); switchCpMsgType(cpMsgType); } else { @@ -118,6 +118,7 @@ public static void initAppNameList() { public static void switchCpMsgType(String msgType) { switch (msgType) { case "文本消息": + case "markdown消息": wxCpMsgForm.getContentTextArea().setVisible(true); wxCpMsgForm.getDescLabel().setVisible(false); wxCpMsgForm.getDescTextField().setVisible(false); @@ -127,10 +128,14 @@ public static void switchCpMsgType(String msgType) { wxCpMsgForm.getUrlTextField().setVisible(false); wxCpMsgForm.getTitleLabel().setVisible(false); wxCpMsgForm.getTitleTextField().setVisible(false); + wxCpMsgForm.getBtnTxtLabel().setVisible(false); + wxCpMsgForm.getBtnTxtTextField().setVisible(false); break; case "图文消息": wxCpMsgForm.getContentLabel().setVisible(false); wxCpMsgForm.getContentTextArea().setVisible(false); + wxCpMsgForm.getBtnTxtLabel().setVisible(false); + wxCpMsgForm.getBtnTxtTextField().setVisible(false); wxCpMsgForm.getDescLabel().setVisible(true); wxCpMsgForm.getDescTextField().setVisible(true); wxCpMsgForm.getPicUrlLabel().setVisible(true); @@ -140,6 +145,20 @@ public static void switchCpMsgType(String msgType) { wxCpMsgForm.getTitleLabel().setVisible(true); wxCpMsgForm.getTitleTextField().setVisible(true); break; + case "文本卡片消息": + wxCpMsgForm.getContentLabel().setVisible(false); + wxCpMsgForm.getContentTextArea().setVisible(false); + wxCpMsgForm.getPicUrlLabel().setVisible(false); + wxCpMsgForm.getPicUrlTextField().setVisible(false); + wxCpMsgForm.getDescLabel().setVisible(true); + wxCpMsgForm.getDescTextField().setVisible(true); + wxCpMsgForm.getBtnTxtLabel().setVisible(true); + wxCpMsgForm.getBtnTxtTextField().setVisible(true); + wxCpMsgForm.getUrlLabel().setVisible(true); + wxCpMsgForm.getUrlTextField().setVisible(true); + wxCpMsgForm.getTitleLabel().setVisible(true); + wxCpMsgForm.getTitleTextField().setVisible(true); + break; default: break; } @@ -154,6 +173,7 @@ public static void clearAllField() { wxCpMsgForm.getPicUrlTextField().setText(""); wxCpMsgForm.getDescTextField().setText(""); wxCpMsgForm.getUrlTextField().setText(""); + wxCpMsgForm.getBtnTxtTextField().setText(""); } public static void save(String msgName) { @@ -184,6 +204,7 @@ public static void save(String msgName) { String picUrl = wxCpMsgForm.getPicUrlTextField().getText(); String desc = wxCpMsgForm.getDescTextField().getText(); String url = wxCpMsgForm.getUrlTextField().getText(); + String btnTxt = wxCpMsgForm.getBtnTxtTextField().getText(); String now = SqliteUtil.nowDateForSqlite(); @@ -197,6 +218,7 @@ public static void save(String msgName) { tMsgWxCp.setImgUrl(picUrl); tMsgWxCp.setDescribe(desc); tMsgWxCp.setUrl(url); + tMsgWxCp.setBtnTxt(btnTxt); tMsgWxCp.setModifiedTime(now); if (existSameMsg) { @@ -229,18 +251,20 @@ public static void save(String msgName) { final JPanel panel1 = new JPanel(); panel1.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); wxCpMsgPanel = new JPanel(); - wxCpMsgPanel.setLayout(new GridLayoutManager(8, 3, new Insets(10, 8, 0, 8), -1, -1)); + wxCpMsgPanel.setLayout(new GridLayoutManager(9, 3, new Insets(10, 8, 0, 8), -1, -1)); panel1.add(wxCpMsgPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); wxCpMsgPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, wxCpMsgPanel.getFont()))); msgTypeLabel = new JLabel(); msgTypeLabel.setText("消息类型"); wxCpMsgPanel.add(msgTypeLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); final Spacer spacer1 = new Spacer(); - wxCpMsgPanel.add(spacer1, new GridConstraints(7, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + wxCpMsgPanel.add(spacer1, new GridConstraints(8, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); msgTypeComboBox = new JComboBox(); final DefaultComboBoxModel defaultComboBoxModel1 = new DefaultComboBoxModel(); defaultComboBoxModel1.addElement("图文消息"); defaultComboBoxModel1.addElement("文本消息"); + defaultComboBoxModel1.addElement("文本卡片消息"); + defaultComboBoxModel1.addElement("markdown消息"); msgTypeComboBox.setModel(defaultComboBoxModel1); wxCpMsgPanel.add(msgTypeComboBox, new GridConstraints(1, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); titleLabel = new JLabel(); @@ -276,6 +300,13 @@ public static void save(String msgName) { wxCpMsgPanel.add(titleTextField, new GridConstraints(3, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, new Dimension(380, -1), new Dimension(380, -1), null, 0, false)); contentTextArea = new JTextArea(); wxCpMsgPanel.add(contentTextArea, new GridConstraints(2, 1, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false)); + btnTxtLabel = new JLabel(); + btnTxtLabel.setText("按钮文字"); + btnTxtLabel.setToolTipText("可不填。默认为“详情”, 不超过4个文字,超过自动截断"); + wxCpMsgPanel.add(btnTxtLabel, new GridConstraints(7, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + btnTxtTextField = new JTextField(); + btnTxtTextField.setToolTipText("可不填。默认为“详情”, 不超过4个文字,超过自动截断"); + wxCpMsgPanel.add(btnTxtTextField, new GridConstraints(7, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); msgTypeLabel.setLabelFor(msgTypeComboBox); titleLabel.setLabelFor(titleTextField); picUrlLabel.setLabelFor(picUrlTextField); diff --git a/src/main/java/com/fangxuele/tool/push/ui/listener/BoostListener.java b/src/main/java/com/fangxuele/tool/push/ui/listener/BoostListener.java index 11372094..d72fa674 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/listener/BoostListener.java +++ b/src/main/java/com/fangxuele/tool/push/ui/listener/BoostListener.java @@ -1,13 +1,42 @@ package com.fangxuele.tool.push.ui.listener; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.cron.CronUtil; +import cn.hutool.cron.pattern.CronPattern; +import cn.hutool.cron.pattern.CronPatternUtil; +import cn.hutool.cron.task.Task; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.fangxuele.tool.push.App; +import com.fangxuele.tool.push.logic.BoostPushRunThread; +import com.fangxuele.tool.push.logic.MessageTypeEnum; +import com.fangxuele.tool.push.logic.PushControl; +import com.fangxuele.tool.push.logic.PushData; import com.fangxuele.tool.push.ui.UiConsts; import com.fangxuele.tool.push.ui.dialog.CommonTipsDialog; +import com.fangxuele.tool.push.ui.form.BoostForm; +import com.fangxuele.tool.push.ui.form.MainWindow; +import com.fangxuele.tool.push.ui.form.MessageEditForm; +import com.fangxuele.tool.push.ui.form.ScheduleForm; import com.fangxuele.tool.push.util.ComponentUtil; +import org.apache.commons.compress.utils.Lists; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.apache.http.HttpResponse; import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import static com.fangxuele.tool.push.ui.form.BoostForm.boostForm; @@ -21,6 +50,14 @@ */ public class BoostListener { + private static final Log logger = LogFactory.get(); + + private static ScheduledExecutorService serviceStartAt; + + private static ScheduledExecutorService serviceStartPerDay; + + private static ScheduledExecutorService serviceStartPerWeek; + public static void addListeners() { boostForm.getBoostModeHelpLabel().addMouseListener(new MouseAdapter() { @Override @@ -30,7 +67,7 @@ public void mousePressed(MouseEvent e) { StringBuilder tipsBuilder = new StringBuilder(); tipsBuilder.append("

什么是性能模式?

"); tipsBuilder.append("

最大限度利用系统资源,提升性能,实验性地不断优化,以期获得更快速的批量推送效果

"); - tipsBuilder.append("

利用异步HTTP、NIO等技术提高批量推送效率

"); + tipsBuilder.append("

利用异步HTTP、NIO、协程等技术提高批量推送效率

"); tipsBuilder.append("

不断学习使用新技术,优化无止境,不择手段地提升批量推送速度

"); tipsBuilder.append("

一个人的力量有限,也希望更多技术大佬提供帮助和支持,一起挑战HTTP极限!

"); tipsBuilder.append("

注意:性能模式下CPU、内存、网络连接资源占用过大," + @@ -58,5 +95,275 @@ public void mouseExited(MouseEvent e) { super.mouseExited(e); } }); + + // 开始按钮事件 + BoostForm.boostForm.getStartButton().addActionListener((e) -> ThreadUtil.execute(() -> { + PushData.boostMode = true; + if (App.config.getMsgType() != MessageTypeEnum.MP_TEMPLATE_CODE) { + JOptionPane.showMessageDialog(MainWindow.mainWindow.getMainPanel(), "性能模式目前仅支持微信模板消息,后续逐步增加对其他消息类型的支持!", "提示", + JOptionPane.INFORMATION_MESSAGE); + return; + } + if (PushControl.pushCheck()) { + int isPush = JOptionPane.showConfirmDialog(boostForm.getBoostPanel(), + "确定开始推送吗?\n\n推送消息:" + + MessageEditForm.messageEditForm.getMsgNameField().getText() + + "\n推送人数:" + PushData.allUser.size() + + "\n\n空跑模式:" + + BoostForm.boostForm.getDryRunCheckBox().isSelected() + "\n", "确认推送?", + JOptionPane.YES_NO_OPTION); + if (isPush == JOptionPane.YES_OPTION) { + ThreadUtil.execute(new BoostPushRunThread()); + } + } + })); + + // 按计划执行按钮事件 + BoostForm.boostForm.getScheduledRunButton().addActionListener((e -> ThreadUtil.execute(() -> { + PushData.boostMode = true; + if (App.config.getMsgType() != MessageTypeEnum.MP_TEMPLATE_CODE) { + JOptionPane.showMessageDialog(MainWindow.mainWindow.getMainPanel(), "性能模式目前仅支持微信模板消息,后续逐步增加对其他消息类型的支持!", "提示", + JOptionPane.INFORMATION_MESSAGE); + return; + } + if (PushControl.pushCheck()) { + + // 看是否存在设置的计划任务 + boolean existScheduleTask = false; + + // 定时开始 + if (App.config.isRadioStartAt()) { + long startAtMills = DateUtil.parse(App.config.getTextStartAt(), DatePattern.NORM_DATETIME_PATTERN).getTime(); + if (startAtMills < System.currentTimeMillis()) { + JOptionPane.showMessageDialog(boostForm.getBoostPanel(), "计划开始推送时间不能小于系统当前时间!\n\n请检查计划任务设置!\n\n", "提示", + JOptionPane.INFORMATION_MESSAGE); + return; + } + + int isSchedulePush = JOptionPane.showConfirmDialog(boostForm.getBoostPanel(), + "将在" + + App.config.getTextStartAt() + + "推送\n\n消息:" + + MessageEditForm.messageEditForm.getMsgNameField().getText() + + "\n\n推送人数:" + PushData.allUser.size() + + "\n\n空跑模式:" + + BoostForm.boostForm.getDryRunCheckBox().isSelected(), "确认定时推送?", + JOptionPane.YES_NO_OPTION); + if (isSchedulePush == JOptionPane.YES_OPTION) { + PushData.scheduling = true; + // 按钮状态 + BoostForm.boostForm.getScheduledRunButton().setEnabled(false); + BoostForm.boostForm.getStartButton().setEnabled(false); + BoostForm.boostForm.getStopButton().setText("停止计划任务"); + BoostForm.boostForm.getStopButton().setEnabled(true); + + BoostForm.boostForm.getScheduledTaskLabel().setVisible(true); + BoostForm.boostForm.getScheduledTaskLabel().setText("计划任务执行中:将在" + + App.config.getTextStartAt() + + "开始推送"); + + serviceStartAt = Executors.newSingleThreadScheduledExecutor(); + serviceStartAt.schedule(new BoostPushRunThread(), startAtMills - System.currentTimeMillis(), TimeUnit.MILLISECONDS); + } + existScheduleTask = true; + } + + // 每天固定时间开始 + if (App.config.isRadioPerDay()) { + long startPerDayMills = DateUtil.parse(DateUtil.today() + " " + App.config.getTextPerDay(), DatePattern.NORM_DATETIME_PATTERN).getTime(); + + int isSchedulePush = JOptionPane.showConfirmDialog(boostForm.getBoostPanel(), + "将在每天" + + App.config.getTextPerDay() + + "推送\n\n消息:" + + MessageEditForm.messageEditForm.getMsgNameField().getText() + + "\n\n推送人数:" + PushData.allUser.size() + + "\n\n空跑模式:" + + BoostForm.boostForm.getDryRunCheckBox().isSelected(), "确认定时推送?", + JOptionPane.YES_NO_OPTION); + if (isSchedulePush == JOptionPane.YES_OPTION) { + PushData.fixRateScheduling = true; + // 按钮状态 + BoostForm.boostForm.getScheduledRunButton().setEnabled(false); + BoostForm.boostForm.getStartButton().setEnabled(false); + BoostForm.boostForm.getStopButton().setText("停止计划任务"); + BoostForm.boostForm.getStopButton().setEnabled(true); + + BoostForm.boostForm.getScheduledTaskLabel().setVisible(true); + BoostForm.boostForm.getScheduledTaskLabel().setText("计划任务执行中:将在每天" + + App.config.getTextPerDay() + + "开始推送"); + + serviceStartPerDay = Executors.newSingleThreadScheduledExecutor(); + long millisBetween = startPerDayMills - System.currentTimeMillis(); + long delay = millisBetween < 0 ? millisBetween + 24 * 60 * 60 * 1000 : millisBetween; + serviceStartPerDay.scheduleAtFixedRate(new BoostPushRunThread(), delay, 24 * 60 * 60 * 1000, TimeUnit.MILLISECONDS); + } + existScheduleTask = true; + } + + // 每周固定时间开始 + if (App.config.isRadioPerWeek()) { + + long todaySetMills = DateUtil.parse(DateUtil.today() + " " + App.config.getTextPerWeekTime(), DatePattern.NORM_DATETIME_PATTERN).getTime(); + int dayBetween = ScheduleForm.getDayOfWeek(App.config.getTextPerWeekWeek()) - DateUtil.thisDayOfWeek(); + long startPerWeekMills = dayBetween < 0 ? (dayBetween + 7) * 24 * 60 * 60 * 1000 : dayBetween * 24 * 60 * 60 * 1000; + + int isSchedulePush = JOptionPane.showConfirmDialog(boostForm.getBoostPanel(), + "将在每周" + App.config.getTextPerWeekWeek() + + App.config.getTextPerWeekTime() + + "推送\n\n消息:" + + MessageEditForm.messageEditForm.getMsgNameField().getText() + + "\n\n推送人数:" + PushData.allUser.size() + + "\n\n空跑模式:" + + BoostForm.boostForm.getDryRunCheckBox().isSelected(), "确认定时推送?", + JOptionPane.YES_NO_OPTION); + if (isSchedulePush == JOptionPane.YES_OPTION) { + PushData.scheduling = true; + PushData.fixRateScheduling = true; + // 按钮状态 + BoostForm.boostForm.getScheduledRunButton().setEnabled(false); + BoostForm.boostForm.getStartButton().setEnabled(false); + BoostForm.boostForm.getStopButton().setText("停止计划任务"); + BoostForm.boostForm.getStopButton().setEnabled(true); + + BoostForm.boostForm.getScheduledTaskLabel().setVisible(true); + BoostForm.boostForm.getScheduledTaskLabel().setText("计划任务执行中:将在每周" + + App.config.getTextPerWeekWeek() + + App.config.getTextPerWeekTime() + + "开始推送"); + + serviceStartPerWeek = Executors.newSingleThreadScheduledExecutor(); + long millisBetween = startPerWeekMills + todaySetMills - System.currentTimeMillis(); + long delay = millisBetween < 0 ? millisBetween + 7 * 24 * 60 * 60 * 1000 : millisBetween; + serviceStartPerWeek.scheduleAtFixedRate(new BoostPushRunThread(), delay, 7 * 24 * 60 * 60 * 1000, TimeUnit.MILLISECONDS); + } + existScheduleTask = true; + } + + // 按Cron表达式触发 + if (App.config.isRadioCron()) { + + List latest5RunTimeList = Lists.newArrayList(); + Date now = new Date(); + for (int i = 0; i < 5; i++) { + Date date = CronPatternUtil.nextDateAfter(new CronPattern(App.config.getTextCron()), DateUtils.addDays(now, i), true); + latest5RunTimeList.add(DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss")); + } + + int isSchedulePush = JOptionPane.showConfirmDialog(boostForm.getBoostPanel(), + "将按" + + App.config.getTextCron() + + "表达式触发推送\n\n" + + "最近5次运行时间:\n" + + String.join("\n", latest5RunTimeList) + + "\n\n消息名称:" + + MessageEditForm.messageEditForm.getMsgNameField().getText() + + "\n推送人数:" + PushData.allUser.size() + + "\n空跑模式:" + + BoostForm.boostForm.getDryRunCheckBox().isSelected(), "确认定时推送?", + JOptionPane.YES_NO_OPTION); + if (isSchedulePush == JOptionPane.YES_OPTION) { + PushData.fixRateScheduling = true; + // 按钮状态 + BoostForm.boostForm.getScheduledRunButton().setEnabled(false); + BoostForm.boostForm.getStartButton().setEnabled(false); + BoostForm.boostForm.getStopButton().setText("停止计划任务"); + BoostForm.boostForm.getStopButton().setEnabled(true); + + BoostForm.boostForm.getScheduledTaskLabel().setVisible(true); + BoostForm.boostForm.getScheduledTaskLabel().setText("计划任务执行中,下一次执行时间:" + latest5RunTimeList.get(0)); + + // 支持秒级别定时任务 + CronUtil.setMatchSecond(true); + CronUtil.schedule(App.config.getTextCron(), (Task) () -> new BoostPushRunThread().start()); + CronUtil.start(); + } + existScheduleTask = true; + } + + if (!existScheduleTask) { + JOptionPane.showMessageDialog(boostForm.getBoostPanel(), "请先设置计划任务!", "提示", + JOptionPane.INFORMATION_MESSAGE); + } + } + }))); + + // 停止按钮事件 + BoostForm.boostForm.getStopButton().addActionListener((e) -> { + ThreadUtil.execute(() -> { + if (PushData.scheduling) { + BoostForm.boostForm.getScheduledTaskLabel().setText(""); + if (serviceStartAt != null) { + serviceStartAt.shutdownNow(); + } + BoostForm.boostForm.getStartButton().setEnabled(true); + BoostForm.boostForm.getScheduledRunButton().setEnabled(true); + BoostForm.boostForm.getStopButton().setText("停止"); + BoostForm.boostForm.getStopButton().setEnabled(false); + BoostForm.boostForm.getStartButton().updateUI(); + BoostForm.boostForm.getScheduledRunButton().updateUI(); + BoostForm.boostForm.getStopButton().updateUI(); + BoostForm.boostForm.getScheduledTaskLabel().setVisible(false); + PushData.scheduling = false; + PushData.running = false; + } + + if (PushData.fixRateScheduling) { + BoostForm.boostForm.getScheduledTaskLabel().setText(""); + if (serviceStartPerDay != null) { + serviceStartPerDay.shutdownNow(); + } + if (serviceStartPerWeek != null) { + serviceStartPerWeek.shutdownNow(); + } + try { + CronUtil.stop(); + } catch (Exception e1) { + logger.warn(e1.toString()); + } + BoostForm.boostForm.getStartButton().setEnabled(true); + BoostForm.boostForm.getScheduledRunButton().setEnabled(true); + BoostForm.boostForm.getStopButton().setText("停止"); + BoostForm.boostForm.getStopButton().setEnabled(false); + BoostForm.boostForm.getStartButton().updateUI(); + BoostForm.boostForm.getScheduledRunButton().updateUI(); + BoostForm.boostForm.getStopButton().updateUI(); + BoostForm.boostForm.getScheduledTaskLabel().setVisible(false); + PushData.fixRateScheduling = false; + PushData.running = false; + } + + if (PushData.running) { + int isStop = JOptionPane.showConfirmDialog(boostForm.getBoostPanel(), + "确定停止当前的推送吗?", "确认停止?", + JOptionPane.YES_NO_OPTION); + if (isStop == JOptionPane.YES_OPTION) { + PushData.running = false; + BoostForm.boostForm.getStartButton().setEnabled(true); + BoostForm.boostForm.getScheduledRunButton().setEnabled(true); + BoostForm.boostForm.getStopButton().setText("停止"); + BoostForm.boostForm.getStopButton().setEnabled(false); + BoostForm.boostForm.getStartButton().updateUI(); + BoostForm.boostForm.getScheduledRunButton().updateUI(); + BoostForm.boostForm.getStopButton().updateUI(); + BoostForm.boostForm.getScheduledTaskLabel().setVisible(false); + } + } + for (Future httpResponseFuture : BoostPushRunThread.futureList) { + httpResponseFuture.cancel(true); + } + }); + }); + } + + static void refreshPushInfo() { + // 总记录数 + long totalCount = PushData.allUser.size(); + BoostForm.boostForm.getMemberCountLabel().setText("消息总数:" + totalCount); + // 可用处理器核心 + BoostForm.boostForm.getProcessorCountLabel().setText("可用处理器核心:" + Runtime.getRuntime().availableProcessors()); + // JVM内存占用 + BoostForm.boostForm.getJvmMemoryLabel().setText("JVM内存占用:" + FileUtil.readableFileSize(Runtime.getRuntime().totalMemory()) + "/" + FileUtil.readableFileSize(Runtime.getRuntime().maxMemory())); } } diff --git a/src/main/java/com/fangxuele/tool/push/ui/listener/PushListener.java b/src/main/java/com/fangxuele/tool/push/ui/listener/PushListener.java index 408325e3..ef4ad54e 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/listener/PushListener.java +++ b/src/main/java/com/fangxuele/tool/push/ui/listener/PushListener.java @@ -11,15 +11,15 @@ import cn.hutool.log.Log; import cn.hutool.log.LogFactory; import com.fangxuele.tool.push.App; +import com.fangxuele.tool.push.logic.PushControl; import com.fangxuele.tool.push.logic.PushData; import com.fangxuele.tool.push.logic.PushRunThread; import com.fangxuele.tool.push.ui.UiConsts; import com.fangxuele.tool.push.ui.dialog.CommonTipsDialog; -import com.fangxuele.tool.push.ui.form.MainWindow; import com.fangxuele.tool.push.ui.form.MessageEditForm; import com.fangxuele.tool.push.ui.form.PushForm; +import com.fangxuele.tool.push.ui.form.ScheduleForm; import org.apache.commons.compress.utils.Lists; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; @@ -59,7 +59,8 @@ public class PushListener { public static void addListeners() { // 开始按钮事件 PushForm.pushForm.getPushStartButton().addActionListener((e) -> ThreadUtil.execute(() -> { - if (checkBeforePush()) { + PushData.boostMode = false; + if (PushControl.pushCheck()) { int isPush = JOptionPane.showConfirmDialog(pushPanel, "确定开始推送吗?\n\n推送消息:" + MessageEditForm.messageEditForm.getMsgNameField().getText() + @@ -88,6 +89,7 @@ public static void addListeners() { PushForm.pushForm.getPushStartButton().updateUI(); PushForm.pushForm.getScheduleRunButton().updateUI(); PushForm.pushForm.getPushStopButton().updateUI(); + PushForm.pushForm.getScheduleDetailLabel().setVisible(false); PushData.scheduling = false; PushData.running = false; } @@ -112,6 +114,7 @@ public static void addListeners() { PushForm.pushForm.getPushStartButton().updateUI(); PushForm.pushForm.getScheduleRunButton().updateUI(); PushForm.pushForm.getPushStopButton().updateUI(); + PushForm.pushForm.getScheduleDetailLabel().setVisible(false); PushData.fixRateScheduling = false; PushData.running = false; } @@ -129,6 +132,7 @@ public static void addListeners() { PushForm.pushForm.getPushStartButton().updateUI(); PushForm.pushForm.getScheduleRunButton().updateUI(); PushForm.pushForm.getPushStopButton().updateUI(); + PushForm.pushForm.getScheduleDetailLabel().setVisible(false); } } }); @@ -136,8 +140,8 @@ public static void addListeners() { // 按计划执行按钮事件 PushForm.pushForm.getScheduleRunButton().addActionListener((e -> ThreadUtil.execute(() -> { - if (checkBeforePush()) { - + PushData.boostMode = false; + if (PushControl.pushCheck()) { // 看是否存在设置的计划任务 boolean existScheduleTask = false; @@ -167,6 +171,7 @@ public static void addListeners() { PushForm.pushForm.getPushStopButton().setText("停止计划任务"); PushForm.pushForm.getPushStopButton().setEnabled(true); + PushForm.pushForm.getScheduleDetailLabel().setVisible(true); PushForm.pushForm.getScheduleDetailLabel().setText("计划任务执行中:将在" + App.config.getTextStartAt() + "开始推送"); @@ -198,6 +203,7 @@ public static void addListeners() { PushForm.pushForm.getPushStopButton().setText("停止计划任务"); PushForm.pushForm.getPushStopButton().setEnabled(true); + PushForm.pushForm.getScheduleDetailLabel().setVisible(true); PushForm.pushForm.getScheduleDetailLabel().setText("计划任务执行中:将在每天" + App.config.getTextPerDay() + "开始推送"); @@ -214,7 +220,7 @@ public static void addListeners() { if (App.config.isRadioPerWeek()) { long todaySetMills = DateUtil.parse(DateUtil.today() + " " + App.config.getTextPerWeekTime(), DatePattern.NORM_DATETIME_PATTERN).getTime(); - int dayBetween = getDayOfWeek(App.config.getTextPerWeekWeek()) - DateUtil.thisDayOfWeek(); + int dayBetween = ScheduleForm.getDayOfWeek(App.config.getTextPerWeekWeek()) - DateUtil.thisDayOfWeek(); long startPerWeekMills = dayBetween < 0 ? (dayBetween + 7) * 24 * 60 * 60 * 1000 : dayBetween * 24 * 60 * 60 * 1000; int isSchedulePush = JOptionPane.showConfirmDialog(pushPanel, @@ -235,6 +241,7 @@ public static void addListeners() { PushForm.pushForm.getPushStopButton().setText("停止计划任务"); PushForm.pushForm.getPushStopButton().setEnabled(true); + PushForm.pushForm.getScheduleDetailLabel().setVisible(true); PushForm.pushForm.getScheduleDetailLabel().setText("计划任务执行中:将在每周" + App.config.getTextPerWeekWeek() + App.config.getTextPerWeekTime() + @@ -278,6 +285,7 @@ public static void addListeners() { PushForm.pushForm.getPushStopButton().setText("停止计划任务"); PushForm.pushForm.getPushStopButton().setEnabled(true); + PushForm.pushForm.getScheduleDetailLabel().setVisible(true); PushForm.pushForm.getScheduleDetailLabel().setText("计划任务执行中,下一次执行时间:" + latest5RunTimeList.get(0)); // 支持秒级别定时任务 @@ -425,68 +433,4 @@ static void refreshPushInfo() { PushForm.pushForm.getJvmMemoryLabel().setText("JVM内存占用:" + FileUtil.readableFileSize(Runtime.getRuntime().totalMemory()) + "/" + FileUtil.readableFileSize(Runtime.getRuntime().maxMemory())); } - /** - * 推送前检查 - * - * @return boolean - */ - private static boolean checkBeforePush() { - if (StringUtils.isEmpty(MessageEditForm.messageEditForm.getMsgNameField().getText())) { - JOptionPane.showMessageDialog(pushPanel, "请先选择一条消息!", "提示", - JOptionPane.INFORMATION_MESSAGE); - MainWindow.mainWindow.getTabbedPane().setSelectedIndex(2); - - return false; - } - if (PushData.allUser == null || PushData.allUser.size() == 0) { - JOptionPane.showMessageDialog(pushPanel, "请先准备目标用户!", "提示", - JOptionPane.INFORMATION_MESSAGE); - - return false; - } - if ("0".equals(PushForm.pushForm.getMaxThreadPoolTextField().getText()) || StringUtils.isEmpty(PushForm.pushForm.getMaxThreadPoolTextField().getText())) { - JOptionPane.showMessageDialog(pushPanel, "请设置每页分配用户数!", "提示", - JOptionPane.INFORMATION_MESSAGE); - - return false; - } - if ("0".equals(PushForm.pushForm.getThreadCountTextField().getText()) || StringUtils.isEmpty(PushForm.pushForm.getThreadCountTextField().getText())) { - JOptionPane.showMessageDialog(pushPanel, "请设置每个线程分配的页数!", "提示", - JOptionPane.INFORMATION_MESSAGE); - - return false; - } - return true; - } - - private static int getDayOfWeek(String week) { - int dayOfWeek; - switch (week) { - case "一": - dayOfWeek = 2; - break; - case "二": - dayOfWeek = 3; - break; - case "三": - dayOfWeek = 4; - break; - case "四": - dayOfWeek = 5; - break; - case "五": - dayOfWeek = 6; - break; - case "六": - dayOfWeek = 7; - break; - case "日": - dayOfWeek = 1; - break; - default: - dayOfWeek = 0; - } - return dayOfWeek; - } - } diff --git a/src/main/java/com/fangxuele/tool/push/ui/listener/ScheduleListener.java b/src/main/java/com/fangxuele/tool/push/ui/listener/ScheduleListener.java index 7d683e62..c416ed42 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/listener/ScheduleListener.java +++ b/src/main/java/com/fangxuele/tool/push/ui/listener/ScheduleListener.java @@ -108,15 +108,17 @@ public static void addListeners() { JOptionPane.ERROR_MESSAGE); return; } - List latest5RunTimeList = Lists.newArrayList(); - Date now = new Date(); - for (int i = 0; i < 5; i++) { - Date date = CronPatternUtil.nextDateAfter(new CronPattern(textCron), DateUtils.addDays(now, i), true); - latest5RunTimeList.add(DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss")); + if (isCron) { + List latest5RunTimeList = Lists.newArrayList(); + Date now = new Date(); + for (int i = 0; i < 5; i++) { + Date date = CronPatternUtil.nextDateAfter(new CronPattern(textCron), DateUtils.addDays(now, i), true); + latest5RunTimeList.add(DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss")); + } + JOptionPane.showMessageDialog(MainWindow.mainWindow.getSchedulePanel(), + "最近5次运行时间:\n" + String.join("\n", latest5RunTimeList), "提示", + JOptionPane.INFORMATION_MESSAGE); } - JOptionPane.showMessageDialog(MainWindow.mainWindow.getSchedulePanel(), - "最近5次运行时间:\n" + String.join("\n", latest5RunTimeList), "提示", - JOptionPane.INFORMATION_MESSAGE); App.config.setRadioCron(isCron); App.config.setTextCron(textCron); } else if (isCron) { diff --git a/src/main/java/com/fangxuele/tool/push/ui/listener/TabListener.java b/src/main/java/com/fangxuele/tool/push/ui/listener/TabListener.java index 27c58a3a..2102e7ad 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/listener/TabListener.java +++ b/src/main/java/com/fangxuele/tool/push/ui/listener/TabListener.java @@ -1,6 +1,7 @@ package com.fangxuele.tool.push.ui.listener; import com.fangxuele.tool.push.ui.form.AboutForm; +import com.fangxuele.tool.push.ui.form.BoostForm; import com.fangxuele.tool.push.ui.form.MainWindow; import com.fangxuele.tool.push.ui.form.MessageEditForm; import com.fangxuele.tool.push.ui.form.PushForm; @@ -47,6 +48,10 @@ public void stateChanged(ChangeEvent e) { PushForm.pushForm.getPushMsgName().setText(MessageEditForm.messageEditForm.getMsgNameField().getText()); PushListener.refreshPushInfo(); break; + case 5: + BoostForm.boostForm.getMsgNameLabel().setText(MessageEditForm.messageEditForm.getMsgNameField().getText()); + BoostListener.refreshPushInfo(); + break; default: break; } diff --git a/src/main/java/com/fangxuele/tool/push/util/ConsoleUtil.java b/src/main/java/com/fangxuele/tool/push/util/ConsoleUtil.java index 95da9807..2ba0bd8c 100644 --- a/src/main/java/com/fangxuele/tool/push/util/ConsoleUtil.java +++ b/src/main/java/com/fangxuele/tool/push/util/ConsoleUtil.java @@ -2,6 +2,7 @@ import cn.hutool.log.Log; import cn.hutool.log.LogFactory; +import com.fangxuele.tool.push.ui.form.BoostForm; import com.fangxuele.tool.push.ui.form.PushForm; import lombok.extern.slf4j.Slf4j; @@ -29,6 +30,17 @@ public static void consoleWithLog(String log) { logger.warn(log); } + /** + * 输出到性能模式控制台和log + * + * @param log + */ + public static void boostConsoleWithLog(String log) { + BoostForm.boostForm.getConsoleTextArea().append(log + "\n"); + BoostForm.boostForm.getConsoleTextArea().setCaretPosition(BoostForm.boostForm.getConsoleTextArea().getText().length()); + logger.warn(log); + } + /** * 仅输出到控制台 * @@ -38,4 +50,14 @@ public static void consoleOnly(String log) { PushForm.pushForm.getPushConsoleTextArea().append(log + "\n"); PushForm.pushForm.getPushConsoleTextArea().setCaretPosition(PushForm.pushForm.getPushConsoleTextArea().getText().length()); } + + /** + * 仅输出到性能模式控制台 + * + * @param log + */ + public static void boostConsoleOnly(String log) { + BoostForm.boostForm.getConsoleTextArea().append(log + "\n"); + BoostForm.boostForm.getConsoleTextArea().setCaretPosition(BoostForm.boostForm.getConsoleTextArea().getText().length()); + } } diff --git a/src/main/java/com/fangxuele/tool/push/util/UpgradeUtil.java b/src/main/java/com/fangxuele/tool/push/util/UpgradeUtil.java index 083be93c..5c857147 100644 --- a/src/main/java/com/fangxuele/tool/push/util/UpgradeUtil.java +++ b/src/main/java/com/fangxuele/tool/push/util/UpgradeUtil.java @@ -130,7 +130,9 @@ public static void smoothUpgrade() { MybatisUtil.executeSql(sql); } catch (SQLException e) { log.error("执行索引为{}的版本对应的sql时异常", i, e); - return; + if (!e.getMessage().contains("duplicate column")) { + return; + } } } upgrade(i); diff --git a/src/main/resources/db_init.sql b/src/main/resources/db_init.sql index 519cd7de..d6052594 100644 --- a/src/main/resources/db_init.sql +++ b/src/main/resources/db_init.sql @@ -155,6 +155,7 @@ create table if not exists t_msg_mail msg_type integer, msg_name text, title text, + Cc text, files text, content text, create_time datetime, @@ -193,6 +194,7 @@ create table if not exists t_msg_wx_cp img_url text, describe text, url text, + btn_txt text, create_time datetime, modified_time datetime ); diff --git a/src/main/resources/icon/introduce-wepush-qrcode.png b/src/main/resources/icon/introduce-wepush-qrcode.png new file mode 100644 index 00000000..54e221c3 Binary files /dev/null and b/src/main/resources/icon/introduce-wepush-qrcode.png differ diff --git a/src/main/resources/mapper/TMsgMailMapper.xml b/src/main/resources/mapper/TMsgMailMapper.xml index 915470c2..1751636b 100644 --- a/src/main/resources/mapper/TMsgMailMapper.xml +++ b/src/main/resources/mapper/TMsgMailMapper.xml @@ -10,9 +10,10 @@ + - id, msg_type, msg_name, title, files, content, create_time, modified_time + id, msg_type, msg_name, title, files, content, create_time, modified_time, Cc @@ -135,6 +147,7 @@ update t_msg_mail set title = #{title,jdbcType=VARCHAR}, + Cc = #{cc,jdbcType=VARCHAR}, files = #{files,jdbcType=VARCHAR}, content = #{content,jdbcType=VARCHAR}, modified_time = #{modifiedTime,jdbcType=VARCHAR} diff --git a/src/main/resources/mapper/TMsgWxCpMapper.xml b/src/main/resources/mapper/TMsgWxCpMapper.xml index 6186250f..247f69a5 100644 --- a/src/main/resources/mapper/TMsgWxCpMapper.xml +++ b/src/main/resources/mapper/TMsgWxCpMapper.xml @@ -14,10 +14,11 @@ + id, msg_type, msg_name, cp_msg_type, agent_id, content, title, img_url, describe, - url, create_time, modified_time + url, create_time, modified_time, btn_txt @@ -189,6 +202,7 @@ img_url = #{imgUrl,jdbcType=VARCHAR}, describe = #{describe,jdbcType=VARCHAR}, url = #{url,jdbcType=VARCHAR}, + btn_txt = #{btnTxt,jdbcType=VARCHAR}, create_time = #{createTime,jdbcType=VARCHAR}, modified_time = #{modifiedTime,jdbcType=VARCHAR} where msg_type = #{msgType,jdbcType=INTEGER} diff --git a/src/main/resources/upgrade/.gitkeep b/src/main/resources/upgrade/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/resources/upgrade/28.sql b/src/main/resources/upgrade/28.sql new file mode 100644 index 00000000..818d9b41 --- /dev/null +++ b/src/main/resources/upgrade/28.sql @@ -0,0 +1,4 @@ +alter table t_msg_wx_cp + add btn_txt text; +alter table t_msg_mail + add Cc text; \ No newline at end of file diff --git a/src/main/resources/version_summary.json b/src/main/resources/version_summary.json index d0f5f88e..44fbc608 100644 --- a/src/main/resources/version_summary.json +++ b/src/main/resources/version_summary.json @@ -1,5 +1,5 @@ { - "currentVersion": "v_3.4.2_190630", + "currentVersion": "v_3.5.0_190713", "versionIndex": { "v_1.1.0_170701": "0", "v_1.2.0_170831": "1", @@ -28,7 +28,8 @@ "v_3.3.0_190608": "24", "v_3.4.0_190619": "25", "v_3.4.1_190624": "26", - "v_3.4.2_190630": "27" + "v_3.4.2_190630": "27", + "v_3.5.0_190713": "28" }, "versionDetailList": [ { @@ -170,6 +171,11 @@ "version": "v_3.4.2_190630", "title": "新增支持微信企业号/企业微信类型消息", "log": "● feature:新增支持发送微信企业号/企业微信类型消息\n● feature:支持按标签按部门导入企业通讯录员工\n● optimization:低分辨率下自动最大化窗口\n● feature:企业号支持应用管理\n● optimization:外观设置中支持从系统可用字体列表中选择字体+默认字体调整为:微软雅黑\n● fix:修复NICK_NAME变量失效的bug\n" + }, + { + "version": "v_3.5.0_190713", + "title": "新增性能模式", + "log": "● feature:新增性能模式(目前仅支持微信模板消息)\n● feature:计划任务增加可以按Cron表达式触发\n● feature:e-mail消息支持抄送\n● feature:企业微信消息新增对文本卡片类型的支持\n● feature:企业微信消息新增对markdown类型的支持\n● optimization:优化平滑升级时sql执行的幂等\n● bug fix:修复普通计划任务保存时误提示最近5次运行时间的问题\n● fix:修复推送总进度条状态异常问题\n● 其他细节调整\n" } ] } \ No newline at end of file