Browse Source

Merge pull request #4400 in DESIGN/design from feature/10.0 to feature/x

* commit '87dd56cc0bef8a610d395cecbfe098035fd5d3fb':
  REPORT-51361 设计器模板维度表移至云端运维插件
research/11.0
superman 4 years ago
parent
commit
073f6e6428
  1. 8
      designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java
  2. 121
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  3. 2
      designer-base/src/main/java/com/fr/design/mainframe/burying/point/AbstractPointCollector.java
  4. 2
      designer-base/src/main/java/com/fr/design/mainframe/burying/point/AbstractPointInfo.java
  5. 2
      designer-base/src/main/java/com/fr/design/mainframe/burying/point/BasePointCollector.java
  6. 2
      designer-base/src/main/java/com/fr/design/mainframe/burying/point/BasePointInfo.java
  7. 20
      designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java
  8. 253
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfo.java
  9. 210
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfoCollector.java
  10. 2
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateOperate.java
  11. 13
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateProcessInfo.java
  12. 2
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java
  13. 31
      designer-base/src/test/java/com/fr/design/mainframe/template/info/SendHelperTest.java
  14. 252
      designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoCollectorTest.java
  15. 143
      designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoTest.java
  16. 9
      designer-form/src/main/java/com/fr/design/form/util/FormDesignerUtils.java
  17. 1
      designer-form/src/main/java/com/fr/design/mainframe/JForm.java
  18. 5
      designer-form/src/main/java/com/fr/design/mainframe/template/info/JFormProcessInfo.java
  19. 130
      designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java
  20. 3
      designer-realize/src/main/java/com/fr/design/mainframe/template/info/JPolyWorkBookProcessInfo.java
  21. 3
      designer-realize/src/main/java/com/fr/design/mainframe/template/info/JWorkBookProcessInfo.java

8
designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java

@ -11,10 +11,10 @@ import com.fr.design.dialog.BasicPane;
import com.fr.design.event.TargetModifiedEvent;
import com.fr.design.event.TargetModifiedListener;
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import java.awt.BorderLayout;
import java.awt.Component;
/**
@ -53,12 +53,11 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener
// 判断是否切换设计器状态到禁止拷贝剪切
if (jt.getTarget().getAttrMark(DesignBanCopyAttrMark.XML_TAG) != null) {
DesignModeContext.switchTo(DesignerMode.BAN_COPY_AND_CUT);
} else if (!DesignModeContext.isVcsMode() && !DesignModeContext.isAuthorityEditing()){
} else if (!DesignModeContext.isVcsMode() && !DesignModeContext.isAuthorityEditing()) {
DesignModeContext.switchTo(DesignerMode.NORMAL);
}
DesignerFrameFileDealerPane.getInstance().setCurrentEditingTemplate(jt);
if (component != null) {
component.onLostFocus();
layeredPane.remove(component);
}
component = jt;
@ -69,7 +68,6 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener
repaint();
revalidate();
component.requestGridFocus();
component.onGetFocus();
}

121
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -41,7 +41,6 @@ import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.chart.info.ChartInfoCollector;
import com.fr.design.mainframe.check.CheckButton;
import com.fr.design.mainframe.template.info.TemplateInfoCollector;
import com.fr.design.mainframe.template.info.TemplateProcessInfo;
import com.fr.design.mainframe.template.info.TimeConsumeTimer;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
@ -83,7 +82,6 @@ import com.fr.stable.core.UUID;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.lock.TplOperator;
import java.util.concurrent.Callable;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
@ -95,6 +93,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
/**
* 报表设计和表单设计的编辑区域(设计器编辑的IO文件)
@ -111,11 +110,24 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
protected U undoState;
protected U authorityUndoState = null;
protected T template; // 当前模板
protected TemplateProcessInfo<T> processInfo; // 模板过程的相关信息
/**
* 模板过程的相关信息
*
* @deprecated move to cloud ops plugin,left only for compatible
*/
@Deprecated
protected TemplateProcessInfo<T> processInfo;
private JComponent centerPane;
private static short currentIndex = 0;// 此变量用于多次新建模板时,让名字不重复
private DesignModelAdapter<T, ?> designModel;
private PreviewProvider previewType;
/**
* 统计模板制作耗时
*
* @deprecated move to cloud ops plugin,left only for compatible
*/
@Deprecated
protected TimeConsumeTimer consumeTimer = new TimeConsumeTimer();
private volatile boolean saving = false;
private volatile boolean opening = false;
@ -165,7 +177,6 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
addCenterPane();
this.undoState = createUndoState();
consumeTimer.setEnabled(shouldInitForCollectInfo(isNewFile));
initAndStartPlugin();
}
@ -210,21 +221,22 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
}
/**
* @deprecated move to cloud ops pluginleft only for compatible
*/
@Deprecated
void onGetFocus() {
consumeTimer.start();
}
/**
* @deprecated move to cloud ops pluginleft only for compatible
*/
@Deprecated
void onLostFocus() {
consumeTimer.stop();
}
private boolean shouldInitForCollectInfo(boolean isNewFile) {
if (isNewFile) {
return true;
}
// 不是新建模板,但是已经在收集列表中
return TemplateInfoCollector.getInstance().contains(template.getTemplateID());
}
// 刷新右侧属性面板
public abstract void refreshEastPropertiesPane();
@ -233,30 +245,33 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
public abstract JComponent getCurrentReportComponentPane();
// 为收集模版信息作准备
private void initForCollect() {
/**
* 为另存的模板创建新的模板id
*/
private void generateNewTemplateIdForSaveAs() {
generateTemplateId();
consumeTimer.setEnabled(true);
consumeTimer.start();
}
private void collectInfo() { // 执行收集操作
collectInfo(StringUtils.EMPTY);
/**
* 收集图表信息
*/
private void collectInfo() {
ChartInfoCollector.getInstance().collectInfo(template.getTemplateID(), StringUtils.EMPTY, getProcessInfo(), 0);
}
private void collectInfo(String originID) { // 执行收集操作
/**
* 另存模板时收集图表信息
*
* @param originID 原始模板id
*/
private void collectInfoWhenSaveAs(String originID) {
ChartInfoCollector.getInstance().collectInfo(template.getTemplateID(), originID, getProcessInfo(), 0);
if (!consumeTimer.isEnabled()) {
return;
}
try {
int timeConsume = consumeTimer.popTime();
TemplateInfoCollector.getInstance().collectInfo(template.getTemplateID(), originID, getProcessInfo(), timeConsume);
} catch (Throwable th) { // 不管收集过程中出现任何异常,都不应该影响模版保存
}
consumeTimer.start(); // 准备下一次计算
}
/**
* @deprecated move to cloud ops plugin
*/
@Deprecated
public abstract TemplateProcessInfo<T> getProcessInfo();
public U getUndoState() {
@ -351,7 +366,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
/**
* 刷新内部资源
*
* <p>
* 刷新资源的同时
* CenterPane 负责监听改动
* 所以需要同步处理
@ -419,7 +434,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
protected abstract DesignModelAdapter<T, ?> createDesignModel();
protected DesignModelAdapter<T, ?> createDesignModel(Parameter[] parameters) {
protected DesignModelAdapter<T, ?> createDesignModel(Parameter[] parameters) {
// 空实现 兼容下
return null;
}
@ -679,6 +694,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
/**
* Web预览的时候需要隐藏掉除报表运行环境外的路径(C盘D盘等) isShowLoc = false
* 被云端运维插件修改用于收集埋点
*
* @param isShowLoc 是否本地
* @return 保存成功返回true
@ -771,20 +787,24 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
}
// 保存新模板时会进入此方法(新建模板直接保存,或者另存为)
/**
* 保存新模板时会进入此方法新建模板直接保存或者另存为
* 被云端运维插件修改用于收集埋点
*/
protected boolean saveNewFile(FILE editingFILE, String oldName) {
String originID = StringUtils.EMPTY;
if (StringUtils.isNotEmpty(this.template.getTemplateID())) {
originID = this.template.getTemplateID();
String currentId = this.template.getTemplateID();
if (StringUtils.isNotEmpty(currentId)) {
originID = currentId;
}
// 在保存之前,初始化 templateID
initForCollect();
generateNewTemplateIdForSaveAs();
this.editingFILE = editingFILE;
boolean result = this.saveToNewFile(oldName);
if (result) {
DesignerFrameFileDealerPane.getInstance().refresh();
collectInfo(originID);
collectInfoWhenSaveAs(originID);
}
return result;
}
@ -798,7 +818,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
}
result = result || saveToNewFile4Cptx(path);
if (!result) {
result = result || this.saveFile();
result = this.saveFile();
//更换最近打开
DesignerEnvManager.getEnvManager().replaceRecentOpenedFilePath(oldName, this.getPath());
this.refreshToolArea();
@ -885,10 +905,10 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
}
/**
* @return java.lang.Integer WorkBook11.cpt则返回11如果没有找到index返回null
* @Description 返回文件名中的index
* @param: prefix 前缀
* @param: fileName 文件名称全名
* @return java.lang.Integer WorkBook11.cpt则返回11如果没有找到index返回null
* @Author Henry.Wang
* @Date 2021/4/9 11:13
**/
@ -1427,8 +1447,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
CallbackSaveWorker worker = new CallbackSaveWorker(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
collectInfo();
return JTemplate.this.saveRealFile();
return saveRealFileByWorker();
}
}, this);
@ -1442,6 +1461,14 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
return worker;
}
/**
* 被云端运维插件修改用于收集埋点
*/
private boolean saveRealFileByWorker() throws Exception {
collectInfo();
return saveRealFile();
}
private void callBackForSave() {
JTemplate.this.saved = true;
JTemplate.this.authoritySaved = true;
@ -1498,7 +1525,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
callBackForSave();
// 当前打开的是正在保存的模板才刷新
if (ComparatorUtils.equals(JTemplate.this.template.getTemplateID(),
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().template.getTemplateID())) {
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().template.getTemplateID())) {
refreshToolArea();
}
DesignerFrameFileDealerPane.getInstance().refresh();
@ -1527,13 +1554,23 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
}
}
/**
* 另存为时在 save worker 中保存实际的文件;
* 被云端运维插件修改用于收集埋点
*/
private boolean saveNewRealFile(FILE editingFILE, String oldName) throws Exception {
consumeTimer.setEnabled(true);
consumeTimer.start();
String originID = StringUtils.EMPTY;
String currentId = this.template.getTemplateID();
if (StringUtils.isNotEmpty(currentId)) {
originID = currentId;
}
// 在保存之前,初始化 templateID
generateNewTemplateIdForSaveAs();
this.editingFILE = editingFILE;
boolean result = this.saveToNewRealFile(oldName);
if (result) {
collectInfo(this.template.getTemplateID());
collectInfoWhenSaveAs(originID);
}
return result;
}

2
designer-base/src/main/java/com/fr/design/mainframe/burying/point/AbstractPointCollector.java

@ -29,7 +29,9 @@ import java.util.concurrent.ConcurrentHashMap;
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-02-21
* @deprecated moved to Cloud Ops plugin
*/
@Deprecated
public abstract class AbstractPointCollector<T extends AbstractPointInfo> implements BasePointCollector {
protected Map<String, T> pointInfoMap;

2
designer-base/src/main/java/com/fr/design/mainframe/burying/point/AbstractPointInfo.java

@ -6,7 +6,9 @@ import java.util.List;
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-02-21
* @deprecated moved to Cloud Ops plugin
*/
@Deprecated
public abstract class AbstractPointInfo implements BasePointInfo {
protected int idleDayCount; // 到现在为止,埋点闲置的天数

2
designer-base/src/main/java/com/fr/design/mainframe/burying/point/BasePointCollector.java

@ -8,7 +8,9 @@ import com.fr.stable.xml.XMLWriter;
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-02-21
* @deprecated moved to Cloud Ops plugin
*/
@Deprecated
public interface BasePointCollector extends XMLReadable, XMLWriter {
/**

2
designer-base/src/main/java/com/fr/design/mainframe/burying/point/BasePointInfo.java

@ -10,7 +10,9 @@ import java.util.Map;
* @author Bjorn
* @version 10.0
* Created by Bjorn on 2020-02-21
* @deprecated moved to Cloud Ops plugin
*/
@Deprecated
public interface BasePointInfo extends XMLReadable, XMLWriter {
/**

20
designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java

@ -5,7 +5,6 @@ import com.fr.chartx.attr.ChartProvider;
import com.fr.chartx.config.info.AbstractConfig;
import com.fr.chartx.config.info.constant.ConfigType;
import com.fr.design.mainframe.burying.point.AbstractPointCollector;
import com.fr.design.mainframe.template.info.TemplateInfo;
import com.fr.design.mainframe.template.info.TemplateProcessInfo;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
@ -31,6 +30,9 @@ public class ChartInfoCollector extends AbstractPointCollector<ChartInfo> {
private static final String XML_CHART_INFO_LIST = "ChartInfoList";
private static final String XML_FILE_NAME = "chart.info";
private static final int VALID_CELL_COUNT = 5; // 有效报表模板的格子数
private static final int VALID_WIDGET_COUNT = 5; // 有效报表模板的控件数
private static ChartInfoCollector instance;
private Map<String, ChartInfo> chartInfoCacheMap;
@ -217,10 +219,10 @@ public class ChartInfoCollector extends AbstractPointCollector<ChartInfo> {
int floatCount = processInfo.getFloatCount();
int blockCount = processInfo.getBlockCount();
int widgetCount = processInfo.getWidgetCount();
return TemplateInfo.isTestTemplate(reportType, cellCount, floatCount, blockCount, widgetCount);
return isTestTemplate(reportType, cellCount, floatCount, blockCount, widgetCount);
}
/**
* 更新 day_count打开设计器却未编辑图表的连续日子
*/
@ -282,4 +284,16 @@ public class ChartInfoCollector extends AbstractPointCollector<ChartInfo> {
writer.end();
}
private boolean isTestTemplate(int reportType, int cellCount, int floatCount, int blockCount, int widgetCount) {
boolean isTestTemplate;
if (reportType == 0) { // 普通报表
isTestTemplate = cellCount <= VALID_CELL_COUNT && floatCount <= 1 && widgetCount <= VALID_WIDGET_COUNT;
} else if (reportType == 1) { // 聚合报表
isTestTemplate = blockCount <= 1 && widgetCount <= VALID_WIDGET_COUNT;
} else { // 表单(reportType == 2)
isTestTemplate = widgetCount <= 1;
}
return isTestTemplate;
}
}

253
designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfo.java

@ -1,253 +0,0 @@
package com.fr.design.mainframe.template.info;
import com.fr.config.MarketConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.burying.point.AbstractPointInfo;
import com.fr.general.CloudCenter;
import com.fr.json.JSON;
import com.fr.json.JSONFactory;
import com.fr.json.JSONObject;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.joda.time.DateTime;
import java.util.HashMap;
import java.util.Map;
/**
* 对应一张模版的记录
* Created by plough on 2019/4/18.
*/
public class TemplateInfo extends AbstractPointInfo {
static final String XML_TAG = "TemplateInfo";
private static final String SIMPLE_DATE_PATTRN = "yyyy-MM-dd HH:mm";
private static final String CONSUMING_URL = CloudCenter.getInstance().acquireUrlByKind("tempinfo.consuming") + "/single";
private static final String PROCESS_URL = CloudCenter.getInstance().acquireUrlByKind("tempinfo.process") + "/single";
private static final String XML_PROCESS_MAP = "processMap";
private static final String XML_CONSUMING_MAP = "consumingMap";
private static final String ATTR_DAY_COUNT = "day_count";
private static final String ATTR_TEMPLATE_ID = "templateID";
private static final String ATTR_ORIGIN_ID = "originID";
private static final String ATTR_PROCESS = "process";
private static final String ATTR_FLOAT_COUNT = "float_count";
private static final String ATTR_WIDGET_COUNT = "widget_count";
private static final String ATTR_CELL_COUNT = "cell_count";
private static final String ATTR_BLOCK_COUNT = "block_count";
private static final String ATTR_REPORT_TYPE = "report_type";
private static final String ATTR_CREATE_TIME = "create_time";
private static final String ATTR_UUID = "uuid";
private static final String ATTR_UID = "uid";
private static final String ATTR_SAVE_RECORD = "saveRecord";
private static final String ATTR_PARA_APPLY = "paraApply";
private static final String ATTR_COMPONENTS_INFO = "components_info";
private static final String ATTR_REUSE_CMP_LIST = "reuseCmptList";
private static final String TEST_TEMPLATE_FLAG = "test_template";
private static final int VALID_CELL_COUNT = 5; // 有效报表模板的格子数
private static final int VALID_WIDGET_COUNT = 5; // 有效报表模板的控件数
private String templateID = StringUtils.EMPTY;
private String originID = StringUtils.EMPTY;
// todo: processMap 和 consumingMap 还可以再拆解为小类,以后继续重构
private Map<String, Object> processMap = new HashMap<>();
private Map<String, Object> consumingMap = new HashMap<>();
private TemplateInfo() {
}
private TemplateInfo(String templateID, String originID) {
this.templateID = templateID;
this.originID = originID;
}
@Override
protected String key() {
return templateID;
}
public static TemplateInfo newInstanceByRead(XMLableReader reader) {
TemplateInfo templateInfo = new TemplateInfo();
reader.readXMLObject(templateInfo);
return templateInfo;
}
public static TemplateInfo newInstance(String templateID) {
return newInstance(templateID, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY);
}
public static TemplateInfo newInstance(String templateID, String originID, String saveRecord) {
String createTime = DateTime.now().toString(SIMPLE_DATE_PATTRN);
return newInstance(templateID, originID, saveRecord, createTime);
}
public static TemplateInfo newInstance(String templateID, String originID, String saveRecord, String createTime) {
HashMap<String, Object> consumingMap = new HashMap<>();
String uuid = DesignerEnvManager.getEnvManager().getUUID();
MarketConfig config = MarketConfig.getInstance();
consumingMap.put(ATTR_UUID, uuid);
consumingMap.put(ATTR_TEMPLATE_ID, templateID);
consumingMap.put(ATTR_ORIGIN_ID, originID);
consumingMap.put(ATTR_CREATE_TIME, createTime);
consumingMap.put(ATTR_UID, config.getBBSAttr().getBbsUid());
consumingMap.put(ATTR_SAVE_RECORD, saveRecord);
TemplateInfo templateInfo = new TemplateInfo(templateID, originID);
templateInfo.consumingMap = consumingMap;
return templateInfo;
}
String getTemplateID() {
return templateID;
}
public String getTemplateInfoID() {
return templateID + "_" + getSaveTime();
}
public long getSaveTime() {
String saveRecord = (String) consumingMap.get(ATTR_SAVE_RECORD);
JSONObject jo = JSONFactory.createJSON(JSON.OBJECT, saveRecord);
return jo.getLong("time");
}
public String getTemplateCreateTime() {
return (String) consumingMap.get(ATTR_CREATE_TIME);
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG(XML_TAG);
if (StringUtils.isNotEmpty(templateID)) {
writer.attr(ATTR_TEMPLATE_ID, this.templateID);
}
if (StringUtils.isNotEmpty(originID)) {
writer.attr(ATTR_ORIGIN_ID, this.originID);
}
if (idleDayCount >= 0) {
writer.attr(ATTR_DAY_COUNT, this.idleDayCount);
}
writer.attr(TEST_TEMPLATE_FLAG, this.testTemplate);
writeProcessMap(writer);
writeConsumingMap(writer);
writer.end();
}
private void writeProcessMap(XMLPrintWriter writer) {
writer.startTAG(XML_PROCESS_MAP);
writer.attr(ATTR_PROCESS, (String) processMap.get(ATTR_PROCESS));
writer.attr(ATTR_FLOAT_COUNT, (int) processMap.get(ATTR_FLOAT_COUNT));
writer.attr(ATTR_WIDGET_COUNT, (int) processMap.get(ATTR_WIDGET_COUNT));
writer.attr(ATTR_CELL_COUNT, (int) processMap.get(ATTR_CELL_COUNT));
writer.attr(ATTR_BLOCK_COUNT, (int) processMap.get(ATTR_BLOCK_COUNT));
writer.attr(ATTR_REPORT_TYPE, (int) processMap.get(ATTR_REPORT_TYPE));
writer.attr(ATTR_PARA_APPLY, (int) processMap.get(ATTR_PARA_APPLY));
writer.attr(ATTR_COMPONENTS_INFO, (String) processMap.get(ATTR_COMPONENTS_INFO));
writer.attr(ATTR_REUSE_CMP_LIST, (String) processMap.get(ATTR_REUSE_CMP_LIST));
writer.end();
}
private void writeConsumingMap(XMLPrintWriter writer) {
writer.startTAG(XML_CONSUMING_MAP);
writer.attr(ATTR_CREATE_TIME, (String) consumingMap.get(ATTR_CREATE_TIME));
writer.attr(ATTR_UUID, (String) consumingMap.get(ATTR_UUID));
writer.attr(ATTR_UID, (int) consumingMap.get(ATTR_UID));
writer.attr(ATTR_SAVE_RECORD, (String) consumingMap.get(ATTR_SAVE_RECORD));
writer.end();
}
@Override
public void readXML(XMLableReader reader) {
if (!reader.isChildNode()) {
idleDayCount = reader.getAttrAsInt(ATTR_DAY_COUNT, 0);
testTemplate = reader.getAttrAsBoolean(TEST_TEMPLATE_FLAG, false);
templateID = reader.getAttrAsString(ATTR_TEMPLATE_ID, StringUtils.EMPTY);
originID = reader.getAttrAsString(ATTR_ORIGIN_ID, StringUtils.EMPTY);
} else {
try {
String name = reader.getTagName();
if (XML_PROCESS_MAP.equals(name)) {
processMap.put(ATTR_PROCESS, reader.getAttrAsString(ATTR_PROCESS, StringUtils.EMPTY));
processMap.put(ATTR_FLOAT_COUNT, reader.getAttrAsInt(ATTR_FLOAT_COUNT, 0));
processMap.put(ATTR_WIDGET_COUNT, reader.getAttrAsInt(ATTR_WIDGET_COUNT, 0));
processMap.put(ATTR_CELL_COUNT, reader.getAttrAsInt(ATTR_CELL_COUNT, 0));
processMap.put(ATTR_BLOCK_COUNT, reader.getAttrAsInt(ATTR_BLOCK_COUNT, 0));
processMap.put(ATTR_REPORT_TYPE, reader.getAttrAsInt(ATTR_REPORT_TYPE, 0));
processMap.put(ATTR_PARA_APPLY, reader.getAttrAsInt(ATTR_PARA_APPLY, 0));
processMap.put(ATTR_COMPONENTS_INFO, reader.getAttrAsString(ATTR_COMPONENTS_INFO, StringUtils.EMPTY));
processMap.put(ATTR_REUSE_CMP_LIST, reader.getAttrAsString(ATTR_REUSE_CMP_LIST, StringUtils.EMPTY));
processMap.put(ATTR_TEMPLATE_ID, templateID);
} else if (XML_CONSUMING_MAP.equals(name)) {
consumingMap.put(ATTR_CREATE_TIME, reader.getAttrAsString(ATTR_CREATE_TIME, StringUtils.EMPTY));
consumingMap.put(ATTR_TEMPLATE_ID, templateID);
consumingMap.put(ATTR_ORIGIN_ID, originID);
consumingMap.put(ATTR_UUID, reader.getAttrAsString(ATTR_UUID, StringUtils.EMPTY));
consumingMap.put(ATTR_UID, reader.getAttrAsInt(ATTR_UID, 0));
consumingMap.put(ATTR_SAVE_RECORD, reader.getAttrAsString(ATTR_SAVE_RECORD, StringUtils.EMPTY));
}
} catch (Exception ex) {
// 什么也不做,使用默认值
}
}
}
@Override
public boolean isTestTemplate() {
return testTemplate;
}
public static boolean isTestTemplate(int reportType, int cellCount, int floatCount, int blockCount, int widgetCount) {
boolean isTestTemplate;
if (reportType == 0) { // 普通报表
isTestTemplate = cellCount <= VALID_CELL_COUNT && floatCount <= 1 && widgetCount <= VALID_WIDGET_COUNT;
} else if (reportType == 1) { // 聚合报表
isTestTemplate = blockCount <= 1 && widgetCount <= VALID_WIDGET_COUNT;
} else { // 表单(reportType == 2)
isTestTemplate = widgetCount <= 1;
}
return isTestTemplate;
}
@Override
protected boolean isComplete() {
return true;
}
@Override
public Map<String, String> getSendInfo() {
Map<String, String> sendMap = new HashMap<>();
sendMap.put(CONSUMING_URL, JSONFactory.createJSON(JSON.OBJECT, consumingMap).toString());
sendMap.put(PROCESS_URL, JSONFactory.createJSON(JSON.OBJECT, processMap).toString());
return sendMap;
}
void updateProcessMap(TemplateProcessInfo processInfo) {
HashMap<String, Object> processMap = new HashMap<>();
// 暂不支持模版制作过程的收集
processMap.put(ATTR_PROCESS, StringUtils.EMPTY);
processMap.put(ATTR_REPORT_TYPE, processInfo.getReportType());
processMap.put(ATTR_CELL_COUNT, processInfo.getCellCount());
processMap.put(ATTR_FLOAT_COUNT, processInfo.getFloatCount());
processMap.put(ATTR_BLOCK_COUNT, processInfo.getBlockCount());
processMap.put(ATTR_WIDGET_COUNT, processInfo.getWidgetCount());
processMap.put(ATTR_PARA_APPLY, processInfo.useParaPane() ? 1 : 0);
processMap.put(ATTR_COMPONENTS_INFO, processInfo.getComponentsInfo().toString());
processMap.put(ATTR_REUSE_CMP_LIST, processInfo.getReuseCmpList().toString());
this.processMap = processMap;
}
int getIdleDayCount() {
return this.idleDayCount;
}
}

210
designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfoCollector.java

@ -1,210 +0,0 @@
package com.fr.design.mainframe.template.info;
import com.fr.design.mainframe.burying.point.AbstractPointCollector;
import com.fr.design.mainframe.burying.point.AbstractPointInfo;
import com.fr.json.JSON;
import com.fr.json.JSONFactory;
import com.fr.json.JSONObject;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 做模板的过程和耗时收集辅助类
* Created by plough on 2017/2/21.
*/
public class TemplateInfoCollector extends AbstractPointCollector<TemplateInfo> {
private static final String XML_TAG = "TplInfo";
private static final String XML_TEMPLATE_INFO_LIST = "TemplateInfoList";
private static final String XML_FILE_NAME = "tpl.info";
private static TemplateInfoCollector instance;
private DesignerOpenHistory designerOpenHistory = DesignerOpenHistory.getInstance();
//记录指定模板最新的模板耗时信息ID
private Map<String, Long> latestTemplateInfo;
private TemplateInfoCollector() {
super();
}
public static TemplateInfoCollector getInstance() {
if (instance == null) {
instance = new TemplateInfoCollector();
}
return instance;
}
/**
* 根据模板ID是否在收集列表中判断是否需要收集当前模板的信息
*/
public boolean contains(String templateID) {
return StringUtils.isNotEmpty(templateID) && latestTemplateInfo.containsKey(templateID);
}
/**
* 收集模板信息如果之前没有记录则新增如果已有记录则更新
* 同时将最新数据保存到文件中
*
* @param templateID 模版id
* @param originID 模版的原始id仅对另存为的模版有效对于非另存为的模版值总是为空
* @param processInfo 包含模版的一些基本信息如模版类型包含控件数量等
* @param timeConsume 本次制作耗时单位为 s
*/
@Override
public void collectInfo(String templateID, String originID, TemplateProcessInfo processInfo, int timeConsume) {
if (!shouldCollectInfo()) {
return;
}
long saveTime = System.currentTimeMillis();
TemplateInfo templateInfo = createTemplateInfo(templateID, originID, saveTime, timeConsume);
pointInfoMap.put(templateInfo.getTemplateInfoID(), templateInfo);
//更新下此模板最新保存记录
updateLatestTemplateInfo(templateID, saveTime);
// 收集模版基本信息
templateInfo.updateProcessMap(processInfo);
//设置是否是测试模板
templateInfo.setTestTemplate(processInfo.isTestTemplate());
// 刷新闲置日计数器
templateInfo.resetIdleDayCount();
// 每次更新之后,都同步到暂存文件中
saveInfo();
}
private TemplateInfo createTemplateInfo(String templateID, String originID, long saveTime, int timeConsume){
JSONObject saveRecord = JSONFactory.createJSON(JSON.OBJECT);
saveRecord.put("time", saveTime);
saveRecord.put("consume", timeConsume);
if (this.contains(templateID)){
return TemplateInfo.newInstance(templateID, originID, saveRecord.toString(), getTemplateCreateTime(templateID));
}
return TemplateInfo.newInstance(templateID, originID, saveRecord.toString());
}
private String getTemplateCreateTime(String templateID) {
long latestSaveTime = latestTemplateInfo.get(templateID);
TemplateInfo latestTemplateInfo = pointInfoMap.get(templateID + "_" + latestSaveTime);
return latestTemplateInfo.getTemplateCreateTime();
}
/**
* 更新 day_count打开设计器却未编辑模板的连续日子
*/
@Override
protected void addIdleDayCount() {
// 判断今天是否第一次打开设计器,为了防止同一天内,多次 addIdleDayCount
if (designerOpenHistory.hasOpenedToday()) {
return;
}
for (TemplateInfo templateInfo : pointInfoMap.values()) {
templateInfo.addIdleDayCountByOne();
}
designerOpenHistory.update();
}
private void updateLatestTemplateInfo(TemplateInfo templateInfo) {
String templateID = templateInfo.getTemplateID();
if (latestTemplateInfo.containsKey(templateID)) {
long latestSaveTime = latestTemplateInfo.get(templateID);
updateLatestTemplateInfo(templateID, Math.max(latestSaveTime, templateInfo.getSaveTime()));
} else {
updateLatestTemplateInfo(templateID, templateInfo.getSaveTime());
}
}
private void updateLatestTemplateInfo(String templateID, long saveTime) {
latestTemplateInfo.put(templateID, saveTime);
}
@Override
public void readXML(XMLableReader reader) {
if (reader.isChildNode()) {
try {
String name = reader.getTagName();
if (DesignerOpenHistory.XML_TAG.equals(name)) {
if (designerOpenHistory == null) {
designerOpenHistory = DesignerOpenHistory.getInstance();
}
reader.readXMLObject(designerOpenHistory);
} else if (TemplateInfo.XML_TAG.equals(name)) {
TemplateInfo templateInfo = TemplateInfo.newInstanceByRead(reader);
updateLatestTemplateInfo(templateInfo);
pointInfoMap.put(templateInfo.getTemplateInfoID(), templateInfo);
}
} catch (Exception ex) {
// 什么也不做,使用默认值
}
}
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG(XML_TAG);
designerOpenHistory.writeXML(writer);
writer.startTAG(XML_TEMPLATE_INFO_LIST);
for (TemplateInfo templateInfo : pointInfoMap.values()) {
templateInfo.writeXML(writer);
}
writer.end();
writer.end();
}
/**
* 获取缓存文件存放路径
*/
@Override
protected String getInfoFilePath() {
return XML_FILE_NAME;
}
@Override
public void sendPointInfo() {
addIdleDayCount();
List<String> removeList = new ArrayList<>();
List<String> sendList = new ArrayList<>();
for (String latestTemplateInfokey : latestTemplateInfo.keySet()) {
AbstractPointInfo pointInfo = pointInfoMap.get(latestTemplateInfokey + "_" + latestTemplateInfo.get(latestTemplateInfokey));
if (pointInfo.isTestTemplate()) {
continue;
}
for (String key : pointInfoMap.keySet()) {
if (key.startsWith(latestTemplateInfokey)) {
sendList.add(key);
}
}
}
// 发送记录
for (String key : sendList) {
if (SendHelper.sendPointInfo(pointInfoMap.get(key))) {
removeList.add(key);
}
}
// 清空记录
for (String key : removeList) {
pointInfoMap.remove(key);
}
saveInfo();
}
@Override
protected void loadFromFile() {
latestTemplateInfo = new ConcurrentHashMap<>();
super.loadFromFile();
}
}

2
designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateOperate.java

@ -4,7 +4,9 @@ import com.fr.json.JSONObject;
/**
* Created by kerry on 2020-05-08
* @deprecated moved to Cloud Ops plugin
*/
@Deprecated
public interface TemplateOperate {
/**
* 获取模板操作类型

13
designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateProcessInfo.java

@ -8,11 +8,11 @@ import com.fr.json.JSONArray;
/**
* Created by plough on 2017/3/17.
*
* @deprecated moved to cloud ops plugin
*/
// todo: 重构
// 1. 命名不好,表意不清晰。
// 2. 逻辑混乱,到底是一个 Info 类,还是一个 InfoCollector 类?
// 3. 耦合太强,用组合替代继承
@Deprecated
public abstract class TemplateProcessInfo<T extends BaseBook> {
protected T template;
@ -56,10 +56,7 @@ public abstract class TemplateProcessInfo<T extends BaseBook> {
if (value instanceof ChartCollection && isTestChartCollection((ChartCollection) value)) {
return true;
}
if (value == null && Style.getInstance().equals(style)) {
return true;
}
return false;
return value == null && Style.getInstance().equals(style);
}
protected boolean isTestChartCollection(ChartCollection chartCollection) {

2
designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java

@ -2,7 +2,9 @@ package com.fr.design.mainframe.template.info;
/**
* Created by plough on 2019/4/19.
* @deprecated moved to Cloud Ops plugin
*/
@Deprecated
public class TimeConsumeTimer {
private static final int ONE_THOUSAND = 1000;
private enum State {

31
designer-base/src/test/java/com/fr/design/mainframe/template/info/SendHelperTest.java

@ -1,38 +1,7 @@
package com.fr.design.mainframe.template.info;
import com.fr.invoke.Reflect;
import com.fr.json.JSONObject;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.javax.xml.stream.XMLStreamException;
import java.io.StringReader;
import java.util.Map;
import static org.junit.Assert.assertTrue;
/**
* Created by plough on 2019/4/25.
*/
public class SendHelperTest {
private static final String CONSUMING_URL = "http://cloud.fanruan.com/api/monitor/record_of_reports_consuming/single";
private static final String PROCESS_URL = "http://cloud.fanruan.com/api/monitor/record_of_reports_process/single";
private static final String NORMAL_INFO = "<TemplateInfo templateID=\"16a988ce-8529-42f5-b17c-2ee849355071\" day_count=\"9\">\n" +
"<processMap process=\"\" float_count=\"0\" widget_count=\"0\" cell_count=\"1\" block_count=\"0\" report_type=\"0\"/>\n" +
"<consumingMap activitykey=\"2e0ea413-fa9c241e0-9723-4354fce51e81\" jar_time=\"不是安装版本\" create_time=\"2019-03-26 16:13\" uuid=\"476ca2cc-f789-4c5d-8e89-ef146580775c\" time_consume=\"129\" version=\"10.0\" username=\"plough\"/>\n" +
"</TemplateInfo>";
// 只在调试的时候运行,不需要每次都自动运行
public static void main(String[] args) throws XMLStreamException {
StringReader sr = new StringReader(NORMAL_INFO);
XMLableReader xmlReader = XMLableReader.createXMLableReader(sr);
TemplateInfo templateInfo = TemplateInfo.newInstanceByRead(xmlReader);
Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
Map processMap = Reflect.on(templateInfo).field("processMap").get();
boolean res = Reflect.on(SendHelper.class).call("sendSinglePointInfo", CONSUMING_URL, new JSONObject(consumingMap).toString()).get();
assertTrue(res);
boolean res2 = Reflect.on(SendHelper.class).call("sendSinglePointInfo", PROCESS_URL, new JSONObject(processMap).toString()).get();
assertTrue(res2);
}
}

252
designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoCollectorTest.java

@ -1,252 +0,0 @@
package com.fr.design.mainframe.template.info;
import com.fr.config.MarketConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.invoke.Reflect;
import com.fr.json.JSON;
import com.fr.json.JSONArray;
import com.fr.json.JSONFactory;
import com.fr.stable.ProductConstants;
import com.fr.stable.StringUtils;
import com.fr.third.org.apache.commons.io.FileUtils;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import static com.fr.design.mainframe.template.info.TemplateInfoTestHelper.assertJsonStringEquals;
import static com.fr.design.mainframe.template.info.TemplateInfoTestHelper.setUpMockForNewInstance;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Created by plough on 2019/4/18.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ProductConstants.class, MarketConfig.class, DesignerEnvManager.class})
@SuppressStaticInitializationFor({"com.fr.jvm.assist.FineAssist"})
public class TemplateInfoCollectorTest {
private String filePath;
private String initialFileContent;
private TemplateProcessInfo mockProcessInfo;
@Before
public void setUp() throws IOException {
PowerMock.mockStatic(ProductConstants.class);
filePath = getClass().getResource("tpl.info").getPath();
String dirPath = filePath.substring(0, filePath.indexOf("tpl.info"));
EasyMock.expect(ProductConstants.getEnvHome()).andReturn(dirPath).anyTimes();
EasyMock.replay();
PowerMock.replayAll();
mockProcessInfo = EasyMock.mock(TemplateProcessInfo.class);
EasyMock.expect(mockProcessInfo.getBlockCount()).andReturn(3).anyTimes();
EasyMock.expect(mockProcessInfo.getCellCount()).andReturn(13).anyTimes();
EasyMock.expect(mockProcessInfo.getFloatCount()).andReturn(1).anyTimes();
EasyMock.expect(mockProcessInfo.getReportType()).andReturn(0).anyTimes();
EasyMock.expect(mockProcessInfo.getWidgetCount()).andReturn(0).anyTimes();
EasyMock.expect(mockProcessInfo.useParaPane()).andReturn(false).anyTimes();
EasyMock.expect(mockProcessInfo.getComponentsInfo()).andReturn(new JSONArray()).anyTimes();
EasyMock.expect(mockProcessInfo.isTestTemplate()).andReturn(true).anyTimes();
EasyMock.expect(mockProcessInfo.getReuseCmpList()).andReturn(JSONArray.create().add("reuse-id-1")).anyTimes();
EasyMock.replay(mockProcessInfo);
// 缓存 tpl.info
initialFileContent = FileUtils.readFileToString(new File(filePath), "utf-8");
Reflect.on(TemplateInfoCollector.class).set("instance", null);
// 后执行 testReadXML 用例时,之前保留的单例会造成影响
Reflect.on(DesignerOpenHistory.class).set("singleton", null);
}
@After
public void tearDown() throws IOException {
// 恢复 tpl.info
FileUtils.writeStringToFile(new File(filePath), initialFileContent, "utf-8");
}
@Test
public void testReadXML() {
assertEquals(",,", DesignerOpenHistory.getInstance().toString());
TemplateInfoCollector collector = TemplateInfoCollector.getInstance();
assertEquals("2020-05-07,2020-05-06,2020-04-30", DesignerOpenHistory.getInstance().toString());
}
@Test
public void testCollectInfo() throws Exception {
setUpMockForNewInstance();
TemplateInfoCollector collector = TemplateInfoCollector.getInstance();
String templateID = "e5d7dbb2-d1df-43d4-b974-67acb5ecbffa";
int timeConsume = 200;
collector.collectInfo(templateID, StringUtils.EMPTY, mockProcessInfo, timeConsume);
// 检查是否写入成功
Reflect.on(collector).call("loadFromFile");
TemplateInfo templateInfo = getTemplateInfoByID(templateID);
Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
Map processMap = Reflect.on(templateInfo).field("processMap").get();
assertJsonStringEquals("{\"process\":\"\",\"float_count\":1,\"widget_count\":0," +
"\"cell_count\":13,\"paraApply\":0,\"block_count\":3,\"report_type\":0,\"components_info\":\"[]\"," +
"\"templateID\":\"e5d7dbb2-d1df-43d4-b974-67acb5ecbffa\",\"reuseCmptList\":\"[\\\"reuse-id-1\\\"]\"" +
"}",
JSONFactory.createJSON(JSON.OBJECT, processMap).toString());
Assert.assertEquals(71113, consumingMap.get("uid"));
Assert.assertEquals("2020-05-07 17:25", consumingMap.get("create_time"));
Assert.assertEquals("e5d7dbb2-d1df-43d4-b974-67acb5ecbffa", consumingMap.get("templateID"));
Assert.assertEquals("6b6699ff-ec63-43b0-9deb-b580a5f10411", consumingMap.get("uuid"));
}
@Test
public void testCollectInfoForNewTemplate() throws Exception {
setUpMockForNewInstance();
TemplateInfoCollector collector = TemplateInfoCollector.getInstance();
String templateID = "e5d7dbb2-d1df-43d4-b974-67acb5ecbffa";
int timeConsume = 200;
collector.collectInfo(templateID, StringUtils.EMPTY, mockProcessInfo, timeConsume);
// 检查是否写入成功
Reflect.on(collector).call("loadFromFile");
assertTrue(collector.contains(templateID));
TemplateInfo templateInfo = getTemplateInfoByID(templateID);
Map processMap = Reflect.on(templateInfo).field("processMap").get();
assertEquals(templateID, templateInfo.getTemplateID());
assertJsonStringEquals("{\"process\":\"\",\"float_count\":1,\"widget_count\":0," +
"\"cell_count\":13,\"paraApply\":0,\"block_count\":3,\"report_type\":0,\"components_info\":\"[]\"," +
"\"templateID\":\"e5d7dbb2-d1df-43d4-b974-67acb5ecbffa\",\"reuseCmptList\":\"[\\\"reuse-id-1\\\"]\"" +
"}", JSONFactory.createJSON(JSON.OBJECT, processMap).toString());
Map<String, Object> consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
Assert.assertEquals(71113, consumingMap.get("uid"));
Assert.assertEquals("2020-05-07 17:25", consumingMap.get("create_time"));
Assert.assertEquals("e5d7dbb2-d1df-43d4-b974-67acb5ecbffa", consumingMap.get("templateID"));
Assert.assertEquals("6b6699ff-ec63-43b0-9deb-b580a5f10411", consumingMap.get("uuid"));
}
@Test
public void testCollectInfoWhenSaveAs() throws Exception {
setUpMockForNewInstance();
TemplateInfoCollector collector = TemplateInfoCollector.getInstance();
String templateID = "e5d7dbb2-d1df-43d4-b974-67acb5ecbffa";
String originID = "16a988ce-8529-42f5-b17c-2ee849355071";
int timeConsume = 200;
collector.collectInfo(templateID, originID, mockProcessInfo, timeConsume);
// 检查是否写入成功
Reflect.on(collector).call("loadFromFile");
TemplateInfo templateInfo = getTemplateInfoByID(templateID);
Map processMap = Reflect.on(templateInfo).field("processMap").get();
assertJsonStringEquals("{\"process\":\"\",\"float_count\":1,\"widget_count\":0," +
"\"cell_count\":13,\"paraApply\":0,\"block_count\":3,\"report_type\":0,\"components_info\":\"[]\"," +
"\"templateID\":\"e5d7dbb2-d1df-43d4-b974-67acb5ecbffa\",\"reuseCmptList\":\"[\\\"reuse-id-1\\\"]\"" +
"}", JSONFactory.createJSON(JSON.OBJECT, processMap).toString());
Map<String, Object> consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
Assert.assertEquals(71113, consumingMap.get("uid"));
Assert.assertEquals("2020-05-07 17:25", consumingMap.get("create_time"));
Assert.assertEquals("e5d7dbb2-d1df-43d4-b974-67acb5ecbffa", consumingMap.get("templateID"));
Assert.assertEquals("6b6699ff-ec63-43b0-9deb-b580a5f10411", consumingMap.get("uuid"));
Assert.assertEquals("16a988ce-8529-42f5-b17c-2ee849355071", consumingMap.get("originID"));
}
@Test
public void testCollectInfoWhenSaveAsWithNoTrackOriginID() throws Exception {
setUpMockForNewInstance();
TemplateInfoCollector collector = TemplateInfoCollector.getInstance();
String templateID = "e5d7dbb2-d1df-43d4-b974-67acb5ecbffa";
String originID = "3kha8jcs-31xw-42f5-h2ww-2ee84935312z";
int timeConsume = 200;
collector.collectInfo(templateID, originID, mockProcessInfo, timeConsume);
TemplateInfo templateInfo = getTemplateInfoByID(templateID);
assertEquals(templateID, templateInfo.getTemplateID());
Map<String, Object> consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
Assert.assertEquals(71113, consumingMap.get("uid"));
Assert.assertEquals("2020-05-07 17:25", consumingMap.get("create_time"));
Assert.assertEquals("e5d7dbb2-d1df-43d4-b974-67acb5ecbffa", consumingMap.get("templateID"));
Assert.assertEquals("6b6699ff-ec63-43b0-9deb-b580a5f10411", consumingMap.get("uuid"));
Assert.assertEquals("3kha8jcs-31xw-42f5-h2ww-2ee84935312z", consumingMap.get("originID"));
}
@Test
public void testAddIdleDateCount() {
String templateID = "e5d7dbb2-d1df-43d4-b974-67acb5ecbffa";
TemplateInfoCollector collecter = TemplateInfoCollector.getInstance();
TemplateInfo templateInfo = getTemplateInfoByID(templateID);
assertEquals(0, templateInfo.getIdleDayCount());
Reflect.on(collecter).call("addIdleDayCount");
assertEquals(1, templateInfo.getIdleDayCount());
// 同一天内多次调用无效
Reflect.on(collecter).call("addIdleDayCount");
assertEquals(1, templateInfo.getIdleDayCount());
}
@Test
public void testContains() {
TemplateInfoCollector collector = TemplateInfoCollector.getInstance();
String templateID1 = "e5d7dbb2-d1df-43d4-b974-67acb5ecbffa";
Assert.assertTrue(collector.contains(templateID1));
String templateID2 = "e5d7dbb2-d1df-43d4-b974-67acb5ecbffb";
Assert.assertFalse(collector.contains(templateID2));
}
@Test
public void testGetTemplateCreateTime() throws Exception {
setUpMockForNewInstance();
TemplateInfoCollector collector = TemplateInfoCollector.getInstance();
String templateID = "e5d7dbb2-d1df-43d4-b974-67acb5ecbffa";
String createTime = Reflect.on(collector).call("getTemplateCreateTime", templateID).get();
Assert.assertEquals("2020-05-07 17:25", createTime);
templateID = "2521d03c-b238-41a5-9a1d-2498efff3a97";
createTime = Reflect.on(collector).call("getTemplateCreateTime", templateID).get();
Assert.assertEquals("2020-05-07 17:45", createTime);
}
private TemplateInfo getTemplateInfoByID(String templateID) {
TemplateInfoCollector collector = TemplateInfoCollector.getInstance();
Map<String, Long> latestTemplateInfo = Reflect.on(collector).field("latestTemplateInfo").get();
Map<String, TemplateInfo> pointInfoMap = Reflect.on(collector).field("pointInfoMap").get();
if (latestTemplateInfo.containsKey(templateID)) {
long latestSaveTime = latestTemplateInfo.get(templateID);
return pointInfoMap.get(templateID + "_" + latestSaveTime);
} else {
return TemplateInfo.newInstance(templateID);
}
}
}

143
designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoTest.java

@ -1,143 +0,0 @@
package com.fr.design.mainframe.template.info;
import com.fr.config.MarketConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.invoke.Reflect;
import com.fr.json.JSON;
import com.fr.json.JSONFactory;
import com.fr.json.JSONObject;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.javax.xml.stream.XMLStreamException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.StringReader;
import java.util.Map;
import static com.fr.design.mainframe.template.info.TemplateInfoTestHelper.assertJsonStringEquals;
import static com.fr.design.mainframe.template.info.TemplateInfoTestHelper.setUpMockForNewInstance;
import static org.junit.Assert.assertEquals;
/**
* Created by plough on 2019/4/19.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({MarketConfig.class, DesignerEnvManager.class})
public class TemplateInfoTest {
private static final String NORMAL_INFO = "<TemplateInfo templateID=\"aac1139e-018b-4481-867a-a18fc6d6f3e6\" day_count=\"0\" test_template=\"true\">\n" +
"<processMap process=\"\" float_count=\"0\" widget_count=\"0\" cell_count=\"3\" block_count=\"0\" report_type=\"0\" paraApply=\"0\" components_info=\"[]\"/>\n" +
"<consumingMap create_time=\"2020-05-07 17:28\" uuid=\"6b6699ff-ec63-43b0-9deb-b580a5f10411\" uid=\"71113\" saveRecord=\"{&quot;time&quot;:1588843693000,&quot;consume&quot;:4}\"/>\n" +
"</TemplateInfo>";
private static final String SAVE_AS_INFO = "<TemplateInfo templateID=\"2521d03c-b238-41a5-9a1d-2498efff3a97\" originID=\"aac1139e-018b-4481-867a-a18fc6d6f3e6\" day_count=\"0\" test_template=\"true\">\n" +
"<processMap process=\"\" float_count=\"0\" widget_count=\"0\" cell_count=\"3\" block_count=\"0\" report_type=\"0\" paraApply=\"0\" components_info=\"[]\"/>\n" +
"<consumingMap create_time=\"2020-05-07 17:45\" uuid=\"6b6699ff-ec63-43b0-9deb-b580a5f10411\" uid=\"71113\" saveRecord=\"{&quot;time&quot;:1588844751000,&quot;consume&quot;:1058}\"/>\n" +
"</TemplateInfo>";
private TemplateInfo templateInfo;
private TemplateInfo templateInfoSaveAs; // 另存为的模版记录
@Before
public void setUp() throws XMLStreamException {
templateInfo = createTemplateInfo(NORMAL_INFO);
templateInfoSaveAs = createTemplateInfo(SAVE_AS_INFO);
}
@Test
public void testNewInstance() throws Exception {
setUpMockForNewInstance();
String templateID = "24avc8n2-1iq8-iuj2-wx24-8yy0i8132302";
TemplateInfo templateInfo = TemplateInfo.newInstance(templateID);
assertEquals(templateID, templateInfo.getTemplateID());
assertEquals(StringUtils.EMPTY, Reflect.on(templateInfo).field("originID").get());
assertEquals(0, (int) Reflect.on(templateInfo).field("idleDayCount").get());
assertEquals(false, templateInfo.isTestTemplate());
Map<String, Object> consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
assertEquals(templateID, consumingMap.get("templateID"));
assertEquals(StringUtils.EMPTY, consumingMap.get("originID"));
assertEquals("6b6699ff-ec63-43b0-9deb-b580a5f10411", consumingMap.get("uuid"));
assertEquals(71113, consumingMap.get("uid"));
assertEquals(StringUtils.EMPTY, consumingMap.get("saveRecord"));
}
@Test
public void testNewInstanceWithMoreArgs() throws Exception {
setUpMockForNewInstance();
String templateID = "24121212-u2c8-ncd2-82nx-8ud0i8138888";
String originID = "24avc8n2-1iq8-iuj2-wx24-8yy0i8132302";
String saveRecord = "{\"time\";:1588843629000,\"consume\":81}";
String createTime = "2020-05-07 17:25";
TemplateInfo templateInfo = TemplateInfo.newInstance(templateID, originID, saveRecord, createTime);
assertEquals(templateID, templateInfo.getTemplateID());
assertEquals(originID, Reflect.on(templateInfo).field("originID").get());
assertEquals(0, (int) Reflect.on(templateInfo).field("idleDayCount").get());
assertEquals(false, templateInfo.isTestTemplate());
Map<String, Object> consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
assertEquals(templateID, consumingMap.get("templateID"));
assertEquals(originID, consumingMap.get("originID"));
assertEquals("6b6699ff-ec63-43b0-9deb-b580a5f10411", consumingMap.get("uuid"));
assertEquals(71113, consumingMap.get("uid"));
assertEquals(saveRecord, consumingMap.get("saveRecord"));
assertEquals(createTime, consumingMap.get("create_time"));
}
@Test
public void testGetTemplateID() {
assertEquals("aac1139e-018b-4481-867a-a18fc6d6f3e6", templateInfo.getTemplateID());
assertEquals("2521d03c-b238-41a5-9a1d-2498efff3a97", templateInfoSaveAs.getTemplateID());
}
@Test
public void testGetSendInfo() {
Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
Map processMap = Reflect.on(templateInfo).field("processMap").get();
Map consumingMap1 = Reflect.on(templateInfoSaveAs).field("consumingMap").get();
Map processMap1 = Reflect.on(templateInfoSaveAs).field("processMap").get();
assertJsonStringEquals("{\"uid\":71113,\"originID\":\"\",\"create_time\":\"2020-05-07 17:28\"," +
"\"saveRecord\":\"{\\\"time\\\":1588843693000,\\\"consume\\\":4}\"," +
"\"templateID\":\"aac1139e-018b-4481-867a-a18fc6d6f3e6\"," +
"\"uuid\":\"6b6699ff-ec63-43b0-9deb-b580a5f10411\"}", JSONFactory.createJSON(JSON.OBJECT, consumingMap).toString());
assertJsonStringEquals("{\"uid\":71113,\"originID\":\"aac1139e-018b-4481-867a-a18fc6d6f3e6\"," +
"\"create_time\":\"2020-05-07 17:45\",\"saveRecord\":\"{\\\"time\\\":1588844751000,\\\"consume\\\":1058}\"," +
"\"templateID\":\"2521d03c-b238-41a5-9a1d-2498efff3a97\"," +
"\"uuid\":\"6b6699ff-ec63-43b0-9deb-b580a5f10411\"}", JSONFactory.createJSON(JSON.OBJECT, consumingMap1).toString());
assertJsonStringEquals("{\"process\":\"\",\"float_count\":0,\"widget_count\":0,\"cell_count\":3," +
"\"paraApply\":0,\"block_count\":0,\"report_type\":0,\"components_info\":\"[]\"," +
"\"templateID\":\"aac1139e-018b-4481-867a-a18fc6d6f3e6\"}", JSONFactory.createJSON(JSON.OBJECT, processMap).toString());
assertJsonStringEquals("{\"process\":\"\",\"float_count\":0,\"widget_count\":0,\"cell_count\":3," +
"\"paraApply\":0,\"block_count\":0,\"report_type\":0,\"components_info\":\"[]\"," +
"\"templateID\":\"2521d03c-b238-41a5-9a1d-2498efff3a97\"}", JSONFactory.createJSON(JSON.OBJECT, processMap1).toString());
}
private TemplateInfo createTemplateInfo(String xmlContent) throws XMLStreamException {
StringReader sr = new StringReader(xmlContent);
XMLableReader xmlReader = XMLableReader.createXMLableReader(sr);
return TemplateInfo.newInstanceByRead(xmlReader);
}
@Test
public void testGetSaveTime() {
Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
String saveRecord = (String) consumingMap.get("saveRecord");
JSONObject object = JSONFactory.createJSON(JSON.OBJECT, saveRecord);
Assert.assertEquals(1588843693000L, object.optLong("time"));
}
@Test
public void testGetTemplateCreateTime() {
Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get();
Assert.assertEquals("2020-05-07 17:28", (String) consumingMap.get("create_time"));
}
}

9
designer-form/src/main/java/com/fr/design/form/util/FormDesignerUtils.java

@ -11,6 +11,7 @@ import com.fr.design.mainframe.template.info.ComponentCreateOperate;
import com.fr.design.mainframe.template.info.ComponentDeleteOperate;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WFitLayout;
import java.awt.Container;
@ -40,11 +41,19 @@ public class FormDesignerUtils {
}
/**
* 添加控件
* 被云端运维插件修改用于收集埋点
*/
public static void addWidgetProcessInfo(Widget widget) {
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
jTemplate.getProcessInfo().updateTemplateOperationInfo(new ComponentCreateOperate(widget));
}
/**
* 删除控件
* 被云端运维插件修改用于收集埋点
*/
public static void removeWidgetProcessInfo(Widget widget) {
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
jTemplate.getProcessInfo().updateTemplateOperationInfo(new ComponentDeleteOperate(widget));

1
designer-form/src/main/java/com/fr/design/mainframe/JForm.java

@ -182,6 +182,7 @@ public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm<F
return DesignState.JFORM;
}
@Override
public TemplateProcessInfo<Form> getProcessInfo() {
//这边需要判空,图表的埋点信息收集时可能没有初始化processInfo
if (processInfo == null) {

5
designer-form/src/main/java/com/fr/design/mainframe/template/info/JFormProcessInfo.java

@ -1,7 +1,6 @@
package com.fr.design.mainframe.template.info;
import com.fr.base.iofile.attr.ExtendSharableAttrMark;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.form.FormElementCaseProvider;
import com.fr.form.main.Form;
@ -21,6 +20,7 @@ import com.fr.general.ComparatorUtils;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.report.cell.DefaultTemplateCellElement;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -30,7 +30,10 @@ import java.util.regex.Pattern;
/**
* Created by plough on 2017/3/17.
*
* @deprecated moved to cloud ops plugin
*/
@Deprecated
public class JFormProcessInfo extends TemplateProcessInfo<Form> {
private static final String REGEX = "^" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Title") + "\\d+$";

130
designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java

@ -1,26 +1,16 @@
/**
*
*/
package com.fr.design.mainframe;
import com.fr.base.FRContext;
import com.fr.common.annotations.Compatible;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.config.MarketConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.chart.info.ChartInfoCollector;
import com.fr.design.mainframe.errorinfo.ErrorInfoUploader;
import com.fr.design.mainframe.messagecollect.impl.FocusPointMessageUploader;
import com.fr.design.mainframe.messagecollect.solid.SolidCollector;
import com.fr.design.mainframe.template.info.TemplateInfoCollector;
import com.fr.general.CloudCenter;
import com.fr.general.ComparatorUtils;
import com.fr.general.DateUtils;
import com.fr.general.DesUtils;
import com.fr.general.GeneralUtils;
import com.fr.general.IOUtils;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.EncodeConstants;
import com.fr.stable.ProductConstants;
@ -32,7 +22,6 @@ import com.fr.stable.xml.XMLTools;
import com.fr.stable.xml.XMLWriter;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.javax.xml.stream.XMLStreamException;
import com.sun.management.OperatingSystemMXBean;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
@ -46,12 +35,10 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executors;
@ -60,8 +47,9 @@ import java.util.concurrent.TimeUnit;
/**
* @author neil
* @date: 2015-4-8-下午5:11:46
* @date 2015-4-8-下午5:11:46
*/
@Compatible
public class InformationCollector implements XMLReadable, XMLWriter {
/**
@ -69,35 +57,26 @@ public class InformationCollector implements XMLReadable, XMLWriter {
*/
private static final long DELTA = 24 * 3600 * 1000L;
private static final long SEND_DELAY = 300 * 1000L;
private static final int BYTE_TO_MB = 1024 * 1024;
private static final String FILE_NAME = "fr.info";
private static final String XML_START_STOP_LIST = "StartStopList";
private static final String XML_START_STOP = "StartStop";
private static final String XML_LAST_TIME = "LastTime";
private static final String ATTR_START = "start";
private static final String ATTR_STOP = "stop";
private static final String XML_JAR = "JarInfo";
private static final String XML_VERSION = "Version";
private static final String XML_USERNAME = "Username";
private static final String XML_UUID = "UUID";
private static final String XML_KEY = "ActiveKey";
private static final String XML_OS = "OS";
private static final String XML_ARCH = "arch";
private static final String XML_AVAILABLE_PROCESSORS = "cpu";
private static final String XML_PHYSICAL_MEMORY = "systemMemory";
private static InformationCollector collector;
/**
* 启动时间与关闭时间列表
*/
private List<StartStopTime> startStop = new ArrayList<StartStopTime>();
private final List<StartStopTime> startStop = new ArrayList<StartStopTime>();
/**
* 上一次的发送时间
*/
private String lastTime;
private StartStopTime current = new StartStopTime();
private final StartStopTime current = new StartStopTime();
public static InformationCollector getInstance() {
if (collector == null) {
@ -125,11 +104,7 @@ public class InformationCollector implements XMLReadable, XMLWriter {
xmlReader.readXMLObject(xmlReadable);
}
xmlInputStream.close();
} catch (FileNotFoundException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (XMLStreamException e) {
} catch (IOException | XMLStreamException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
@ -143,77 +118,24 @@ public class InformationCollector implements XMLReadable, XMLWriter {
private long getLastTimeMillis() {
if (StringUtils.isEmpty(this.lastTime)) {
return 0;
return 0L;
}
try {
return Objects.requireNonNull(DateUtils.string2Date(this.lastTime, true)).getTime();
} catch (Exception e) {
return -1;
return -1L;
}
}
private JSONObject getJSONContentAsByte() {
JSONObject content = new JSONObject();
JSONArray startStopArray = new JSONArray();
for (StartStopTime startStopTime : startStop) {
JSONObject jo = new JSONObject();
jo.put(ATTR_START, startStopTime.getStartDate());
jo.put(ATTR_STOP, startStopTime.getStopDate());
startStopArray.put(jo);
}
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager();
content.put(XML_START_STOP, startStopArray);
content.put(XML_UUID, envManager.getUUID());
content.put(XML_JAR, GeneralUtils.readBuildNO());
content.put(XML_VERSION, ProductConstants.RELEASE_VERSION);
content.put(XML_USERNAME, MarketConfig.getInstance().getBbsUsername());
content.put(XML_KEY, envManager.getActivationKey());
content.put(XML_OS, System.getProperty("os.name"));
content.put(XML_ARCH, System.getProperty("os.arch"));
content.put(XML_AVAILABLE_PROCESSORS, Runtime.getRuntime().availableProcessors());
content.put(XML_PHYSICAL_MEMORY, getTotalPhysicalMemorySize());
return content;
}
/**
* 获取物理内存单位GB
*
* @return 物理内存
*/
private static long getTotalPhysicalMemorySize() {
OperatingSystemMXBean bean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
return bean.getTotalPhysicalMemorySize() / BYTE_TO_MB;
}
private void sendUserInfo() {
private void sendInfoSuccessCallback() {
long currentTime = System.currentTimeMillis();
long lastTime = getLastTimeMillis();
if (currentTime - lastTime <= DELTA) {
return;
}
JSONObject content = getJSONContentAsByte();
String url = CloudCenter.getInstance().acquireUrlByKind("user.info.v10");
if (StringUtils.isBlank(url)) {
return;
}
boolean success = false;
try {
HashMap<String, Object> para = new HashMap<>();
para.put("token", SiteCenterToken.generateToken());
para.put("content", content);
String res = HttpToolbox.post(url, para);
success = ComparatorUtils.equals(new JSONObject(res).get("status"), "success");
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (success) {
this.reset();
}
this.reset();
}
/**
@ -221,27 +143,22 @@ public class InformationCollector implements XMLReadable, XMLWriter {
*/
public void collectStartTime() {
this.current.setStartDate(dateToString());
sendUserInfoInOtherThread();
sendInfo();
}
private void sendUserInfoInOtherThread() {
private void sendInfo() {
if (!DesignerEnvManager.getEnvManager().isJoinProductImprove() || !FRContext.isChineseEnv()) {
return;
}
ScheduledExecutorService service = Executors
.newSingleThreadScheduledExecutor(new NamedThreadFactory("InformationCollector"));
service.schedule(new Runnable() {
@Override
public void run() {
SolidCollector.getInstance().sendToCloudCenterAndDeleteFile();
sendUserInfo();
FocusPointMessageUploader.getInstance().sendToCloudCenter();
TemplateInfoCollector.getInstance().sendPointInfo();
ChartInfoCollector.getInstance().sendPointInfo();
ErrorInfoUploader.getInstance().sendErrorInfo();
}
service.schedule(() -> {
SolidCollector.getInstance().sendToCloudCenterAndDeleteFile();
FocusPointMessageUploader.getInstance().sendToCloudCenter();
ChartInfoCollector.getInstance().sendPointInfo();
ErrorInfoUploader.getInstance().sendErrorInfo();
sendInfoSuccessCallback();
}, SEND_DELAY, TimeUnit.MILLISECONDS);
service.shutdown();
}
@ -306,7 +223,7 @@ public class InformationCollector implements XMLReadable, XMLWriter {
//启停信息
writeStartStopList(writer);
//上一次更新的时间
writeTag(XML_LAST_TIME, this.lastTime, writer);
writeLastTime(this.lastTime, writer);
writer.end();
}
@ -320,12 +237,11 @@ public class InformationCollector implements XMLReadable, XMLWriter {
writer.end();
}
private void writeTag(String tag, String content, XMLPrintWriter writer) {
private void writeLastTime(String content, XMLPrintWriter writer) {
if (StringUtils.isEmpty(content)) {
return;
}
writer.startTAG(tag);
writer.startTAG(InformationCollector.XML_LAST_TIME);
writer.textNode(content);
writer.end();
}
@ -364,7 +280,7 @@ public class InformationCollector implements XMLReadable, XMLWriter {
});
}
private class StartStopTime implements XMLReadable, XMLWriter {
private static class StartStopTime implements XMLReadable, XMLWriter {
private String startDate;
private String stopDate;

3
designer-realize/src/main/java/com/fr/design/mainframe/template/info/JPolyWorkBookProcessInfo.java

@ -11,7 +11,10 @@ import java.util.Iterator;
/**
* Created by kerry on 2020-05-06
*
* @deprecated moved to plugin ops plugin
*/
@Deprecated
public class JPolyWorkBookProcessInfo extends JWorkBookProcessInfo {
public JPolyWorkBookProcessInfo(WorkBook template) {
super(template);

3
designer-realize/src/main/java/com/fr/design/mainframe/template/info/JWorkBookProcessInfo.java

@ -17,7 +17,10 @@ import java.util.Iterator;
/**
* Created by plough on 2017/3/17.
*
* @deprecated moved to cloud ops plugin
*/
@Deprecated
public class JWorkBookProcessInfo extends TemplateProcessInfo<WorkBook> {
public JWorkBookProcessInfo(WorkBook wb) {

Loading…
Cancel
Save