From 4c198a62abf1ece2e1a577499ee72fd124e005cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E5=B2=B3?= <445798420@qq.com> Date: Wed, 19 Feb 2020 16:28:09 +0800 Subject: [PATCH] =?UTF-8?q?CHART-12746=20=E5=9B=BE=E8=A1=A8=E5=9F=8B?= =?UTF-8?q?=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/fr/design/mainframe/JTemplate.java | 6 +- .../mainframe/chart/info/ChartInfo.java | 256 ++++++++++++++ .../chart/info/ChartInfoCollector.java | 333 ++++++++++++++++++ .../mainframe/chart/info/ChartSendHelper.java | 40 +++ .../java/com/fr/design/chart/ChartDialog.java | 24 +- .../com/fr/design/chart/ChartTypePane.java | 11 + .../design/mainframe/chart/ChartEditPane.java | 44 ++- .../chart/gui/ChartTypeButtonPane.java | 11 +- .../type/AbstractVanChartTypePane.java | 5 + .../mainframe/FormCreatorDropTarget.java | 36 +- .../mainframe/InformationCollector.java | 2 + .../poly/hanlder/PolyDesignerDropTarget.java | 68 ++-- 12 files changed, 772 insertions(+), 64 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfo.java create mode 100644 designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java create mode 100644 designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartSendHelper.java 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 305edac11..e99df1baa 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 @@ -36,6 +36,7 @@ import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.gui.itree.filetree.TemplateFileTree; 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.template.info.TemplateInfoCollector; import com.fr.design.mainframe.template.info.TemplateProcessInfo; import com.fr.design.mainframe.template.info.TimeConsumeTimer; @@ -70,11 +71,11 @@ import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.undo.UndoManager; -import java.awt.BorderLayout; import java.util.ArrayList; import java.util.Arrays; import java.util.Set; import java.util.regex.Pattern; +import java.awt.BorderLayout; /** * 报表设计和表单设计的编辑区域(设计器编辑的IO文件) @@ -164,6 +165,7 @@ public abstract class JTemplate> } private void collectInfo(String originID) { // 执行收集操作 + ChartInfoCollector.getInstance().collectInfo(template.getTemplateID(), originID, getProcessInfo()); if (!consumeTimer.isEnabled()) { return; } @@ -1233,7 +1235,7 @@ public abstract class JTemplate> public abstract String route(); - public String getTemplateName(){ + public String getTemplateName() { return getEditingFILE().getName(); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfo.java b/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfo.java new file mode 100644 index 000000000..e55746248 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfo.java @@ -0,0 +1,256 @@ +package com.fr.design.mainframe.chart.info; + +import com.fr.base.io.BaseBook; +import com.fr.config.MarketConfig; +import com.fr.design.DesignModelAdapter; +import com.fr.design.DesignerEnvManager; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.general.GeneralUtils; +import com.fr.json.JSONObject; +import com.fr.stable.ProductConstants; +import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLReadable; +import com.fr.stable.xml.XMLWriter; +import com.fr.stable.xml.XMLableReader; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-02-17 + */ +public class ChartInfo implements XMLReadable, XMLWriter { + public static final String XML_TAG = "ChartInfo"; + + private static final String XML_CHART_CONSUMING_MAP = "chartConsumingMap"; + private static final String ATTR_TEST_TEMPLATE = "testTemplate"; + private static final String ATTR_DAY_COUNT = "day_count"; + private static final String ATTR_USERNAME = "username"; + private static final String ATTR_UUID = "uuid"; + private static final String ATTR_ACTIVITYKEY = "activityKey"; + private static final String ATTR_TEMPLATE_ID = "templateID"; + private static final String ATTR_REPORT_TYPE = "type"; + private static final String ATTR_CHART_ID = "chartId"; + private static final String ATTR_CHART_TYPE = "chartType"; + private static final String ATTR_CHART_CREATE_TIME = "chartCreateTime"; + private static final String ATTR_CHART_TYPE_TIME = "chartTypeTime"; + private static final String ATTR_CHART_PROPERTY_FIRST_TIME = "chartPropertyFirstTime"; + private static final String ATTR_CHART_PROPERTY_END_TIME = "chartPropertyEndTime"; + private static final String ATTR_JAR_TIME = "jarTime"; + private static final String ATTR_VERSION = "version"; + + private static final int COMPLETE_DAY_COUNT = 3; // 判断图表是否可以上传的天数 + + private int idleDayCount; // 到现在为止,图表闲置(上次保存后没有再编辑过)的天数 + + private String chartId = StringUtils.EMPTY; + + private String templateId = StringUtils.EMPTY; + + private Map chartConsumingMap = new HashMap<>(); + + private BaseBook book; + + private boolean testTemplate; + + private ChartInfo() { + } + + private ChartInfo(String chartId, String templateId, BaseBook book) { + this.chartId = chartId; + this.templateId = templateId; + this.book = book; + } + + public String getChartId() { + return chartId; + } + + public String getTemplateId() { + return templateId; + } + + public void setTemplateId(String templateId) { + this.templateId = templateId; + this.chartConsumingMap.put(ATTR_TEMPLATE_ID, templateId); + } + + + public BaseBook getBook() { + return book; + } + + public boolean isTestTemplate() { + return testTemplate; + } + + public void setTestTemplate(boolean testTemplate) { + this.testTemplate = testTemplate; + } + + static ChartInfo newInstanceByRead(XMLableReader reader) { + ChartInfo chartInfo = new ChartInfo(); + reader.readXMLObject(chartInfo); + return chartInfo; + } + + public static ChartInfo newInstance(String chartId, String chartType) { + return newInstance(chartId, chartType, null); + } + + public static ChartInfo newInstance(String chartId, String chartType, String createTime) { + HashMap chartConsumingMap = new HashMap<>(); + + String username = MarketConfig.getInstance().getBbsUsername(); + String uuid = DesignerEnvManager.getEnvManager().getUUID(); + String activitykey = DesignerEnvManager.getEnvManager().getActivationKey(); + + BaseBook book = DesignModelAdapter.getCurrentModelAdapter().getBook(); + String templateId = book.getTemplateID(); + int reportType = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getProcessInfo().getReportType(); + + String typeTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()); + + createTime = createTime == null ? typeTime : createTime; + + String jarTime = GeneralUtils.readBuildNO(); + String version = ProductConstants.VERSION; + chartConsumingMap.put(ATTR_USERNAME, username); + chartConsumingMap.put(ATTR_UUID, uuid); + chartConsumingMap.put(ATTR_ACTIVITYKEY, activitykey); + chartConsumingMap.put(ATTR_TEMPLATE_ID, templateId); + chartConsumingMap.put(ATTR_REPORT_TYPE, reportType); + chartConsumingMap.put(ATTR_CHART_ID, chartId); + chartConsumingMap.put(ATTR_CHART_TYPE, chartType); + chartConsumingMap.put(ATTR_CHART_CREATE_TIME, createTime); + chartConsumingMap.put(ATTR_CHART_TYPE_TIME, typeTime); + chartConsumingMap.put(ATTR_CHART_PROPERTY_FIRST_TIME, ""); + chartConsumingMap.put(ATTR_CHART_PROPERTY_END_TIME, ""); + chartConsumingMap.put(ATTR_JAR_TIME, jarTime); + chartConsumingMap.put(ATTR_VERSION, version); + + ChartInfo chartInfo = new ChartInfo(chartId, templateId, book); + chartInfo.chartConsumingMap = chartConsumingMap; + + return chartInfo; + } + + + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(XML_TAG); + if (StringUtils.isNotEmpty(chartId)) { + writer.attr(ATTR_CHART_ID, this.chartId); + } + if (StringUtils.isNotEmpty(templateId)) { + writer.attr(ATTR_TEMPLATE_ID, this.templateId); + } + if (idleDayCount >= 0) { + writer.attr(ATTR_DAY_COUNT, this.idleDayCount); + } + writer.attr(ATTR_TEST_TEMPLATE, this.testTemplate); + writer.startTAG(XML_CHART_CONSUMING_MAP); + writer.attr(ATTR_USERNAME, (String) chartConsumingMap.get(ATTR_USERNAME)); + writer.attr(ATTR_UUID, (String) chartConsumingMap.get(ATTR_UUID)); + writer.attr(ATTR_ACTIVITYKEY, (String) chartConsumingMap.get(ATTR_ACTIVITYKEY)); + writer.attr(ATTR_REPORT_TYPE, (int) chartConsumingMap.get(ATTR_REPORT_TYPE)); + writer.attr(ATTR_CHART_TYPE, (String) chartConsumingMap.get(ATTR_CHART_TYPE)); + writer.attr(ATTR_CHART_CREATE_TIME, (String) chartConsumingMap.get(ATTR_CHART_CREATE_TIME)); + writer.attr(ATTR_CHART_TYPE_TIME, (String) chartConsumingMap.get(ATTR_CHART_TYPE_TIME)); + writer.attr(ATTR_CHART_PROPERTY_FIRST_TIME, (String) chartConsumingMap.get(ATTR_CHART_PROPERTY_FIRST_TIME)); + writer.attr(ATTR_CHART_PROPERTY_END_TIME, (String) chartConsumingMap.get(ATTR_CHART_PROPERTY_END_TIME)); + writer.attr(ATTR_JAR_TIME, (String) chartConsumingMap.get(ATTR_JAR_TIME)); + writer.attr(ATTR_VERSION, (String) chartConsumingMap.get(ATTR_VERSION)); + writer.end(); + writer.end(); + } + + public void readXML(XMLableReader reader) { + + if (!reader.isChildNode()) { + idleDayCount = reader.getAttrAsInt(ATTR_DAY_COUNT, 0); + chartId = reader.getAttrAsString(ATTR_CHART_ID, StringUtils.EMPTY); + templateId = reader.getAttrAsString(ATTR_TEMPLATE_ID, StringUtils.EMPTY); + testTemplate = reader.getAttrAsBoolean(ATTR_TEST_TEMPLATE, true); + } else { + try { + String name = reader.getTagName(); + if (XML_CHART_CONSUMING_MAP.equals(name)) { + chartConsumingMap.put(ATTR_USERNAME, reader.getAttrAsString(ATTR_USERNAME, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_UUID, reader.getAttrAsString(ATTR_UUID, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_ACTIVITYKEY, reader.getAttrAsString(ATTR_ACTIVITYKEY, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_TEMPLATE_ID, templateId); + chartConsumingMap.put(ATTR_REPORT_TYPE, reader.getAttrAsInt(ATTR_REPORT_TYPE, 0)); + chartConsumingMap.put(ATTR_CHART_ID, chartId); + chartConsumingMap.put(ATTR_CHART_TYPE, reader.getAttrAsString(ATTR_CHART_TYPE, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_CHART_CREATE_TIME, reader.getAttrAsString(ATTR_CHART_CREATE_TIME, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_CHART_TYPE_TIME, reader.getAttrAsString(ATTR_CHART_TYPE_TIME, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_CHART_PROPERTY_FIRST_TIME, reader.getAttrAsString(ATTR_CHART_PROPERTY_FIRST_TIME, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_CHART_PROPERTY_END_TIME, reader.getAttrAsString(ATTR_CHART_PROPERTY_END_TIME, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_JAR_TIME, reader.getAttrAsString(ATTR_JAR_TIME, StringUtils.EMPTY)); + chartConsumingMap.put(ATTR_VERSION, reader.getAttrAsString(ATTR_VERSION, "8.0")); + } + } catch (Exception ex) { + // 什么也不做,使用默认值 + } + } + } + + public void resetIdleDayCount() { + this.idleDayCount = 0; + } + + public void addIdleDayCountByOne() { + this.idleDayCount += 1; + } + + public int getIdleDayCount() { + return this.idleDayCount; + } + + boolean isComplete() { + // 连续3天打开了设计器但是没有编辑 + return idleDayCount > COMPLETE_DAY_COUNT; + } + + String getChartConsumingMapJsonString() { + return new JSONObject(chartConsumingMap).toString(); + } + + public void updatePropertyTime() { + String propertyTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()); + + if (StringUtils.isEmpty((String) chartConsumingMap.get(ATTR_CHART_PROPERTY_FIRST_TIME))) { + chartConsumingMap.put(ATTR_CHART_PROPERTY_FIRST_TIME, propertyTime); + } + chartConsumingMap.put(ATTR_CHART_PROPERTY_END_TIME, propertyTime); + } + + public void updateChartType(String chartType) { + String typeTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()); + + chartConsumingMap.put(ATTR_CHART_TYPE_TIME, typeTime); + chartConsumingMap.put(ATTR_CHART_TYPE, chartType); + chartConsumingMap.put(ATTR_CHART_PROPERTY_FIRST_TIME, ""); + chartConsumingMap.put(ATTR_CHART_PROPERTY_END_TIME, ""); + } + + @Override + public ChartInfo clone() { + ChartInfo chartInfo = new ChartInfo(); + chartInfo.chartId = this.chartId; + chartInfo.idleDayCount = this.idleDayCount; + chartInfo.templateId = this.templateId; + chartInfo.testTemplate = this.testTemplate; + Map chartConsumingMap = new HashMap<>(); + for (Map.Entry entry : this.chartConsumingMap.entrySet()) { + chartConsumingMap.put(entry.getKey(), entry.getValue()); + } + chartInfo.chartConsumingMap = chartConsumingMap; + return chartInfo; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java new file mode 100644 index 000000000..e7330d137 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java @@ -0,0 +1,333 @@ +package com.fr.design.mainframe.chart.info; + +import com.fr.base.FRContext; +import com.fr.base.io.BaseBook; +import com.fr.base.io.XMLReadHelper; +import com.fr.design.DesignerEnvManager; +import com.fr.design.mainframe.template.info.TemplateProcessInfo; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ProductConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLReadable; +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.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.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-02-18 + */ +public class ChartInfoCollector implements XMLReadable, XMLWriter { + private static final String XML_TAG = "ChartInfoCollector"; + private static final String XML_LAST_EDIT_DAY = "lastEditDay"; + + 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 static final int MAX_SIZE = 512 * 1024 * 1024; + private Map chartInfoMap; + + private Map chartInfoCacheMap; + + private String lastEditDay = StringUtils.EMPTY; + + private ChartInfoCollector() { + init(); + } + + private void init() { + chartInfoMap = new ConcurrentHashMap<>(); + chartInfoCacheMap = new HashMap<>(); + loadFromFile(); + } + + public static ChartInfoCollector getInstance() { + if (instance == null) { + instance = new ChartInfoCollector(); + } + return instance; + } + + /** + * 新建图表,保存状态 + */ + public void collection(String chartId, String chartType, String createTime) { + if (!shouldCollectInfo()) { + return; + } + + ChartInfo chartInfo = ChartInfo.newInstance(chartId, chartType, createTime); + chartInfoCacheMap.put(chartId, chartInfo); + } + + /** + * 图表编辑,更新编辑时间 + */ + public void updateChartPropertyTime(String chartId, String chartType) { + if (!shouldCollectInfo()) { + return; + } + ChartInfo chartInfo = getOrCreateChartInfo(chartId, chartType); + + //更新编辑时间 + chartInfo.updatePropertyTime(); + + //重置计数 + chartInfo.resetIdleDayCount(); + } + + /** + * 图表类型变化,更新类型和类型确认时间 + */ + public void updateChartTypeTime(String chartId, String chartType) { + if (!shouldCollectInfo()) { + return; + } + + ChartInfo chartInfo = getOrCreateChartInfo(chartId, chartType); + + //更新类型确认时间和类型 + chartInfo.updateChartType(chartType); + + //重置计数 + chartInfo.resetIdleDayCount(); + } + + private ChartInfo getOrCreateChartInfo(String chartId, String chartType) { + //缓存中有从缓存中拿 + if (chartInfoCacheMap.containsKey(chartId)) { + return chartInfoCacheMap.get(chartId); + } + //缓存中没有从文件中读取的信息中拷贝到缓存 + if (chartInfoMap.containsKey(chartId)) { + ChartInfo chartInfo = chartInfoMap.get(chartId).clone(); + chartInfoCacheMap.put(chartId, chartInfo); + return chartInfo; + } + //都有的话创建一个并加入到缓存中 + ChartInfo chartInfo = ChartInfo.newInstance(chartId, chartType); + chartInfoCacheMap.put(chartId, chartInfo); + return chartInfo; + } + + /** + * 保存模板的时候将该模板中的图表埋点信息保存 + */ + public void collectInfo(String templateId, String originID, TemplateProcessInfo processInfo) { + if (!shouldCollectInfo()) { + return; + } + if (StringUtils.isEmpty(originID)) { + originID = templateId; + } + boolean testTemplate = isTestTemplate(processInfo); + + for (ChartInfo chartInfo : chartInfoMap.values()) { + if (originID.equals(chartInfo.getTemplateId())) { + chartInfo.setTemplateId(templateId); + chartInfo.setTestTemplate(testTemplate); + } + } + + for (ChartInfo chartInfo : chartInfoCacheMap.values()) { + BaseBook book = chartInfo.getBook(); + if ((book != null && templateId.equals(book.getTemplateID())) || + originID.equals(chartInfo.getTemplateId())) { + chartInfo.setTemplateId(templateId); + chartInfo.setTestTemplate(testTemplate); + chartInfoMap.put(chartInfo.getChartId(), chartInfo); + } + } + + + + // 每次更新之后,都同步到暂存文件中 + saveInfo(); + } + + private boolean isTestTemplate(TemplateProcessInfo processInfo) { + int reportType = processInfo.getReportType(); + int cellCount = processInfo.getCellCount(); + int floatCount = processInfo.getFloatCount(); + int blockCount = processInfo.getBlockCount(); + int widgetCount = processInfo.getWidgetCount(); + + 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; + } + + /** + * 发送本地图表信息到服务器,并清空已发送图表的本地记录 + */ + public void sendChartInfo() { + + addIdleDayCount(); + + List removeLaterList = new ArrayList<>(); + + for (String key : chartInfoMap.keySet()) { + ChartInfo chartInfo = chartInfoMap.get(key); + if (chartInfo.isComplete()) { + if (!chartInfo.isTestTemplate()) { + if (ChartSendHelper.sendChartInfo(chartInfo)) { + removeLaterList.add(key); + } + } else { + removeLaterList.add(key); + } + } + } + + // 清空记录 + for (String key : removeLaterList) { + chartInfoMap.remove(key); + } + + saveInfo(); + } + + /** + * 更新 day_count:打开设计器却未编辑图表的连续日子 + */ + private void addIdleDayCount() { + // 判断今天是否第一次打开设计器,为了防止同一天内,多次 addIdleDayCount + String today = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); + if (ComparatorUtils.equals(today, lastEditDay)) { + return; + } + for (ChartInfo chartInfo : chartInfoMap.values()) { + chartInfo.addIdleDayCountByOne(); + } + lastEditDay = today; + } + + private 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); + } + } + } + + /** + * 获取缓存文件存放路径 + */ + private static File getInfoFile() { + File file = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), XML_FILE_NAME)); + try { + if (!file.exists()) { + file.createNewFile(); + } + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return file; + } + + private boolean shouldCollectInfo() { + return FileUtils.sizeOf(getInfoFile()) <= MAX_SIZE && DesignerEnvManager.getEnvManager().isJoinProductImprove() && FRContext.isChineseEnv(); + } + + + /** + * 将包含所有信息的对象保存到文件 + */ + private 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()); + } + } + + @Override + public void readXML(XMLableReader reader) { + if (reader.isChildNode()) { + try { + String name = reader.getTagName(); + if (ChartInfo.XML_TAG.equals(name)) { + ChartInfo chartInfo = ChartInfo.newInstanceByRead(reader); + chartInfoMap.put(chartInfo.getChartId(), chartInfo); + } else if (XML_LAST_EDIT_DAY.equals(name)) { + lastEditDay = reader.getElementValue(); + } + } catch (Exception ex) { + // 什么也不做,使用默认值 + } + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(XML_TAG); + + writer.startTAG(XML_LAST_EDIT_DAY); + writer.textNode(lastEditDay); + writer.end(); + + writer.startTAG(XML_CHART_INFO_LIST); + for (ChartInfo chartInfo : chartInfoMap.values()) { + chartInfo.writeXML(writer); + } + writer.end(); + + writer.end(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartSendHelper.java b/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartSendHelper.java new file mode 100644 index 000000000..6c5b4676f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartSendHelper.java @@ -0,0 +1,40 @@ +package com.fr.design.mainframe.chart.info; + +import com.fr.design.mainframe.SiteCenterToken; +import com.fr.general.CloudCenter; +import com.fr.general.ComparatorUtils; +import com.fr.general.http.HttpToolbox; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-02-19 + */ +class ChartSendHelper { + private static final String CHART_CONSUMING_URL = CloudCenter.getInstance().acquireUrlByKind("chartinfo.consuming") + "/single"; + + static boolean sendChartInfo(ChartInfo chartInfo) { + return sendSingleChartInfo(CHART_CONSUMING_URL, chartInfo.getChartConsumingMapJsonString()); + } + + private static boolean sendSingleChartInfo(String url, String content) { + Map para = new HashMap<>(); + para.put("token", SiteCenterToken.generateToken()); + para.put("content", content); + + try { + String res = HttpToolbox.post(url, para); + return ComparatorUtils.equals(new JSONObject(res).get("status"), "success"); + } catch (Throwable e) { + // 客户不需要关心,错误等级为 debug 就行了 + FineLoggerFactory.getLogger().debug(e.getMessage(), e); + } + return false; + } + +} diff --git a/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java b/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java index a7dd9f564..1916eb784 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java +++ b/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java @@ -1,5 +1,15 @@ package com.fr.design.chart; +import com.fr.base.chart.BaseChartCollection; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.gui.chart.MiddleChartDialog; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.JPanel; +import java.text.SimpleDateFormat; +import java.util.Calendar; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.FlowLayout; @@ -7,16 +17,6 @@ import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import javax.swing.JPanel; - -import com.fr.base.chart.BaseChartCollection; -import com.fr.chart.chartattr.ChartCollection; -import com.fr.design.gui.chart.MiddleChartDialog; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.dialog.BasicDialog; - -import com.fr.design.utils.gui.GUICoreUtils; - /** * 封装一层 图表新建的对话框, 配合属性表确定: 先单独只要一种图表类型的对话框. * @author kunsnat E-mail:kunsnat@gmail.com @@ -40,6 +40,8 @@ public class ChartDialog extends MiddleChartDialog { } private void initComponent() { + final String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()); + this.setModal(true); this.setLayout(new BorderLayout()); final ChartTypePane chartTypePane = new ChartTypePane(); @@ -63,7 +65,7 @@ public class ChartDialog extends MiddleChartDialog { ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - chartTypePane.update((ChartCollection)cc); + chartTypePane.update((ChartCollection)cc, createTime); doOK(); } }); diff --git a/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java b/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java index 19c613785..a0a9d82b4 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java @@ -7,10 +7,12 @@ import com.fr.chart.chartattr.ChartCollection; import com.fr.chart.charttypes.ChartTypeManager; import com.fr.chartx.attr.ChartProvider; import com.fr.design.ChartTypeInterfaceManager; +import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.log.FineLoggerFactory; +import com.fr.plugin.chart.vanchart.VanChart; import com.fr.stable.StringUtils; import javax.swing.BorderFactory; @@ -119,6 +121,10 @@ public class ChartTypePane extends ChartCommonWizardPane { } public void update(ChartCollection cc) { + update(cc, null); + } + + public void update(ChartCollection cc, String creatTime) { if (cc == null) { return; } @@ -130,6 +136,11 @@ public class ChartTypePane extends ChartCommonWizardPane { try { chart4Update = (ChartProvider) chart.clone(); cc.addChart(chart4Update); + //记录埋点 + if (chart4Update instanceof VanChart) { + VanChart vanChart = (VanChart) chart4Update; + ChartInfoCollector.getInstance().collection(vanChart.getUuid(), vanChart.getID(), creatTime); + } } catch (CloneNotSupportedException ex) { FineLoggerFactory.getLogger().error(ex.getMessage(), ex); } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java index a2d824f51..db5524f26 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java @@ -6,6 +6,7 @@ import com.fr.chart.chartattr.ChartCollection; import com.fr.chartx.attr.ChartProvider; import com.fr.design.ChartTypeInterfaceManager; import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.data.DesignTableDataManager; import com.fr.design.data.tabledata.Prepare4DataSourceChange; import com.fr.design.dialog.BasicPane; @@ -26,13 +27,13 @@ import com.fr.plugin.chart.vanchart.VanChart; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.CardLayout; import java.util.ArrayList; import java.util.Calendar; import java.util.List; +import java.awt.BorderLayout; +import java.awt.CardLayout; -public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4DataSourceChange, ChartEditPaneProvider { +public class ChartEditPane extends BasicPane implements AttributeChange, Prepare4DataSourceChange, ChartEditPaneProvider { private final static int CHANGE_MIN_TIME = 80; @@ -107,11 +108,15 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 return; } AbstractChartAttrPane selectedPane = paneList.get(tabsHeaderIconPane.getSelectedIndex()); + //图表配置变化,埋点记录 + VanChart vanChart = collection.getSelectedChartProvider(VanChart.class); + if (vanChart != null) { + ChartInfoCollector.getInstance().updateChartPropertyTime(vanChart.getUuid(), vanChart.getID()); + } selectedPane.update(collection); if (!ComparatorUtils.equals(collection, lastCollection)) { - VanChart vanChart = collection.getSelectedChartProvider(VanChart.class); if (vanChart != null) { //此处画图 vanChart.demoImgEvent(true); @@ -122,7 +127,7 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 } catch (CloneNotSupportedException e) { FineLoggerFactory.getLogger().error("error in clone ChartEditPane"); } - if(ComparatorUtils.equals(selectedPane.title4PopupWindow(),PaneTitleConstants.CHART_STYLE_TITLE)){ + if (ComparatorUtils.equals(selectedPane.title4PopupWindow(), PaneTitleConstants.CHART_STYLE_TITLE)) { dealWithStyleChange(); } @@ -138,10 +143,11 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 /** * 重新构造面板 + * * @param currentChart 图表 */ public void reLayout(ChartProvider currentChart) { - if(currentChart != null){ + if (currentChart != null) { int chartIndex = getSelectedChartIndex(currentChart); this.removeAll(); this.setLayout(new BorderLayout()); @@ -151,18 +157,18 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 String chartID = currentChart.getID(); boolean isDefault = ChartTypeInterfaceManager.getInstance().isUseDefaultPane(chartID); - if(isDefault){ + if (isDefault) { paneList.add(dataPane4SupportCell); paneList.add(stylePane); paneList.add(otherPane); this.isDefaultPane = true; - }else{ + } else { ChartDataPane chartDataPane = createChartDataPane(chartID); if (chartDataPane != null) { paneList.add(chartDataPane); } AbstractChartAttrPane[] otherPaneList = ChartTypeInterfaceManager.getInstance().getAttrPaneArray(chartID, listener); - for(int i = 0; i < otherPaneList.length; i++){ + for (int i = 0; i < otherPaneList.length; i++) { otherPaneList[i].addAttributeChangeListener(listener); paneList.add(otherPaneList[i]); } @@ -235,7 +241,7 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 if (checkNeedsReLayout(chartProvider)) { String chartID = chartProvider.getID(); if ("WaferChipChart".equals(chartID) || "BoxPlotChart".equals(chartID)) { - reLayout((Chart)chartProvider); + reLayout((Chart) chartProvider); } else { reLayout(chartProvider); } @@ -266,10 +272,10 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 public int getSelectedChartIndex(ChartProvider chart) { int index = 0; - if(typePane != null){ + if (typePane != null) { FurtherBasicBeanPane[] paneList = typePane.getPaneList(); - for(; index < paneList.length; index++){ - if(paneList[index].accept(chart)){ + for (; index < paneList.length; index++) { + if (paneList[index].accept(chart)) { return index; } } @@ -279,7 +285,7 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 //populate的时候看看要不要重构面板 private boolean checkNeedsReLayout(ChartProvider chart) { - if(chart != null){ + if (chart != null) { int lastIndex = typePane.getSelectedIndex(); int currentIndex = getSelectedChartIndex(chart); String chartID = chart.getID(); @@ -292,9 +298,10 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 /** * 当前界面是否是默认的界面 + * * @return 是否是默认的界面 */ - public boolean isDefaultPane(){ + public boolean isDefaultPane() { return this.isDefaultPane; } @@ -326,15 +333,16 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4 } } - protected void dealWithStyleChange(){ + protected void dealWithStyleChange() { } /** - *主要用于图表设计器,判断样式改变是否来自工具栏的全局样式按钮 + * 主要用于图表设计器,判断样式改变是否来自工具栏的全局样式按钮 + * * @param isFromToolBar 是否来自工具栏 */ - public void styleChange(boolean isFromToolBar){ + public void styleChange(boolean isFromToolBar) { } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypeButtonPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypeButtonPane.java index 8877ed9da..d7cd8a107 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypeButtonPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypeButtonPane.java @@ -6,6 +6,7 @@ import com.fr.chart.chartattr.ChartCollection; import com.fr.chart.charttypes.ChartTypeManager; import com.fr.chartx.attr.ChartProvider; import com.fr.design.beans.BasicBeanPane; +import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.dialog.DialogActionListener; import com.fr.design.dialog.UIDialog; import com.fr.design.event.UIObserver; @@ -25,6 +26,9 @@ import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.SwingUtilities; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; @@ -41,9 +45,6 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; /** * 图表 类型 增删 控制按钮界面. @@ -151,6 +152,10 @@ public class ChartTypeButtonPane extends BasicBeanPane implemen try { ChartProvider newChart = (ChartProvider) chart.clone(); editingCollection.addNamedChart(name, newChart); + if (newChart instanceof VanChart) { + VanChart vanchart = (VanChart) newChart; + ChartInfoCollector.getInstance().collection(vanchart.getUuid(), vanchart.getID(), null); + } } catch (CloneNotSupportedException e1) { FineLoggerFactory.getLogger().error("Error in Clone"); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java index b8550e0d4..7901ac29b 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java @@ -12,6 +12,7 @@ import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.MultilineLabel; import com.fr.design.mainframe.chart.gui.type.AbstractChartTypePane; import com.fr.design.mainframe.chart.gui.type.ChartImagePane; +import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.general.Background; import com.fr.js.NameJavaScriptGroup; import com.fr.log.FineLoggerFactory; @@ -105,6 +106,10 @@ public abstract class AbstractVanChartTypePane extends AbstractChartTypePane designer.getHeight() - SCROLL_POINT){ JScrollBar verticalBar = designer.getVerticalScrollBar(); verticalBar.setValue(verticalBar.getValue() + SCROLL_DISTANCE); } - + } }); tt.start(); } - + //设置是否显示 禁止组件重叠 窗口 private void setForbiddenWindowVisibility(Point loc){ BlockCreator creator = addingData.getCreator(); Rectangle pixRec = getCreatorPixRectangle(creator, loc); UnitRectangle rec = new UnitRectangle(pixRec, resolution); - + if(designer.intersectsAllBlock(rec, creator.getValue().getBlockName())){ int x = (int) (designer.getAreaLocationX() + pixRec.getCenterX() - designer.getHorizontalValue()); int y = (int) (designer.getAreaLocationY() + pixRec.getCenterY() - designer.getVerticalValue()); @@ -149,9 +154,9 @@ public class PolyDesignerDropTarget extends DropTargetAdapter { /** * 放下事件 - * + * * @param dtde 鼠标事件 - * + * */ public void drop(DropTargetDropEvent dtde) { if (addingData != null) { @@ -162,8 +167,10 @@ public class PolyDesignerDropTarget extends DropTargetAdapter { if(!intersectLocation(pixRec, creator)){ return; } - + designer.addBlockCreator(creator); + //图表埋点 + dealChartBuryingPoint(creator); designer.stopEditing(); designer.setSelection(creator); //在重新设置了选择之后,要对菜单和工具进行target的重新设置 @@ -174,7 +181,7 @@ public class PolyDesignerDropTarget extends DropTargetAdapter { addingData = null; } } - + //聚焦选中块 private void focusOnSelection(){ if (designer.getSelection().getEditingElementCasePane() == null) { @@ -185,7 +192,7 @@ public class PolyDesignerDropTarget extends DropTargetAdapter { grid.requestFocus(); } } - + //检测新加入的creator位置是否与老的重叠, 重叠返回false private boolean intersectLocation(Rectangle pixRec, BlockCreator creator){ if (pixRec.getX() < 0 || pixRec.getY() < 0) { @@ -200,12 +207,12 @@ public class PolyDesignerDropTarget extends DropTargetAdapter { designer.repaint(); return false; } - + creator.getValue().setBounds(rec); - + return true; } - + private Rectangle getCreatorPixRectangle(BlockCreator creator, Point location){ int width = creator.getWidth(); int height = creator.getHeight(); @@ -216,17 +223,28 @@ public class PolyDesignerDropTarget extends DropTargetAdapter { /** * 拖拽移出去事件 - * + * * @param dte 拖拽事件 - * + * */ public void dragExit(DropTargetEvent dte) { if (addingData != null) { addingData.reset(); designer.repaint(); } - + forbiddenWindow.hideWindow(); } - + + private void dealChartBuryingPoint(BlockCreator creator) { + if (creator instanceof ChartBlockCreator) { + PolyChartBlock value = ((ChartBlockCreator) creator).getValue(); + ChartCollection chartCollection = (ChartCollection) value.getChartCollection(); + VanChart vanChart = chartCollection.getSelectedChartProvider(VanChart.class); + if (vanChart != null) { + ChartInfoCollector.getInstance().collection(vanChart.getUuid(), vanChart.getID(), null); + } + } + } + } \ No newline at end of file