Browse Source

Merge pull request #8918 in DESIGN/design from release/11.0 to bugfix/11.0

* commit '8c2a9b8597012107c35277490e42c32390e2158b': (49 commits)
  REPORT-71213 关闭alphafine 默认不展示悬浮弹窗
  REPORT-71544 M1-MAC 设计器启动后会卡住 主要是转译时,Instrumentation 的性能问题。 马上发布了屏蔽一下,暂时 windows, intel-mac 都未发现这个问题 如果还是有,那就下个版本优化一下,做一个智能判断
  REPORT-71449 【冒烟】不复制新的数据集,“剪贴版”的数据集会变化 【问题原因】粘贴的时候没有做clone处理,假如修改粘贴后的数据集,会同步修改掉剪切板里存的Tableda 【改动思路】添加粘贴时TableData的clone逻辑 【review建议】
  REPORT-71449 【冒烟】不复制新的数据集,“剪贴版”的数据集会变化 【问题原因】复制到剪切板中的数据集,在粘贴的时候,TableData没做clone处理,当修改粘贴出来的数据集时,会同步影响剪切板里的TableData 【改动思路】粘贴时增加clone处理 【review建议】无
  REPORT-71309 fix 可能的npe
  REPORT-71213 拆分下大方法 && 处理空值
  REPORT-71309 && REPORT-71298 搜索展示异常
  REPORT-71213 交互点补充:关闭了产品动态时,悬浮按钮不显示有新消息推送
  REPORT-71213 设计器关闭失败
  REPORT-70446 mac下悬浮弹窗隐藏重新展示时偶现白点
  REPORT-70857 数据集复制后独立 【问题原因】匹配TableData时,用的equals比较,但是同一个对象equals为false,目前已知的是存储过程TableData,已经跟rinoux沟通 【改动思路】直接换成对象比较 【review建议】无
  REPORT-70857 数据集复制后独立 【问题原因】处理重复代码问题 【改动思路】处理重复代码问题 【review建议】无
  REPORT-70857 数据集复制后独立 删去多余import
  REPORT-70857 数据集复制后独立 【问题原因】跟随复制的时候需要处理存储过程名称问题,其中有匹配TableData的操作,而复制本身还需要处理TableData的clone,如果先clone,再去匹配TableData,对象就不相等了 【改动思路】将匹配TableData的操作放在clone处理之前 【review建议】无
  REPORT-70446 mac下悬浮弹窗隐藏重新展示时偶现白点
  REPORT-71213 设计器关闭失败
  REPORT-70857 数据集复制后独立 【问题原因】数据集在做复制粘贴的时候,没有clone数据源,导致许多变量都共用了,于是会改一个=改一片 【改动方案】添加clone处理 【review建议】无
  REPORT-69285 数据连接安全关键字检查拦截,设计器
  REPORT-71062 【冒烟】设计器启动报错 不影响功能的报错日志 调整
  REPORT-71158 打开fvs,从远程切换到本地,设计器模板展示空白
  ...
bugfix/11.0
superman 3 years ago
parent
commit
a2e4e42eae
  1. 72
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java
  2. 7
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  3. 2
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java
  4. 12
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java
  5. 23
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  6. 7
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java
  7. 2
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionShowPane.java
  8. 8
      designer-base/src/main/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboard.java
  9. 87
      designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java
  10. 8
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java
  11. 2
      designer-base/src/main/java/com/fr/design/gui/style/TextFormatPane.java
  12. 2
      designer-base/src/main/java/com/fr/design/login/socketio/LoginAuthServer.java
  13. 2
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java
  14. 2
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java
  15. 56
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java
  16. 28
      designer-base/src/main/java/com/fr/design/utils/SvgPaintUtils.java
  17. 7
      designer-base/src/main/java/com/fr/exit/ConfigToPropMigrator.java
  18. 12
      designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ColSelectedWithSummaryMethodEditor.java
  19. 11
      designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java
  20. 4
      designer-form/src/main/java/com/fr/design/gui/xpane/LayoutBorderPane.java
  21. 6
      designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java
  22. 4
      designer-form/src/main/java/com/fr/design/widget/ui/designer/component/WidgetBoundPane.java
  23. 2
      designer-realize/src/main/java/com/fr/design/mainframe/HyperlinkGroupPaneActionImpl.java
  24. 16
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineUtil.java
  25. 210
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineFrame.java
  26. 10
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineList.java
  27. 4
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsImagePanel.java
  28. 24
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionPane.java
  29. 11
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionWindow.java
  30. 7
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/ProductNewsSearchWorkerManager.java
  31. 7
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchWorkerManager.java
  32. 12
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/fun/AlphaFineSearchProvider.java
  33. 7
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ActionSearchManager.java
  34. 13
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/DocumentSearchManager.java
  35. 7
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/FileSearchManager.java
  36. 11
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/PluginSearchManager.java
  37. 2
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/group_new.svg

72
designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java

@ -9,7 +9,7 @@ import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReadable; import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLable; import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader; import com.fr.stable.xml.XMLableReader;
import java.util.ArrayList; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -99,7 +99,6 @@ public class AlphaFineConfigManager implements XMLable {
private String cacheBuildNO; private String cacheBuildNO;
// todo 暂不持久化 方便测试
/** /**
* key: 登录的bbs用户 * key: 登录的bbs用户
* value: alphaFine历史搜索记录 * value: alphaFine历史搜索记录
@ -154,6 +153,10 @@ public class AlphaFineConfigManager implements XMLable {
} else if (reader.isChildNode()) { } else if (reader.isChildNode()) {
if (ComparatorUtils.equals(reader.getTagName(), "ActionSearchTextCache")) { if (ComparatorUtils.equals(reader.getTagName(), "ActionSearchTextCache")) {
readActionSearchTextCacheXML(reader); readActionSearchTextCacheXML(reader);
} else if ("SearchHistory".equals(reader.getTagName())) {
readHistorySearch(reader);
} else if ("ReadSet".equals(reader.getTagName())) {
readReadSet(reader);
} }
} }
} }
@ -180,6 +183,53 @@ public class AlphaFineConfigManager implements XMLable {
}); });
} }
private void readHistorySearch(XMLableReader reader) {
reader.readXMLObject(new XMLReadable() {
@Override
public void readXML(XMLableReader xmLableReader) {
if (ComparatorUtils.equals(reader.getTagName(), "history")) {
String tmpVal = reader.getElementValue();
if (tmpVal != null) {
tmpVal = tmpVal.replace("[",StringUtils.EMPTY).replace("]",StringUtils.EMPTY);
Stack<String> stack = new SizedStack<>(3);
String[] historyList = tmpVal.split(",");
for (String history : historyList) {
String value = history.trim();
if (StringUtils.isNotEmpty(value)) {
stack.add(value);
}
}
historySearchMap.put(reader.getAttrAsString("user", StringUtils.EMPTY), stack);
}
}
}
});
}
private void readReadSet(XMLableReader reader) {
reader.readXMLObject(new XMLReadable() {
@Override
public void readXML(XMLableReader xmLableReader) {
if (ComparatorUtils.equals(reader.getTagName(), "readId")) {
String tmpVal = reader.getElementValue();
if (tmpVal != null) {
tmpVal = tmpVal.replace("[",StringUtils.EMPTY).replace("]",StringUtils.EMPTY);
String[] idArr = tmpVal.split(",");
Set<Long> setId = new HashSet<>();
for (String id : idArr) {
String value = id.trim();
if (StringUtils.isNotEmpty(value)) {
setId.add(Long.parseLong(value));
}
}
readSetMap.put(reader.getAttrAsString("user", StringUtils.EMPTY), setId);
}
}
}
});
}
@Override @Override
public void writeXML(XMLPrintWriter writer) { public void writeXML(XMLPrintWriter writer) {
writer.startTAG("AlphaFineConfigManager"); writer.startTAG("AlphaFineConfigManager");
@ -198,6 +248,8 @@ public class AlphaFineConfigManager implements XMLable {
.attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService()) .attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService())
.attr("productDynamics", this.isProductDynamics()); .attr("productDynamics", this.isProductDynamics());
writeActionSearchTextCacheXML(writer); writeActionSearchTextCacheXML(writer);
writeSearchHistory(writer);
writeReadSet(writer);
writer.end(); writer.end();
} }
@ -212,6 +264,22 @@ public class AlphaFineConfigManager implements XMLable {
writer.end(); writer.end();
} }
private void writeSearchHistory(XMLPrintWriter writer) {
writer.startTAG("SearchHistory");
for (Map.Entry<String, Stack<String>> entry : historySearchMap.entrySet()) {
writer.startTAG("history").attr("user", entry.getKey()).textNode(entry.getValue().toString()).end();
}
writer.end();
}
private void writeReadSet(XMLPrintWriter writer) {
writer.startTAG("ReadSet");
for (Map.Entry<String, Set<Long>> entry : readSetMap.entrySet()) {
writer.startTAG("readId").attr("user", entry.getKey()).textNode(entry.getValue().toString()).end();
}
writer.end();
}
public boolean isSearchOnLine() { public boolean isSearchOnLine() {
return searchOnLine; return searchOnLine;
} }

7
designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java

@ -19,6 +19,7 @@ import com.fr.design.data.datapane.management.search.pane.TreeSearchToolbarPane;
import com.fr.design.data.datapane.management.search.searcher.TableDataSearchMode; import com.fr.design.data.datapane.management.search.searcher.TableDataSearchMode;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager; import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.tabledata.StoreProcedureWorkerListener; import com.fr.design.data.tabledata.StoreProcedureWorkerListener;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane; import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
@ -1132,8 +1133,10 @@ public class TableDataTreePane extends BasicTableDataTreePane {
// 处理数据集名称 // 处理数据集名称
String dsName = getNoRepeatedDsName4Paste(dataWrapperEntry.getKey()); String dsName = getNoRepeatedDsName4Paste(dataWrapperEntry.getKey());
AbstractTableDataWrapper wrapper = dataWrapperEntry.getValue(); AbstractTableDataWrapper wrapper = dataWrapperEntry.getValue();
AbstractTableDataPane<?> tableDataPane = wrapper.creatTableDataPane(); AbstractTableDataPane<?> tableDataPane = TableDataFollowingPasteUtils.generateTableDataPaneWhenPaste(wrapper);
addDataPane(tableDataPane, dsName); if (tableDataPane != null) {
addDataPane(tableDataPane, dsName);
}
} }
} }
} }

2
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java

@ -142,7 +142,7 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
if (StringUtils.isNotBlank(s)) { if (StringUtils.isNotBlank(s)) {
// 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白 // 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白
// 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置 // 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置
if (ConnectionConfig.getInstance().getConnection(s) != null) { if (nameList.contains(s)) {
this.setSelectedItem(s); this.setSelectedItem(s);
} }
} }

12
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java

@ -2,11 +2,15 @@ package com.fr.design.data.datapane.connect;
import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.editlock.EditLockUtils; import com.fr.design.editlock.EditLockUtils;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerContext;
import com.fr.file.ConnectionConfig; import com.fr.file.ConnectionConfig;
import com.fr.report.LockItem; import com.fr.report.LockItem;
import javax.swing.JOptionPane;
/** /**
* @author hades * @author hades
* @version 11.0 * @version 11.0
@ -32,7 +36,13 @@ public class ConnectionListDialogActionAdapter extends DialogActionAdapter {
connectionListDialog.setDoOKSucceed(false); connectionListDialog.setDoOKSucceed(false);
return; return;
} }
connectionManagerPane.update(connectionConfig); try {
connectionManagerPane.update(connectionConfig);
} catch (Exception e) {
connectionListDialog.setDoOKSucceed(false);
FineJOptionPane.showMessageDialog(connectionManagerPane, e.getMessage(), Toolkit.i18nText("Fine-Design_Basic_Error"), JOptionPane.ERROR_MESSAGE);
return;
}
DesignerContext.getDesignerBean("databasename").refreshBeanElement(); DesignerContext.getDesignerBean("databasename").refreshBeanElement();
// 关闭定义数据连接页面,为其解锁 // 关闭定义数据连接页面,为其解锁
EditLockUtils.unlock(LockItem.CONNECTION); EditLockUtils.unlock(LockItem.CONNECTION);

23
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java

@ -1,6 +1,7 @@
package com.fr.design.data.datapane.connect; package com.fr.design.data.datapane.connect;
import com.fr.config.RemoteConfigEvent; import com.fr.config.RemoteConfigEvent;
import com.fr.data.core.db.JDBCSecurityChecker;
import com.fr.data.impl.Connection; import com.fr.data.impl.Connection;
import com.fr.data.impl.ConnectionBean; import com.fr.data.impl.ConnectionBean;
import com.fr.data.impl.JDBCDatabaseConnection; import com.fr.data.impl.JDBCDatabaseConnection;
@ -28,6 +29,7 @@ import com.fr.transaction.WorkerFacade;
import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContext;
import java.awt.Window; import java.awt.Window;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -166,7 +168,7 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
/** /**
* Update. * Update.
*/ */
public void update(ConnectionConfig connectionConfig) { public void update(ConnectionConfig connectionConfig) throws Exception {
// Nameable[]居然不能强转成NameObject[],一定要这么写... // Nameable[]居然不能强转成NameObject[],一定要这么写...
Nameable[] res = this.update(); Nameable[] res = this.update();
Map<String, Connection> updatedMap = new LinkedHashMap<>(); Map<String, Connection> updatedMap = new LinkedHashMap<>();
@ -188,10 +190,27 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
} }
}); });
this.checkSecurity(addedOrUpdatedConnections);
this.alterConnections(removedConnNames, addedOrUpdatedConnections); this.alterConnections(removedConnNames, addedOrUpdatedConnections);
} }
private void checkSecurity(List<ConnectionBean> addedOrUpdatedConnections) throws Exception {
for (ConnectionBean connectionBean : addedOrUpdatedConnections) {
Connection connection = connectionBean.getConnection();
if (connection instanceof JDBCDatabaseConnection) {
try {
JDBCSecurityChecker.checkURL(((JDBCDatabaseConnection) connection).getURL());
JDBCSecurityChecker.checkValidationQuery(((JDBCDatabaseConnection) connection).getDbcpAttr().getValidationQuery());
} catch (SQLException e) {
throw new SQLException(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Invalid_Config", connectionBean.getName()) + ", " + e.getMessage(), e.getCause());
}
}
}
}
private void alterConnections(List<String> removedConnNames, List<ConnectionBean> addedOrUpdatedConnections) { private void alterConnections(List<String> removedConnNames, List<ConnectionBean> addedOrUpdatedConnections) {
try { try {

7
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java

@ -4,9 +4,8 @@ import com.fr.design.gui.frpane.LoadingBasicPane;
import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.file.ConnectionConfig; import com.fr.file.ConnectionConfig;
import javax.swing.JPanel;
import javax.swing.*; import java.awt.BorderLayout;
import java.awt.*;
import java.util.HashMap; import java.util.HashMap;
public class ConnectionManagerPane extends LoadingBasicPane implements ConnectionShowPane { public class ConnectionManagerPane extends LoadingBasicPane implements ConnectionShowPane {
@ -39,7 +38,7 @@ public class ConnectionManagerPane extends LoadingBasicPane implements Connectio
this.connectionListPane.populate(datasourceManager); this.connectionListPane.populate(datasourceManager);
} }
public void update(ConnectionConfig datasourceManager) { public void update(ConnectionConfig datasourceManager) throws Exception {
this.connectionListPane.update(datasourceManager); this.connectionListPane.update(datasourceManager);
} }

2
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionShowPane.java

@ -7,7 +7,7 @@ import com.fr.file.ConnectionConfig;
* 数据链接显示面板 * 数据链接显示面板
*/ */
public interface ConnectionShowPane { public interface ConnectionShowPane {
void update(ConnectionConfig connectionConfig); void update(ConnectionConfig connectionConfig) throws Exception;
void populate(ConnectionConfig connectionConfig); void populate(ConnectionConfig connectionConfig);

8
designer-base/src/main/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboard.java

@ -1,6 +1,9 @@
package com.fr.design.data.datapane.management.clip; package com.fr.design.data.datapane.management.clip;
import com.fr.base.TableData;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
import com.fr.general.NameObject; import com.fr.general.NameObject;
import java.util.HashMap; import java.util.HashMap;
@ -45,7 +48,10 @@ public class TableDataTreeClipboard {
return resultMap; return resultMap;
} }
for (NameObject selectedNameObject : selectedNameObjects) { for (NameObject selectedNameObject : selectedNameObjects) {
resultMap.put(selectedNameObject.getName(), (AbstractTableDataWrapper) selectedNameObject.getObject()); TableData cloned = TableDataFollowingPasteUtils.cloneTableData(((AbstractTableDataWrapper) selectedNameObject.getObject()).getTableData());
if (cloned != null) {
resultMap.put(selectedNameObject.getName(), new TemplateTableDataWrapper(cloned));
}
} }
return resultMap; return resultMap;
} }

87
designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java

@ -3,10 +3,12 @@ package com.fr.design.data.tabledata.paste;
import com.fr.base.TableData; import com.fr.base.TableData;
import com.fr.base.chart.BaseChartCollection; import com.fr.base.chart.BaseChartCollection;
import com.fr.data.TableDataSource; import com.fr.data.TableDataSource;
import com.fr.data.impl.storeproc.StoreProcedure;
import com.fr.design.DesignModelAdapter; import com.fr.design.DesignModelAdapter;
import com.fr.design.data.DesignTableDataManager; import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.ProcedureDataPane;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper; import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
@ -26,6 +28,7 @@ import com.fr.report.cell.FloatElement;
import com.fr.report.cell.tabledata.ElementUsedTableDataProvider; import com.fr.report.cell.tabledata.ElementUsedTableDataProvider;
import com.fr.report.worksheet.FormElementCase; import com.fr.report.worksheet.FormElementCase;
import com.fr.stable.StringUtils; import com.fr.stable.StringUtils;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -63,8 +66,10 @@ public class TableDataFollowingPasteUtils {
continue; continue;
} }
AbstractTableDataWrapper tableDataWrapper = new TemplateTableDataWrapper(dataWrapperEntry.getValue(), dsName); AbstractTableDataWrapper tableDataWrapper = new TemplateTableDataWrapper(dataWrapperEntry.getValue(), dsName);
AbstractTableDataPane<?> tableDataPane = tableDataWrapper.creatTableDataPane(); AbstractTableDataPane<?> tableDataPane = generateTableDataPaneWhenPaste(tableDataWrapper);
tableDataTreePane.addDataPane(tableDataPane, dsName); if (tableDataPane != null) {
tableDataTreePane.addDataPane(tableDataPane, dsName);
}
} }
} }
@ -96,20 +101,32 @@ public class TableDataFollowingPasteUtils {
} }
} }
} }
// 处理存储过程名称问题 return dealWithTableDataMap(tempMap);
return dealWithStoreProcedure(tempMap);
} catch (Exception e) { } catch (Exception e) {
FineLoggerFactory.getLogger().error("transfer widget tabledata failed", e); FineLoggerFactory.getLogger().error("transfer widget tabledata failed", e);
} }
return new HashMap<>(); return new HashMap<>();
} }
/**
* 处理结果集
* @param tableDataMap
* @return
*/
private static Map<String, TableData> dealWithTableDataMap(Map<String, TableData> tableDataMap) {
// 处理存储过程名称问题,名称问题需要优先处理,否则就找不到匹配的TableData了
tableDataMap = dealWithStoreProcedure(tableDataMap);
// 对TableData做clone处理
tableDataMap = dealWithTableData4Clone(tableDataMap);
return tableDataMap;
}
/** /**
* 处理结果集将结果集中的存储过程子表替换为原本的存储过程否则跟随粘贴过去的存储过程名称有问题 * 处理结果集将结果集中的存储过程子表替换为原本的存储过程否则跟随粘贴过去的存储过程名称有问题
* *
* @param tableDataMap * @param tableDataMap
*/ */
public static Map<String, TableData> dealWithStoreProcedure(Map<String, TableData> tableDataMap) { private static Map<String, TableData> dealWithStoreProcedure(Map<String, TableData> tableDataMap) {
Map<String, TableData> resultMap = new HashMap<>(); Map<String, TableData> resultMap = new HashMap<>();
if (tableDataMap == null) { if (tableDataMap == null) {
return resultMap; return resultMap;
@ -149,7 +166,8 @@ public class TableDataFollowingPasteUtils {
for (Map.Entry<String, TableDataWrapper> dataWrapperEntry : dataWrapperMap.entrySet()) { for (Map.Entry<String, TableDataWrapper> dataWrapperEntry : dataWrapperMap.entrySet()) {
String tdName = dataWrapperEntry.getKey(); String tdName = dataWrapperEntry.getKey();
TableData td = dataWrapperEntry.getValue().getTableData(); TableData td = dataWrapperEntry.getValue().getTableData();
if (ComparatorUtils.equals(td, tableData)) { // 有些数据集的equals方法有问题,这里直接判断对象地址
if (td == tableData) {
return tdName; return tdName;
} }
} }
@ -178,14 +196,30 @@ public class TableDataFollowingPasteUtils {
collectTableDataInChartCollection(templateTableData, tempMap, widget); collectTableDataInChartCollection(templateTableData, tempMap, widget);
collectTableDataInElementCaseEditor(templateTableData, tempMap, widget); collectTableDataInElementCaseEditor(templateTableData, tempMap, widget);
} }
// 处理存储过程名称问题 return dealWithTableDataMap(tempMap);
return dealWithStoreProcedure(tempMap);
} catch (Exception e) { } catch (Exception e) {
FineLoggerFactory.getLogger().error("transfer widget tabledata failed", e); FineLoggerFactory.getLogger().error("transfer widget tabledata failed", e);
} }
return new HashMap<>(); return new HashMap<>();
} }
/**
* 对Map中所有的TableData做clone处理
* @param tempMap
*/
private static Map<String, TableData> dealWithTableData4Clone(Map<String, TableData> tempMap) {
Map<String, TableData> resultMap = new HashMap<>();
for (Map.Entry<String, TableData> entry : tempMap.entrySet()) {
String name = entry.getKey();
TableData tableData = entry.getValue();
TableData clonedTableData = cloneTableData(tableData);
if (clonedTableData != null) {
resultMap.put(name, clonedTableData);
}
}
return resultMap;
}
/** /**
* 收集控件-报表块中使用的数据集 * 收集控件-报表块中使用的数据集
* *
@ -337,4 +371,41 @@ public class TableDataFollowingPasteUtils {
return templeteDataSet; return templeteDataSet;
} }
/**
* 生成粘贴新建时使用的AbstractTableDataPane
* 主要是为了处理StoreProcedure它在远程情况下无法及时获取参数这边因为是复制粘贴所以直接用原TableData的参数即可
* @param tableDataWrapper wrapper
* @return AbstractTableDataPane,当TableData clone失败时方法返回null
*/
@Nullable
public static AbstractTableDataPane<?> generateTableDataPaneWhenPaste(AbstractTableDataWrapper tableDataWrapper) {
// 粘贴时再做一次TableData的clone
TableData clonedTableData = cloneTableData(tableDataWrapper.getTableData());
if (clonedTableData == null) {
return null;
}
AbstractTableDataWrapper clonedWrapper = new TemplateTableDataWrapper(clonedTableData);
AbstractTableDataPane<?> tableDataPane = clonedWrapper.creatTableDataPane();
TableData tableData = clonedWrapper.getTableData();
if (tableData instanceof StoreProcedure) {
StoreProcedure storeProcedure = (StoreProcedure) tableData;
((ProcedureDataPane) tableDataPane).populateParameters(storeProcedure.getParameters());
}
return tableDataPane;
}
/**
* clone数据源如果失败打印日志并返回null谨慎使用
* @param tableData
* @return
*/
@Nullable
public static TableData cloneTableData(TableData tableData) {
try {
return (TableData) tableData.clone();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "clone table data {} failed", tableData.getName());
}
return null;
}
} }

8
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java

@ -225,6 +225,14 @@ public class ProcedureDataPane extends AbstractTableDataPane<StoreProcedure> imp
} }
/**
* 手动更新参数用于上面populateBean方法中SwingWorker查询来不及的情况
* @param procedureParameters
*/
public void populateParameters(StoreProcedureParameter[] procedureParameters) {
this.editorPane.populate(procedureParameters);
}
/** /**
* 增加存储过程监听器 * 增加存储过程监听器
* *

2
designer-base/src/main/java/com/fr/design/gui/style/TextFormatPane.java

@ -58,7 +58,7 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
private static final Integer[] TYPES = new Integer[]{ private static final Integer[] TYPES = new Integer[]{
FormatContents.NULL, FormatContents.NUMBER, FormatContents.NULL, FormatContents.NUMBER,
FormatContents.CURRENCY, FormatContents.PERCENT, FormatContents.CURRENCY, FormatContents.PERCENT,
FormatContents.THOUSANDTHS,FormatContents.SCIENTIFIC, FormatContents.SCIENTIFIC,
FormatContents.DATE, FormatContents.TIME, FormatContents.DATE, FormatContents.TIME,
FormatContents.TEXT}; FormatContents.TEXT};

2
designer-base/src/main/java/com/fr/design/login/socketio/LoginAuthServer.java

@ -74,7 +74,7 @@ public class LoginAuthServer {
try { try {
server.start(); server.start();
} catch (Exception e) { } catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e); FineLoggerFactory.getLogger().warn(e.getMessage(), e);
} }
} }

2
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java

@ -41,7 +41,7 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare {
@Override @Override
public void start() { public void start() {
OptimizeUtil.open(() -> { OptimizeUtil.open(OptimizeUtil.Module.ANALYZER,() -> {
AnalyzerAssemblyFactory basicFactory = createBasicFactory(); AnalyzerAssemblyFactory basicFactory = createBasicFactory();

2
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java

@ -18,6 +18,6 @@ public class DesignerAnalyzerListener extends AgentBuilder.Listener.Adapter {
@Override @Override
public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) { public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) {
FineLoggerFactory.getLogger().error("Designer-Analyzer transform error:" + typeName); FineLoggerFactory.getLogger().warn("Designer-Analyzer transform error:" + typeName);
} }
} }

56
designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java

@ -5,22 +5,18 @@ import com.fr.general.GeneralUtils;
import com.fr.intelli.measure.Estimator; import com.fr.intelli.measure.Estimator;
import com.fr.intelli.metrics.Compute; import com.fr.intelli.metrics.Compute;
import com.fr.intelli.metrics.MessageRecorderFactory; import com.fr.intelli.metrics.MessageRecorderFactory;
import com.fr.intelli.metrics.SessionBinder;
import com.fr.intelli.metrics.SupervisoryConfig; import com.fr.intelli.metrics.SupervisoryConfig;
import com.fr.intelli.record.Measurable; import com.fr.intelli.record.Measurable;
import com.fr.intelli.record.MeasureObject; import com.fr.intelli.record.MeasureObject;
import com.fr.intelli.record.MeasureUnit; import com.fr.intelli.record.MeasureUnit;
import com.fr.log.FineLoggerFactory; import com.fr.log.FineLoggerFactory;
import com.fr.measure.DBMeterFactory; import com.fr.measure.DBMeterFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StringUtils; import com.fr.stable.StringUtils;
import com.fr.stable.web.Session;
import com.fr.stable.web.SessionProvider;
import com.fr.third.net.bytebuddy.asm.Advice; import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import com.fr.web.core.SessionPoolManager;
import com.fr.web.session.SessionLocalManager; import com.fr.web.session.SessionLocalManager;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -33,32 +29,31 @@ import java.util.regex.Pattern;
* created by Harrison on 2022/03/07 * created by Harrison on 2022/03/07
**/ **/
public class MonitorAdvice implements DesignerAnalyzerAdvice { public class MonitorAdvice implements DesignerAnalyzerAdvice {
private static final Pattern P = Pattern.compile("-?\\d+"); private static final Pattern P = Pattern.compile("-?\\d+");
private static final int MIN_ERROR_CODE = 10000000; private static final int MIN_ERROR_CODE = 10000000;
@Advice.OnMethodEnter @Advice.OnMethodEnter
public static void onMethodEnter(@Advice.Origin Method method, public static void onMethodEnter(@Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args,
@Advice.Local("startTime") Long startTime, @Advice.Local("startTime") Long startTime,
@Advice.Local("registeredSession") Boolean registeredSession) { @Advice.Local("sessionBinder") SessionBinder sessionBinder) {
startTime = (System.currentTimeMillis()); startTime = (System.currentTimeMillis());
registeredSession = (findSessionAnnotation(method, args)); sessionBinder = new SessionBinder();
sessionBinder.attachSession(method, args);
} }
@Advice.OnMethodExit(onThrowable = Exception.class) @Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self,
@Advice.Origin Method method, @Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args,
@Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e, @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e,
@Advice.Local("startTime") Long startTime, @Advice.Local("startTime") Long startTime,
@Advice.Local("registeredSession") Boolean registeredSession) throws Exception { @Advice.Local("sessionBinder") SessionBinder sessionBinder) throws Exception {
String error = StringUtils.EMPTY; String error = StringUtils.EMPTY;
try { try {
if (e != null) { if (e != null) {
try { try {
error = getErrorContent(e); error = getErrorContent(e);
@ -95,14 +90,11 @@ public class MonitorAdvice implements DesignerAnalyzerAdvice {
} catch (Exception ignore) { } catch (Exception ignore) {
//埋点信息入库失败应该不能影响业务流程 //埋点信息入库失败应该不能影响业务流程
} finally { } finally {
if (registeredSession) { sessionBinder.detachSession();
// 如果上面记录了,这里就要释放
SessionLocalManager.releaseSession();
}
} }
} }
} }
public static String getErrorContent(Exception e) { public static String getErrorContent(Exception e) {
int errorCode = GeneralUtils.objectToNumber( int errorCode = GeneralUtils.objectToNumber(
extractCodeFromString(e.getMessage()) extractCodeFromString(e.getMessage())
@ -110,7 +102,7 @@ public class MonitorAdvice implements DesignerAnalyzerAdvice {
// 提取字符串中的第一个数字,最小的错误码为10000000 // 提取字符串中的第一个数字,最小的错误码为10000000
return e.getClass().getName() + ":" + (errorCode >= MIN_ERROR_CODE ? errorCode : StringUtils.EMPTY); return e.getClass().getName() + ":" + (errorCode >= MIN_ERROR_CODE ? errorCode : StringUtils.EMPTY);
} }
public static String extractCodeFromString(String errorMsg) { public static String extractCodeFromString(String errorMsg) {
Matcher m = P.matcher(errorMsg); Matcher m = P.matcher(errorMsg);
if (m.find()) { if (m.find()) {
@ -118,38 +110,22 @@ public class MonitorAdvice implements DesignerAnalyzerAdvice {
} }
return StringUtils.EMPTY; return StringUtils.EMPTY;
} }
public static void recordSQLDetail(String uuid) { public static void recordSQLDetail(String uuid) {
DBMeterFactory.getMeter().submit(uuid); DBMeterFactory.getMeter().submit(uuid);
} }
public static void recordSQL(Compute once, MeasureObject measureObject) { public static void recordSQL(Compute once, MeasureObject measureObject) {
if (SupervisoryConfig.getInstance().isEnableMeasureSql() && once.computeSql()) { if (SupervisoryConfig.getInstance().isEnableMeasureSql() && once.computeSql()) {
measureObject.sqlTime(SessionLocalManager.getSqlTime()); measureObject.sqlTime(SessionLocalManager.getSqlTime());
measureObject.sql(SessionLocalManager.getSql()); measureObject.sql(SessionLocalManager.getSql());
} }
} }
public static void recordMemory(Compute once, Measurable measurable, MeasureObject measureObject) { public static void recordMemory(Compute once, Measurable measurable, MeasureObject measureObject) {
if (SupervisoryConfig.getInstance().isEnableMeasureMemory() && once.computeMemory()) { if (SupervisoryConfig.getInstance().isEnableMeasureMemory() && once.computeMemory()) {
MeasureUnit unit = measurable.measureUnit(); MeasureUnit unit = measurable.measureUnit();
measureObject.memory(unit.measureMemory()); measureObject.memory(unit.measureMemory());
} }
} }
public static boolean findSessionAnnotation(Method method, Object[] args) {
Annotation[][] all = method.getParameterAnnotations();
int len = ArrayUtils.getLength(args);
for (int i = 0; i < len; i++) {
Annotation[] current = all[i];
for (Annotation annotation : current) {
if (annotation.annotationType().equals(Session.class)) {
SessionLocalManager.setSession(
SessionPoolManager.getSessionIDInfor(GeneralUtils.objectToString(args[i]), SessionProvider.class));
return true;
}
}
}
return false;
}
} }

28
designer-base/src/main/java/com/fr/design/utils/SvgPaintUtils.java

@ -0,0 +1,28 @@
package com.fr.design.utils;
import com.fr.base.svg.SVGLoader;
import com.fr.base.svg.SystemScaleUtils;
import java.awt.Graphics2D;
/**
* 用于绘制svg图片缩放(高分屏下)
*
* @author hades
* @version 11.0
* Created by hades on 2022/5/6
*/
public class SvgPaintUtils {
public static void beforePaint(Graphics2D g2) {
if (SystemScaleUtils.isJreHiDPIEnabled()) {
g2.scale(1 / SVGLoader.SYSTEM_SCALE, 1 / SVGLoader.SYSTEM_SCALE);
}
}
public static void afterPaint(Graphics2D g2) {
if (SystemScaleUtils.isJreHiDPIEnabled()) {
g2.scale(SVGLoader.SYSTEM_SCALE, SVGLoader.SYSTEM_SCALE);
}
}
}

7
designer-base/src/main/java/com/fr/exit/ConfigToPropMigrator.java

@ -40,7 +40,14 @@ public class ConfigToPropMigrator {
} }
public void execute() { public void execute() {
try {
_execute();
} catch (Throwable throwable) {
FineLoggerFactory.getLogger().warn(throwable.getMessage(), throwable);
}
}
private void _execute() {
if (WorkContext.getCurrent().isLocal()) { if (WorkContext.getCurrent().isLocal()) {
String url = "jdbc:hsqldb:file://" + WorkContext.getCurrent().getPath() + "/" + ProjectConstants.EMBED_DB_DIRECTORY + "/finedb/db;hsqldb.tx=mvcc"; String url = "jdbc:hsqldb:file://" + WorkContext.getCurrent().getPath() + "/" + ProjectConstants.EMBED_DB_DIRECTORY + "/finedb/db;hsqldb.tx=mvcc";

12
designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ColSelectedWithSummaryMethodEditor.java

@ -2,6 +2,7 @@ package com.fr.design.chart.series.SeriesCondition;
import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.Chart;
import com.fr.data.DSColumnWithSummaryMethod; import com.fr.data.DSColumnWithSummaryMethod;
import com.fr.data.util.function.AbstractDataFunction;
import com.fr.design.chart.ChartDataHelper; import com.fr.design.chart.ChartDataHelper;
import com.fr.design.data.datapane.SummaryMethodComboBox; import com.fr.design.data.datapane.SummaryMethodComboBox;
import com.fr.design.editor.editor.Editor; import com.fr.design.editor.editor.Editor;
@ -19,18 +20,21 @@ public class ColSelectedWithSummaryMethodEditor extends Editor<DSColumnWithSumma
private static DefaultComboBoxModel<String> summaryMethodComboBoxModel = new DefaultComboBoxModel<>(SummaryMethodComboBox.CALCULATE_ARRAY); private static DefaultComboBoxModel<String> summaryMethodComboBoxModel = new DefaultComboBoxModel<>(SummaryMethodComboBox.CALCULATE_ARRAY);
public ColSelectedWithSummaryMethodEditor() { public ColSelectedWithSummaryMethodEditor() {
this.setName(Toolkit.i18nText("Fine-Design_Chart_Summary_Array")); this.setName(Toolkit.i18nText("Fine-Design_Chart_Summary_Field_Value"));
this.setLayout(FRGUIPaneFactory.createLeftZeroLayout()); this.setLayout(FRGUIPaneFactory.createLeftZeroLayout());
if (columnNameComboBox == null) { if (columnNameComboBox == null) {
columnNameComboBox = new UIComboBox(); columnNameComboBox = new UIComboBox();
} }
columnNameComboBox.setPreferredSize(new Dimension(82, 20)); columnNameComboBox.setPreferredSize(new Dimension(82, 20));
this.add(columnNameComboBox);
summaryMethodComboBox = new SummaryMethodComboBox(); summaryMethodComboBox = new SummaryMethodComboBox();
summaryMethodComboBox.setModel(summaryMethodComboBoxModel); summaryMethodComboBox.setModel(summaryMethodComboBoxModel);
summaryMethodComboBox.setPreferredSize(new Dimension(82, 20)); summaryMethodComboBox.setPreferredSize(new Dimension(82, 20));
this.setLayout(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout());
this.add(columnNameComboBox);
this.add(summaryMethodComboBox); this.add(summaryMethodComboBox);
columnNameComboBox.setModel(columnNameComboBoxModel); columnNameComboBox.setModel(columnNameComboBoxModel);
columnNameComboBox.setSelectedItem(null);
summaryMethodComboBox.setSelectedItem(null);
} }
public static void refreshCommonChartFieldNames(Chart chart) { public static void refreshCommonChartFieldNames(Chart chart) {
@ -52,6 +56,8 @@ public class ColSelectedWithSummaryMethodEditor extends Editor<DSColumnWithSumma
for (String method : SummaryMethodComboBox.CALCULATE_ARRAY) { for (String method : SummaryMethodComboBox.CALCULATE_ARRAY) {
summaryMethodComboBoxModel.addElement(method); summaryMethodComboBoxModel.addElement(method);
} }
columnNameComboBoxModel.setSelectedItem(null);
summaryMethodComboBoxModel.setSelectedItem(null);
} else { } else {
columnNameComboBoxModel.removeAllElements(); columnNameComboBoxModel.removeAllElements();
summaryMethodComboBoxModel.removeAllElements(); summaryMethodComboBoxModel.removeAllElements();
@ -77,7 +83,7 @@ public class ColSelectedWithSummaryMethodEditor extends Editor<DSColumnWithSumma
public void setValue(DSColumnWithSummaryMethod value) { public void setValue(DSColumnWithSummaryMethod value) {
if (value != null) { if (value != null) {
columnNameComboBox.setSelectedItem(value.getFieldName()); columnNameComboBox.setSelectedItem(value.getFieldName());
summaryMethodComboBox.setSelectedItem(value.getDataFunction()); summaryMethodComboBox.populateBean((AbstractDataFunction)value.getDataFunction());
} }
} }

11
designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java

@ -10,6 +10,7 @@ import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper; import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.chart.mode.ChartEditContext;
import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.stable.Nameable; import com.fr.stable.Nameable;
import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.TableLayout4VanChartHelper;
@ -128,7 +129,9 @@ public abstract class VanChartUIListControlPane extends UIListControlPane implem
public void populate(Nameable[] nameableArray) { public void populate(Nameable[] nameableArray) {
//特殊处理,使用instanceof判断,弹出不同的面板 //特殊处理,使用instanceof判断,弹出不同的面板
if (SwingUtilities.getWindowAncestor(this) instanceof PopupEditDialog) { //悬浮窗图表弹框 || 场景地图编辑弹框 都是真正的弹框 从if走
//fvs.chart走super
if (SwingUtilities.getWindowAncestor(this) instanceof JDialog && !ChartEditContext.duchampMode()) {
popupEditDialog = new HyperDialog(cardPane); popupEditDialog = new HyperDialog(cardPane);
} }
super.populate(nameableArray); super.populate(nameableArray);
@ -136,7 +139,7 @@ public abstract class VanChartUIListControlPane extends UIListControlPane implem
protected void popupEditDialog(Point mousePos) { protected void popupEditDialog(Point mousePos) {
//特殊处理,处理连续弹窗情况,弹出面板定为方式不同 //特殊处理,处理连续弹窗情况,弹出面板定为方式不同
if (SwingUtilities.getWindowAncestor(this) instanceof PopupEditDialog) { if (SwingUtilities.getWindowAncestor(this) instanceof JDialog && !ChartEditContext.duchampMode()) {
GUICoreUtils.centerWindow(popupEditDialog); GUICoreUtils.centerWindow(popupEditDialog);
popupEditDialog.setVisible(true); popupEditDialog.setVisible(true);
return; return;
@ -170,12 +173,8 @@ public abstract class VanChartUIListControlPane extends UIListControlPane implem
JPanel buttonsPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); JPanel buttonsPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));
controlPane.add(buttonsPane, BorderLayout.EAST); controlPane.add(buttonsPane, BorderLayout.EAST);
//确定 //确定
addOkButton(buttonsPane); addOkButton(buttonsPane);
//取消
addCancelButton(buttonsPane);
controlPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); controlPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
return controlPane; return controlPane;

4
designer-form/src/main/java/com/fr/design/gui/xpane/LayoutBorderPane.java

@ -333,8 +333,8 @@ public class LayoutBorderPane extends BasicPane {
JPanel rightPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); JPanel rightPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
defaultPane.add(rightPane, BorderLayout.EAST); defaultPane.add(rightPane, BorderLayout.EAST);
rightPane.add(initRightBottomPane(), BorderLayout.CENTER); rightPane.add(initRightBottomPane(), BorderLayout.CENTER);
JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); JTemplate<?, ?> jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
if (!jTemplate.isJWorkBook() && ((JForm)jTemplate).isSelectRootPane()){ if (!jTemplate.isJWorkBook() && jTemplate instanceof JForm && ((JForm)jTemplate).isSelectRootPane()){
//界面上表单主体只有背景和透明度可以设置 //界面上表单主体只有背景和透明度可以设置
rightPane.add(initBodyRightTopPane(), BorderLayout.NORTH); rightPane.add(initBodyRightTopPane(), BorderLayout.NORTH);
} else { } else {

6
designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java

@ -66,8 +66,10 @@ public class LayoutStylePane extends BasicBeanPane<LayoutBorderStyle> {
this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); JTemplate<?, ?> currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
boolean isRootLayout = currentEditingTemplate != null && !currentEditingTemplate.isJWorkBook() && ((JForm)currentEditingTemplate).isSelectRootPane(); boolean isRootLayout = currentEditingTemplate != null &&
!currentEditingTemplate.isJWorkBook() &&
currentEditingTemplate instanceof JForm && ((JForm)currentEditingTemplate).isSelectRootPane();
namedTitleStylePane = createNamedTitleStylePane(isRootLayout); namedTitleStylePane = createNamedTitleStylePane(isRootLayout);
namedBodyStylePane = createNamedBodyStylePane(isRootLayout); namedBodyStylePane = createNamedBodyStylePane(isRootLayout);

4
designer-form/src/main/java/com/fr/design/widget/ui/designer/component/WidgetBoundPane.java

@ -76,8 +76,8 @@ public class WidgetBoundPane extends BasicPane {
height.setEnabled(false); height.setEnabled(false);
} }
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (jTemplate.isJWorkBook() || !((JForm)jTemplate).isSelectRootPane()) { if (jTemplate.isJWorkBook() || !((jTemplate instanceof JForm) && ((JForm)jTemplate).isSelectRootPane())) {
ratioLockedButton = new AspectRatioLockedButton(width, height); ratioLockedButton = new AspectRatioLockedButton(width, height);
ratioLockedButton.setGlobalName(i18nText("Fine-Design_Form_Coords_And_Size")); ratioLockedButton.setGlobalName(i18nText("Fine-Design_Form_Coords_And_Size"));
ratioLockedButton.setLockEnabled(false); ratioLockedButton.setLockEnabled(false);

2
designer-realize/src/main/java/com/fr/design/mainframe/HyperlinkGroupPaneActionImpl.java

@ -89,7 +89,7 @@ public class HyperlinkGroupPaneActionImpl implements HyperlinkGroupPaneActionPro
} }
// 首次添加超链接,将文字样式默认改为蓝色下划线 // 首次添加超链接,将文字样式默认改为蓝色下划线
if (editCellElement.getNameHyperlinkGroup() == null && hyperlinkGroupPane.getCurrentEvent() != null && hyperlinkGroupPane.getCurrentEvent().getType() == ListDataEvent.INTERVAL_ADDED) { if ((editCellElement.getNameHyperlinkGroup() == null || editCellElement.getNameHyperlinkGroup().size() == 0) && hyperlinkGroupPane.getCurrentEvent() != null && hyperlinkGroupPane.getCurrentEvent().getType() == ListDataEvent.INTERVAL_ADDED) {
editCellElement.setStyle(elementStyle.deriveFRFont(frFont)); editCellElement.setStyle(elementStyle.deriveFRFont(frFont));
} }

16
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineUtil.java

@ -32,6 +32,10 @@ public class AlphaFineUtil {
private static String getReplacedString(String modelName, String string) { private static String getReplacedString(String modelName, String string) {
// 如果是直接包含了高亮字符 返回
if (StringUtils.contains(modelName, string)) {
return string;
}
//需要考虑modelName有空格的情况 //需要考虑modelName有空格的情况
//比如现在是work boo k 搜索词是workb,应该要替换的部分是work b //比如现在是work boo k 搜索词是workb,应该要替换的部分是work b
//先去掉已经匹配替换过的部分,因为考虑到分词的情况,可能会进行多次替换 //先去掉已经匹配替换过的部分,因为考虑到分词的情况,可能会进行多次替换
@ -53,6 +57,18 @@ public class AlphaFineUtil {
return result.toString(); return result.toString();
} }
public static String escapeExprSpecialWord(String keyword) {
if (StringUtils.isNotBlank(keyword)) {
String[] fbsArr = { "\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|" };
for (String key : fbsArr) {
if (keyword.contains(key)) {
keyword = keyword.replace(key, "\\" + key);
}
}
}
return keyword;
}
public static boolean unread() { public static boolean unread() {
Set<Long> readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet(); Set<Long> readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet();
Set<Long> idSet = ProductNewsSearchManager.getInstance().getIdSet(); Set<Long> idSet = ProductNewsSearchManager.getInstance().getIdSet();

210
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineFrame.java

@ -77,6 +77,18 @@ import javax.swing.Timer;
public class AlphaFineFrame extends JFrame { public class AlphaFineFrame extends JFrame {
private static final String ADVANCED_SEARCH_MARK = "k:"; private static final String ADVANCED_SEARCH_MARK = "k:";
private static final String ACTION_MARK_SHORT = "k:1 ";
private static final String ACTION_MARK = "k:setting ";
private static final String DOCUMENT_MARK_SHORT = "k:2 ";
private static final String DOCUMENT_MARK = "k:help ";
private static final String FILE_MARK_SHORT = "k:3 ";
private static final String FILE_MARK = "k:reportlets ";
private static final String CPT_MARK = "k:cpt ";
private static final String FRM_MARK = "k:frm ";
private static final String DS_MARK = "k:ds ";
private static final String DS_NAME = "dsname=\"";
private static final String PLUGIN_MARK_SHORT = "k:4 ";
private static final String PLUGIN_MARK = "k:shop ";
private static final int TIMER_DELAY = 300; private static final int TIMER_DELAY = 300;
@ -171,38 +183,26 @@ public class AlphaFineFrame extends JFrame {
this.settingSearchWorkerManager = new SearchWorkerManager( this.settingSearchWorkerManager = new SearchWorkerManager(
CellType.ACTION, CellType.ACTION,
searchTextBean -> { searchTextBean -> ActionSearchManager.getInstance().getSearchResult(searchTextBean),
ActionSearchManager.getInstance().getLessSearchResult(searchTextBean.getSegmentation());
return ActionSearchManager.getInstance().getMoreSearchResult(searchTextBean.getSearchText());
},
this, this,
new SimpleRightSearchResultPane(new NoResultPane(NO_RESULT, AlphaFineConstants.NO_RESULT_ICON)) new SimpleRightSearchResultPane(new NoResultPane(NO_RESULT, AlphaFineConstants.NO_RESULT_ICON))
); );
fileSearchWorkerManager = new SearchWorkerManager( fileSearchWorkerManager = new SearchWorkerManager(
CellType.FILE, CellType.FILE,
searchTextBean -> { searchTextBean -> FileSearchManager.getInstance().getSearchResult(searchTextBean),
FileSearchManager.getInstance().getLessSearchResult(searchTextBean.getSearchText(), searchTextBean.getSegmentation());
return FileSearchManager.getInstance().getMoreSearchResult(searchTextBean.getSearchText());
},
this, this,
new LoadingRightSearchResultPane() new LoadingRightSearchResultPane()
); );
documentWorkerManager = new SearchWorkerManager( documentWorkerManager = new SearchWorkerManager(
CellType.DOCUMENT, CellType.DOCUMENT,
searchTextBean -> { searchTextBean -> DocumentSearchManager.getInstance().getSearchResult(searchTextBean),
DocumentSearchManager.getInstance().getLessSearchResult(searchTextBean.getSegmentation());
return DocumentSearchManager.getInstance().getMoreSearchResult(searchTextBean.getSearchText());
},
this, this,
new SimpleRightSearchResultPane(new JPanel()) new SimpleRightSearchResultPane(new JPanel())
); );
pluginSearchWorkerManager = new SearchWorkerManager( pluginSearchWorkerManager = new SearchWorkerManager(
CellType.PLUGIN, CellType.PLUGIN,
searchTextBean -> { searchTextBean -> PluginSearchManager.getInstance().getSearchResult(searchTextBean),
PluginSearchManager.getInstance().getLessSearchResult(searchTextBean.getSegmentation());
return PluginSearchManager.getInstance().getMoreSearchResult(searchTextBean.getSearchText());
},
this, this,
new LoadingRightSearchResultPane() new LoadingRightSearchResultPane()
); );
@ -294,6 +294,7 @@ public class AlphaFineFrame extends JFrame {
@Override @Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
searchTextField.setText(StringUtils.EMPTY); searchTextField.setText(StringUtils.EMPTY);
beforeSearchStr = StringUtils.EMPTY;
clearLabel.setVisible(false); clearLabel.setVisible(false);
} }
}); });
@ -366,6 +367,87 @@ public class AlphaFineFrame extends JFrame {
JPanel tabPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 10)); JPanel tabPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 10));
tabPane.setBackground(Color.WHITE); tabPane.setBackground(Color.WHITE);
List<SelectedLabel> selectedLabelList = createSelectedLabelList();
selectedType = selectedLabelList.get(0).getCellType();
// 第一个tab 非产品动态
if (selectedType != CellType.PRODUCT_NEWS) {
tabLabel.setText(selectedLabelList.get(0).getText());
readLabel.setVisible(false);
}
for (SelectedLabel selectedLabel : selectedLabelList) {
selectedLabel.addMouseListener(createMouseListener(selectedLabelList, selectedLabel, tabPane, tabLabel, readLabel));
tabPane.add(selectedLabel);
}
showPane.add(tabPane, BorderLayout.NORTH);
showPane.add(labelPane, BorderLayout.CENTER);
showPane.add(resultPane, BorderLayout.SOUTH);
return showPane;
}
private MouseAdapter createMouseListener(List<SelectedLabel> selectedLabelList, SelectedLabel selectedLabel,
JPanel tabPane, UILabel tabLabel, UILabel readLabel) {
return new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
for (SelectedLabel label : selectedLabelList) {
label.setSelected(false);
label.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8);
}
selectedLabel.setSelected(true);
// 处理产品动态 tab与下方文字展示不一致
if (ComparatorUtils.equals(selectedLabel.getText().trim(), PRODUCT_NEWS)) {
tabLabel.setText(PRODUCT_DYNAMICS);
} else {
tabLabel.setText(selectedLabel.getText());
}
readLabel.setVisible(false);
tabPane.repaint();
switch (selectedLabel.getCellType()) {
case PRODUCT_NEWS:
readLabel.setVisible(true);
switchType(CellType.PRODUCT_NEWS);
break;
case ACTION:
currentSearchWorkerManager = settingSearchWorkerManager;
switchType(CellType.ACTION);
break;
case FILE:
currentSearchWorkerManager = fileSearchWorkerManager;
switchType(CellType.FILE);
break;
case DOCUMENT:
currentSearchWorkerManager = documentWorkerManager;
switchType(CellType.DOCUMENT);
break;
case PLUGIN:
currentSearchWorkerManager = pluginSearchWorkerManager;
switchType(CellType.PLUGIN);
break;
}
if (currentSearchWorkerManager != null) {
AlphaFineList alphaFineList = currentSearchWorkerManager.getSearchResultList();
if (alphaFineList != null) {
alphaFineList.setSelectedIndex(0);
}
}
}
private Color defaultColor;
@Override
public void mouseEntered(MouseEvent e) {
defaultColor = selectedLabel.getForeground();
selectedLabel.setForeground(AlphaFineConstants.SUSPENDED_COLOR);
}
@Override
public void mouseExited(MouseEvent e) {
selectedLabel.setForeground(defaultColor);
}
};
}
private List<SelectedLabel> createSelectedLabelList() {
List<SelectedLabel> selectedLabelList = new ArrayList<>(); List<SelectedLabel> selectedLabelList = new ArrayList<>();
AlphaFineConfigManager alphaFineConfigManager = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager(); AlphaFineConfigManager alphaFineConfigManager = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager();
if (alphaFineConfigManager.isProductDynamics()) { if (alphaFineConfigManager.isProductDynamics()) {
@ -383,74 +465,7 @@ public class AlphaFineFrame extends JFrame {
if (alphaFineConfigManager.isContainPlugin()) { if (alphaFineConfigManager.isContainPlugin()) {
selectedLabelList.add(new SelectedLabel(PLUGIN, CellType.PLUGIN)); selectedLabelList.add(new SelectedLabel(PLUGIN, CellType.PLUGIN));
} }
selectedType = selectedLabelList.get(0).getCellType(); return selectedLabelList;
for (SelectedLabel selectedLabel : selectedLabelList) {
selectedLabel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
for (SelectedLabel label : selectedLabelList) {
label.setSelected(false);
label.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8);
}
selectedLabel.setSelected(true);
// 处理产品动态 tab与下方文字展示不一致
if (ComparatorUtils.equals(selectedLabel.getText().trim(), PRODUCT_NEWS)) {
tabLabel.setText(PRODUCT_DYNAMICS);
} else {
tabLabel.setText(selectedLabel.getText());
}
readLabel.setVisible(false);
tabPane.repaint();
switch (selectedLabel.getCellType()) {
case PRODUCT_NEWS:
readLabel.setVisible(true);
switchType(CellType.PRODUCT_NEWS);
break;
case ACTION:
currentSearchWorkerManager = settingSearchWorkerManager;
switchType(CellType.ACTION);
break;
case FILE:
currentSearchWorkerManager = fileSearchWorkerManager;
switchType(CellType.FILE);
break;
case DOCUMENT:
currentSearchWorkerManager = documentWorkerManager;
switchType(CellType.DOCUMENT);
break;
case PLUGIN:
currentSearchWorkerManager = pluginSearchWorkerManager;
switchType(CellType.PLUGIN);
break;
}
if (currentSearchWorkerManager != null) {
AlphaFineList alphaFineList = currentSearchWorkerManager.getSearchResultList();
if (alphaFineList != null) {
alphaFineList.setSelectedIndex(0);
}
}
}
private Color defaultColor;
@Override
public void mouseEntered(MouseEvent e) {
defaultColor = selectedLabel.getForeground();
selectedLabel.setForeground(AlphaFineConstants.SUSPENDED_COLOR);
}
@Override
public void mouseExited(MouseEvent e) {
selectedLabel.setForeground(defaultColor);
}
});
tabPane.add(selectedLabel);
}
showPane.add(tabPane, BorderLayout.NORTH);
showPane.add(labelPane, BorderLayout.CENTER);
showPane.add(resultPane, BorderLayout.SOUTH);
return showPane;
} }
private void fireOneClickRead() { private void fireOneClickRead() {
@ -555,6 +570,8 @@ public class AlphaFineFrame extends JFrame {
if (StringUtils.isNotEmpty(searchTextField.getText())) { if (StringUtils.isNotEmpty(searchTextField.getText())) {
clearLabel.setVisible(true); clearLabel.setVisible(true);
SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane); SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane);
} else {
beforeSearchStr = StringUtils.EMPTY;
} }
AlphaFineToolTipList alphaFineToolTipList = SearchTooltipPopup.getInstance().getAlphaFineToolTipList(); AlphaFineToolTipList alphaFineToolTipList = SearchTooltipPopup.getInstance().getAlphaFineToolTipList();
if (e.getKeyCode() == KeyEvent.VK_ENTER) { if (e.getKeyCode() == KeyEvent.VK_ENTER) {
@ -602,6 +619,7 @@ public class AlphaFineFrame extends JFrame {
SearchTooltipPopup.getInstance().hide(); SearchTooltipPopup.getInstance().hide();
clearLabel.setVisible(false); clearLabel.setVisible(false);
switchType(selectedType); switchType(selectedType);
beforeSearchStr = StringUtils.EMPTY;
} else if (searchTextField.hasFocus()) { } else if (searchTextField.hasFocus()) {
clearLabel.setVisible(true); clearLabel.setVisible(true);
SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane); SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane);
@ -663,11 +681,15 @@ public class AlphaFineFrame extends JFrame {
resultPane.add(panel, flag); resultPane.add(panel, flag);
} }
public void removeSearchResultPane(JPanel panel) {
resultPane.remove(panel);
}
private void doSearch(String text) { private void doSearch(String text) {
initSearchLoadingPane(); initSearchLoadingPane();
SearchTextBean searchTextBean = new SearchTextBean(text, segmentationResult); SearchTextBean searchTextBean = generateSearchTextBean(text);
this.productNewsSearchWorkerManager.doSearch(searchTextBean); this.productNewsSearchWorkerManager.doSearch(searchTextBean);
this.settingSearchWorkerManager.doSearch(searchTextBean); this.settingSearchWorkerManager.doSearch(searchTextBean);
this.fileSearchWorkerManager.doSearch(searchTextBean); this.fileSearchWorkerManager.doSearch(searchTextBean);
@ -675,6 +697,21 @@ public class AlphaFineFrame extends JFrame {
this.pluginSearchWorkerManager.doSearch(searchTextBean); this.pluginSearchWorkerManager.doSearch(searchTextBean);
} }
private SearchTextBean generateSearchTextBean(String searchText) {
if (searchText.startsWith(ACTION_MARK_SHORT) || searchText.startsWith(ACTION_MARK)
|| searchText.startsWith(DOCUMENT_MARK_SHORT) || searchText.startsWith(DOCUMENT_MARK)) {
return new SearchTextBean(StringUtils.EMPTY, new String[]{getStoreText(searchText)});
} else if (searchText.startsWith(FILE_MARK_SHORT) || searchText.startsWith(FILE_MARK)
|| searchText.startsWith(CPT_MARK) || searchText.startsWith(FRM_MARK)
|| searchText.startsWith(PLUGIN_MARK_SHORT) || searchText.startsWith(PLUGIN_MARK)) {
return new SearchTextBean(getStoreText(searchText), new String[]{getStoreText(searchText)});
} else if (searchText.startsWith(DS_MARK)) {
return new SearchTextBean(getStoreText(searchText), new String[]{DS_NAME + getStoreText(searchText)});
} else {
return new SearchTextBean(searchText, segmentationResult == null ? new String[]{} : segmentationResult);
}
}
/** /**
* 仅搜索依赖网络的搜索项 * 仅搜索依赖网络的搜索项
* *
@ -780,6 +817,9 @@ public class AlphaFineFrame extends JFrame {
public void setVisible(boolean b) { public void setVisible(boolean b) {
super.setVisible(b); super.setVisible(b);
QuestionWindow.getInstance().setVisible(!b); QuestionWindow.getInstance().setVisible(!b);
if (!b) {
AlphaFineHelper.resetAlphaFineDialog();
}
} }
@Override @Override

10
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineList.java

@ -3,6 +3,7 @@ package com.fr.design.mainframe.alphafine.component;
import com.fr.design.mainframe.alphafine.AlphaFineConstants; import com.fr.design.mainframe.alphafine.AlphaFineConstants;
import com.fr.design.mainframe.alphafine.AlphaFineHelper; import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel;
import com.fr.design.mainframe.alphafine.cell.model.DocumentModel;
import com.fr.design.mainframe.alphafine.preview.ResultShowPane; import com.fr.design.mainframe.alphafine.preview.ResultShowPane;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
@ -26,7 +27,10 @@ public class AlphaFineList extends JList<AlphaCellModel> {
AlphaCellModel selectedValue = getSelectedValue(); AlphaCellModel selectedValue = getSelectedValue();
if (e.getClickCount() == AlphaFineConstants.DEFAULT_CLICK_COUNT && selectedValue.hasAction()) { if (e.getClickCount() == AlphaFineConstants.DEFAULT_CLICK_COUNT && selectedValue.hasAction()) {
// 点击搜索结果 主页面移动到后面 // 点击搜索结果 主页面移动到后面
AlphaFineHelper.getAlphaFineDialog().toBack(); if (!(selectedValue instanceof DocumentModel)) {
// 帮助文档不跳转
AlphaFineHelper.getAlphaFineDialog().toBack();
}
dealWithSearchResult(); dealWithSearchResult();
} }
} }
@ -45,6 +49,10 @@ public class AlphaFineList extends JList<AlphaCellModel> {
@Override @Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) { if (e.getKeyCode() == KeyEvent.VK_ENTER) {
AlphaCellModel selectedValue = getSelectedValue();
if (selectedValue.hasAction() && !(selectedValue instanceof DocumentModel)) {
AlphaFineHelper.getAlphaFineDialog().toBack();
}
dealWithSearchResult(); dealWithSearchResult();
} }
} }

4
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsImagePanel.java

@ -2,8 +2,10 @@ package com.fr.design.mainframe.alphafine.component;
import com.fr.base.GraphHelper; import com.fr.base.GraphHelper;
import com.fr.base.svg.SVGLoader; import com.fr.base.svg.SVGLoader;
import com.fr.base.svg.SystemScaleUtils;
import com.fr.design.DesignerEnvManager; import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.alphafine.model.ProductNews; import com.fr.design.mainframe.alphafine.model.ProductNews;
import com.fr.design.utils.SvgPaintUtils;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
@ -56,7 +58,9 @@ public class ProductNewsImagePanel extends JPanel {
} }
Set<Long> readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet(); Set<Long> readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet();
if (!readSet.contains(productNews.getId())) { if (!readSet.contains(productNews.getId())) {
SvgPaintUtils.beforePaint(g2);
g2.drawImage(NEW_TIP_IMAGE, 0, 0, this); g2.drawImage(NEW_TIP_IMAGE, 0, 0, this);
SvgPaintUtils.afterPaint(g2);
} }
g2.setColor(BACKGROUND_COLOR); g2.setColor(BACKGROUND_COLOR);

24
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionPane.java

@ -1,13 +1,15 @@
package com.fr.design.mainframe.alphafine.question; package com.fr.design.mainframe.alphafine.question;
import com.fr.base.svg.SVGLoader; import com.fr.base.svg.SVGLoader;
import com.fr.base.svg.SystemScaleUtils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.alphafine.AlphaFineUtil; import com.fr.design.mainframe.alphafine.AlphaFineUtil;
import com.fr.design.utils.SvgPaintUtils;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
import java.awt.RenderingHints;
import javax.swing.JPanel; import javax.swing.JPanel;
/** /**
@ -23,7 +25,6 @@ public class QuestionPane extends JPanel {
private static final Image QUESTION_BACKGROUND_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/groupbackgroud.svg"); private static final Image QUESTION_BACKGROUND_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/groupbackgroud.svg");
public QuestionPane() { public QuestionPane() {
this.setBackground(new Color(0, 0, 0, 0)); this.setBackground(new Color(0, 0, 0, 0));
} }
@ -32,14 +33,21 @@ public class QuestionPane extends JPanel {
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g; Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); SvgPaintUtils.beforePaint(g2);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); // 宽高保持
if (AlphaFineUtil.unread()) { int width = SystemScaleUtils.isJreHiDPIEnabled() ? (int) (getWidth() * SVGLoader.SYSTEM_SCALE) : getWidth();
g2.drawImage(NEW_MESSAGE_IMAGE, 0, 0, getWidth(), getHeight(), this); int height = SystemScaleUtils.isJreHiDPIEnabled() ? (int) (getHeight() * SVGLoader.SYSTEM_SCALE) : getHeight();
if (AlphaFineUtil.unread() && DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isProductDynamics()) {
g2.drawImage(NEW_MESSAGE_IMAGE, 0, 0, this);
} else { } else {
g2.drawImage(QUESTION_BACKGROUND_IMAGE, 0, 0, getWidth(), getHeight(), this); g2.drawImage(QUESTION_BACKGROUND_IMAGE, 0, 0, this);
} }
g2.drawImage(QUESTION_IMAGE, (getWidth() - QUESTION_IMAGE.getWidth(this)) / 2, (getHeight() - QUESTION_IMAGE.getHeight(this)) / 2, this);
int imageWidth = QUESTION_IMAGE.getWidth(this);
int imageHeight = QUESTION_IMAGE.getHeight(this);
g2.drawImage(QUESTION_IMAGE, (width - imageWidth) / 2 - 2, (height - imageHeight) / 2 - 2,this);
SvgPaintUtils.afterPaint(g2);
} }

11
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionWindow.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe.alphafine.question; package com.fr.design.mainframe.alphafine.question;
import com.fr.design.DesignerEnvManager;
import com.fr.design.i18n.Toolkit; import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.alphafine.AlphaFineHelper; import com.fr.design.mainframe.alphafine.AlphaFineHelper;
@ -55,9 +56,9 @@ public class QuestionWindow extends JWindow {
@Override @Override
public void windowDeactivated(WindowEvent e) { public void windowDeactivated(WindowEvent e) {
QuestionWindow.getInstance().dispose();
QuestionWindow.getInstance().setVisible(false); QuestionWindow.getInstance().setVisible(false);
} }
}); });
questionPane.setToolTipText(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Learn_More_About")); questionPane.setToolTipText(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Learn_More_About"));
this.setContentPane(questionPane); this.setContentPane(questionPane);
@ -68,6 +69,14 @@ public class QuestionWindow extends JWindow {
DesignerContext.getDesignerFrame().getHeight() - 100); DesignerContext.getDesignerFrame().getHeight() - 100);
} }
@Override
public void setVisible(boolean visible) {
if (visible && !DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isEnabled()) {
return;
}
super.setVisible(visible);
}
public static QuestionWindow getInstance() { public static QuestionWindow getInstance() {
return INSTANCE; return INSTANCE;
} }

7
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/ProductNewsSearchWorkerManager.java

@ -48,10 +48,11 @@ public class ProductNewsSearchWorkerManager implements SearchManager {
checkSearchWork(); checkSearchWork();
searchOver = false; searchOver = false;
networkError = false; networkError = false;
if (searchResultPane == null) { if (searchResultPane != null) {
searchResultPane = new ProductNewsSearchResultPane(searchTextBean.getSegmentation()); alphaFineFrame.removeSearchResultPane(searchResultPane);
alphaFineFrame.addResult(searchResultPane, cellType.getFlagStr4Result());
} }
searchResultPane = new ProductNewsSearchResultPane(searchTextBean.getSegmentation());
alphaFineFrame.addResult(searchResultPane, cellType.getFlagStr4Result());
this.searchWorker = new SwingWorker<DefaultListModel<ProductNews>, Void>() { this.searchWorker = new SwingWorker<DefaultListModel<ProductNews>, Void>() {
@Override @Override

7
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchWorkerManager.java

@ -48,10 +48,11 @@ public class SearchWorkerManager implements SearchManager {
} }
private void initSearchResult(SearchTextBean searchTextBean) { private void initSearchResult(SearchTextBean searchTextBean) {
if (searchResultPane == null) { if (searchResultPane != null) {
searchResultPane = new SearchResultPane(searchTextBean.getSegmentation(), resultShowPane); alphaFineFrame.removeSearchResultPane(searchResultPane);
alphaFineFrame.addResult(searchResultPane, cellType.getFlagStr4Result());
} }
searchResultPane = new SearchResultPane(searchTextBean.getSegmentation(), resultShowPane);
alphaFineFrame.addResult(searchResultPane, cellType.getFlagStr4Result());
} }

12
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/fun/AlphaFineSearchProvider.java

@ -1,6 +1,7 @@
package com.fr.design.mainframe.alphafine.search.manager.fun; package com.fr.design.mainframe.alphafine.search.manager.fun;
import com.fr.design.mainframe.alphafine.model.SearchResult; import com.fr.design.mainframe.alphafine.model.SearchResult;
import com.fr.design.mainframe.alphafine.search.SearchTextBean;
/** /**
* Created by XiaXiang on 2017/3/27. * Created by XiaXiang on 2017/3/27.
@ -20,4 +21,15 @@ public interface AlphaFineSearchProvider {
* @return * @return
*/ */
SearchResult getMoreSearchResult(String searchText); SearchResult getMoreSearchResult(String searchText);
/**
* 获取所有搜索结果 取决于具体实现
*
* @param searchTextBean
* @return
*/
default SearchResult getSearchResult(SearchTextBean searchTextBean) {
return new SearchResult();
}
} }

7
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ActionSearchManager.java

@ -8,6 +8,7 @@ import com.fr.design.mainframe.alphafine.cell.model.ActionModel;
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel;
import com.fr.design.mainframe.alphafine.cell.model.MoreModel; import com.fr.design.mainframe.alphafine.cell.model.MoreModel;
import com.fr.design.mainframe.alphafine.model.SearchResult; import com.fr.design.mainframe.alphafine.model.SearchResult;
import com.fr.design.mainframe.alphafine.search.SearchTextBean;
import com.fr.design.mainframe.alphafine.search.manager.fun.AlphaFineSearchProvider; import com.fr.design.mainframe.alphafine.search.manager.fun.AlphaFineSearchProvider;
import com.fr.design.mainframe.toolbar.UpdateActionManager; import com.fr.design.mainframe.toolbar.UpdateActionManager;
import com.fr.design.mainframe.toolbar.UpdateActionModel; import com.fr.design.mainframe.toolbar.UpdateActionModel;
@ -101,4 +102,10 @@ public class ActionSearchManager implements AlphaFineSearchProvider {
public SearchResult getMoreSearchResult(String searchText) { public SearchResult getMoreSearchResult(String searchText) {
return moreModelList; return moreModelList;
} }
@Override
public SearchResult getSearchResult(SearchTextBean searchTextBean) {
getLessSearchResult(searchTextBean.getSegmentation());
return filterModelList;
}
} }

13
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/DocumentSearchManager.java

@ -7,6 +7,7 @@ import com.fr.design.mainframe.alphafine.CellType;
import com.fr.design.mainframe.alphafine.cell.model.DocumentModel; import com.fr.design.mainframe.alphafine.cell.model.DocumentModel;
import com.fr.design.mainframe.alphafine.cell.model.MoreModel; import com.fr.design.mainframe.alphafine.cell.model.MoreModel;
import com.fr.design.mainframe.alphafine.model.SearchResult; import com.fr.design.mainframe.alphafine.model.SearchResult;
import com.fr.design.mainframe.alphafine.search.SearchTextBean;
import com.fr.design.mainframe.alphafine.search.manager.fun.AlphaFineSearchProvider; import com.fr.design.mainframe.alphafine.search.manager.fun.AlphaFineSearchProvider;
import com.fr.general.http.HttpToolbox; import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray; import com.fr.json.JSONArray;
@ -15,7 +16,6 @@ import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory; import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils; import com.fr.stable.ArrayUtils;
import java.io.IOException;
/** /**
* Created by XiaXiang on 2017/3/27. * Created by XiaXiang on 2017/3/27.
@ -24,6 +24,7 @@ public class DocumentSearchManager implements AlphaFineSearchProvider {
private static volatile DocumentSearchManager instance; private static volatile DocumentSearchManager instance;
private SearchResult lessModelList; private SearchResult lessModelList;
private SearchResult moreModelList; private SearchResult moreModelList;
private SearchResult searchResult;
public static DocumentSearchManager getInstance() { public static DocumentSearchManager getInstance() {
if (instance == null) { if (instance == null) {
@ -54,6 +55,7 @@ public class DocumentSearchManager implements AlphaFineSearchProvider {
public SearchResult getLessSearchResult(String[] searchText) { public SearchResult getLessSearchResult(String[] searchText) {
lessModelList = new SearchResult(); lessModelList = new SearchResult();
moreModelList = new SearchResult(); moreModelList = new SearchResult();
searchResult = new SearchResult();
if (DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isContainDocument()) { if (DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isContainDocument()) {
if (ArrayUtils.isEmpty(searchText)) { if (ArrayUtils.isEmpty(searchText)) {
lessModelList.add(new MoreModel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help"))); lessModelList.add(new MoreModel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help")));
@ -63,7 +65,7 @@ public class DocumentSearchManager implements AlphaFineSearchProvider {
if(noConnectList != null){ if(noConnectList != null){
return noConnectList; return noConnectList;
} }
SearchResult searchResult = new SearchResult(); searchResult = new SearchResult();
for (int j = 0; j < searchText.length; j++) { for (int j = 0; j < searchText.length; j++) {
String url = AlphaFineConstants.DOCUMENT_SEARCH_URL + searchText[j]; String url = AlphaFineConstants.DOCUMENT_SEARCH_URL + searchText[j];
try { try {
@ -81,6 +83,8 @@ public class DocumentSearchManager implements AlphaFineSearchProvider {
} }
} }
} }
} catch (JSONException jsonException) {
FineLoggerFactory.getLogger().warn(jsonException, jsonException.getMessage());
} catch (Exception e) { } catch (Exception e) {
FineLoggerFactory.getLogger().error("document search error: " + e.getMessage()); FineLoggerFactory.getLogger().error("document search error: " + e.getMessage());
} }
@ -106,4 +110,9 @@ public class DocumentSearchManager implements AlphaFineSearchProvider {
return moreModelList; return moreModelList;
} }
@Override
public SearchResult getSearchResult(SearchTextBean searchTextBean) {
getLessSearchResult(searchTextBean.getSegmentation());
return searchResult;
}
} }

7
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/FileSearchManager.java

@ -9,6 +9,7 @@ import com.fr.design.mainframe.alphafine.CellType;
import com.fr.design.mainframe.alphafine.cell.model.FileModel; import com.fr.design.mainframe.alphafine.cell.model.FileModel;
import com.fr.design.mainframe.alphafine.cell.model.MoreModel; import com.fr.design.mainframe.alphafine.cell.model.MoreModel;
import com.fr.design.mainframe.alphafine.model.SearchResult; import com.fr.design.mainframe.alphafine.model.SearchResult;
import com.fr.design.mainframe.alphafine.search.SearchTextBean;
import com.fr.design.mainframe.alphafine.search.manager.fun.AlphaFineSearchProvider; import com.fr.design.mainframe.alphafine.search.manager.fun.AlphaFineSearchProvider;
import com.fr.file.filetree.FileNode; import com.fr.file.filetree.FileNode;
import com.fr.file.filetree.FileNodes; import com.fr.file.filetree.FileNodes;
@ -114,6 +115,12 @@ public class FileSearchManager implements AlphaFineSearchProvider {
return moreModelList; return moreModelList;
} }
@Override
public SearchResult getSearchResult(SearchTextBean searchTextBean) {
getLessSearchResult(searchTextBean.getSearchText(), searchTextBean.getSegmentation());
return filterModelList;
}
private void doSearch(String searchText) { private void doSearch(String searchText) {
if (DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isContainTemplate()) { if (DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isContainTemplate()) {
for (FileNode node : fileNodes) { for (FileNode node : fileNodes) {

11
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/PluginSearchManager.java

@ -7,6 +7,7 @@ import com.fr.design.mainframe.alphafine.CellType;
import com.fr.design.mainframe.alphafine.cell.model.MoreModel; import com.fr.design.mainframe.alphafine.cell.model.MoreModel;
import com.fr.design.mainframe.alphafine.cell.model.PluginModel; import com.fr.design.mainframe.alphafine.cell.model.PluginModel;
import com.fr.design.mainframe.alphafine.model.SearchResult; import com.fr.design.mainframe.alphafine.model.SearchResult;
import com.fr.design.mainframe.alphafine.search.SearchTextBean;
import com.fr.design.mainframe.alphafine.search.manager.fun.AlphaFineSearchProvider; import com.fr.design.mainframe.alphafine.search.manager.fun.AlphaFineSearchProvider;
import com.fr.general.ComparatorUtils; import com.fr.general.ComparatorUtils;
import com.fr.general.http.HttpToolbox; import com.fr.general.http.HttpToolbox;
@ -28,6 +29,7 @@ import java.net.URLEncoder;
public class PluginSearchManager implements AlphaFineSearchProvider { public class PluginSearchManager implements AlphaFineSearchProvider {
private SearchResult lessModelList; private SearchResult lessModelList;
private SearchResult moreModelList; private SearchResult moreModelList;
private SearchResult searchResult;
private PluginSearchManager() { private PluginSearchManager() {
@ -97,7 +99,7 @@ public class PluginSearchManager implements AlphaFineSearchProvider {
public SearchResult getLessSearchResult(String[] searchText) { public SearchResult getLessSearchResult(String[] searchText) {
this.lessModelList = new SearchResult(); this.lessModelList = new SearchResult();
this.moreModelList = new SearchResult(); this.moreModelList = new SearchResult();
SearchResult searchResult = new SearchResult(); this.searchResult = new SearchResult();
if (DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isContainPlugin()) { if (DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isContainPlugin()) {
if (ArrayUtils.isEmpty(searchText)) { if (ArrayUtils.isEmpty(searchText)) {
lessModelList.add(new MoreModel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon"))); lessModelList.add(new MoreModel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon")));
@ -146,4 +148,11 @@ public class PluginSearchManager implements AlphaFineSearchProvider {
public SearchResult getMoreSearchResult(String searchText) { public SearchResult getMoreSearchResult(String searchText) {
return this.moreModelList; return this.moreModelList;
} }
@Override
public SearchResult getSearchResult(SearchTextBean searchTextBean) {
getLessSearchResult(searchTextBean.getSegmentation());
return searchResult;
}
} }

2
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/group_new.svg

@ -1,4 +1,4 @@
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.9794 8.01574C32.1473 8.63412 31.1164 9 30 9C27.2386 9 25 6.76142 25 4C25 3.15756 25.2083 2.36378 25.5763 1.66737C23.2735 0.597339 20.7065 0 18 0C8.05887 0 0 8.05887 0 18C0 27.9411 8.05887 36 18 36C27.9411 36 36 27.9411 36 18C36 14.3065 34.8875 10.8728 32.9794 8.01574ZM18.1874 10C19.6551 10 20.8185 10.3972 21.7062 11.2167C22.5658 12.0066 23 13.095 23 14.46C23 15.483 22.7055 16.3837 22.1198 17.1565C21.8802 17.444 21.2511 18.0441 20.3133 18.8752C19.8557 19.2704 19.533 19.6504 19.3154 20.042C19.0497 20.4917 18.9221 20.9866 18.9221 21.5577V22.0647L18.7384 22.2483H16.975L16.7913 22.0647V21.5577C16.7913 20.8039 16.9292 20.1376 17.2053 19.5623C17.5279 18.8711 18.2717 18.0163 19.4682 16.9531C19.9441 16.4772 20.096 16.3188 20.2041 16.1747C20.6219 15.6525 20.8251 15.119 20.8251 14.5481C20.8251 13.7278 20.5868 13.0854 20.1267 12.6253C19.6672 12.1457 18.9969 11.9104 18.0992 11.9104C17.0461 11.9104 16.29 12.2425 15.7969 12.9202C15.3385 13.5036 15.1087 14.3027 15.1087 15.3417L14.9251 15.5253H13.1837L13 15.3417C13 13.7383 13.4434 12.465 14.3483 11.5149C15.2669 10.5045 16.5511 10 18.1874 10ZM18.9571 23.8527C18.6667 23.5624 18.2962 23.4242 17.8573 23.4242C17.4239 23.4242 17.0725 23.5598 16.7796 23.8527C16.4894 24.1185 16.3511 24.4706 16.3511 24.9084C16.3511 25.3419 16.4867 25.6932 16.7796 25.9861C17.0907 26.2715 17.4454 26.4146 17.8573 26.4146C18.2693 26.4146 18.6239 26.2715 18.9293 25.9916C19.2344 25.7119 19.3856 25.3529 19.3856 24.9084C19.3856 24.4919 19.2388 24.1345 18.9571 23.8527Z" fill="#419BF9"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M32.9794 8.01574C32.1473 8.63412 31.1164 9 30 9C27.2386 9 25 6.76142 25 4C25 3.15756 25.2083 2.36378 25.5763 1.66737C23.2735 0.597339 20.7065 0 18 0C8.05887 0 0 8.05887 0 18C0 27.9411 8.05887 36 18 36C27.9411 36 36 27.9411 36 18C36 14.3065 34.8875 10.8728 32.9794 8.01574Z" fill="#419BF9"/>
<circle cx="30" cy="4" r="4" fill="#EB1D1F"/> <circle cx="30" cy="4" r="4" fill="#EB1D1F"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 489 B

Loading…
Cancel
Save