Browse Source
* commit '50de08b80dab6a7cbc6f69fcd228a47e0de869a0': (155 commits) 无jira任务, 冲突修复 MOBILE-25614 && MOBILE-25605 ct ct ct ct ct ct ct ct ct ct 代码合并冲突 CHART-12814 悬浮图表去掉clone CHART-12814 悬浮图表数据问题 CHART-12815 天数不增加的问题 MOBILE-25493 && MOBILE-25540 交互调整 CHART-12746 埋点接口 CHART-12746 CHART-12746 ...research/11.0
neil
5 years ago
258 changed files with 5268 additions and 1935 deletions
@ -0,0 +1,290 @@ |
|||||||
|
package com.fr.design.dialog; |
||||||
|
|
||||||
|
import com.fr.invoke.Reflect; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
import javax.swing.JDialog; |
||||||
|
import javax.swing.JOptionPane; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.HeadlessException; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Joe |
||||||
|
* @version 10.0 |
||||||
|
* Created by Joe on 12/5/2019 |
||||||
|
*/ |
||||||
|
public class FineJOptionPane extends JOptionPane { |
||||||
|
|
||||||
|
public final static String[] OPTION_DEFAULT = { com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Button_OK") }; |
||||||
|
public final static String[] OPTION_YES_NO = { com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Yes"), |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_No") }; |
||||||
|
public final static String[] OPTION_YES_NO_CANCEL = { com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Yes"), |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_No"), |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Button_Cancel") }; |
||||||
|
public final static String[] OPTION_OK_CANCEL = { com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Button_OK"), |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Button_Cancel") }; |
||||||
|
|
||||||
|
//选项类型optionType 和 选项字符串数组 一一对应
|
||||||
|
private final static Map<Integer, String[]> OPTION_MAP = new HashMap<>(); |
||||||
|
|
||||||
|
static { |
||||||
|
OPTION_MAP.put(DEFAULT_OPTION, OPTION_DEFAULT); |
||||||
|
OPTION_MAP.put(YES_NO_OPTION, OPTION_YES_NO); |
||||||
|
OPTION_MAP.put(YES_NO_CANCEL_OPTION, OPTION_YES_NO_CANCEL); |
||||||
|
OPTION_MAP.put(OK_CANCEL_OPTION, OPTION_OK_CANCEL); |
||||||
|
} |
||||||
|
|
||||||
|
private final static String MESSAGE_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Message"); |
||||||
|
private final static String CONFIRM_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Confirm"); |
||||||
|
private final static String INPUT_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 标题 和 消息类型 的消息提示弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static void showMessageDialog(Component parentComponent, Object message) |
||||||
|
throws HeadlessException { |
||||||
|
showMessageDialog(parentComponent, message, MESSAGE_DIALOG_TITLE, |
||||||
|
INFORMATION_MESSAGE); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 Icon 的消息提示弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @param title 标题 |
||||||
|
* @param messageType 消息类型 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static void showMessageDialog(Component parentComponent, Object message, |
||||||
|
String title, int messageType) |
||||||
|
throws HeadlessException { |
||||||
|
showMessageDialog(parentComponent, message, title, messageType, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 选项类型、选项 和 初始选项 的消息提示弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @param title 标题 |
||||||
|
* @param messageType 消息类型 |
||||||
|
* @param icon 图标 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static void showMessageDialog(Component parentComponent, Object message, |
||||||
|
String title, int messageType, Icon icon) |
||||||
|
throws HeadlessException { |
||||||
|
showMessageDialog(parentComponent, message, title, DEFAULT_OPTION, |
||||||
|
messageType, icon, OPTION_DEFAULT, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 自定义的消息提示弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @param title 标题 |
||||||
|
* @param optionType 选项类型 |
||||||
|
* @param messageType 消息类型 |
||||||
|
* @param icon 图标 |
||||||
|
* @param options 选项 |
||||||
|
* @param initialValue 初始选项 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static void showMessageDialog(Component parentComponent, Object message, |
||||||
|
String title, int optionType, int messageType, |
||||||
|
Icon icon, Object[] options, Object initialValue) |
||||||
|
throws HeadlessException { |
||||||
|
showOptionDialog(parentComponent, message, title, optionType, |
||||||
|
messageType, icon, options, initialValue); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 标题 和 选项类型 的确认弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static int showConfirmDialog(Component parentComponent, Object message) |
||||||
|
throws HeadlessException { |
||||||
|
return showConfirmDialog(parentComponent, message, |
||||||
|
CONFIRM_DIALOG_TITLE, |
||||||
|
YES_NO_CANCEL_OPTION); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 消息类型 的确认弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @param title 标题 |
||||||
|
* @param optionType 选项类型 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static int showConfirmDialog(Component parentComponent, Object message, |
||||||
|
String title, int optionType) throws HeadlessException { |
||||||
|
return showConfirmDialog(parentComponent, message, title, optionType, |
||||||
|
QUESTION_MESSAGE); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 Icon 的确认弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @param title 标题 |
||||||
|
* @param optionType 选项类型 |
||||||
|
* @param messageType 消息类型 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static int showConfirmDialog(Component parentComponent, Object message, |
||||||
|
String title, int optionType, int messageType) |
||||||
|
throws HeadlessException { |
||||||
|
return showConfirmDialog(parentComponent, message, title, optionType, |
||||||
|
messageType, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据 选项类型 获取对应 选项 ,且使用默认 初始选项 的确认弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @param title 标题 |
||||||
|
* @param optionType 选项类型 |
||||||
|
* @param messageType 消息类型 |
||||||
|
* @param icon 图标 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static int showConfirmDialog(Component parentComponent, Object message, |
||||||
|
String title, int optionType, int messageType, Icon icon) |
||||||
|
throws HeadlessException { |
||||||
|
String[] options = OPTION_MAP.get(optionType); |
||||||
|
return showConfirmDialog(parentComponent, message, title, optionType, |
||||||
|
messageType, icon, options, options[0]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 自定义的确认弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 具体的提示消息 |
||||||
|
* @param title 标题 |
||||||
|
* @param optionType 选项类型 |
||||||
|
* @param messageType 消息类型 |
||||||
|
* @param icon 图标 |
||||||
|
* @param options 选项 |
||||||
|
* @param initialValue 初始选项 |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static int showConfirmDialog(Component parentComponent, Object message, |
||||||
|
String title, int optionType, int messageType, Icon icon, |
||||||
|
Object[] options, Object initialValue) |
||||||
|
throws HeadlessException { |
||||||
|
return showOptionDialog(parentComponent, message, title, optionType, |
||||||
|
messageType, icon, options, initialValue); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 指定消息内容的输入弹出框 |
||||||
|
* @param message 消息内容 |
||||||
|
* @return |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static String showInputDialog(Object message) |
||||||
|
throws HeadlessException { |
||||||
|
return showInputDialog(null, message); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 标题 和 消息类型 的输入弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 消息内容 |
||||||
|
* @return |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static String showInputDialog(Component parentComponent, |
||||||
|
Object message) throws HeadlessException { |
||||||
|
return showInputDialog(parentComponent, message, INPUT_DIALOG_TITLE, QUESTION_MESSAGE); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 标题、消息类型、Icon 和 选项 的输入弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 消息类型 |
||||||
|
* @param initialSelectionValue 初始选项 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String showInputDialog(Component parentComponent, Object message, |
||||||
|
Object initialSelectionValue) { |
||||||
|
return (String)showInputDialog(parentComponent, message, |
||||||
|
INPUT_DIALOG_TITLE, QUESTION_MESSAGE, null, null, |
||||||
|
initialSelectionValue); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 父容器、消息内容 和 初始选项 的输入弹出框 |
||||||
|
* @param message 消息内容 |
||||||
|
* @param initialSelectionValue 初始选项 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String showInputDialog(Object message, Object initialSelectionValue) { |
||||||
|
return showInputDialog(null, message, initialSelectionValue); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用默认 Icon、选项 和 初始选项 的输入弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 消息内容 |
||||||
|
* @param title 标题 |
||||||
|
* @param messageType 消息类型 |
||||||
|
* @return |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static String showInputDialog(Component parentComponent, |
||||||
|
Object message, String title, int messageType) |
||||||
|
throws HeadlessException { |
||||||
|
return (String)showInputDialog(parentComponent, message, title, |
||||||
|
messageType, null, null, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 自定义的输入弹出框 |
||||||
|
* @param parentComponent 父容器 |
||||||
|
* @param message 消息内容 |
||||||
|
* @param title 标题 |
||||||
|
* @param messageType 消息类型 |
||||||
|
* @param icon 图标 |
||||||
|
* @param selectionValues 选项 |
||||||
|
* @param initialSelectionValue 初始选项 |
||||||
|
* @return |
||||||
|
* @throws HeadlessException |
||||||
|
*/ |
||||||
|
public static Object showInputDialog(Component parentComponent, |
||||||
|
Object message, String title, int messageType, Icon icon, |
||||||
|
Object[] selectionValues, Object initialSelectionValue) |
||||||
|
throws HeadlessException { |
||||||
|
JOptionPane pane = new JOptionPane(message, messageType, |
||||||
|
OK_CANCEL_OPTION, icon, |
||||||
|
OPTION_OK_CANCEL, null); |
||||||
|
|
||||||
|
pane.setWantsInput(true); |
||||||
|
pane.setSelectionValues(selectionValues); |
||||||
|
pane.setInitialSelectionValue(initialSelectionValue); |
||||||
|
pane.setComponentOrientation(((parentComponent == null) ? |
||||||
|
getRootFrame() : parentComponent).getComponentOrientation()); |
||||||
|
|
||||||
|
int style = Reflect.on(JOptionPane.class).call("styleFromMessageType", messageType).get(); |
||||||
|
JDialog dialog = Reflect.on(pane).call("createDialog", parentComponent, title, style).get(); |
||||||
|
|
||||||
|
pane.selectInitialValue(); |
||||||
|
dialog.show(); |
||||||
|
dialog.dispose(); |
||||||
|
|
||||||
|
Object value = pane.getInputValue(); |
||||||
|
|
||||||
|
if (value == UNINITIALIZED_VALUE) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,57 @@ |
|||||||
|
package com.fr.design.formula; |
||||||
|
|
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Joe |
||||||
|
* @version 10.0 |
||||||
|
* Created by Joe on 10/30/2019 |
||||||
|
*/ |
||||||
|
public enum FormulaConstants { |
||||||
|
|
||||||
|
PAGE_NUMBER("$$page_number", "Page_Number"), |
||||||
|
TOTAL_PAGE_NUMBER("$$totalPage_number", "Total_Page_Number"), |
||||||
|
FINE_USERNAME("$fine_username", "Fine_Username"), |
||||||
|
FINE_ROLE("$fine_role", "Fine_Role"), |
||||||
|
FINE_POSITION("$fine_position", "Fine_Position"), |
||||||
|
NULL("NULL", "Null"), |
||||||
|
NOFILTER("NOFILTER", "No_Filter"), |
||||||
|
REPORT_NAME("reportName", "Report_Name"), |
||||||
|
FORMLET_NAME("formletName", "Formlet_Name"), |
||||||
|
SERVLET_URL("servletURL", "Servlet_URL"), |
||||||
|
SERVER_SCHEMA("serverSchema", "Server_Schema"), |
||||||
|
SERVER_NAME("serverName", "Server_Name"), |
||||||
|
SERVER_PORT("serverPort", "Server_Port"), |
||||||
|
SERVER_URL("serverURL", "Server_URL"), |
||||||
|
CONTEXT_PATH("contextPath", "Context_Path"), |
||||||
|
SESSION_ID("sessionID", "SessionID"); |
||||||
|
|
||||||
|
private String key; |
||||||
|
private String value; |
||||||
|
private static final String KEY_PREFIX = "Fine-Design_CurReport_Variable_"; |
||||||
|
|
||||||
|
private FormulaConstants(String key, String value) { |
||||||
|
this.key = key; |
||||||
|
this.value = KEY_PREFIX + value; |
||||||
|
} |
||||||
|
|
||||||
|
public String getKey() { |
||||||
|
return key; |
||||||
|
} |
||||||
|
|
||||||
|
public String getValue() { |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
public static String getValueByKey(String key) { |
||||||
|
for (FormulaConstants formulaConstant : values()) { |
||||||
|
if (formulaConstant.getKey().equals(key)) { |
||||||
|
return formulaConstant.getValue(); |
||||||
|
} |
||||||
|
} |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.fr.design.fun; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.form.ui.mobile.MobileBookMarkStyle; |
||||||
|
import com.fr.stable.fun.mark.Mutable; |
||||||
|
|
||||||
|
/** |
||||||
|
* 移动端书签样式扩展接口 |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2019/12/23 |
||||||
|
*/ |
||||||
|
public interface MobileBookMarkStyleProvider extends Mutable { |
||||||
|
|
||||||
|
String XML_TAG = "MobileBookMarkStyleProvider"; |
||||||
|
|
||||||
|
int CURRENT_LEVEL = 1; |
||||||
|
|
||||||
|
/** |
||||||
|
* 书签样式 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Class<? extends MobileBookMarkStyle> classForMobileBookMarkStyle(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 书签样式面板 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Class<? extends BasicBeanPane<MobileBookMarkStyle>> classForMobileBookMarkStyleAppearance(); |
||||||
|
|
||||||
|
String displayName(); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.fr.design.fun.impl; |
||||||
|
|
||||||
|
import com.fr.design.fun.MobileBookMarkStyleProvider; |
||||||
|
import com.fr.stable.fun.impl.AbstractProvider; |
||||||
|
import com.fr.stable.fun.mark.API; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2019/12/24 |
||||||
|
*/ |
||||||
|
@API(level = MobileBookMarkStyleProvider.CURRENT_LEVEL) |
||||||
|
public abstract class AbstractMobileBookMarkStyleProvider extends AbstractProvider implements MobileBookMarkStyleProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String mark4Provider() { |
||||||
|
return getClass().getName(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package com.fr.design.gui.ibutton; |
||||||
|
|
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 互斥的按钮 |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2019/11/12 |
||||||
|
*/ |
||||||
|
public class ModeButtonGroup<T> extends ButtonGroup { |
||||||
|
|
||||||
|
private Map<T, AbstractButton> buttonMap = new LinkedHashMap<>(); |
||||||
|
|
||||||
|
public void put(T t, AbstractButton button) { |
||||||
|
add(button); |
||||||
|
buttonMap.put(t, button); |
||||||
|
} |
||||||
|
|
||||||
|
public void setSelectButton(T t) { |
||||||
|
buttonMap.get(t).setSelected(true); |
||||||
|
} |
||||||
|
|
||||||
|
public T getCurrentSelected() { |
||||||
|
for (Map.Entry<T, AbstractButton> entry : buttonMap.entrySet()) { |
||||||
|
if (entry.getValue().isSelected()) { |
||||||
|
return entry.getKey(); |
||||||
|
} |
||||||
|
} |
||||||
|
return buttonMap.entrySet().iterator().next().getKey(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,53 +0,0 @@ |
|||||||
package com.fr.design.gui.itextfield; |
|
||||||
|
|
||||||
import java.awt.Graphics; |
|
||||||
|
|
||||||
import javax.swing.plaf.metal.MetalTextFieldUI; |
|
||||||
import javax.swing.text.JTextComponent; |
|
||||||
|
|
||||||
import de.muntjak.tinylookandfeel.Theme; |
|
||||||
|
|
||||||
public class TextFieldUI extends MetalTextFieldUI { |
|
||||||
|
|
||||||
|
|
||||||
protected void paintBackground(Graphics g) { |
|
||||||
JTextComponent editor = getComponent(); |
|
||||||
// We will only be here if editor is opaque, so we don't have to test
|
|
||||||
|
|
||||||
if(editor.isEnabled()) { |
|
||||||
if(editor.isEditable()) { |
|
||||||
g.setColor(editor.getBackground()); |
|
||||||
} |
|
||||||
else { |
|
||||||
// not editable
|
|
||||||
if(editor.getBackground().equals(Theme.textBgColor[Theme.style].getColor())) { |
|
||||||
// set default panel background
|
|
||||||
g.setColor(Theme.backColor[Theme.style].getColor()); |
|
||||||
} |
|
||||||
else { |
|
||||||
// color changed by user - set textfield background
|
|
||||||
g.setColor(editor.getBackground()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
g.fillRect(0, 0, editor.getWidth(), editor.getHeight()); |
|
||||||
} |
|
||||||
else { |
|
||||||
if(editor.getBackground().equals(Theme.textBgColor[Theme.style].getColor())) { |
|
||||||
g.setColor(Theme.textDisabledBgColor[Theme.style].getColor()); |
|
||||||
} |
|
||||||
else { |
|
||||||
// color changed by user - set textfield background
|
|
||||||
g.setColor(editor.getBackground()); |
|
||||||
} |
|
||||||
|
|
||||||
g.fillRect(0, 0, editor.getWidth(), editor.getHeight()); |
|
||||||
|
|
||||||
if(Theme.style != Theme.YQ_STYLE) return; |
|
||||||
|
|
||||||
g.setColor(Theme.backColor[Theme.style].getColor()); |
|
||||||
g.drawRect(1, 1, editor.getWidth() - 3, editor.getHeight() - 3); |
|
||||||
g.drawRect(2, 2, editor.getWidth() - 5, editor.getHeight() - 5); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,130 @@ |
|||||||
|
package com.fr.design.mainframe.burying.point; |
||||||
|
|
||||||
|
import com.fr.base.FRContext; |
||||||
|
import com.fr.base.io.XMLReadHelper; |
||||||
|
import com.fr.design.DesignerEnvManager; |
||||||
|
import com.fr.design.mainframe.template.info.SendHelper; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.xml.XMLPrintWriter; |
||||||
|
import com.fr.stable.xml.XMLTools; |
||||||
|
import com.fr.stable.xml.XMLableReader; |
||||||
|
import com.fr.third.javax.xml.stream.XMLStreamException; |
||||||
|
import com.fr.third.org.apache.commons.io.FileUtils; |
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.File; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Bjorn |
||||||
|
* @version 10.0 |
||||||
|
* Created by Bjorn on 2020-02-21 |
||||||
|
*/ |
||||||
|
public abstract class AbstractPointCollector<T extends AbstractPointInfo> implements BasePointCollector { |
||||||
|
|
||||||
|
protected Map<String, T> pointInfoMap; |
||||||
|
|
||||||
|
private static final int MAX_SIZE = 512 * 1024 * 1024; |
||||||
|
|
||||||
|
public AbstractPointCollector() { |
||||||
|
pointInfoMap = new ConcurrentHashMap<>(); |
||||||
|
loadFromFile(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取是否满足触发埋点的要求 |
||||||
|
*/ |
||||||
|
protected boolean shouldCollectInfo() { |
||||||
|
return FileUtils.sizeOf(getInfoFile()) <= MAX_SIZE && DesignerEnvManager.getEnvManager().isJoinProductImprove() && FRContext.isChineseEnv(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void sendPointInfo() { |
||||||
|
|
||||||
|
addIdleDayCount(); |
||||||
|
|
||||||
|
List<String> removeList = new ArrayList<>(); |
||||||
|
List<String> sendList = new ArrayList<>(); |
||||||
|
|
||||||
|
for (String key : pointInfoMap.keySet()) { |
||||||
|
AbstractPointInfo pointInfo = pointInfoMap.get(key); |
||||||
|
pointInfo.selectPoint(removeList, sendList); |
||||||
|
} |
||||||
|
|
||||||
|
// 发送记录
|
||||||
|
for (String key : sendList) { |
||||||
|
if(SendHelper.sendPointInfo(pointInfoMap.get(key))){ |
||||||
|
removeList.add(key); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 清空记录
|
||||||
|
for (String key : removeList) { |
||||||
|
pointInfoMap.remove(key); |
||||||
|
} |
||||||
|
|
||||||
|
saveInfo(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从文件中读取埋点信息 |
||||||
|
*/ |
||||||
|
protected void loadFromFile() { |
||||||
|
if (!getInfoFile().exists()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
XMLableReader reader = null; |
||||||
|
try (InputStream in = new FileInputStream(getInfoFile())) { |
||||||
|
// XMLableReader 还是应该考虑实现 Closable 接口的,这样就能使用 try-with 语句了
|
||||||
|
reader = XMLReadHelper.createXMLableReader(in, XMLPrintWriter.XML_ENCODER); |
||||||
|
if (reader == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
reader.readXMLObject(this); |
||||||
|
} catch (FileNotFoundException e) { |
||||||
|
// do nothing
|
||||||
|
} catch (XMLStreamException | IOException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} finally { |
||||||
|
try { |
||||||
|
if (reader != null) { |
||||||
|
reader.close(); |
||||||
|
} |
||||||
|
} catch (XMLStreamException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存埋点信息到文件中 |
||||||
|
*/ |
||||||
|
protected void saveInfo() { |
||||||
|
try { |
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
||||||
|
XMLTools.writeOutputStreamXML(this, out); |
||||||
|
out.flush(); |
||||||
|
out.close(); |
||||||
|
String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); |
||||||
|
FileUtils.writeStringToFile(getInfoFile(), fileContent, StandardCharsets.UTF_8); |
||||||
|
} catch (Exception ex) { |
||||||
|
FineLoggerFactory.getLogger().error(ex.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取缓存文件存放路径 |
||||||
|
*/ |
||||||
|
protected abstract File getInfoFile(); |
||||||
|
|
||||||
|
protected abstract void addIdleDayCount(); |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
package com.fr.design.mainframe.burying.point; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Bjorn |
||||||
|
* @version 10.0 |
||||||
|
* Created by Bjorn on 2020-02-21 |
||||||
|
*/ |
||||||
|
public abstract class AbstractPointInfo implements BasePointInfo { |
||||||
|
|
||||||
|
protected int idleDayCount; // 到现在为止,埋点闲置的天数
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void resetIdleDayCount() { |
||||||
|
this.idleDayCount = 0; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addIdleDayCountByOne() { |
||||||
|
this.idleDayCount += 1; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 上传前判断该埋点,是否需要被上传,或者删除,或者什么都不做。 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void selectPoint(List<String> removeList, List<String> sendList) { |
||||||
|
//埋点还未完成,直接返回
|
||||||
|
if (!isComplete()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
//属于测试模板,直接删除,否则发送信息
|
||||||
|
if (isTestTemplate()) { |
||||||
|
removeList.add(key()); |
||||||
|
} else { |
||||||
|
sendList.add(key()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否为测试模板 |
||||||
|
*/ |
||||||
|
protected abstract boolean isTestTemplate(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否已经制作完成 |
||||||
|
*/ |
||||||
|
protected abstract boolean isComplete(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 埋点记录的主键 |
||||||
|
*/ |
||||||
|
protected abstract String key(); |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package com.fr.design.mainframe.burying.point; |
||||||
|
|
||||||
|
import com.fr.design.mainframe.template.info.TemplateProcessInfo; |
||||||
|
import com.fr.stable.xml.XMLReadable; |
||||||
|
import com.fr.stable.xml.XMLWriter; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Bjorn |
||||||
|
* @version 10.0 |
||||||
|
* Created by Bjorn on 2020-02-21 |
||||||
|
*/ |
||||||
|
public interface BasePointCollector extends XMLReadable, XMLWriter { |
||||||
|
|
||||||
|
/** |
||||||
|
* 发送埋点信息到服务器 |
||||||
|
*/ |
||||||
|
public void sendPointInfo(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存埋点的信息到本地 |
||||||
|
*/ |
||||||
|
public void collectInfo(String templateID, String originID, TemplateProcessInfo processInfo, int timeConsume); |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue