diff --git a/build.gradle b/build.gradle index 9f6c3dd88b..2c657959ce 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,8 @@ allprojects { implementation 'com.fr.third:fine-third:' + frVersion implementation 'com.fr.core:fine-core:' + frDevVersion implementation 'com.fr.activator:fine-activator:' + frVersion - implementation 'com.fr.datasource:fine-datasource:' + frVersion + implementation 'com.fr.datasource:fine-datasource-api:4.1-SNAPSHOT' + implementation 'com.fr.datasource:fine-datasource-core:4.1-SNAPSHOT' implementation 'com.fr.decision:fine-decision:' + frVersion implementation 'com.fr.schedule:fine-schedule:' + frVersion implementation 'com.fr.report:engine-report:' + frDevVersion diff --git a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java index c95f1e5cab..10e515f9c7 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java @@ -1906,6 +1906,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter, AsyncXmlReada .init("jdkHome", (e) -> this.jdkHome = e.getElementValue()) .init("lastBBSTime", DesignerEnvManager.this::readLastBBSTime) .init("lastBBSNewsTime", DesignerEnvManager.this::readLastBBSNewsTime) + .init("uuid", DesignerEnvManager.this::readUUID) .init("ActivationKey", DesignerEnvManager.this::readActiveKey) .init("status", DesignerEnvManager.this::readActiveStatus) .init(CAS_PARAS, DesignerEnvManager.this::readHttpsParas) diff --git a/designer-base/src/main/java/com/fr/design/carton/CartonConstants.java b/designer-base/src/main/java/com/fr/design/carton/CartonConstants.java new file mode 100644 index 0000000000..c51f1193c5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/carton/CartonConstants.java @@ -0,0 +1,61 @@ +package com.fr.design.carton; + +import com.fr.stable.ProductConstantsBase; +import com.fr.stable.StableUtils; + +import java.text.SimpleDateFormat; + +/** + * 卡顿常量类管理 + * + * @author Levy.Xie + * @since 11.0 + * Created on 2024/07/04 + */ +public class CartonConstants { + + public static final String TIME = "time"; + public static final String APPID = "appId"; + public static final String USERID = "userId"; + public static final String LOCAL = "local"; + public static final String REMOTE = "remote"; + public static final String OPERANDS_NUM = "operands"; + public static final String DESIGN_METHOD = "designMethod"; + public static final String DESIGNER_VERSION = "designerVersion"; + public static final String DESIGNER_ID = "designerId"; + + public static final String EASY_CHECKER_FILE_NAME = "easy_check_log.csv"; + public static final String TIMER_CHECKER_FILE_NAME = "timer_check_log.csv"; + + /** + * 开启间隔检测后两次检测的相隔时间ms + */ + public static final long CHECK_INTERVAL_MS = 100; + + /** + * 最大的事件允许执行时间,超过该时间则打印堆栈等相关信息 + */ + public static final long UNREASONABLE_DISPATCH_DURATION_MS = 1500; + + /** + * UI检测采样频率 + */ + public static final int LATENCY_SAMPLING_FREQUENCY = 100; + + /** + * 输出日志所在地址 + */ + public static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log"); + + /** + * 日期事件格式 + */ + public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + /** + * Designer4Debug类名 + */ + public static final String DEBUG_MAIN_CLASS_NAME = "com.fr.start.Designer4Debug"; + + +} diff --git a/designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java b/designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java index 39525110b3..d366791b25 100644 --- a/designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java +++ b/designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java @@ -57,18 +57,18 @@ public class CartonThreadExecutorPool extends ThreadPoolExecutor { private void examineHang() { StackTraceElement[] currentStack = eventThread.getStackTrace(); - if (lastReportedStack!=null && EventDispatchThreadHangMonitor.stacksEqual(currentStack, lastReportedStack)) { + if (lastReportedStack!=null && CartonUtils.stacksEqual(currentStack, lastReportedStack)) { return; } lastReportedStack = currentStack; - String stackTrace = EventDispatchThreadHangMonitor.stackTraceToString(currentStack); + String stackTrace = CartonUtils.stackTraceToString(currentStack); JSONObject jsonObject = new JSONObject(); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormatThreadSafe.format(System.currentTimeMillis())); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "swingWorker_" + hangNumber); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Duration_Task_Execute"), timeSoFar() + "ms"); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace); - EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG); - EventDispatchThreadHangMonitor.checkForDeadlock(); + CartonUtils.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG); + CartonUtils.checkForDeadlock(); } } @@ -129,7 +129,7 @@ public class CartonThreadExecutorPool extends ThreadPoolExecutor { jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "swingWorker_" + concurrentHashMap.get(currentThreadId).hangNumber); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), simpleDateFormatThreadSafe.format(concurrentHashMap.get(currentThreadId).startTime)); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), runTime + "ms"); - EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG); + CartonUtils.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG); } concurrentHashMap.remove(currentThreadId); diff --git a/designer-base/src/main/java/com/fr/design/carton/CartonUtils.java b/designer-base/src/main/java/com/fr/design/carton/CartonUtils.java new file mode 100644 index 0000000000..df8361662b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/carton/CartonUtils.java @@ -0,0 +1,147 @@ +package com.fr.design.carton; + +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import org.jetbrains.annotations.NotNull; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.text.SimpleDateFormat; + +import static com.fr.design.carton.CartonConstants.EASY_CHECKER_FILE_NAME; +import static com.fr.design.carton.CartonConstants.JOURNAL_FILE_PATH; +import static com.fr.design.carton.CartonConstants.TIMER_CHECKER_FILE_NAME; + +/** + * 设计器卡顿业务工具类 + * + * @author Levy.Xie + * @since 11.0 + * Created on 2024/07/10 + */ +public class CartonUtils { + + /** + * 堆栈元素输出为文本 + * + * @param stackTrace 堆栈元素 + * @return 文本 + */ + public static String stackTraceToString(StackTraceElement[] stackTrace) { + StringBuilder result = new StringBuilder(); + for (StackTraceElement stackTraceElement : stackTrace) { + String indentation = " "; + result.append("~").append(indentation).append(stackTraceElement); + } + return result.toString(); + } + + /** + * 命令行显示堆栈信息 + * + * @param stackTrace 堆栈元素 + * @return 文本 + */ + public static String stackTraceToStringForConsole(StackTraceElement[] stackTrace) { + StringBuilder result = new StringBuilder(); + for (StackTraceElement stackTraceElement : stackTrace) { + String indentation = " "; + result.append("\r\n").append(indentation).append(stackTraceElement); + } + return result.toString(); + } + + /** + * 堆栈是否一致 + * + * @param a 堆栈A + * @param b 堆栈B + * @return 是否一致 + */ + public static boolean stacksEqual(@NotNull StackTraceElement[] a, @NotNull StackTraceElement[] b) { + if (!ArrayUtils.isSameLength(a, b)) { + return false; + } + for (int i = 0; i < a.length; ++i) { + if (!a[i].equals(b[i])) { + return false; + } + } + return true; + } + + /** + * 检查死锁 + */ + public static void checkForDeadlock() { + ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); + long[] threadIds = threadBean.findDeadlockedThreads(); + if (threadIds == null) { + return; + } + FineLoggerFactory.getLogger().warn("deadlock detected involving the following threads:"); + ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE); + for (ThreadInfo info : threadInfos) { + FineLoggerFactory.getLogger().warn("Thread # {} {} ( {} ) waiting on {} held by {} {}", info.getThreadId(), info.getThreadName(), + info.getThreadState(), info.getLockName(), info.getLockOwnerName(), CartonUtils.stackTraceToStringForConsole(info.getStackTrace())); + } + } + + /** + * 输出卡顿日志 + * + * @param message 文本信息 + * @param flag 类型,true时为简单检查、false时为定时检查 + */ + public static void outPutJournalLog(String message, int flag) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String date = simpleDateFormat.format(System.currentTimeMillis()); + String filename = flag == SwitchForSwingChecker.EASY_CHECK_FLAG ? EASY_CHECKER_FILE_NAME : TIMER_CHECKER_FILE_NAME; + String[] split = date.split("-"); + int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]); + String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date); + File dirFile = new File(dirPath); + File file = new File(StableUtils.pathJoin(dirPath, filename)); + try { + if (!file.exists()) { + if (!dirFile.exists()) { + dirFile.mkdirs(); + } + file.createNewFile(); + } + try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, true))) { + String outputMessage = message.replaceAll("~", "\r\n") + "," + "\r\n"; + bufferedWriter.write(outputMessage); + } + } catch (IOException e) { + FineLoggerFactory.getLogger().error("output fail", e); + } + } + + /** + * 用于判断是不是特定的堆栈 + */ + public static boolean stackTraceElementIs(StackTraceElement e, String className, String methodName, boolean isNative) { + return e.getClassName().equals(className) && e.getMethodName().equals(methodName) && e.isNativeMethod() == isNative; + } + + /** + * 用于判断某个堆栈是否在等待另一个事件 + * 取当前堆栈前三层判断是是不是匹配等待堆栈的格式 + */ + public static boolean isWaitingForNextEvent(StackTraceElement[] currentStack) { + + return currentStack != null && currentStack.length >= 3 && + stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true) + && stackTraceElementIs(currentStack[1], "java.lang.Object", "wait", false) + && stackTraceElementIs(currentStack[2], "java.awt.EventQueue", "getNextEvent", false); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java b/designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java index a7bf03b407..988e7dd81d 100644 --- a/designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java +++ b/designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java @@ -1,34 +1,26 @@ package com.fr.design.carton; import com.fr.concurrent.FineExecutors; +import com.fr.design.carton.latency.DesignerLatencyMetric; import com.fr.design.ui.util.UIUtil; import com.fr.json.JSONObject; -import com.fr.log.FineLoggerFactory; -import com.fr.stable.ArrayUtils; -import com.fr.stable.ProductConstantsBase; -import com.fr.stable.StableUtils; -import com.fr.stable.StringUtils; -import org.jetbrains.annotations.NotNull; import javax.swing.SwingUtilities; import java.awt.EventQueue; import java.awt.Toolkit; import java.awt.AWTEvent; import java.awt.event.WindowEvent; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; -import java.text.SimpleDateFormat; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import static com.fr.design.carton.CartonConstants.CHECK_INTERVAL_MS; +import static com.fr.design.carton.CartonConstants.DATE_FORMAT; +import static com.fr.design.carton.CartonConstants.LATENCY_SAMPLING_FREQUENCY; +import static com.fr.design.carton.CartonConstants.UNREASONABLE_DISPATCH_DURATION_MS; + /** * 参考自git swinghelper * 用于卡顿检测 @@ -38,31 +30,16 @@ import java.util.concurrent.TimeUnit; */ public final class EventDispatchThreadHangMonitor extends EventQueue { - /** - * 日期事件格式 - */ - private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + public static final EventDispatchThreadHangMonitor INSTANCE = new EventDispatchThreadHangMonitor(); /** * 一个timer */ private Timer timer; - /** - * 开启间隔检测后两次检测的相隔时间ms - */ - private static final long CHECK_INTERVAL_MS = 100; - /** - * 最大的事件允许执行时间,超过该时间则打印堆栈等相关信息 - */ - private static final long UNREASONABLE_DISPATCH_DURATION_MS = 1500; /** * 事件唯一编码,用于方便日志的查看 */ - private static long hangCount = 0; - /** - * 输出日志所在地址 - */ - private static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log"); + private static long hangCount = 0; /** * 类似于一个开关,当该值为默认的false启动时,定时任务在窗口开启前都不会对执行的事件进行检查 */ @@ -103,43 +80,6 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { return hangCount++; } - /** - * @param a can not be null - * @param b can not be null - * @return - */ - public static boolean stacksEqual(@NotNull StackTraceElement[] a, @NotNull StackTraceElement[] b) { - - if (!ArrayUtils.isSameLength(a, b)) { - return false; - } - for (int i = 0; i < a.length; ++i) { - if (!a[i].equals(b[i])) { - return false; - } - } - return true; - } - - /** - * 用于判断是不是特定的堆栈 - */ - public static boolean stackTraceElementIs(StackTraceElement e, String className, String methodName, boolean isNative) { - return e.getClassName().equals(className) && e.getMethodName().equals(methodName) && e.isNativeMethod() == isNative; - } - - /** - * 用于判断某个堆栈是否在等待另一个事件 - * 取当前堆栈前三层判断是是不是匹配等待堆栈的格式 - */ - public static boolean isWaitingForNextEvent(StackTraceElement[] currentStack) { - - return currentStack != null && currentStack.length >= 3 && - stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true) - && stackTraceElementIs(currentStack[1], "java.lang.Object", "wait", false) - && stackTraceElementIs(currentStack[2], "java.awt.EventQueue", "getNextEvent", false); - } - /** * event事件的包装类 */ @@ -153,11 +93,13 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { //事件开始的时间 private final long startDispatchTimeMillis = System.currentTimeMillis(); //事件编号 - private long hangNumber; + private final long hangNumber; + //构造函数,给当前对象赋一个递增的唯一编号 - public DispatchInfo() { + public DispatchInfo() { hangNumber = getHangCount(); } + //定时调度任务检测的入口,如果执行时间大于设定的值就进入examineHang()方法 public void checkForHang() { if (timeSoFar() > UNREASONABLE_DISPATCH_DURATION_MS) { @@ -168,36 +110,38 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { private void examineHang() { //获取执行线程的当前堆栈 StackTraceElement[] currentStack = eventDispatchThread.getStackTrace(); - if (isWaitingForNextEvent(currentStack)) { + if (CartonUtils.isWaitingForNextEvent(currentStack)) { return; } //某个事件执行时间很长,定时处理时可能会连续打很多个堆栈,对同一个事件的相同堆栈只打一次 - if (lastReportedStack !=null && stacksEqual(lastReportedStack, currentStack)) { + if (lastReportedStack != null && CartonUtils.stacksEqual(lastReportedStack, currentStack)) { return; } - String stackTrace = stackTraceToString(currentStack); + String stackTrace = CartonUtils.stackTraceToString(currentStack); lastReportedStack = currentStack; JSONObject jsonObject = new JSONObject(); - jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormat.format(System.currentTimeMillis())); + jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), DATE_FORMAT.format(System.currentTimeMillis())); jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "eventQueue_" + hangNumber); jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Duration_Task_Execute"), timeSoFar() + "ms"); jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace); - outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG); - checkForDeadlock(); + CartonUtils.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG); + CartonUtils.checkForDeadlock(); } + //记录连续运行了多长时间 - private long timeSoFar() { + public long timeSoFar() { return (System.currentTimeMillis() - lastDispatchTimeMillis); } + //记录一个事件从被分发到结束的总运行时间 - private long totalTime() { + public long totalTime() { return (System.currentTimeMillis() - startDispatchTimeMillis); } //事件处理完后的时间判断 public void dispose() { if (timeSoFar() > UNREASONABLE_DISPATCH_DURATION_MS) { exportCartonLog(true); - } else if (lastReportedStack != null){ + } else if (lastReportedStack != null) { exportCartonLog(false); } } @@ -208,40 +152,15 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { */ private void exportCartonLog(boolean flag) { JSONObject jsonObject = new JSONObject(); - jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormat.format(System.currentTimeMillis())); + jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), DATE_FORMAT.format(System.currentTimeMillis())); jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "eventQueue_" + hangNumber); - jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), simpleDateFormat.format(startDispatchTimeMillis)); + jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), DATE_FORMAT.format(startDispatchTimeMillis)); if (flag) { jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), timeSoFar() + "ms"); } else { jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), totalTime() + "ms"); } - outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG); - } - } - - public static void outPutJournalLog(String message, int flag) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - String date = simpleDateFormat.format(System.currentTimeMillis()); - String filename = flag == SwitchForSwingChecker.EASY_CHECK_FLAG ? SwitchForSwingChecker.EASY_CHECKER_FILE_NAME: SwitchForSwingChecker.TIMER_CHECKER_FILE_NAME; - String[] split = date.split("-"); - int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]); - String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date); - File dirFile = new File(dirPath); - File file = new File( StableUtils.pathJoin(dirPath, filename)); - try { - if (!file.exists()) { - if (!dirFile.exists()) { - dirFile.mkdirs(); - } - file.createNewFile(); - } - BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, true)); - String outputMessage = new StringBuilder(message.replaceAll("~", "\r\n")).append(",").append("\r\n").toString(); - bufferedWriter.write(outputMessage); - bufferedWriter.close(); - } catch (IOException e) { - FineLoggerFactory.getLogger().error("output fail", e); + CartonUtils.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG); } } @@ -325,8 +244,7 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { */ @Override protected void dispatchEvent(AWTEvent event) { - //如果两个开关都没开,那就不走重写方法了 - if (!isEasyWitch() && !isTimerWitch()) { + if (!useCustomEventQueue()) { super.dispatchEvent(event); } else { try { @@ -342,6 +260,18 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } } + private boolean useCustomEventQueue() { + // 开启性能监控或开启卡顿工具箱,则走自定义的EventQueue + return SwitchForSwingChecker.isLatencyMonitoring() || + isEasyWitch() || isTimerWitch(); + } + + private boolean needSampling() { + // UI性能采样逻辑:开启采样并且符合采样频次 + return SwitchForSwingChecker.isLatencyMonitoring() + && (hangCount % LATENCY_SAMPLING_FREQUENCY == 0); + } + /** * Starts tracking a dispatch. */ @@ -357,6 +287,9 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { private synchronized void postDispatchEvent() { synchronized (dispatches) { DispatchInfo justFinishedDispatch = dispatches.removeLast(); + if (needSampling()) { + DesignerLatencyMetric.getInstance().record(justFinishedDispatch.timeSoFar()); + } if (isEasyWitch()) { justFinishedDispatch.dispose(); } @@ -370,39 +303,4 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } } - /** - * 检查死锁 - */ - public static void checkForDeadlock() { - ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); - long[] threadIds = threadBean.findDeadlockedThreads(); - if (threadIds == null) { - return; - } - FineLoggerFactory.getLogger().warn("deadlock detected involving the following threads:"); - ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE); - for (ThreadInfo info : threadInfos) { - FineLoggerFactory.getLogger().warn("Thread # {} {} ( {} ) waiting on {} held by {} {}", info.getThreadId(), info.getThreadName(), - info.getThreadState(), info.getLockName(), info.getLockOwnerName(), stackTraceToStringForConsole(info.getStackTrace())); - } - } - - public static String stackTraceToString(StackTraceElement[] stackTrace) { - StringBuilder result = new StringBuilder(); - for (StackTraceElement stackTraceElement : stackTrace) { - String indentation = " "; - result.append("~").append(indentation).append(stackTraceElement); - } - return result.toString(); - } - - public static String stackTraceToStringForConsole(StackTraceElement[] stackTrace) { - StringBuilder result = new StringBuilder(); - for (StackTraceElement stackTraceElement : stackTrace) { - String indentation = " "; - result.append("\r\n").append(indentation).append(stackTraceElement); - } - return result.toString(); - } - } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java b/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java index a3e01ecf02..9c0e7c8095 100644 --- a/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java +++ b/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java @@ -50,6 +50,8 @@ import java.text.ParseException; import java.util.List; import java.util.Objects; +import static com.fr.design.carton.CartonConstants.JOURNAL_FILE_PATH; + public class FeedbackToolboxDialog extends JDialog { private UIDatePicker uiDatePicker; @@ -148,7 +150,7 @@ public class FeedbackToolboxDialog extends JDialog { //selectDate 2002-03-09例子 String[] split = selectDate.split("-"); int month = Integer.parseInt(split[1]); - String sourceFilePath = StableUtils.pathJoin(SwitchForSwingChecker.JOURNAL_FILE_PATH, split[0], "month-" + month, selectDate); + String sourceFilePath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, selectDate); File sourceFile = new File(sourceFilePath); if (sourceFile.exists()) { exportCartonLog(sourceFile, path, sourceFilePath); diff --git a/designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java b/designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java index 683179293e..758017465d 100644 --- a/designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java +++ b/designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java @@ -7,7 +7,6 @@ import com.fr.json.JSON; import com.fr.json.JSONArray; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; -import com.fr.stable.ProductConstantsBase; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import com.fr.stable.xml.XMLPrintWriter; @@ -29,11 +28,13 @@ import java.util.Map; import java.util.Date; import java.util.Calendar; +import static com.fr.design.carton.CartonConstants.DEBUG_MAIN_CLASS_NAME; +import static com.fr.design.carton.CartonConstants.EASY_CHECKER_FILE_NAME; +import static com.fr.design.carton.CartonConstants.JOURNAL_FILE_PATH; +import static com.fr.design.carton.CartonConstants.TIMER_CHECKER_FILE_NAME; + public class SwitchForSwingChecker implements XMLReadable, XMLWriter { - /** - * Designer4Debug类名 - */ - private static final String DEBUG_MAIN_CLASS_NAME = "com.fr.start.Designer4Debug"; + /** * XML标签 */ @@ -46,18 +47,16 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter { * 简单记录事件执行时间的开关 */ private static boolean easyChecker = false; + /** + * UI性能监控埋点的开关 + */ + private static boolean latencyMonitor = true; /** * 一个标识位用于区分耗时任务时长检测(简单检测)和timer检测 */ public static final int TIMER_CHECK_FLAG = 0; public static final int EASY_CHECK_FLAG = 1; - /** - * 日志存储地址 - */ - public static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log"); - public static final String EASY_CHECKER_FILE_NAME = "easy_check_log.csv"; - public static final String TIMER_CHECKER_FILE_NAME = "timer_check_log.csv"; public static boolean isCheckerTimerSwitch() { return checkerTimerSwitch; } @@ -66,6 +65,13 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter { return easyChecker; } + /** + * 是否开启UI性能检测 + */ + public static boolean isLatencyMonitoring() { + return latencyMonitor; + } + public static volatile SwitchForSwingChecker switchForSwingChecker = new SwitchForSwingChecker(); public static SwitchForSwingChecker getInstance() { @@ -137,7 +143,7 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter { } /** - *处理文件 + * 处理文件 * 一共四种情况, * 两个文件都不存在 * 文件一存在,文件二不存在 @@ -224,7 +230,7 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter { /** * /埋点方法上传卡顿信息入口 - date为 2022-09-08的格式 + * date为 2022-09-08的格式 */ public static List uploadJournalLog(Date dateTime) { List res = new ArrayList<>(); @@ -245,9 +251,8 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter { /** * 初始化监控任务,主要是替换EventQueue以及SwingWorker执行任务的线程池 - * */ - public static void initThreadMonitoring () { + public static void initThreadMonitoring() { String mainClass = System.getProperty("sun.java.command"); //判断一下,如果是以Designer4Debug启动,就不注册代码,不然会覆盖掉SwingExplorer,导致其无法使用 if (!StringUtils.equals(mainClass, DEBUG_MAIN_CLASS_NAME)) { @@ -293,6 +298,7 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter { if (reader.isAttr()) { checkerTimerSwitch = reader.getAttrAsBoolean("checkerTimerSwitch", false); easyChecker = reader.getAttrAsBoolean("easyChecker", false); + latencyMonitor = reader.getAttrAsBoolean("latencyMonitor", true); } try { initSwitchChecker(); @@ -306,6 +312,7 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter { writer.startTAG(XML_TAG); writer.attr("checkerTimerSwitch", checkerTimerSwitch); writer.attr("easyChecker", easyChecker); + writer.attr("latencyMonitor", latencyMonitor); writer.end(); } diff --git a/designer-base/src/main/java/com/fr/design/carton/latency/DesignerLatencyMetric.java b/designer-base/src/main/java/com/fr/design/carton/latency/DesignerLatencyMetric.java new file mode 100644 index 0000000000..75fa28ef1e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/carton/latency/DesignerLatencyMetric.java @@ -0,0 +1,174 @@ +package com.fr.design.carton.latency; + +import com.fr.concurrent.NamedThreadFactory; +import com.fr.config.MarketConfig; +import com.fr.design.DesignerEnvManager; +import com.fr.design.carton.SwitchForSwingChecker; +import com.fr.design.mainframe.SiteCenterToken; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.general.CloudCenter; +import com.fr.general.GeneralUtils; +import com.fr.general.http.HttpToolbox; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.Workspace; +import com.fr.workspace.WorkspaceEvent; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static com.fr.design.carton.CartonConstants.APPID; +import static com.fr.design.carton.CartonConstants.DESIGNER_ID; +import static com.fr.design.carton.CartonConstants.DESIGNER_VERSION; +import static com.fr.design.carton.CartonConstants.DESIGN_METHOD; +import static com.fr.design.carton.CartonConstants.LOCAL; +import static com.fr.design.carton.CartonConstants.OPERANDS_NUM; +import static com.fr.design.carton.CartonConstants.REMOTE; +import static com.fr.design.carton.CartonConstants.TIME; +import static com.fr.design.carton.CartonConstants.USERID; + +/** + * 设计器延迟时间记录Metric + * + * @author Levy.Xie + * @since 11.0 + * Created on 2024/07/01 + */ +public class DesignerLatencyMetric { + + private String latencyUrl; + private ExecutorService executorService; + private ScheduledExecutorService scheduler; + private static final Map LATENCY_CONTAINER = new ConcurrentHashMap<>(); + + private static final String DEFAULT_MONITOR_URL = "https://cloud.fanruan.com/api/monitor/"; + private static final String LATENCY_TABLE_SUFFIX = "record_of_designer_latency/single"; + + private final static class InstanceHolder { + static final DesignerLatencyMetric INSTANCE = new DesignerLatencyMetric(); + } + + /** + * 获取单例 + */ + public static DesignerLatencyMetric getInstance() { + return DesignerLatencyMetric.InstanceHolder.INSTANCE; + } + + private DesignerLatencyMetric() { + } + + /** + * 启动 + */ + public void start() { + if (SwitchForSwingChecker.isLatencyMonitoring()) { + // 初始化容器 + initializeContainer(); + // 启动异步性能记录线程池 + executorService = Executors.newFixedThreadPool(8); + // 启动定时埋点 + this.scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("LatencyMetricWorker")); + this.scheduler.scheduleWithFixedDelay(this::collectAndSubmit, 60, 60, TimeUnit.MINUTES); + // 注册设计器工作目录切换事件监听 + EventDispatcher.listen(WorkspaceEvent.BeforeSwitch, new Listener() { + @Override + public void on(Event event, Workspace param) { + collectAndSubmit(); + } + }); + FineLoggerFactory.getLogger().info("[Latency] designer latency metric started."); + } + } + + /** + * 关闭 + */ + public void stop() { + if (SwitchForSwingChecker.isLatencyMonitoring()) { + if (this.executorService != null) { + this.executorService.shutdown(); + } + if (this.scheduler != null) { + this.scheduler.shutdown(); + } + collectAndSubmit(); + FineLoggerFactory.getLogger().info("[Latency] designer latency metric stopped."); + } + } + + private String getLatencyUrl() { + if (StringUtils.isEmpty(latencyUrl)) { + String monitorEntry = CloudCenter.getInstance().acquireUrlByKind("cloud.monitor.api.entrypoint"); + latencyUrl = (StringUtils.isNotEmpty(monitorEntry) ? monitorEntry : DEFAULT_MONITOR_URL) + + LATENCY_TABLE_SUFFIX; + } + return latencyUrl; + } + + private void initializeContainer() { + for (LatencyLevel level : LatencyLevel.values()) { + LATENCY_CONTAINER.put(level, new AtomicInteger()); + } + } + + private void resetContainer() { + LATENCY_CONTAINER.values().forEach(count -> count.set(0)); + } + + /** + * 记录性能信息 + */ + public void record(long cost) { + executorService.submit(() -> { + try { + LatencyLevel level = LatencyLevel.measure(cost); + LATENCY_CONTAINER.computeIfAbsent(level, k -> new AtomicInteger()).incrementAndGet(); + } catch (Throwable ignore) { + // 记录失败不影响业务 + } + }); + } + + /** + * 汇总并提交性能监控埋点 + */ + public void collectAndSubmit() { + Map para = new HashMap<>(); + para.put("token", SiteCenterToken.generateToken()); + para.put("content", collect()); + try { + HttpToolbox.post(getLatencyUrl(), para); + FineLoggerFactory.getLogger().debug("[Latency] submit latency log to cloud."); + } catch (Throwable t) { + FineLoggerFactory.getLogger().debug(t,"[Latency] failed to submit latency log to cloud."); + } + resetContainer(); + } + + private JSONObject collect() { + JSONObject info = new JSONObject(); + info.put(TIME, System.currentTimeMillis()); + info.put(APPID, MarketConfig.getInstance().getCloudOperationMaintenanceId()); + info.put(USERID, MarketConfig.getInstance().getBbsUid()); + info.put(DESIGNER_ID, DesignerEnvManager.getEnvManager().getUUID()); + info.put(DESIGNER_VERSION, GeneralUtils.getVersion()); + info.put(DESIGN_METHOD, WorkContext.getCurrent().isLocal() ? LOCAL : REMOTE); + info.put(OPERANDS_NUM, LATENCY_CONTAINER.values().stream().mapToInt(AtomicInteger::get).sum()); + for (Map.Entry entry : LATENCY_CONTAINER.entrySet()) { + info.put(entry.getKey().getMark(), entry.getValue().get()); + } + return info; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/carton/latency/LatencyLevel.java b/designer-base/src/main/java/com/fr/design/carton/latency/LatencyLevel.java new file mode 100644 index 0000000000..f190bb883d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/carton/latency/LatencyLevel.java @@ -0,0 +1,65 @@ +package com.fr.design.carton.latency; + +/** + * 卡顿等级 + * + * @author Levy.Xie + * @since 11.0 + * Created on 2024/07/01 + */ +public enum LatencyLevel { + + // 非常流畅 + FLASH(0, 50, "waitNum1"), + // 流畅 + SMOOTH(50, 100, "waitNum2"), + // 轻微卡顿 + SLIGHT(100, 200, "waitNum3"), + // 中等卡顿 + MILD(200, 500, "waitNum4"), + // 明显卡顿 + NOTICEABLE(500, 1000, "waitNum5"), + // 严重卡顿 + SERVE(1000, 2000, "waitNum6"), + // 非常严重卡顿 + EXTREME(2000, 3000, "waitNum7"), + // 极度卡顿 + CRITICAL(3000, Long.MAX_VALUE, "waitNum8"); + + final long start; + final long end; + final String mark; + + LatencyLevel(long start, long end, String mark) { + this.start = start; + this.end = end; + this.mark = mark; + } + + public long getStart() { + return start; + } + + public long getEnd() { + return end; + } + + public String getMark() { + return mark; + } + + /** + * 评估当前卡顿等级 + * + * @param cost UI-EventQueue响应耗时 + * @return 卡顿等级 + */ + public static LatencyLevel measure(long cost) { + for (LatencyLevel level : LatencyLevel.values()) { + if (cost >= level.getStart() && cost < level.getEnd()) { + return level; + } + } + return CRITICAL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java index e0a3ca99e6..ded01fa3b1 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java @@ -355,7 +355,6 @@ public class ChoosePane extends BasicBeanPane implements Refresha */ @Override public void refresh() { - DBUtils.refreshDatabase(); String schema = StringUtils.isEmpty(schemaBox.getSelectedItem()) ? null : schemaBox.getSelectedItem(); DataCoreUtils.refreshTables(getConnection(), TableProcedure.TABLE, schema); FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh_Successfully") + "!", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh_Database"), diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java index 5a0515a59e..76b032ee3d 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java @@ -1,5 +1,7 @@ package com.fr.design.data.datapane.preview.desensitization.view.rule; +import com.fine.swing.ui.layout.Column; +import com.fine.swing.ui.layout.Layouts; import com.fr.data.desensitize.rule.base.DesensitizationCondition; import com.fr.data.desensitize.rule.base.DesensitizationRule; import com.fr.data.desensitize.rule.base.DesensitizationRuleSource; @@ -28,6 +30,10 @@ import java.awt.event.FocusListener; import java.util.Arrays; import java.util.Set; +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.column; +import static com.fine.swing.ui.layout.Layouts.row; + /** * 脱敏规则编辑页 * @@ -157,26 +163,29 @@ public class DesensitizationRuleEditPane extends BasicBeanPane column = column( + 4, + row( + cell(new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_One") + StringUtils.BLANK)), + cell(retainFrontTextField), + cell(new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Two") + StringUtils.BLANK)), + cell(retainBackTextField), + cell(new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Four") + StringUtils.BLANK)) + ), + row( + cell(new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Three") + StringUtils.BLANK)), + cell(firstSymbolTextField) + ) + ); // 整体替换 JPanel characterAllReplacePane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); UILabel allReplaceLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_All_Character_Replace_By") + StringUtils.BLANK); @@ -186,7 +195,7 @@ public class DesensitizationRuleEditPane extends BasicBeanPane implemen private void refreshParameters() { String[] paramTexts = new String[2]; - paramTexts[0] = SqlUtils.tryPureSqlText(this.sqlTextPane.getText()); - paramTexts[1] = SqlUtils.tryPureSqlText(this.pageQuery); + paramTexts[0] = SqlUtils.clearSqlComments(this.sqlTextPane.getText()); + paramTexts[1] = SqlUtils.clearSqlComments(this.pageQuery); List existParameterList = this.editorPane.update(); Parameter[] ps = (existParameterList == null) ? new Parameter[0] : existParameterList.toArray(new Parameter[0]); diff --git a/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java b/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java index d45c4c1813..cb4d5550f7 100644 --- a/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java +++ b/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java @@ -32,7 +32,7 @@ public abstract class EditLockChangeChecker { */ public void start() { this.scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("EditLockChangeChecker")); - this.scheduler.scheduleAtFixedRate(new Runnable() { + this.scheduler.scheduleWithFixedDelay(new Runnable() { @Override public void run() { // 判断是否为远程设计环境 diff --git a/designer-base/src/main/java/com/fr/design/file/DefaultTemplateTreeDefineProcessor.java b/designer-base/src/main/java/com/fr/design/file/DefaultTemplateTreeDefineProcessor.java index 39ce819dd6..d96675c941 100644 --- a/designer-base/src/main/java/com/fr/design/file/DefaultTemplateTreeDefineProcessor.java +++ b/designer-base/src/main/java/com/fr/design/file/DefaultTemplateTreeDefineProcessor.java @@ -422,7 +422,9 @@ public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefi dialog.setVisible(true); DesignerFrameFileDealerPane.getInstance().getSelectedOperation().refresh(); - LocateAction.gotoEditingTemplateLeaf(targetFile); + SwingUtilities.invokeLater(() -> { + LocateAction.gotoEditingTemplateLeaf(targetFile); + }); } } diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java index cb4ff46cdd..44fba28f5a 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java @@ -121,6 +121,9 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li for (int i = 0, size = widget.getListenerSize(); i < size; i++) { Listener listener = widget.getListener(i); if (!listener.isDefault()) { + if (StringUtils.isEmpty(listener.getEventName())) { + continue; + } String eventName = switchLang(listener.getEventName()) + (nameObjectList.size() + 1); NameObject nameObject = new NameObject(eventName, listener); nameObjectList.add(nameObject); diff --git a/designer-base/src/main/java/com/fr/design/login/message/DesignerMessageHelper.java b/designer-base/src/main/java/com/fr/design/login/message/DesignerMessageHelper.java index f3768629b4..58960d170c 100644 --- a/designer-base/src/main/java/com/fr/design/login/message/DesignerMessageHelper.java +++ b/designer-base/src/main/java/com/fr/design/login/message/DesignerMessageHelper.java @@ -77,6 +77,7 @@ public class DesignerMessageHelper { String url = CloudCenter.getInstance().acquireUrlByKind("designer.message.push", "https://market.fanruan.com/api/v1/message/designer"); Map params = new HashMap<>(); params.put("designerId", DesignerEnvManager.getEnvManager().getUUID()); + params.put("lang", DesignerEnvManager.getEnvManager().getLanguage().toString()); String result = HttpToolbox.post(url, params); JSONObject response = JSONFactory.createJSON(JSON.OBJECT, result); String status = response.optString(STATUS); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java index afa1a3bcb2..e20debacb7 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java @@ -11,6 +11,7 @@ import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.core.ActionFactory; import com.fr.design.base.mode.DesignModeContext; import com.fr.design.base.mode.DesignerMode; +import com.fr.design.carton.latency.DesignerLatencyMetric; import com.fr.design.constants.UIConstants; import com.fr.design.data.DesignTableDataManager; import com.fr.design.data.datapane.TableDataTreePane; @@ -1161,6 +1162,7 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta }); DesignerEnvManager.getEnvManager().saveXMLFile(); + DesignerLatencyMetric.getInstance().stop(); } /** diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index 0a99b80b20..27e6c1bd69 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -7,6 +7,7 @@ import com.fr.base.extension.FileExtension; import com.fr.base.info.TemplateSaveInfoContext; import com.fr.base.io.BaseBook; import com.fr.base.iofile.attr.DesignBanCopyAttrMark; +import com.fr.base.iofile.attr.ForkIdAttrMark; import com.fr.base.iofile.attr.TemplateIdAttrMark; import com.fr.base.iofile.attr.TemplateThemeAttrMark; import com.fr.base.svg.IconUtils; @@ -342,6 +343,18 @@ public abstract class JTemplate> generateTemplateId(); } + /** + * 如果没有 forkId, 则计算 forkId + * 要求在 templateId, 创建后执行。 + */ + protected void computeForkIdIfAbsent() { + + ForkIdAttrMark forkIdAttrMark = this.template.getAttrMark(ForkIdAttrMark.XML_TAG); + if (forkIdAttrMark == null || StringUtils.isEmpty(forkIdAttrMark.getForkId())) { + this.template.addAttrMark(new ForkIdAttrMark(this.template.getTemplateID())); + } + } + /** * 收集图表信息 */ @@ -970,6 +983,7 @@ public abstract class JTemplate> } // 在保存之前,初始化 templateID generateNewTemplateIdForSaveAs(); + computeForkIdIfAbsent(); this.editingFILE = editingFILE; TemplateSaveInfoContext.getInstance().startCollect(template); @@ -1862,6 +1876,8 @@ public abstract class JTemplate> } // 在保存之前,初始化 templateID generateNewTemplateIdForSaveAs(); + computeForkIdIfAbsent(); + this.editingFILE = editingFILE; boolean result = this.saveToNewRealFile(oldName); if (result) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStyleDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStyleDefinePane.java index 8008c5ce8e..e1af0670a8 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStyleDefinePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStyleDefinePane.java @@ -8,6 +8,7 @@ import com.fr.design.gui.icombobox.LineComboBox; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayoutHelper; @@ -210,7 +211,7 @@ public class MobileStyleDefinePane extends BasicBeanPane { private UILabel createConfigLabel(String title) { UILabel label = new UILabel(title + ":", UILabel.RIGHT); - label.setPreferredSize(new Dimension(75, 20)); + label.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.mainframe.mobile.ui.MobileStyleDefinePane.configLabel")); return label; } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java index a2e8d0656f..fae27d5e93 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java @@ -4,6 +4,7 @@ import com.fr.design.constants.LayoutConstants; import com.fr.design.designer.IntervalConstants; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.widget.UITitleSplitLine; import com.fr.design.style.color.NewColorSelectBox; @@ -44,7 +45,7 @@ public class DesignerUtils { public static UILabel createConfigLabel(String title) { UILabel label = new UILabel(title, UILabel.RIGHT); - label.setPreferredSize(new Dimension(100, 20)); + label.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.mainframe.mobile.utils.DesignerUtils.configLabel")); return label; } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java index a4ddfcd4e8..e2c94a8f10 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java @@ -88,8 +88,9 @@ public class MonitorAdvice implements DesignerAnalyzerAdvice { MessageRecorderFactory.getInstance().syncSubmit(message); } } - } catch (Exception ignore) { + } catch (Exception ex) { //埋点信息入库失败应该不能影响业务流程 + FineLoggerFactory.getLogger().debug("[Metric] failed to log message.", ex); } finally { sessionBinder.detachSession(); } @@ -113,7 +114,11 @@ public class MonitorAdvice implements DesignerAnalyzerAdvice { } public static void recordSQLDetail(String uuid) { - DBMeterFactory.getMeter().submit(uuid); + try { + DBMeterFactory.getMeter().submit(uuid); + } catch (Exception e) { + FineLoggerFactory.getLogger().debug("[Metric] failed to log sql detail.", e); + } } public static void recordSQL(Compute once, MeasureObject measureObject) { diff --git a/designer-base/src/main/java/com/fr/design/style/background/image/ImagePreviewPane.java b/designer-base/src/main/java/com/fr/design/style/background/image/ImagePreviewPane.java index bc4f3f41cc..f24fed4ba0 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/image/ImagePreviewPane.java +++ b/designer-base/src/main/java/com/fr/design/style/background/image/ImagePreviewPane.java @@ -9,6 +9,7 @@ import com.fr.base.Style; import com.fr.design.gui.iscrollbar.UIScrollBar; import com.fr.general.ImageWithSuffix; +import com.fr.log.FineLoggerFactory; import com.fr.stable.CoreGraphHelper; import javax.swing.JComponent; @@ -92,9 +93,14 @@ public class ImagePreviewPane extends JComponent implements Scrollable, ImagePre isLoading = false; CoreGraphHelper.waitForImage(image); - imageWidth = image.getWidth(null); - imageHeight = image.getHeight(null); - + if (image.getFineImage() != null && image.getImage() != null) { + try { + imageWidth = image.getWidth(null); + imageHeight = image.getHeight(null); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } this.setToolTipText("Image Size: " + imageWidth + "x" + imageHeight + "px"); } fireChangeListener(); diff --git a/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java b/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java index 40a386ae30..29327a557c 100644 --- a/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java +++ b/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java @@ -13,6 +13,7 @@ import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.ActionLabel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; diff --git a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java index ea06248163..178c322ba7 100644 --- a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java @@ -329,7 +329,7 @@ public class DesignUtils { @Override protected FRFont compute() { FRFont guiFRFont; - Locale defaultLocale = Locale.getDefault(); + Locale defaultLocale = GeneralContext.getLocale(); // JDK9 之后宋体在计算label中字母的空间上出现问题,暂时先用雅黑兼容,以后再统一字体 if (StableUtils.getMajorJavaVersion() >= 9 && OperatingSystem.isWindows()) { guiFRFont = getNamedFont("Microsoft YaHei"); diff --git a/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java b/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java index c3c087b4db..4bc1794561 100644 --- a/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java @@ -18,13 +18,23 @@ public class AdjustWorkBookDefaultStyleUtils { private static final Color TEMPLATE_BACKGROUND = new Color(16, 11, 43); private static final Color CELL_ELEMENT_BORDER = new Color(110, 110, 110); private static final Color CELL_ELEMENT_FONT_FOREGROUND = Color.WHITE; + private static final Color CELL_ELEMENT_FONT_FOREGROUND_4_LIGHT_THEME = Color.BLACK; private static Color currentStoryBack = null; + private static boolean isDarkTheme = true; public static void setCurrentStoryBack(Color color) { currentStoryBack = color; } + public static void setIsDarkTheme(boolean isDarkTheme) { + AdjustWorkBookDefaultStyleUtils.isDarkTheme = isDarkTheme; + } + + private static Color getCellForegroundColor() { + return isDarkTheme ? CELL_ELEMENT_FONT_FOREGROUND : CELL_ELEMENT_FONT_FOREGROUND_4_LIGHT_THEME; + } + private static Color getCurrentStoryBack() { return currentStoryBack == null ? TEMPLATE_BACKGROUND : currentStoryBack; } @@ -39,7 +49,7 @@ public class AdjustWorkBookDefaultStyleUtils { public static Style adjustCellElement(Style style) { if (DesignModeContext.isDuchampMode()) { - style = style.deriveFRFont(style.getFRFont().applyForeground(CELL_ELEMENT_FONT_FOREGROUND)); + style = style.deriveFRFont(style.getFRFont().applyForeground(getCellForegroundColor())); style = style.deriveBorder(0, CELL_ELEMENT_BORDER, 0, CELL_ELEMENT_BORDER, 0, CELL_ELEMENT_BORDER, @@ -49,7 +59,7 @@ public class AdjustWorkBookDefaultStyleUtils { } public static Color adjustCellElementFontForeground(Color color) { - return DesignModeContext.isDuchampMode() ? CELL_ELEMENT_FONT_FOREGROUND : color; + return DesignModeContext.isDuchampMode() ? getCellForegroundColor() : color; } public static void adjustFloatElement(FloatElement floatElement) { diff --git a/designer-base/src/main/java/com/fr/design/widget/component/NumberEditorValidatePane.java b/designer-base/src/main/java/com/fr/design/widget/component/NumberEditorValidatePane.java index 3196769942..3bd408b90c 100644 --- a/designer-base/src/main/java/com/fr/design/widget/component/NumberEditorValidatePane.java +++ b/designer-base/src/main/java/com/fr/design/widget/component/NumberEditorValidatePane.java @@ -251,7 +251,6 @@ public class NumberEditorValidatePane extends JPanel { allowNegativeCheckBox.setSelected(e.isAllowNegative()); if (AssistUtils.equals(e.getMaxValue(),Double.MAX_VALUE)) { setMaxValueCheckBox.setSelected(false); - maxValueSpinner.setValue(Double.MAX_VALUE); maxValueSpinner.setEnabled(false); } else { setMaxValueCheckBox.setSelected(true); @@ -261,7 +260,6 @@ public class NumberEditorValidatePane extends JPanel { if (AssistUtils.equals(e.getMinValue(),-Double.MAX_VALUE)) { setMinValueCheckBox.setSelected(false); - minValueSpinner.setValue(-Double.MAX_VALUE); minValueSpinner.setEnabled(false); } else { diff --git a/designer-base/src/main/java/com/fr/design/write/submit/DBManipulationPane.java b/designer-base/src/main/java/com/fr/design/write/submit/DBManipulationPane.java index 5de1d0d052..57e24e1fe2 100644 --- a/designer-base/src/main/java/com/fr/design/write/submit/DBManipulationPane.java +++ b/designer-base/src/main/java/com/fr/design/write/submit/DBManipulationPane.java @@ -35,6 +35,7 @@ import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilist.CheckBoxList; import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.i18n.Toolkit; import com.fr.design.javascript.JavaScriptActionPane; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; @@ -318,7 +319,10 @@ public class DBManipulationPane extends BasicBeanPane { cr.setForeground(UIConstants.NORMAL_BACKGROUND); JScrollPane jp = new JScrollPane(conditionsTree); jp.setPreferredSize(FineUIScale.scale(new Dimension(0, 40))); - UIButton addSubmitConditionButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Set_Submit_Condition")); + addComponent(conditionPane, jp); + String submitCondition = Toolkit.i18nText("Fine-Design_Basic_Set_Submit_Condition"); + UIButton addSubmitConditionButton = new UIButton(submitCondition); + addSubmitConditionButton.setToolTipText(submitCondition); addSubmitConditionButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java index 8bae70e837..4af7b9b6d1 100644 --- a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java @@ -1,11 +1,15 @@ package com.fr.widgettheme.theme.edit.widget; +import com.fine.swing.ui.layout.Column; import com.fr.base.background.ColorBackground; import com.fr.base.theme.TemplateTheme; import com.fr.design.gui.icombobox.LineComboBox; import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; import com.fr.design.style.color.NewColorSelectBox; import com.fr.design.utils.DesignUtils; +import com.fr.design.widget.FRWidgetFactory; import com.fr.locale.InterProviderFactory; import com.fr.stable.StringUtils; import com.fr.util.ColorUtils; @@ -13,8 +17,6 @@ import com.fr.widgettheme.theme.widget.style.BorderStyle; import com.fr.widgettheme.theme.widget.style.ButtonBackgroundStyle; import com.fr.widgettheme.theme.widget.style.ThemeTextStyle; import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.i18n.Toolkit; import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; import com.fr.widgettheme.util.WidgetStyleComponentCombiner; import com.fr.widgettheme.util.WidgetThemeDesignerUtils; @@ -22,6 +24,9 @@ import com.fr.widgettheme.util.WidgetThemeDesignerUtils; import java.awt.Color; import java.awt.Component; +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.column; + /** * 桌面端主题面板 @@ -52,7 +57,7 @@ public class DesktopWidgetStyleEditPane extends WidgetS initFontNameSelectBox(); return new Component[][]{ new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Color")), colorSelectBox}, - new Component[]{WidgetThemeDesignerUtils.createTopAlignmentLabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Widget_Background")), WidgetStyleComponentCombiner.combineWidgetBackgroundComponent(widgetBgColorSelectBox, widgetBgAlphaDragPane, colorSelectBox.getPreferredSize().width)}, + new Component[]{WidgetThemeDesignerUtils.createTopAlignmentLabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Widget_Background")), initBackGroundComponent()}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Line")), lineComboBox}, new Component[]{null, lineComboColorSelectBox}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Radius")), borderRadiusSpinner}, @@ -63,6 +68,13 @@ public class DesktopWidgetStyleEditPane extends WidgetS }; } + private Column initBackGroundComponent() { + return column(10, + cell(widgetBgColorSelectBox), + cell(FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))), + cell(widgetBgAlphaDragPane)).getComponent(); + } + private void initSelectBackgroundColorBox() { selectBackgroundColorBox = new NewColorSelectBox(140, true); selectBackgroundColorBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_THEME_COLOR); diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java index 21a64ad229..bf6ad6c4fd 100644 --- a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java @@ -1,5 +1,6 @@ package com.fr.widgettheme.theme.edit.widget; +import com.fine.swing.ui.layout.Column; import com.fr.base.theme.TemplateTheme; import com.fr.design.beans.BasicBeanPane; import com.fr.design.designer.IntervalConstants; @@ -17,6 +18,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.style.color.NewColorSelectBox; +import com.fr.design.widget.FRWidgetFactory; import com.fr.general.IOUtils; import com.fr.stable.StringUtils; import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; @@ -29,6 +31,9 @@ import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.Component; +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.column; + /** * 组件样式编辑基础类 @@ -104,7 +109,7 @@ public class WidgetStyleEditPane extends BasicBeanPane< public Component[][] generateComponent() { return new Component[][]{ new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Color")), colorSelectBox}, - new Component[]{WidgetThemeDesignerUtils.createTopAlignmentLabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Widget_Background")), WidgetStyleComponentCombiner.combineWidgetBackgroundComponent(widgetBgColorSelectBox, widgetBgAlphaDragPane, colorSelectBox.getPreferredSize().width)}, + new Component[]{WidgetThemeDesignerUtils.createTopAlignmentLabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Widget_Background")), initBackGroundComponent()}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Line")), lineComboBox}, new Component[]{null, lineComboColorSelectBox}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Radius")), borderRadiusSpinner}, @@ -113,6 +118,14 @@ public class WidgetStyleEditPane extends BasicBeanPane< }; } + private Column initBackGroundComponent() { + return column(10, + cell(widgetBgColorSelectBox), + cell(FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))), + cell(widgetBgAlphaDragPane) + ).getComponent(); + } + private void initCommonStyleEditor() { colorSelectBox = new NewColorSelectBox(WidgetThemeDisplayConstants.THEME_WIDGET_COMPONENT_WIDTH, true); colorSelectBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_THEME_COLOR); diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties index bf7aba4f40..9a00559eae 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties @@ -27,3 +27,6 @@ com.fr.design.file.MultiTemplateTabPane.popUpMenu=350*65 com.fr.design.data.datapane.preview.desensitization.view.rule.DesensitizationRuleChoosePane.ruleEditPane=800*600 com.fr.design.formula.FormulaPane=900*600 com.fr.design.formula.FormulaPaneWhenReserveFormula=1200*600 +com.fr.design.mainframe.mobile.ui.MobileStyleDefinePane.configLabel=130*20 +com.fr.design.mainframe.mobile.utils.DesignerUtils.configLabel=140*20 +com.fr.design.update.ui.dialog.UpdateMainDialog.updateButton=100*24 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties index d070015063..d052ead680 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties @@ -26,3 +26,6 @@ com.fr.design.file.MultiTemplateTabPane.popUpMenu=240*65 com.fr.design.data.datapane.preview.desensitization.view.rule.DesensitizationRuleChoosePane.ruleEditPane=800*600 com.fr.design.formula.FormulaPane=900*600 com.fr.design.formula.FormulaPaneWhenReserveFormula=900*600 +com.fr.design.mainframe.mobile.ui.MobileStyleDefinePane.configLabel=100*20 +com.fr.design.mainframe.mobile.utils.DesignerUtils.configLabel=130*20 +com.fr.design.update.ui.dialog.UpdateMainDialog.updateButton=160*24 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties index 3fd1ffcad1..525bfe56ad 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties @@ -14,7 +14,7 @@ com.fr.design.report.fit.firstColumn=130*20 com.fr.design.report.fit.column=100*20 com.fr.design.lock.LockInfoDialog=500*180 com.fr.design.mainframe.ForbiddenPane.refreshButton=80*24 -com.fr.start.common.DesignerOpenEmptyPanel.createButton=70*24 +com.fr.start.common.DesignerOpenEmptyPanel.createButton=90*24 com.fr.design.cell.expand.sort.pane=267*165 com.fr.design.sort.rule.item=125*20 com.fr.design.ds.column.sort.pane=250*180 @@ -26,3 +26,6 @@ com.fr.design.file.MultiTemplateTabPane.popUpMenu=240*65 com.fr.design.data.datapane.preview.desensitization.view.rule.DesensitizationRuleChoosePane.ruleEditPane=800*600 com.fr.design.formula.FormulaPane=900*600 com.fr.design.formula.FormulaPaneWhenReserveFormula=900*600 +com.fr.design.mainframe.mobile.ui.MobileStyleDefinePane.configLabel=75*20 +com.fr.design.mainframe.mobile.utils.DesignerUtils.configLabel=100*20 +com.fr.design.update.ui.dialog.UpdateMainDialog.updateButton=80*24 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties index e69042470d..1286e77fb6 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties @@ -26,3 +26,6 @@ com.fr.design.report.WatermarkSettingPane=660*600 com.fr.design.file.MultiTemplateTabPane.popUpMenu=170*65 com.fr.design.formula.FormulaPane=900*600 com.fr.design.formula.FormulaPaneWhenReserveFormula=900*600 +com.fr.design.mainframe.mobile.ui.MobileStyleDefinePane.configLabel=75*20 +com.fr.design.mainframe.mobile.utils.DesignerUtils.configLabel=100*20 +com.fr.design.update.ui.dialog.UpdateMainDialog.updateButton=80*24 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties index faa620cfc8..e1bcdba473 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties @@ -25,3 +25,6 @@ com.fr.design.report.WatermarkSettingPane=720*600 com.fr.design.file.MultiTemplateTabPane.popUpMenu=170*65 com.fr.design.formula.FormulaPane=900*600 com.fr.design.formula.FormulaPaneWhenReserveFormula=900*600 +com.fr.design.mainframe.mobile.ui.MobileStyleDefinePane.configLabel=75*20 +com.fr.design.mainframe.mobile.utils.DesignerUtils.configLabel=100*20 +com.fr.design.update.ui.dialog.UpdateMainDialog.updateButton=80*24 diff --git a/designer-base/src/test/java/com/fr/design/EnvChangeEntranceTest.java b/designer-base/src/test/java/com/fr/design/EnvChangeEntranceTest.java index cab7037cd2..dd7617d95c 100644 --- a/designer-base/src/test/java/com/fr/design/EnvChangeEntranceTest.java +++ b/designer-base/src/test/java/com/fr/design/EnvChangeEntranceTest.java @@ -49,7 +49,7 @@ public class EnvChangeEntranceTest { EasyMock.expect(selectedEnv.getRemindTime()).andReturn(null); FunctionalHttpRequest request = EasyMock.mock(FunctionalHttpRequest.class); - EasyMock.expect(request.getServiceList()).andReturn(null); + EasyMock.expect(request.getServiceList(connectionInfo)).andReturn(null); PowerMock.expectNew(FunctionalHttpRequest.class, connectionInfo).andReturn(request).anyTimes(); EasyMock.expect(request.getServerBranch()).andReturn(remoteBranch); diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/AbstractChartTypePane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/AbstractChartTypePane.java index cde6e8fd6e..d662289006 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/AbstractChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/AbstractChartTypePane.java @@ -100,7 +100,7 @@ public abstract class AbstractChartTypePane extends Fur } } - double[] columnSize = {p, vs, f}; + double[] columnSize = {f}; double[] rowSize = {p, p, p, p, p, p, p}; if (styleList != null && !styleList.isEmpty()) { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/ComboBoxDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/ComboBoxDefinePane.java index c4a300387f..f6d6c12e91 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/ComboBoxDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/ComboBoxDefinePane.java @@ -24,7 +24,7 @@ public class ComboBoxDefinePane extends DictEditorDefinePane { public Component[] createWaterMarkPane() { waterMarkField = new UITextField(); - return new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_WaterMark")), waterMarkField}; + return new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_PlaceHolder")), waterMarkField}; } protected void populateSubDictionaryEditorBean(ComboBox ob){ diff --git a/designer-form/src/main/java/com/fr/design/widgettheme/BaseStyleSettingPane.java b/designer-form/src/main/java/com/fr/design/widgettheme/BaseStyleSettingPane.java index ef93914823..14183ed2e6 100644 --- a/designer-form/src/main/java/com/fr/design/widgettheme/BaseStyleSettingPane.java +++ b/designer-form/src/main/java/com/fr/design/widgettheme/BaseStyleSettingPane.java @@ -1,26 +1,20 @@ package com.fr.design.widgettheme; +import com.fine.swing.ui.layout.Column; import com.fr.base.background.ColorBackground; import com.fr.base.theme.TemplateTheme; -import com.fr.design.gui.frpane.FontSizeComboPane; -import com.fr.design.gui.frpane.UIPercentDragPane; -import com.fr.design.gui.ibutton.UIColorButton; -import com.fr.design.gui.ibutton.UIToggleButton; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.utils.DesignUtils; -import com.fr.general.IOUtils; -import com.fr.util.ColorUtils; -import com.fr.widgettheme.theme.widget.style.BorderStyle; -import com.fr.widgettheme.theme.widget.style.ButtonBackgroundStyle; -import com.fr.widgettheme.theme.widget.style.ThemeTextStyle; -import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; -import com.fr.widgettheme.theme.bean.ButtonBackground; import com.fr.design.beans.BasicBeanPane; import com.fr.design.designer.IntervalConstants; import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.frpane.FontSizeComboPane; +import com.fr.design.gui.frpane.UIPercentDragPane; import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIToggleButton; import com.fr.design.gui.icombobox.LineComboBox; +import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; import com.fr.design.gui.style.FRFontPane; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; @@ -28,10 +22,18 @@ import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.JTemplate; import com.fr.design.style.color.NewColorSelectBox; -import com.fr.design.widget.ui.designer.component.UIBoundSpinner; +import com.fr.design.utils.DesignUtils; +import com.fr.design.widget.FRWidgetFactory; import com.fr.form.ui.Widget; import com.fr.general.FRFont; +import com.fr.general.IOUtils; +import com.fr.util.ColorUtils; +import com.fr.widgettheme.theme.bean.ButtonBackground; import com.fr.widgettheme.theme.panel.ButtonStyleDefinedPane; +import com.fr.widgettheme.theme.widget.style.BorderStyle; +import com.fr.widgettheme.theme.widget.style.ButtonBackgroundStyle; +import com.fr.widgettheme.theme.widget.style.ThemeTextStyle; +import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; import com.fr.widgettheme.util.WidgetStyleComponentCombiner; import com.fr.widgettheme.util.WidgetThemeDesignerUtils; @@ -45,6 +47,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.column; + /** * 样式设置pane抽象类 * @@ -68,7 +73,7 @@ public abstract class BaseStyleSettingPane extends BasicBeanPa */ protected NewColorSelectBox borderColorSelectBox; // 圆角边框 - protected UIBoundSpinner borderRadiusSpinner; + protected UISpinner borderRadiusSpinner; // 字体详细设置 protected FRFontPane frFontPane; // 按钮背景设置 @@ -152,10 +157,19 @@ public abstract class BaseStyleSettingPane extends BasicBeanPa paneMap.put(StyleSetting.FONT, frFontPane); paneMap.put(StyleSetting.BTN_BACKGROUND, buttonStyleDefinedPane); paneMap.put(StyleSetting.SELECT_COLOR, selectBgColorBox); - paneMap.put(StyleSetting.WIDGET_BACKGROUND, WidgetStyleComponentCombiner.combineWidgetBackgroundComponent(widgetBgColorSelectBox, widgetBgAlphaDragPane, WidgetThemeDisplayConstants.THEME_PC_WIDGET_BACKGROUND_WIDTH)); + paneMap.put(StyleSetting.WIDGET_BACKGROUND, initBackGroundComponent()); paneMap.put(StyleSetting.ICON_COLOR, iconColorSelectBox); } + private Column initBackGroundComponent() { + return column( + 10, + cell(widgetBgColorSelectBox), + cell(FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))), + cell(widgetBgAlphaDragPane) + ).getComponent(); + } + protected JPanel createHeadPane() { UILabel headLabel = new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Style_Setting")); String[] titles = new String[]{Toolkit.i18nText("Fine-Design_Widget_Follow_Theme"), Toolkit.i18nText("Fine-Design_Widget_Theme_Custom")}; @@ -346,7 +360,7 @@ public abstract class BaseStyleSettingPane extends BasicBeanPa private void initBorderPane() { lineComboBox = new LineComboBox(WidgetThemeDisplayConstants.BORDER_LINE_STYLE_ARRAY); borderColorSelectBox = new NewColorSelectBox(WidgetThemeDisplayConstants.THEME_WIDGET_COMPONENT_WIDTH, true); - borderRadiusSpinner = new UIBoundSpinner(0, Integer.MAX_VALUE, 1); + borderRadiusSpinner = new UISpinner(0, Integer.MAX_VALUE, 1); lineComboBox.addItemListener(e -> borderColorSelectBox.setVisible(!Integer.valueOf(0).equals(e.getItem()))); } } diff --git a/designer-form/src/main/java/com/fr/design/widgettheme/ParaEditorSettingPane.java b/designer-form/src/main/java/com/fr/design/widgettheme/ParaEditorSettingPane.java index 5a67090bc2..314e1f5930 100644 --- a/designer-form/src/main/java/com/fr/design/widgettheme/ParaEditorSettingPane.java +++ b/designer-form/src/main/java/com/fr/design/widgettheme/ParaEditorSettingPane.java @@ -41,6 +41,7 @@ public class ParaEditorSettingPane extends EditorSettingPane extends EditorSettingPane void acceptEditor(Class creator, List> extraPaneList) { - boolean accept = WidgetThemeServerUtils.isNewComboBoxTreeEditor(creator) || EDITOR_SET.contains(creator); + boolean accept = EDITOR_SET.contains(creator); if (accept) { insertShortCut(extraPaneList, new EditorSettingPane<>()); } @@ -126,7 +126,7 @@ public class WidgetThemeCreatorPaneAdder { } private static void acceptSelect(Class creator, List> extraPaneList) { - boolean accept = SELECT_SET.contains(creator); + boolean accept = WidgetThemeServerUtils.isNewComboBoxTreeEditor(creator) || SELECT_SET.contains(creator); if (accept) { insertShortCut(extraPaneList, new SelectEditorSettingPane<>()); } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java index 525b3c0ca4..9a30b3266d 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java @@ -6,20 +6,21 @@ import com.fr.design.actions.core.ActionFactory; import com.fr.design.actions.form.FormECBackgroundAction; import com.fr.design.actions.form.FormECColumnsAction; import com.fr.design.actions.form.FormECFrozenAction; -import com.fr.design.designer.creator.XElementCase; +import com.fr.design.base.mode.DesignModeContext; import com.fr.design.event.TargetModifiedEvent; import com.fr.design.event.TargetModifiedListener; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fit.NewUIModeCellElementPainter; -import com.fr.design.fit.common.FormDesignerUtil; import com.fr.design.gui.frpane.HyperlinkGroupPane; import com.fr.design.mainframe.*; import com.fr.design.mainframe.cell.QuickEditorRegion; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.MenuDef; import com.fr.design.menu.ShortCut; import com.fr.design.menu.ToolBarDef; import com.fr.design.present.ConditionAttributesGroupPane; +import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils; import com.fr.form.fit.common.LightTool; import com.fr.form.main.Form; import com.fr.grid.Grid; @@ -27,6 +28,7 @@ import com.fr.grid.GridColumn; import com.fr.grid.GridCorner; import com.fr.grid.GridRow; import com.fr.page.ReportSettingsProvider; +import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.elementcase.TemplateElementCase; import com.fr.report.worksheet.FormElementCase; import com.fr.design.selection.SelectionEvent; @@ -34,7 +36,6 @@ import com.fr.design.selection.SelectionListener; import javax.swing.JComponent; import javax.swing.JPanel; -import java.awt.Insets; import java.awt.Rectangle; /** @@ -69,6 +70,16 @@ public class FormElementCasePaneDelegate extends ElementCasePane { + DefaultTemplateCellElement defaultTemplateCellElement = DefaultThemedTemplateCellElementCase.createInstance(); + // fvs调整单元格默认样式 + AdjustWorkBookDefaultStyleUtils.adjustCellElement(defaultTemplateCellElement); + return defaultTemplateCellElement; + }); + } } private Rectangle getBoundsLineRect(TemplateElementCase elementCase) { diff --git a/designer-realize/src/main/java/com/fr/design/present/PresentPane.java b/designer-realize/src/main/java/com/fr/design/present/PresentPane.java index 8e8a669c9f..95d45fa45d 100644 --- a/designer-realize/src/main/java/com/fr/design/present/PresentPane.java +++ b/designer-realize/src/main/java/com/fr/design/present/PresentPane.java @@ -52,10 +52,9 @@ public class PresentPane extends UIComboBoxPane { @Override public void populateBean(Present ob) { if(ob == null) { - dictPresentPane.reset(); - formulaPresentPane.reset(); - barCodePane.reset(); - currencyLinePane.reset(); + for (FurtherBasicBeanPane pane : cards) { + pane.reset(); + } } super.populateBean(ob); } diff --git a/designer-realize/src/main/java/com/fr/design/widget/ui/MultiFileEditorPane.java b/designer-realize/src/main/java/com/fr/design/widget/ui/MultiFileEditorPane.java index 39815c5575..2837939f21 100644 --- a/designer-realize/src/main/java/com/fr/design/widget/ui/MultiFileEditorPane.java +++ b/designer-realize/src/main/java/com/fr/design/widget/ui/MultiFileEditorPane.java @@ -40,6 +40,7 @@ public class MultiFileEditorPane extends FieldEditorDefinePane UIComponentUtils.setLineWrap(singleFileCheckBox); acceptType = new DictionaryComboBox(DictionaryConstants.acceptTypes, DictionaryConstants.fileTypeDisplays); fileSizeField = new UISpinner(0, Integer.MAX_VALUE, 1, -1); + fileSizeField.setPreferredSize(new Dimension(140, 20)); JPanel fileSizePane = new JPanel(new BorderLayout()); UILabel fileTypeLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Utils_File_Type")); diff --git a/designer-realize/src/main/java/com/fr/grid/selection/CellSelection.java b/designer-realize/src/main/java/com/fr/grid/selection/CellSelection.java index c5ec43463f..c4e78dd2b4 100644 --- a/designer-realize/src/main/java/com/fr/grid/selection/CellSelection.java +++ b/designer-realize/src/main/java/com/fr/grid/selection/CellSelection.java @@ -32,6 +32,7 @@ import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.report.RowColumnPane; import com.fr.design.selection.QuickEditor; +import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils; import com.fr.grid.GridUtils; import com.fr.report.cell.CellElement; import com.fr.report.cell.DefaultTemplateCellElement; @@ -560,6 +561,8 @@ public class CellSelection extends Selection { for (int i = 0; i < removeElementList.size(); i++) { CellElement element = removeElementList.get(i); element.setStyle(null); + // fvs调整单元格默认样式 + AdjustWorkBookDefaultStyleUtils.adjustCellElement(element); } break; diff --git a/designer-realize/src/main/java/com/fr/start/MainDesigner.java b/designer-realize/src/main/java/com/fr/start/MainDesigner.java index 07f28165f8..dccf53bbef 100644 --- a/designer-realize/src/main/java/com/fr/start/MainDesigner.java +++ b/designer-realize/src/main/java/com/fr/start/MainDesigner.java @@ -13,6 +13,7 @@ import com.fr.design.actions.server.ServerConfigManagerAction; import com.fr.design.actions.server.TemplateThemeManagerAction; import com.fr.design.actions.server.WidgetManagerAction; import com.fr.design.base.mode.DesignModeContext; +import com.fr.design.carton.latency.DesignerLatencyMetric; import com.fr.design.carton.SwitchForSwingChecker; import com.fr.design.constants.DesignerLaunchStatus; import com.fr.design.deeplink.DeepLinkManager; @@ -155,10 +156,11 @@ public class MainDesigner extends BaseDesigner { ServerTray.init(); } FineLoggerFactory.getLogger().info("Designer started.Time used {} ms", DesignerStartupContext.getRecorder().getTime(TimeUnit.MILLISECONDS)); - + DesignerStartupContext.getRecorder().stop(); SwitchForSwingChecker.initThreadMonitoring(); // new UiInspector(); // EdtInvocationManager.installEDTCheckers(); + DesignerLatencyMetric.getInstance().start(); } /**