Browse Source

REPORT-75093 运营产品化二期

提交release10
security/10.0
Link.Zhao 2 years ago
parent
commit
3f3fe2de5b
  1. 41
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java
  2. 166
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java
  3. 5
      designer-base/src/main/java/com/fr/design/dialog/UIDialog.java
  4. 107
      designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java
  5. 194
      designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java
  6. 80
      designer-base/src/main/java/com/fr/design/utils/LinkStrUtils.java
  7. 22
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineConstants.java
  8. 18
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/CellType.java
  9. 99
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/action/StartUseAction.java
  10. 14
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/cell/model/DocumentModel.java
  11. 334
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineFrame.java
  12. 21
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsList.java
  13. 74
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/RecommendSearchPane.java
  14. 82
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/TemplateResourceImagePanel.java
  15. 226
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/TemplateResourcePageGridPane.java
  16. 128
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/TemplateResourcePanel.java
  17. 10
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketConstants.java
  18. 149
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketDownloadManager.java
  19. 47
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/ProductNews.java
  20. 222
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/TemplateResource.java
  21. 239
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/TemplateResourceDetail.java
  22. 233
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateResourceDetailPane.java
  23. 189
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateShopPane.java
  24. 108
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/TemplateResourceSearchWorkerManager.java
  25. 347
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java
  26. 64
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ProductNewsSearchManager.java
  27. 102
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/TemplateResourceSearchManager.java
  28. 67
      designer-realize/src/main/java/com/fr/market/key/FineMarketDefaultKeyProperties.java
  29. 29
      designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyConstants.java
  30. 48
      designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyHolder.java
  31. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bottom.svg
  32. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bottom_disable.svg
  33. 5
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/caution.svg
  34. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/config.svg
  35. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/down.svg
  36. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/down_disable.svg
  37. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/loading.svg
  38. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_template1.png
  39. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_template2.png
  40. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_template3.png
  41. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_template4.png
  42. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/more.png
  43. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/next.svg
  44. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/prev.svg
  45. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/top.svg
  46. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/top_disable.svg
  47. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/up.svg
  48. 3
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/up_disable.svg
  49. 110
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/template_resource/local_templates.json
  50. 1
      designer-realize/src/main/resources/com/fr/market/key/76c1/default
  51. 1
      designer-realize/src/main/resources/com/fr/market/key/943f/default
  52. 1
      designer-realize/src/main/resources/com/fr/market/key/d8a3/default

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

@ -10,18 +10,16 @@ import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.KeyStroke;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
/**
* AlphaFine配置类
@ -54,13 +52,17 @@ public class AlphaFineConfigManager implements XMLable {
*/
private boolean containRecommend = true;
/**
* 设置
* 功能
*/
private boolean containAction = true;
/**
* 帮助文档
*/
private boolean containDocument = true;
/**
* 我的模板
* */
private boolean containMyTemplate = true;
/**
* 模板
*/
@ -70,7 +72,7 @@ public class AlphaFineConfigManager implements XMLable {
*/
private boolean containFileContent;
/**
* 应用中心
* 插件中心
*/
private boolean containPlugin = true;
/**
@ -95,6 +97,11 @@ public class AlphaFineConfigManager implements XMLable {
*/
private boolean productDynamics = true;
/**
* 模板商城是否展示
* */
private boolean showTemplateShop = true;
private Map<String, String> actionSearchTextCache = new HashMap<>(8);
private String cacheBuildNO;
@ -326,6 +333,14 @@ public class AlphaFineConfigManager implements XMLable {
this.containDocument = containDocument;
}
public void setContainMyTemplate(boolean containMyTemplate) {
this.containMyTemplate = containMyTemplate;
}
public boolean isContainMyTemplate() {
return containMyTemplate;
}
public boolean isContainTemplate() {
return containTemplate;
}
@ -446,6 +461,14 @@ public class AlphaFineConfigManager implements XMLable {
return productDynamics && FRContext.isChineseEnv();
}
public boolean hasTemplateShop() {
return showTemplateShop && FRContext.isChineseEnv();
}
public void setShowTemplateShop(boolean showTemplateShop) {
this.showTemplateShop = showTemplateShop;
}
public void setProductDynamics(boolean productDynamics) {
this.productDynamics = productDynamics;
}

166
designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java

@ -1,17 +1,29 @@
package com.fr.design.actions.help.alphafine;
import com.fr.base.FRContext;
import com.fr.base.svg.IconUtils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.log.FineLoggerFactory;
import javax.swing.*;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
@ -25,14 +37,22 @@ import java.awt.event.MouseEvent;
public class AlphaFineConfigPane extends BasicPane {
private static final String TYPE = "pressed";
private static final String DISPLAY_TYPE = "+";
private static final Color LABEL_TEXT = new Color(0x919193);
private static final double COLUMN_GAP = 180;
private static final double ROW_GAP = 25;
private static final double COLUMN_WIDTH = 150;
private static final double ROW_HEIGHT = 25;
private KeyStroke shortCutKeyStore = null;
private UICheckBox enabledCheckbox, searchOnlineCheckbox, needSegmentationCheckbox, needIntelligentCustomerService, productDynamicsCheckbox, containActionCheckbox, containDocumentCheckbox, containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox;
private UICheckBox enabledCheckbox, searchOnlineCheckbox, needSegmentationCheckbox;
private UICheckBox productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox,
containPluginCheckbox, containActionCheckbox, containMyTemplateCheckbox;
private UITextField shortcutsField;
// 搜索范围-我的模板,相关组件
private JPanel containMyTemplatePane;
private JButton myTemplateSearchConfigButton;
private UIPopupMenu myTemplateSearchMenu;
private UICheckBox containTemplateNameSearchCheckbox, containFileContentSearchCheckbox;
public AlphaFineConfigPane() {
this.initComponents();
}
@ -45,15 +65,6 @@ public class AlphaFineConfigPane extends BasicPane {
createSearchConfigPane(contentPane);
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.add(contentPane, BorderLayout.NORTH);
}
private Component[][] initSearchRangeComponents() {
Component[][] components = new Component[][]{
new Component[]{productDynamicsCheckbox, containActionCheckbox, containDocumentCheckbox},
new Component[]{containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox},
};
return components;
}
private Component[][] initOnlineComponents() {
@ -63,24 +74,99 @@ public class AlphaFineConfigPane extends BasicPane {
return components;
}
// 搜索范围
private void createSearchConfigPane(JPanel contentPane) {
double[] rowSize = {ROW_GAP, ROW_GAP, ROW_GAP};
double[] columnSize = {COLUMN_GAP, COLUMN_GAP, COLUMN_GAP};
double[] rowSize = {ROW_HEIGHT, ROW_HEIGHT, ROW_HEIGHT};
double[] columnSize = {COLUMN_WIDTH, COLUMN_WIDTH, COLUMN_WIDTH};
JPanel northPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Search_Range"));
productDynamicsCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_Dynamics"));
containActionCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Set"));
productDynamicsCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_News"));
containActionCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Function"));
containPluginCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon"));
containDocumentCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help"));
containTemplateCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Templates"));
containFileContentCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Templates_Content"));
needIntelligentCustomerService = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Intelligent_Customer_Service"));
containMyTemplateCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_My_Templates"));
containFileContentSearchCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Templates_Content"));
containTemplateShopCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Shop"));
containMyTemplateCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_My_Templates"));
JPanel searchConfigPane = TableLayoutHelper.createTableLayoutPane(initSearchRangeComponents(), rowSize, columnSize);
northPane.add(searchConfigPane);
contentPane.add(northPane);
}
private Component[][] initSearchRangeComponents() {
// 我的模板checkbox设置,点击后
initMyTemplateSearchPane();
Component[][] components = new Component[][]{
new Component[]{productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox},
new Component[]{containPluginCheckbox, containActionCheckbox, containMyTemplatePane},
};
for (int i = 0; i < components.length; i++) {
for (int j = 0; j < components[i].length; j++) {
if (components[i][j] instanceof UICheckBox) {
UICheckBox box = (UICheckBox) components[i][j];
}
}
}
return components;
}
/**
* 搜索范围中的复选框有无选中的
* */
private boolean hasSelectedSearchRangeCheckBox() {
return productDynamicsCheckbox.isSelected() || containTemplateShopCheckbox.isSelected() || containDocumentCheckbox.isSelected()
|| containPluginCheckbox.isSelected() || containActionCheckbox.isSelected() || containMyTemplateCheckbox.isSelected();
}
// 搜索范围-我的模板
private void initMyTemplateSearchPane() {
containMyTemplatePane = new JPanel(new FlowLayout(FlowLayout.LEFT,4,5));
containMyTemplateCheckbox.setBorder(BorderFactory.createEmptyBorder());
containMyTemplateCheckbox.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (containMyTemplateCheckbox.isSelected()) {
myTemplateSearchConfigButton.setVisible(true);
} else {
myTemplateSearchConfigButton.setVisible(false);
}
}
}
);
myTemplateSearchConfigButton = new JButton();
myTemplateSearchConfigButton.setBorder(BorderFactory.createEmptyBorder());
myTemplateSearchConfigButton.setMargin(new Insets(0,0,0,0));
myTemplateSearchConfigButton.setIcon(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/config.svg"));
myTemplateSearchMenu = new UIPopupMenu();
containTemplateNameSearchCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_AlphaFine_Config_Name_Search"));
containFileContentSearchCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_AlphaFine_Config_Content_Search"));
containTemplateNameSearchCheckbox.setSelected(true);
containTemplateNameSearchCheckbox.setEnabled(false);
containTemplateNameSearchCheckbox.setBackground(null);
containFileContentSearchCheckbox.setBackground(null);
myTemplateSearchMenu.add(containTemplateNameSearchCheckbox);
myTemplateSearchMenu.add(containFileContentSearchCheckbox);
myTemplateSearchConfigButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
GUICoreUtils.showPopupMenu(myTemplateSearchMenu, containMyTemplatePane, containMyTemplateCheckbox.getWidth(), containMyTemplatePane.getY());
}
@Override
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
myTemplateSearchMenu.setVisible(false);
}
});
containMyTemplatePane.add("containMyTemplateCheckbox", containMyTemplateCheckbox);
containMyTemplatePane.add("myTemplateSearchConfigButton", myTemplateSearchConfigButton);
}
private void createShortcutsPane(JPanel contentPane) {
JPanel northPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Shortcut_Config"));
shortcutsField = new UITextField();
@ -91,7 +177,7 @@ public class AlphaFineConfigPane extends BasicPane {
northPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Open") + ":"));
northPane.add(shortcutsField);
UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_SetShortcuts"));
label.setForeground(Color.RED);
label.setForeground(LABEL_TEXT);
northPane.add(label);
contentPane.add(northPane);
}
@ -130,21 +216,21 @@ public class AlphaFineConfigPane extends BasicPane {
productDynamicsCheckbox.setEnabled(false);
containPluginCheckbox.setEnabled(false);
containDocumentCheckbox.setEnabled(false);
needIntelligentCustomerService.setEnabled(false);
containTemplateShopCheckbox.setEnabled(false);
productDynamicsCheckbox.setSelected(false);
containPluginCheckbox.setSelected(false);
containDocumentCheckbox.setSelected(false);
needIntelligentCustomerService.setSelected(false);
containTemplateShopCheckbox.setSelected(false);
} else {
productDynamicsCheckbox.setEnabled(true);
containPluginCheckbox.setEnabled(true);
containDocumentCheckbox.setEnabled(true);
needIntelligentCustomerService.setEnabled(true);
containTemplateShopCheckbox.setEnabled(true);
}
}
});
double[] rowSize = {ROW_GAP};
double[] columnSize = {COLUMN_GAP, COLUMN_GAP, COLUMN_GAP};
double[] rowSize = {ROW_HEIGHT};
double[] columnSize = {COLUMN_WIDTH, COLUMN_WIDTH, COLUMN_WIDTH};
JPanel onlinePane = TableLayoutHelper.createTableLayoutPane(initOnlineComponents(), rowSize, columnSize);
northPane.add(onlinePane);
contentPane.add(northPane);
@ -172,8 +258,10 @@ public class AlphaFineConfigPane extends BasicPane {
this.searchOnlineCheckbox.setSelected(enabled4Locale);
this.containActionCheckbox.setSelected(alphaFineConfigManager.isContainAction());
this.containTemplateCheckbox.setSelected(alphaFineConfigManager.isContainTemplate());
this.containFileContentCheckbox.setSelected(alphaFineConfigManager.isContainFileContent());
this.containMyTemplateCheckbox.setSelected(alphaFineConfigManager.isContainMyTemplate());
this.myTemplateSearchConfigButton.setVisible(alphaFineConfigManager.isContainMyTemplate());
this.containFileContentSearchCheckbox.setSelected(alphaFineConfigManager.isContainFileContent());
this.containDocumentCheckbox.setSelected(alphaFineConfigManager.isContainDocument() && enabled4Locale);
this.containDocumentCheckbox.setEnabled(enabled4Locale);
@ -184,13 +272,13 @@ public class AlphaFineConfigPane extends BasicPane {
this.productDynamicsCheckbox.setSelected(alphaFineConfigManager.isProductDynamics() && enabled4Locale);
this.productDynamicsCheckbox.setEnabled(enabled4Locale);
this.containTemplateShopCheckbox.setSelected(alphaFineConfigManager.hasTemplateShop() && enabled4Locale);
this.containTemplateShopCheckbox.setEnabled(enabled4Locale);
this.shortcutsField.setText(AlphaFineShortCutUtil.getDisplayShortCut(alphaFineConfigManager.getShortcuts()));
this.needSegmentationCheckbox.setSelected(alphaFineConfigManager.isNeedSegmentationCheckbox());
this.needIntelligentCustomerService.setSelected(alphaFineConfigManager.isNeedIntelligentCustomerService() && enabled4Locale);
this.needIntelligentCustomerService.setEnabled(enabled4Locale);
shortCutKeyStore = convert2KeyStroke(alphaFineConfigManager.getShortcuts());
}
@ -201,12 +289,12 @@ public class AlphaFineConfigPane extends BasicPane {
alphaFineConfigManager.setContainAction(this.containActionCheckbox.isSelected());
alphaFineConfigManager.setContainDocument(this.containDocumentCheckbox.isSelected());
alphaFineConfigManager.setProductDynamics(this.productDynamicsCheckbox.isSelected());
alphaFineConfigManager.setShowTemplateShop(this.containTemplateShopCheckbox.isSelected());
alphaFineConfigManager.setEnabled(this.enabledCheckbox.isSelected());
alphaFineConfigManager.setSearchOnLine(this.searchOnlineCheckbox.isSelected());
alphaFineConfigManager.setContainTemplate(this.containTemplateCheckbox.isSelected());
alphaFineConfigManager.setContainFileContent(this.containFileContentCheckbox.isSelected());
alphaFineConfigManager.setContainMyTemplate(this.containMyTemplateCheckbox.isSelected());
alphaFineConfigManager.setContainFileContent(this.containFileContentSearchCheckbox.isSelected());
alphaFineConfigManager.setNeedSegmentationCheckbox(this.needSegmentationCheckbox.isSelected());
alphaFineConfigManager.setNeedIntelligentCustomerService(this.needIntelligentCustomerService.isSelected());
alphaFineConfigManager.setShortcuts(shortCutKeyStore != null ? shortCutKeyStore.toString().replace(TYPE, DISPLAY_TYPE) : this.shortcutsField.getText());
designerEnvManager.setAlphaFineConfigManager(alphaFineConfigManager);
try {
@ -233,10 +321,10 @@ public class AlphaFineConfigPane extends BasicPane {
}
public UICheckBox getIsContainFileContentCheckbox() {
return containFileContentCheckbox;
return containFileContentSearchCheckbox;
}
public void setIsContainFileContentCheckbox(UICheckBox isContainFileContentCheckbox) {
this.containFileContentCheckbox = isContainFileContentCheckbox;
this.containFileContentSearchCheckbox = isContainFileContentCheckbox;
}
}

5
designer-base/src/main/java/com/fr/design/dialog/UIDialog.java

@ -18,6 +18,7 @@ import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
@ -43,6 +44,10 @@ public abstract class UIDialog extends JDialog {
super(parent);
}
public UIDialog(Window parent) {
super(parent);
}
public UIDialog(Frame parent, BasicPane pane) {
this(parent, pane, true);

107
designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java

@ -1,16 +1,18 @@
package com.fr.design.dialog.link;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.utils.LinkStrUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import javax.swing.JEditorPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Font;
import java.net.URI;
import java.net.URL;
import static com.fr.design.utils.LinkStrUtils.LABEL;
/**
* 用来构建JOptionPane带超链的消息提示
@ -21,8 +23,32 @@ import java.net.URI;
*/
public class MessageWithLink extends JEditorPane {
private static final UILabel LABEL = new UILabel();
private static final String HTML_BODY = "<body";
private static final String HTML_STYLE_FORMAT = " style=\"%s\"";
/**
* 直接放入 html 内容
* 如果有超链接标签 <a href=""></a> 的话将会自动点击匹配 url
*
* @param htmlText html内容
*/
public MessageWithLink(String htmlText) {
super("text/html", htmlText);
initListener();
setEditable(false);
setBorder(null);
}
public MessageWithLink(String htmlText, Runnable action) {
super("text/html", htmlText);
initListener(action);
setEditable(false);
setBorder(null);
}
public MessageWithLink(String message, String linkName, String link) {
this(message, linkName, link, LABEL.getBackground(), LABEL.getFont());
@ -48,37 +74,74 @@ public class MessageWithLink extends JEditorPane {
this(frontMessage, linkName, link, backMessage, color, font, LABEL.getForeground());
}
public MessageWithLink(String htmlText, Font font) {
this(setHtmlFont(htmlText, font));
}
/**
* 将指定的字体赋给html文本
* 任何失败返回原html文本
* */
private static String setHtmlFont(String htmlText, Font font) {
try {
int bodyIndex = htmlText.indexOf(HTML_BODY);
StringBuilder sb = new StringBuilder();
String left = htmlText.substring(0, bodyIndex + HTML_BODY.length());
String right = htmlText.substring(bodyIndex + HTML_BODY.length());
sb.append(left);
sb.append(String.format(HTML_STYLE_FORMAT, LinkStrUtils.generateStyle(Color.WHITE, font, Color.BLACK)));
sb.append(right);
return sb.toString();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
return htmlText;
}
public MessageWithLink(String frontMessage, String linkName, String link, String backMessage, Color backgroundColor, Font font, Color fontColor) {
super("text/html", "<html><body style=\"" + generateStyle(backgroundColor, font, fontColor) + "\">" + frontMessage + "<a href=\"" + link + "\">" + linkName + "</a>" + backMessage + "</body></html>");
super("text/html", "<html><body style=\"" + LinkStrUtils.generateStyle(backgroundColor, font, fontColor) + "\">" + frontMessage + "<a href=\"" + link + "\">" + linkName + "</a>" + backMessage + "</body></html>");
initListener(link);
setEditable(false);
setBorder(null);
}
protected void initListener(String link) {
addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
try {
Desktop.getDesktop().browse(URI.create(link));
} catch (Exception exception) {
FineLoggerFactory.getLogger().error(exception.getMessage(), exception);
}
protected void initListener() {
addHyperlinkListener(hyperlinkEvent -> {
try {
if (hyperlinkEvent.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
URL url = hyperlinkEvent.getURL();
Desktop.getDesktop().browse(url.toURI());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
});
}
private static StringBuilder generateStyle(Color backgroundColor, Font font, Color fontColor) {
// 构建相同风格样式
StringBuilder style = new StringBuilder("font-family:" + font.getFamily() + ";");
style.append("font-weight:").append(font.isBold() ? "bold" : "normal").append(";");
style.append("font-size:").append(font.getSize()).append("pt;");
style.append("color:rgb(").append(fontColor.getRed()).append(",").append(fontColor.getGreen()).append(",").append(fontColor.getBlue()).append(");");
style.append("background-color: rgb(").append(backgroundColor.getRed()).append(",").append(backgroundColor.getGreen()).append(",").append(backgroundColor.getBlue()).append(");");
protected void initListener(Runnable runnable) {
return style;
addHyperlinkListener(e -> {
if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
runnable.run();
}
});
}
protected void initListener(String link) {
initListener(() -> {
try {
Desktop.getDesktop().browse(URI.create(link));
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
});
}
}

194
designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java

@ -0,0 +1,194 @@
package com.fr.design.mainframe.toast;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.dialog.UIDialog;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.module.ModuleContext;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Window;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* toast弹窗
* */
public class SimpleToast extends UIDialog {
private static final int MIN_HEIGHT = 36;
private static final String TOAST_MSG_TIMER = "TOAST_MSG_TIMER";
private static final long DEFAULT_DISAPPEAR_DELAY = 5000;
private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
private ScheduledExecutorService timer;
private int hideHeight = 0;
private JPanel contentPane;
private boolean show = false;
private Window parent;
private boolean autoDisappear;
public SimpleToast(Window parent, Icon icon, String text, boolean autoDisappear) {
super(parent);
this.parent = parent;
this.autoDisappear = autoDisappear;
JPanel panel = createContentPane(icon, text);
init(panel);
}
private JPanel createContentPane(Icon icon, String text) {
JPanel pane = FRGUIPaneFactory.createBorderLayout_S_Pane();
UILabel iconLabel = new UILabel(icon);
iconLabel.setVerticalAlignment(SwingConstants.TOP);
iconLabel.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));
UILabel textLabel = new UILabel(text);
pane.add(iconLabel, BorderLayout.WEST);
pane.add(textLabel, BorderLayout.CENTER);
pane.setBorder(BorderFactory.createEmptyBorder(8, 15, 8, 15));
return pane;
}
private void init(JPanel panel) {
setFocusable(false);
setAutoRequestFocus(false);
setUndecorated(true);
contentPane = panel;
initComponent();
}
private void initComponent() {
this.getContentPane().setLayout(null);
this.getContentPane().add(contentPane);
Dimension dimension = calculatePreferSize();
hideHeight = dimension.height;
setSize(new Dimension(dimension.width, 0));
contentPane.setSize(dimension);
setRelativeLocation(dimension);
if (autoDisappear) {
disappear(contentPane);
}
}
private void setRelativeLocation(Dimension dimension) {
int positionX = parent.getLocationOnScreen().x + (parent.getWidth() - dimension.width) / 2;
int positionY = parent.getLocationOnScreen().y + 10;
this.setLocation(positionX, positionY);
}
private Dimension calculatePreferSize() {
Dimension contentDimension = contentPane.getPreferredSize();
int height = Math.max(MIN_HEIGHT, contentDimension.height);
return new Dimension(contentDimension.width, height);
}
public void display(JPanel outerPanel) {
show = true;
outerPanel.setLocation(0, -hideHeight);
ScheduledExecutorService tipToolTimer = createToastScheduleExecutorService();
tipToolTimer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(()->{
displayStep(outerPanel, tipToolTimer);
});
}
}, 0, 50, TimeUnit.MILLISECONDS);
}
void displayStep(JPanel outerPanel, ScheduledExecutorService timer) {
Point point = outerPanel.getLocation();
if (point.y >= 0 && !timer.isShutdown()) {
timer.shutdown();
}
int showDistance = 5 + point.y < 0 ? 5 : -point.y;
outerPanel.setLocation(point.x, point.y + showDistance);
Dimension dimension = SimpleToast.this.getSize();
SimpleToast.this.setSize(new Dimension(dimension.width, dimension.height + showDistance));
}
private void disappear(JPanel outerPanel, long delay, TimeUnit timeUnit) {
timer = createToastScheduleExecutorService();
timer.schedule(new DisappearMotion(outerPanel), delay, timeUnit);
}
/**
* toast消失的动画效果
* */
class DisappearMotion implements Runnable {
JPanel panel;
DisappearMotion(JPanel panel) {
this.panel = panel;
}
@Override
public void run() {
ScheduledExecutorService tipToolTimer = createToastScheduleExecutorService();
tipToolTimer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(()->{
disappearStep(tipToolTimer);
});
}
}, 0, 50, TimeUnit.MILLISECONDS);
}
void disappearStep(ScheduledExecutorService timer) {
Point point = panel.getLocation();
if (point.y <= -hideHeight && !timer.isShutdown()) {
timer.shutdown();
SimpleToast.this.setVisible(false);
SimpleToast.this.dispose();
SimpleToast.this.show = false;
}
panel.setLocation(point.x, point.y - 5);
Dimension dimension = SimpleToast.this.getSize();
SimpleToast.this.setSize(new Dimension(dimension.width, dimension.height - 5));
}
}
private void disappear(JPanel outerPanel) {
disappear(outerPanel, DEFAULT_DISAPPEAR_DELAY, DEFAULT_TIME_UNIT);
}
private ScheduledExecutorService createToastScheduleExecutorService() {
return ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory(TOAST_MSG_TIMER));
}
@Override
public void checkValid() throws Exception {
}
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
display(contentPane);
}
}
@Override
public void dispose() {
super.dispose();
}
}

80
designer-base/src/main/java/com/fr/design/utils/LinkStrUtils.java

@ -0,0 +1,80 @@
package com.fr.design.utils;
import com.fr.design.gui.ilable.UILabel;
import com.fr.stable.StringUtils;
import javax.swing.JComponent;
import java.awt.Color;
import java.awt.Font;
/**
* created by Harrison on 2022/05/24
**/
public class LinkStrUtils {
public static final UILabel LABEL = new UILabel();
public static UILabel generateLabel(String html, JComponent templateLabel) {
String style = generateStyle(templateLabel.getBackground(), templateLabel.getFont(), templateLabel.getForeground());
String fullHtml = generateHtmlTag(style, html);
return new UILabel(fullHtml);
}
public static String generateHtmlTag(String html) {
String defaultStyle = generateDefaultStyle();
return generateHtmlTag(defaultStyle, html);
}
public static String generateHtmlTag(String style, String html) {
if (StringUtils.isEmpty(style)) {
throw new NullPointerException("style");
}
if (StringUtils.isEmpty(html)) {
throw new NullPointerException("html");
}
return "<html><body style=\"" + style + "\">" + html + "</body></html>";
}
public static String generateLinkTag(String link, String text) {
return "<a href=\"" + link + "\">" + text + "</a>";
}
public static String generateLinkTagWithoutUnderLine(String link, String text) {
return "<a style=\"text-decoration:none;\" href=\"" + link + "\">" + text + "</a>";
}
public static String generateStyle(Color backgroundColor, Font font, Color fontColor) {
// 构建相同风格样式
StringBuilder style = new StringBuilder("font-family:" + font.getFamily() + ";");
style.append("font-weight:").append(font.isBold() ? "bold" : "normal").append(";");
style.append("font-size:").append(font.getSize()).append("pt;");
style.append("color:rgb(").append(fontColor.getRed()).append(",").append(fontColor.getGreen()).append(",").append(fontColor.getBlue()).append(");");
style.append("background-color: rgb(").append(backgroundColor.getRed()).append(",").append(backgroundColor.getGreen()).append(",").append(backgroundColor.getBlue()).append(");");
return style.toString();
}
public static String generateStyle(Font font, Color fontColor) {
// 构建相同风格样式
StringBuilder style = new StringBuilder("font-family:" + font.getFamily() + ";");
style.append("font-weight:").append(font.isBold() ? "bold" : "normal").append(";");
style.append("font-size:").append(font.getSize()).append("pt;");
style.append("color:rgb(").append(fontColor.getRed()).append(",").append(fontColor.getGreen()).append(",").append(fontColor.getBlue()).append(");");
return style.toString();
}
public static String generateDefaultStyle() {
return generateStyle(LABEL.getBackground(), LABEL.getFont(), LABEL.getForeground());
}
}

22
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineConstants.java

@ -5,8 +5,9 @@ import com.fr.base.svg.IconUtils;
import com.fr.design.i18n.Toolkit;
import com.fr.design.utils.DesignUtils;
import com.fr.general.CloudCenter;
import com.fr.general.IOUtils;
import javax.swing.Icon;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
@ -14,7 +15,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.swing.Icon;
/**
@ -81,6 +81,8 @@ public class AlphaFineConstants {
public static final Color WHITE = new Color(0xf9f9f9);
public static final Color LABEL_SELECTED = new Color(0x419bf9);
public static final Color GRAY = new Color(0xd2d2d2);
public static final Color LIGHT_GRAY = new Color(0xcccccc);
@ -154,9 +156,21 @@ public class AlphaFineConstants {
public static final String ALPHA_PREVIEW = CloudCenter.getInstance().acquireUrlByKind("af.preview");
public static final String ALPHA_CID = CloudCenter.getInstance().acquireUrlByKind("af.cid", "https://cid.fanruan.com/api/nav/alphafine");
public static final String ALPHA_CID = CloudCenter.getInstance().acquireUrlByKind("af.cid.new");
public static final String ALPHA_CID_USER_GROUP_INFO = CloudCenter.getInstance().acquireUrlByKind("af.cid.user.group.info");
public static final String SEARCH_BY_ID = "?id=";
private static final String QUICK_START_URL = CloudCenter.getInstance().acquireUrlByKind("af.help.quick.start");
private static final String REPORT_LEARNING_PATH = CloudCenter.getInstance().acquireUrlByKind("af.help.report.learning.path");
private static final String PARAMETER_LEARNING_PATH = CloudCenter.getInstance().acquireUrlByKind("af.help.param.learning.path");
private static final String FILL_LEARNING_PATH = CloudCenter.getInstance().acquireUrlByKind("af.help.fill.learning.path");
private static final String API_SUMMARY = CloudCenter.getInstance().acquireUrlByKind("af.help.api.summary");
private static final String MONTHLY_DOCUMENT = CloudCenter.getInstance().acquireUrlByKind("af.help.monthly.document");
private static final String DEFAULT_RECOMMEND = "[ { \"name\":\"快速入门指南\", \"link\":\"https://help.fanruan.com/finereport/doc-view-1335.html?source=3\" }, { \"name\":\"报表应用学习路径\", \"link\":\"https://help.fanruan.com/finereport/doc-view-1336.html?source=3\" }, { \"name\":\"参数应用学习路径\", \"link\":\"https://help.fanruan.com/finereport/doc-view-4219.html?source=3\" }, { \"name\":\"填报学习路径\", \"link\":\"https://help.fanruan.com/finereport/doc-view-4103.html?source=3\" }, { \"name\":\"API接口汇总\", \"link\":\"https://help.fanruan.com/finereport/doc-view-4327.html?source=3\" }, { \"name\":\"文档月刊\", \"link\":\"https://help.fanruan.com/finereport/doc-view-4613.html?source=3\" } ]";
private static final String DEFAULT_RECOMMEND = "[ { \"name\":\"快速入门指南\", \"link\":\"" + QUICK_START_URL + "\" }, { \"name\":\"报表应用学习路径\", \"link\":\"" + REPORT_LEARNING_PATH + "\" }, { \"name\":\"参数应用学习路径\", \"link\":\"" + PARAMETER_LEARNING_PATH + "\" }, { \"name\":\"填报学习路径\", \"link\":\"" + FILL_LEARNING_PATH + "\" }, { \"name\":\"API接口汇总\", \"link\":\"" + API_SUMMARY + "\" }, { \"name\":\"文档月刊\", \"link\":\"" + MONTHLY_DOCUMENT + "\" } ]";
public static final String ALPHA_HELP_RECOMMEND = CloudCenter.getInstance().acquireUrlByKind("af.recommend", DEFAULT_RECOMMEND);

18
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/CellType.java

@ -17,7 +17,8 @@ public enum CellType {
RECOMMEND_ROBOT(8),
BOTTOM(9),
ROBOT(10),
PRODUCT_NEWS(11, "productNews", "productNewsResult", true);
PRODUCT_NEWS(11, "productNews", "productNewsResult", true, false),
TEMPLATE_SHOP(12, "templateShop", "templateShop", false, true);
private int typeValue;
@ -35,11 +36,19 @@ public enum CellType {
private boolean needNetWork = true;
CellType(int type, String flagStr4None, String flagStr4Result, boolean needNetWork) {
private boolean canLocalSearch = false;
CellType(int type, String flagStr4None, String flagStr4Result, boolean needNetWork, boolean canLocalSearch) {
this.typeValue = type;
this.flagStr4None = flagStr4None;
this.flagStr4Result = flagStr4Result;
this.needNetWork = needNetWork;
this.canLocalSearch = canLocalSearch;
}
CellType(int type, String flagStr4None, String flagStr4Result, boolean needNetWork) {
this(type, flagStr4None, flagStr4Result, needNetWork, false);
}
CellType(int type) {
@ -75,5 +84,8 @@ public enum CellType {
public boolean isNeedNetWork() {
return needNetWork;
}
}
public boolean isCanLocalSearch() {
return canLocalSearch;
}
}

99
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/action/StartUseAction.java

@ -0,0 +1,99 @@
package com.fr.design.mainframe.alphafine.action;
import com.fr.common.util.Strings;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.download.FineMarketConstants;
import com.fr.design.mainframe.alphafine.download.FineMarketDownloadManager;
import com.fr.design.mainframe.alphafine.model.TemplateResourceDetail;
import com.fr.file.FileFILE;
import com.fr.log.FineLoggerFactory;
import javax.swing.SwingWorker;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
/**
* alphaFine - 模板资源 - 二级界面 - 开始使用按钮的绑定事件
*
* 点击后跳转至帆软市场下载对应模板资源
*
* TODO:可以参考mini组件商城的下载@ComponentsPackageInstallation#install
* */
public class StartUseAction implements ActionListener {
TemplateResourceDetail resourceDetail;
public StartUseAction(TemplateResourceDetail detail) {
this.resourceDetail = detail;
}
@Override
public void actionPerformed(ActionEvent e) {
new SwingWorker<String, Void>() {
@Override
protected String doInBackground() throws Exception {
return FineMarketDownloadManager.getInstance().installResource(resourceDetail.getRoot(), AlphaFineHelper.getAlphaFineDialog());
}
@Override
protected void done() {
try {
open(get());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
super.done();
}
}.execute();
}
/**
* 打开模板并打开文件目录
* */
void open(String fileName) throws IOException {
if (Strings.isEmpty(fileName)) {
return;
}
// 打开模板
openInDesigner(fileName);
// 打开系统文件夹
File parentDir = new File(fileName).getParentFile();
Desktop.getDesktop().open(parentDir);
}
void openInDesigner(String fileName) {
File fileNeedOpen = new File(fileName);
if (fileName.endsWith(FineMarketConstants.ZIP)) {
File[] files = fileNeedOpen.getParentFile().listFiles();
fileNeedOpen = getFirstCptOrFrm(files);
} else if (fileName.endsWith(FineMarketConstants.RAR)) {
// rar资源没有解压,所以不用打开模板
return;
}
// 打开模板
if (fileNeedOpen == null) {
//有可能压缩包解压出来还是压缩包
FineLoggerFactory.getLogger().error("AlphaFine open resource error: " + fileName);
} else {
DesignerContext.getDesignerFrame().openTemplate(new FileFILE(fileNeedOpen));
}
}
private File getFirstCptOrFrm(File[] files) {
for (File f : files) {
if (f.getName().endsWith(FineMarketConstants.CPT) || f.getName().endsWith(FineMarketConstants.FRM)) {
return f;
}
}
return null;
}
}

14
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/cell/model/DocumentModel.java

@ -2,11 +2,10 @@ package com.fr.design.mainframe.alphafine.cell.model;
import com.fr.design.mainframe.alphafine.AlphaFineConstants;
import com.fr.design.mainframe.alphafine.CellType;
import com.fr.log.FineLoggerFactory;
import com.fr.json.JSONException;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import java.awt.*;
import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
@ -60,8 +59,15 @@ public class DocumentModel extends AlphaCellModel {
@Override
public void doAction() {
openInBrowser(getDocumentUrl());
}
/**
* 方便埋点
* */
void openInBrowser(String url) {
try {
Desktop.getDesktop().browse(new URI(getDocumentUrl()));
Desktop.getDesktop().browse(new URI(url));
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (URISyntaxException e) {

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

@ -22,20 +22,34 @@ import com.fr.design.mainframe.alphafine.preview.NoResultPane;
import com.fr.design.mainframe.alphafine.preview.NoResultWithLinkPane;
import com.fr.design.mainframe.alphafine.preview.SearchLoadingPane;
import com.fr.design.mainframe.alphafine.preview.SimpleRightSearchResultPane;
import com.fr.design.mainframe.alphafine.preview.TemplateShopPane;
import com.fr.design.mainframe.alphafine.question.QuestionWindow;
import com.fr.design.mainframe.alphafine.search.ProductNewsSearchWorkerManager;
import com.fr.design.mainframe.alphafine.search.SearchTextBean;
import com.fr.design.mainframe.alphafine.search.SearchWorkerManager;
import com.fr.design.mainframe.alphafine.search.TemplateResourceSearchWorkerManager;
import com.fr.design.mainframe.alphafine.search.manager.impl.ActionSearchManager;
import com.fr.design.mainframe.alphafine.search.manager.impl.DocumentSearchManager;
import com.fr.design.mainframe.alphafine.search.manager.impl.FileSearchManager;
import com.fr.design.mainframe.alphafine.search.manager.impl.PluginSearchManager;
import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager;
import com.fr.design.mainframe.alphafine.search.manager.impl.SegmentationManager;
import com.fr.design.mainframe.alphafine.search.manager.impl.TemplateResourceSearchManager;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
@ -62,16 +76,6 @@ import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
/**
* @author hades
@ -98,7 +102,7 @@ public class AlphaFineFrame extends JFrame {
private static final String PLACE_HOLDER = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine");
private static final String SETTING = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Set");
private static final String FUNCTION = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Function");
private static final String NO_RESULT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_No_Result");
@ -110,7 +114,7 @@ public class AlphaFineFrame extends JFrame {
private static final String GO_FORUM = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Go_Forum");
private static final String TEMPLATES = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Templates");
private static final String MY_TEMPLATES = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_My_Templates");
public static final String PRODUCT_NEWS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_News");
@ -122,7 +126,7 @@ public class AlphaFineFrame extends JFrame {
private static final String NO_SEARCH_RESULT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_NO_Result");
private static final String PRODUCT_DYNAMICS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_Dynamics");
private static final String TEMPLATE_SHOP = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Shop");
private static final Image SEARCH_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/search.svg");
@ -152,7 +156,19 @@ public class AlphaFineFrame extends JFrame {
private JPanel tabPane;
private CellType selectedType;
private JPanel labelPane;
private JPanel labelContentPane;
private JPanel labelEastPane;
private JPanel labelWestPane;
private UILabel tabLabel;
private UILabel readLabel;
private SelectedLabel selectedTab;
private String beforeSearchStr = StringUtils.EMPTY;
@ -168,15 +184,38 @@ public class AlphaFineFrame extends JFrame {
private ProductNewsSearchWorkerManager productNewsSearchWorkerManager;
private TemplateResourceSearchWorkerManager templateResourceSearchWorkerManager;
public AlphaFineFrame() {
this.setTitle(AlphaFineConstants.TITLE);
//去掉边框
setUndecorated(true);
setSize(AlphaFineConstants.FIELD_SIZE);
setSize(AlphaFineConstants.FULL_SIZE);
initComponents();
centerWindow(this);
initSearchManager();
}
public void showResult(String flag) {
cardLayout.show(resultPane, flag);
}
public void addResult(JPanel panel, String flag) {
resultPane.add(panel, flag);
}
public void removeSearchResultPane(JPanel panel) {
resultPane.remove(panel);
}
public String getSearchText() {
return searchTextField.getText();
}
public CellType getSelectedType() {
return selectedTab.getCellType();
}
private void initSearchManager() {
this.productNewsSearchWorkerManager = new ProductNewsSearchWorkerManager(
@ -213,20 +252,26 @@ public class AlphaFineFrame extends JFrame {
new LoadingRightSearchResultPane()
);
templateResourceSearchWorkerManager = new TemplateResourceSearchWorkerManager(
CellType.TEMPLATE_SHOP,
searchTextBean -> {
return TemplateResourceSearchManager.getInstance().getSearchResult(searchTextBean.getSearchText());
},
this
);
}
/**
* 初始化全部组件
*/
private void initComponents() {
add(createTopPane(), BorderLayout.NORTH);
initSearchTextField();
add(createSearchPane(), BorderLayout.CENTER);
add(createShowPane(), BorderLayout.SOUTH);
this.getContentPane().setBackground(Color.WHITE);
this.setIconImage(SEARCH_IMAGE);
this.setSize(AlphaFineConstants.FULL_SIZE);
this.setIconImage(SEARCH_IMAGE); // 应用图标
}
private JPanel createTopPane() {
@ -289,7 +334,6 @@ public class AlphaFineFrame extends JFrame {
}
};
private JPopupMenu createTipPop() {
JPanel panel = new JPanel(new BorderLayout());
String toolTip = AlphaFineShortCutUtil.getDisplayShortCut(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Short_Cut", DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getShortcuts()));
@ -305,7 +349,7 @@ public class AlphaFineFrame extends JFrame {
popupMenu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
// do nothing
// do nothing
}
@Override
@ -372,29 +416,35 @@ public class AlphaFineFrame extends JFrame {
return searchPane;
}
/**
* showPane,内容展示区分为三个小区tab区label区内容区
* */
private JPanel createShowPane() {
JPanel showPane = new JPanel(new BorderLayout());
// 内容区,card layout
resultPane.add(new DefaultProductNewsPane(), CellType.PRODUCT_NEWS.getFlagStr4None());
resultPane.add(new NoResultWithLinkPane(GO_FORUM, AlphaFineConstants.NO_RESULT_ICON), CellType.NO_RESULT.getFlagStr4None());
resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.ACTION.getFlagStr4None());
resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.FILE.getFlagStr4None());
resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.PLUGIN.getFlagStr4None());
resultPane.add(new HelpDocumentNoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.DOCUMENT.getFlagStr4None());
resultPane.add(TemplateShopPane.getInstance(), CellType.TEMPLATE_SHOP.getFlagStr4None());
resultPane.add(new NetWorkFailedPane(this::reSearch), AlphaFineConstants.NETWORK_ERROR);
JPanel labelPane = new JPanel(new BorderLayout());
// label区,border layout
labelPane = new JPanel(new BorderLayout());
labelPane.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 20));
labelPane.setBackground(Color.WHITE);
JPanel labelContentPane = new JPanel(new BorderLayout());
UILabel tabLabel = new UILabel(PRODUCT_DYNAMICS);
tabLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6);
tabLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
tabLabel.setPreferredSize(new Dimension(100, 30));
JPanel westPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
westPane.add(tabLabel);
labelContentPane.add(westPane, BorderLayout.WEST);
JPanel eastPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
UILabel readLabel = new UILabel(ONE_CLICK_READ);
labelContentPane = new JPanel(new BorderLayout());
tabLabel = createTabLabel(PRODUCT_NEWS);
labelWestPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
labelWestPane.add(tabLabel);
labelContentPane.add(labelWestPane, BorderLayout.WEST);
labelEastPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
// 一键已读
readLabel = new UILabel(ONE_CLICK_READ);
readLabel.setHorizontalAlignment(SwingConstants.RIGHT);
readLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));;
readLabel.setPreferredSize(new Dimension(100, 30));
@ -406,24 +456,30 @@ public class AlphaFineFrame extends JFrame {
showPane.repaint();
}
});
eastPane.add(readLabel);
labelContentPane.add(eastPane, BorderLayout.EAST);
labelEastPane.add(readLabel);
labelContentPane.add(labelEastPane, BorderLayout.EAST);
labelContentPane.setBackground(new Color(245, 245, 247));
labelPane.add(labelContentPane);
labelPane.setPreferredSize(new Dimension(AlphaFineConstants.FULL_SIZE.width, 30));
// tab区 flow layout
tabPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 10));
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());
selectedTab = null;
for (SelectedLabel label : selectedLabelList) {
if (label.isSelected()) {
selectedTab = label;
break;
}
}
if (this.selectedTab.getCellType() != CellType.PRODUCT_NEWS) {
tabLabel.setText(this.selectedTab.getText());
readLabel.setVisible(false);
}
for (SelectedLabel selectedLabel : selectedLabelList) {
selectedLabel.addMouseListener(createMouseListener(selectedLabelList, selectedLabel, tabPane, tabLabel, readLabel));
tabPane.add(selectedLabel);
for (SelectedLabel label : selectedLabelList) {
label.addMouseListener(createMouseListener(selectedLabelList, label, tabPane, tabLabel, readLabel));
tabPane.add(label);
}
showPane.add(tabPane, BorderLayout.NORTH);
showPane.add(labelPane, BorderLayout.CENTER);
@ -431,46 +487,55 @@ public class AlphaFineFrame extends JFrame {
return showPane;
}
private UILabel createTabLabel(String labelName) {
UILabel label = new UILabel(labelName);
label.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
label.setPreferredSize(new Dimension(60, 30));
label.setForeground(AlphaFineConstants.LABEL_SELECTED);
return label;
}
public JPanel getLabelWestPane() {
return labelWestPane;
}
public UILabel getTabLabel() {
return tabLabel;
}
private MouseAdapter createMouseListener(List<SelectedLabel> selectedLabelList, SelectedLabel selectedLabel,
JPanel tabPane, UILabel tabLabel, UILabel readLabel) {
return new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// tab栏里的label全设置为没选中,并设置颜色为灰色
for (SelectedLabel label : selectedLabelList) {
label.setSelected(false);
label.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8);
}
// 选中
selectedLabel.setSelected(true);
AlphaFineFrame.this.selectedTab = selectedLabel;
// 处理产品动态 tab与下方文字展示不一致
if (ComparatorUtils.equals(selectedLabel.getText().trim(), PRODUCT_NEWS)) {
tabLabel.setText(PRODUCT_DYNAMICS);
tabLabel.setText(PRODUCT_NEWS);
} else {
tabLabel.setText(selectedLabel.getText());
}
// 刷新westlabelpane
refreshLabelPane();
// 将已读设置不可见
readLabel.setVisible(false);
// tab栏重新绘制
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;
}
// 选中事件
switchTab(selectedLabel.getCellType(), readLabel);
if (currentSearchWorkerManager != null) {
AlphaFineList alphaFineList = currentSearchWorkerManager.getSearchResultList();
if (alphaFineList != null) {
@ -494,17 +559,51 @@ public class AlphaFineFrame extends JFrame {
};
}
// 方便记埋点
private void switchTab(CellType cellType, UILabel readLabel) {
switch (cellType) {
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;
case TEMPLATE_SHOP:
TemplateShopPane.getInstance().showResult();
switchType(CellType.TEMPLATE_SHOP);
break;
}
}
private void refreshLabelPane() {
labelWestPane.removeAll();
tabLabel.setForeground(AlphaFineConstants.LABEL_SELECTED);
labelWestPane.add(tabLabel);
}
private List<SelectedLabel> createSelectedLabelList() {
List<SelectedLabel> selectedLabelList = new ArrayList<>();
AlphaFineConfigManager alphaFineConfigManager = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager();
if (alphaFineConfigManager.isProductDynamics()) {
selectedLabelList.add(new SelectedLabel(PRODUCT_NEWS, CellType.PRODUCT_NEWS, true));
}
if (alphaFineConfigManager.isContainAction()) {
selectedLabelList.add(new SelectedLabel(SETTING, CellType.ACTION));
selectedLabelList.add(new SelectedLabel(PRODUCT_NEWS, CellType.PRODUCT_NEWS));
}
if (alphaFineConfigManager.isContainFileContent() || alphaFineConfigManager.isContainTemplate()) {
selectedLabelList.add(new SelectedLabel(TEMPLATES, CellType.FILE));
if (alphaFineConfigManager.hasTemplateShop()) {
selectedLabelList.add(new SelectedLabel(TEMPLATE_SHOP, CellType.TEMPLATE_SHOP));
}
if (alphaFineConfigManager.isContainDocument()) {
selectedLabelList.add(new SelectedLabel(HELP, CellType.DOCUMENT));
@ -512,6 +611,19 @@ public class AlphaFineFrame extends JFrame {
if (alphaFineConfigManager.isContainPlugin()) {
selectedLabelList.add(new SelectedLabel(PLUGIN, CellType.PLUGIN));
}
if (alphaFineConfigManager.isContainAction()) {
selectedLabelList.add(new SelectedLabel(FUNCTION, CellType.ACTION));
}
if (alphaFineConfigManager.isContainMyTemplate()) {
selectedLabelList.add(new SelectedLabel(MY_TEMPLATES, CellType.FILE));
}
// 默认选中第一个tab
if (!selectedLabelList.isEmpty()) {
selectedLabelList.get(0).setSelected(true);
}
return selectedLabelList;
}
@ -524,7 +636,6 @@ public class AlphaFineFrame extends JFrame {
}
private void switchType(CellType cellType) {
this.selectedType = cellType;
if (StringUtils.isEmpty(searchTextField.getText())) {
cardLayout.show(resultPane, cellType.getFlagStr4None());
} else {
@ -541,8 +652,7 @@ public class AlphaFineFrame extends JFrame {
if (checkNetworkError()) {
return;
}
cardLayout.show(resultPane, cellType.getFlagStr4Result());
showResult(cellType.getFlagStr4Result());
checkSearchResult();
}
@ -550,23 +660,27 @@ public class AlphaFineFrame extends JFrame {
private boolean checkNetworkError() {
boolean networkError;
if (selectedType == CellType.PRODUCT_NEWS) {
if (selectedTab.getCellType() == CellType.PRODUCT_NEWS) {
networkError = productNewsSearchWorkerManager.isNetWorkError();
} else if (selectedTab.getCellType() == CellType.TEMPLATE_SHOP) {
networkError = templateResourceSearchWorkerManager.isNetWorkError();
} else {
networkError = currentSearchWorkerManager.isNetWorkError();
}
cardLayout.show(resultPane, AlphaFineConstants.NETWORK_ERROR);
showResult(AlphaFineConstants.NETWORK_ERROR);
return networkError;
}
private boolean checkSearchLoading() {
boolean searchOver;
if (selectedType == CellType.PRODUCT_NEWS) {
if (selectedTab.getCellType() == CellType.PRODUCT_NEWS) {
searchOver = productNewsSearchWorkerManager.isSearchOver();
} else if (selectedTab.getCellType() == CellType.TEMPLATE_SHOP) {
searchOver = templateResourceSearchWorkerManager.isSearchOver();
} else {
searchOver = currentSearchWorkerManager.isSearchOver();
}
cardLayout.show(resultPane, AlphaFineConstants.LOADING);
showResult(AlphaFineConstants.LOADING);
return searchOver;
}
@ -586,17 +700,20 @@ public class AlphaFineFrame extends JFrame {
if (searchResultList != null) {
searchResultList.requestFocus();
}
boolean hasSearchResult = true;
if (selectedType == CellType.PRODUCT_NEWS) {
hasSearchResult = productNewsSearchWorkerManager.hasSearchResult();
} else {
hasSearchResult = currentSearchWorkerManager.hasSearchResult();
}
if (!hasSearchResult) {
cardLayout.show(resultPane, CellType.NO_RESULT.getFlagStr4None());
if (!hasSearchResult()) {
showResult(CellType.NO_RESULT.getFlagStr4None());
}
}
private boolean hasSearchResult() {
if (selectedTab.getCellType() == CellType.PRODUCT_NEWS) {
return productNewsSearchWorkerManager.hasSearchResult();
} else if (selectedTab.getCellType() == CellType.TEMPLATE_SHOP) {
return templateResourceSearchWorkerManager.hasSearchResult();
} else {
return currentSearchWorkerManager.hasSearchResult();
}
}
private void initSearchTextField() {
@ -608,7 +725,6 @@ public class AlphaFineFrame extends JFrame {
searchTextField.setBorder(null);
}
private void initTextFieldListener() {
searchTextField.addKeyListener(new KeyAdapter() {
@Override
@ -659,20 +775,24 @@ public class AlphaFineFrame extends JFrame {
}
/**
* 控制搜索tip框弹出收起
* 不断地刷新tab页并防止tab页显示错误
* */
private void startSearchTextFieldTimer() {
Timer timer = new Timer(TIMER_DELAY, e -> {
// 坑 isShowing返回false 即使textField有内容 getText返回的也是空
if (searchTextField.isShowing() && StringUtils.isEmpty(searchTextField.getText())) {
SearchTooltipPopup.getInstance().hide();
clearLabel.setVisible(false);
switchType(selectedType);
switchType(selectedTab.getCellType());
TemplateShopPane.getInstance().quitSearchResultPane();
beforeSearchStr = StringUtils.EMPTY;
} else if (searchTextField.hasFocus()) {
clearLabel.setVisible(true);
SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane);
}
tabPane.repaint();
});
timer.start();
}
@ -751,21 +871,8 @@ public class AlphaFineFrame extends JFrame {
}
}
public void showResult(String flag) {
cardLayout.show(resultPane, flag);
}
public void addResult(JPanel panel, String flag) {
resultPane.add(panel, flag);
}
public void removeSearchResultPane(JPanel panel) {
resultPane.remove(panel);
}
private void doSearch(String text) {
refreshLabelPane();
initSearchLoadingPane();
SearchTextBean searchTextBean = generateSearchTextBean(text);
this.productNewsSearchWorkerManager.doSearch(searchTextBean);
@ -773,6 +880,7 @@ public class AlphaFineFrame extends JFrame {
this.fileSearchWorkerManager.doSearch(searchTextBean);
this.documentWorkerManager.doSearch(searchTextBean);
this.pluginSearchWorkerManager.doSearch(searchTextBean);
this.templateResourceSearchWorkerManager.doSearch(searchTextBean);
}
private SearchTextBean generateSearchTextBean(String searchText) {
@ -806,25 +914,15 @@ public class AlphaFineFrame extends JFrame {
this.pluginSearchWorkerManager.doSearch(searchTextBean);
}
/**
* 所有tab页搜索通用的加载panel
* */
private void initSearchLoadingPane() {
if (searchLoadingPane == null) {
searchLoadingPane = new SearchLoadingPane();
}
resultPane.add(searchLoadingPane, AlphaFineConstants.LOADING);
cardLayout.show(resultPane, AlphaFineConstants.LOADING);
}
public String getSearchText() {
return searchTextField.getText();
}
public CellType getSelectedType() {
return selectedType;
}
public void setStoreText(String storeText) {
this.storeText = storeText;
showResult(AlphaFineConstants.LOADING);
}
/**
@ -839,6 +937,9 @@ public class AlphaFineFrame extends JFrame {
return storeText;
}
public void setStoreText(String storeText) {
this.storeText = storeText;
}
/**
* 去除特殊字符空格等
@ -894,6 +995,7 @@ public class AlphaFineFrame extends JFrame {
@Override
public void setVisible(boolean b) {
super.setVisible(b);
switchTab(selectedTab.getCellType(), readLabel);
QuestionWindow.getInstance().setVisible(!b);
if (!b) {
AlphaFineHelper.resetAlphaFineDialog();
@ -907,4 +1009,4 @@ public class AlphaFineFrame extends JFrame {
QuestionWindow.getInstance().setVisible(true);
}
}
}

21
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsList.java

@ -4,18 +4,16 @@ import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.alphafine.AlphaFineConstants;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.model.ProductNews;
import com.fr.log.FineLoggerFactory;
import com.fr.design.utils.BrowseUtils;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListModel;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.net.URI;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListModel;
/**
* @author hades
@ -63,15 +61,16 @@ public class ProductNewsList extends JList<ProductNews> {
private void dealWithClick() {
ProductNews productNews = getSelectedValue();
try {
Desktop.getDesktop().browse(new URI(productNews.getUrl()));
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
openNewsInBrowser(productNews.getUrl());
DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet().add(productNews.getId());
AlphaFineHelper.getAlphaFineDialog().repaint();
}
// 方便埋点
private void openNewsInBrowser(String url) {
BrowseUtils.browser(url);
}
public int getHoverIndex() {
return hoverIndex;
}

74
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/RecommendSearchPane.java

@ -0,0 +1,74 @@
package com.fr.design.mainframe.alphafine.component;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
public class RecommendSearchPane extends TemplateResourcePanel {
private static final Color BORDER_WHITE = new Color(0xe8e8e9);
private static final Color RECOMMEND_SEARCH_KEY_BLUE = new Color(0x419bf9);
public RecommendSearchPane(TemplateResource templateResource) {
super();
setTemplateResource(templateResource);
initComponent();
this.setLayout(new BorderLayout());
this.setBorder(BorderFactory.createLineBorder(BORDER_WHITE, 1));
this.add(getNorthPane(), BorderLayout.NORTH);
this.add(getCenterPane(), BorderLayout.CENTER);
}
private void initComponent() {
createNorthPane();
createCenterPane();
}
private void createCenterPane() {
setCenterPane(new JPanel(new FlowLayout(FlowLayout.LEFT)));
JPanel centerPane = getCenterPane();
centerPane.setBackground(Color.WHITE);
JLabel recommend = new JLabel(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Recommend_For_You"));
centerPane.add(recommend);
List<String> searchKeys = getTemplateResource().getRecommendSearchKey();
for (String key : searchKeys) {
JLabel keyLabel = new SearchKeyLabel(key);
centerPane.add(keyLabel);
}
}
class SearchKeyLabel extends JLabel {
String searchKey;
SearchKeyLabel(String searchKey) {
this.searchKey = searchKey;
setText(searchKey);
setBackground(Color.WHITE);
setForeground(RECOMMEND_SEARCH_KEY_BLUE);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
AlphaFineHelper.getAlphaFineDialog().fireSearch(searchKey);
}
});
}
}
}

82
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/TemplateResourceImagePanel.java

@ -0,0 +1,82 @@
package com.fr.design.mainframe.alphafine.component;
import com.fr.base.GraphHelper;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import com.fr.design.utils.DesignUtils;
import com.fr.general.FRFont;
import com.fr.third.jodd.util.StringUtil;
import javax.swing.JPanel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
public class TemplateResourceImagePanel extends JPanel {
private static final int BACKGROUND_HEIGHT = 20;
private static final Color BACKGROUND_COLOR = new Color(0x419BF9);
private static final Font TAG_FONT = DesignUtils.getDefaultGUIFont().applySize(12);
private static final Color COVER_COLOR = new Color(116, 181, 249, 26);
private TemplateResource templateResource;
private int width = 200;
private int height = 100;
public TemplateResourceImagePanel(TemplateResource templateResource) {
this.templateResource = templateResource;
}
public TemplateResourceImagePanel(TemplateResource templateResource, int width, int height) {
this(templateResource);
this.width = width;
this.height = height;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Color defaultColor = g2.getColor();
Image image = templateResource.getImage();
if (image != null) {
g2.drawImage(templateResource.getImage(), 0, 0, getWidth(), getHeight(), this);
} else {
g2.setColor(COVER_COLOR);
g2.fillRect(0, 0, getWidth(), getHeight());
}
String tagName = templateResource.getType().getName();
if (!StringUtil.isEmpty(tagName)) {
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, .8f));
g2.setColor(BACKGROUND_COLOR);
g2.fillRect(0, getHeight() - BACKGROUND_HEIGHT, getWidth(), BACKGROUND_HEIGHT);
g2.setColor(Color.WHITE);
int x = (getWidth() - GraphHelper.getWidth(tagName, g2.getFont())) / 2;
g2.setFont(TAG_FONT);
g2.drawString(tagName, x, getHeight() - 5);
}
g2.setColor(defaultColor);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
}

226
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/TemplateResourcePageGridPane.java

@ -0,0 +1,226 @@
package com.fr.design.mainframe.alphafine.component;
import com.fr.base.svg.IconUtils;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Label;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 卡片布局每个卡片里塞了scrollpanel
* */
public class TemplateResourcePageGridPane extends JPanel {
private List<TemplateResource> data;
private CardLayout cardLayout;
private List<Page> pages;
private int totalPage;
List<UIScrollPane> scrollPanes = new ArrayList<>();
private static final int PAGE_MAX_SIZE = 12;
private static final int TABLE_MAX_ROW_COUNT = 4;
private static final int TABLE_COL_COUNT = 3;
private static final int TABLE_VGAP = 15;
private static final int TABLE_HGAP = 15;
private static final int RESOURCE_WIDTH = 197;
private static final int RESOURCE_HEIGHT = 128;
public TemplateResourcePageGridPane(List<TemplateResource> templateResourceList) {
this.data = templateResourceList;
totalPage = (int) Math.ceil((double)data.size() / PAGE_MAX_SIZE);
createPages();
initComponents();
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 20));
switchPage(1);
}
private void initComponents() {
cardLayout = new CardLayout();
this.setLayout(cardLayout);
this.setBackground(Color.WHITE);
for (int i = 0; i < pages.size(); i++) {
UIScrollPane scrollPane = new UIScrollPane(pages.get(i));
scrollPanes.add(scrollPane);
this.add(scrollPane, String.valueOf(i + 1));
}
}
/**
* 构建分页将资源切分到每一页并在每一页尾部添加分页按钮
* */
private void createPages() {
int dataCnt = data.size();
List<TemplateResource>[] slice = new ArrayList[totalPage];
for (int i = 0; i < dataCnt; i++) {
int index = i / PAGE_MAX_SIZE;
if (slice[index] == null) {
slice[index] = new ArrayList<>();
}
slice[index].add(data.get(i));
}
pages = new ArrayList<>();
for (int i = 0; i < totalPage; i++) {
pages.add(new Page(slice[i], i + 1));
}
}
private void switchPage(int pageNumber) {
if (pageNumber < 1 || pageNumber > this.totalPage) {
return;
}
cardLayout.show(TemplateResourcePageGridPane.this, String.valueOf(pageNumber));
scrollPanes.get(pageNumber - 1).getVerticalScrollBar().setValue(0);
// 坑,切换页面会刷新失败,需要手动滚动一下才能刷新
scrollPanes.get(pageNumber - 1).getVerticalScrollBar().setValue(1);
scrollPanes.get(pageNumber - 1).getVerticalScrollBar().setValue(0);
}
/**
* 分页panelborderlayout布局north为信息页south为分页按钮区
* */
private class Page extends JPanel {
List<TemplateResource> pageData;
Component[][] comps;
JPanel contentPane;
JPanel pageButtonPane;
JButton prev, next;
JTextField pageNumberField;
JLabel pageCnt;
int pageNumber;
Page(List<TemplateResource> pageData, int pageNumber) {
super();
this.pageData = pageData;
this.pageNumber = pageNumber;
initComponents();
this.setLayout(new BorderLayout());
this.add(contentPane, BorderLayout.NORTH);
if (totalPage > 1) {
this.add(pageButtonPane, BorderLayout.SOUTH);
}
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createEmptyBorder());
}
private void initComponents() {
createContentPane();
createPageButtonPane();
}
void createContentPane() {
int dataCnt = pageData.size();
int rowCnt = (int) Math.ceil((double)dataCnt / 3);
double[] rowHeight = new double[rowCnt];
double[] colWidth = new double[TABLE_COL_COUNT];
Arrays.fill(rowHeight, RESOURCE_HEIGHT);
Arrays.fill(colWidth, RESOURCE_WIDTH);
comps = new Component[rowCnt][TABLE_COL_COUNT];
for (int i = 0; i < rowCnt; i++) {
for (int j = 0; j < TABLE_COL_COUNT; j++) {
int which = i * 3 + j;
if (which >= dataCnt) {
Label empty = new Label();
empty.setPreferredSize(new Dimension(RESOURCE_WIDTH, RESOURCE_HEIGHT));
empty.setVisible(false);
comps[i][j] = empty;
} else {
TemplateResourcePanel resource = TemplateResourcePanel.create(pageData.get(which));
resource.setPreferredSize(new Dimension(RESOURCE_WIDTH, RESOURCE_HEIGHT));
comps[i][j] = resource;
}
}
}
contentPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowHeight, colWidth, TABLE_HGAP, TABLE_VGAP);
contentPane.setBackground(Color.WHITE);
}
void createPageButtonPane() {
prev = new JButton(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/prev.svg"));
next = new JButton(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/next.svg"));
pageNumberField = new JTextField((int) Math.log10(totalPage) + 1);
pageNumberField.setText(String.valueOf(this.pageNumber));
pageCnt = new JLabel("/ " + totalPage);
pageButtonPane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
pageButtonPane.add(prev);
pageButtonPane.add(pageNumberField);
pageButtonPane.add(pageCnt);
pageButtonPane.add(next);
addPageAction();
}
// 添加翻页按钮事件
void addPageAction() {
addPrevPageAction();
addNextPageAction();
addGotoPageAction();
}
void addPrevPageAction() {
prev.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (pageNumber > 1) {
switchPage(pageNumber - 1);
}
}
});
};
void addNextPageAction() {
next.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (pageNumber < totalPage) {
switchPage(pageNumber + 1);
}
}
});
}
void addGotoPageAction() {
pageNumberField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
String numb = pageNumberField.getText();
if (numb != null && !numb.equals(pageNumber)) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
switchPage(Integer.parseInt(numb));
}
}
}
});
}
}
}

128
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/TemplateResourcePanel.java

@ -0,0 +1,128 @@
package com.fr.design.mainframe.alphafine.component;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import com.fr.design.mainframe.alphafine.preview.TemplateShopPane;
import com.fr.design.utils.BrowseUtils;
import com.fr.design.utils.DesignUtils;
import com.fr.log.FineLoggerFactory;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class TemplateResourcePanel extends JPanel {
private JPanel northPane;
private JPanel centerPane;
private TemplateResource templateResource;
private static final Color PANEL_BORDER_COLOR = new Color(0xe8e8e9);
private static final Color DEMO_LABEL_FOREGROUND = new Color(0x419bf9);
private static final Font RESOURCE_NAME_FONT = DesignUtils.getDefaultGUIFont().applySize(12);
private static final Color RESOURCE_NAME_COLOR = new Color(0x5c5c5d);
protected TemplateResourcePanel() {
}
protected TemplateResourcePanel(TemplateResource templateResource) {
this.templateResource = templateResource;
initComponent();
this.setLayout(new BorderLayout());
this.setBorder(BorderFactory.createLineBorder(PANEL_BORDER_COLOR, 1));
this.add(northPane, BorderLayout.NORTH);
this.add(centerPane, BorderLayout.CENTER);
addAction();
}
private void addAction() {
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
TemplateShopPane.getInstance().searchAndShowDetailPane(templateResource);
}
});
}
public static TemplateResourcePanel create(TemplateResource templateResource) {
if (TemplateResource.Type.RECOMMEND_SEARCH.equals(templateResource.getType())) {
return new RecommendSearchPane(templateResource);
} else {
return new TemplateResourcePanel(templateResource);
}
}
public JPanel getNorthPane() {
return northPane;
}
public JPanel getCenterPane() {
return centerPane;
}
public TemplateResource getTemplateResource() {
return templateResource;
}
public void setNorthPane(JPanel northPane) {
this.northPane = northPane;
}
public void setCenterPane(JPanel centerPane) {
this.centerPane = centerPane;
}
public void setTemplateResource(TemplateResource templateResource) {
this.templateResource = templateResource;
}
private void initComponent() {
createNorthPane();
createCenterPane();
}
protected void createNorthPane() {
northPane = new TemplateResourceImagePanel(templateResource);
}
private void createCenterPane() {
JLabel nameLabel = new JLabel(templateResource.getName());
nameLabel.setFont(RESOURCE_NAME_FONT);
nameLabel.setForeground(RESOURCE_NAME_COLOR);
nameLabel.setBackground(Color.WHITE);
nameLabel.setBorder(BorderFactory.createEmptyBorder());
JLabel demoLabel = new JLabel();
if (templateResource.hasDemoUrl()) {
demoLabel.setText(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Demo"));
demoLabel.setForeground(DEMO_LABEL_FOREGROUND);
demoLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
try {
BrowseUtils.browser(templateResource.getDemoUrl());
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex, ex.getMessage());
}
}
});
}
centerPane = new JPanel(new BorderLayout());
centerPane.setBackground(Color.WHITE);
centerPane.add(nameLabel, BorderLayout.WEST);
centerPane.add(demoLabel, BorderLayout.EAST);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(180, 90);
}
}

10
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketConstants.java

@ -0,0 +1,10 @@
package com.fr.design.mainframe.alphafine.download;
public class FineMarketConstants {
public static final String REPORTLETS = "/reportlets";
public static final String ZIP = ".zip";
public static final String RAR = ".rar";
public static final String CPT = ".cpt";
public static final String FRM = ".frm";
}

149
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketDownloadManager.java

@ -0,0 +1,149 @@
package com.fr.design.mainframe.alphafine.download;
import com.fr.base.svg.IconUtils;
import com.fr.common.util.Strings;
import com.fr.design.DesignerEnvManager;
import com.fr.design.extra.Process;
import com.fr.design.i18n.Toolkit;
import com.fr.design.login.DesignerLoginHelper;
import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import com.fr.design.mainframe.alphafine.search.helper.FineMarketClientHelper;
import com.fr.design.mainframe.toast.SimpleToast;
import com.fr.log.FineLoggerFactory;
import com.fr.third.jodd.io.ZipUtil;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileSystemView;
import java.awt.Window;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
/**
* 在这里统一管理帆软市场的下载
* 下载的流程控制尽量都在这个类内部完成
* 通过Process类来实现下载流程控制
* */
public class FineMarketDownloadManager {
private static final FineMarketDownloadManager INSTANCE = new FineMarketDownloadManager();
public static final FineMarketDownloadManager getInstance() {
return INSTANCE;
}
public static final double PROCESS_SUCCESS = 1d;
public static final double PROCESS_FAILED = -1d;
public static final double OPENING_FILE = 2d;
private static final String OPENING_PLEASE_WAIT = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Opening");
private static final String DOWNLOAD_FAILED = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Download_Failed_Check_Network");
/**
* 下载资源并解压
* */
public String installResource(TemplateResource resource, Window parentWindow){
// 验证登录
String token = DesignerEnvManager.getEnvManager().getDesignerLoginRefreshToken();
if (Strings.isEmpty(token)) {
DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL, new HashMap<>(), AlphaFineHelper.getAlphaFineDialog());
return null;
}
return install(resource, parentWindow);
}
private String install(TemplateResource resource, Window parentWindow) {
// 默认下载到桌面
String workDir = FileSystemView.getFileSystemView().getHomeDirectory().getPath();
File destDir = new File(workDir);
DownloadProcess downloadProcess = new DownloadProcess(parentWindow);
String fileName = null;
try {
fileName = FineMarketClientHelper.getInstance().download(resource, destDir, downloadProcess);
unzip(fileName, downloadProcess);
return fileName;
} catch (Exception e) {
downloadProcess.process(FineMarketDownloadManager.PROCESS_FAILED);
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
return null;
}
void unzip(String fileName, DownloadProcess process) throws IOException {
process.process(OPENING_FILE);
if (fileName.endsWith(FineMarketConstants.ZIP)) {
File file = new File(fileName);
File parentDir = file.getParentFile();
ZipUtil.unzip(file, parentDir);
}
}
/**
* 下载流程控制主要控制ui的显示
* */
class DownloadProcess implements Process<Double> {
SimpleToast downloadingToast;
SimpleToast openingToast;
SimpleToast failedToast;
Window parent;
public DownloadProcess(Window parentWindow) {
this.parent = parentWindow;
init();
}
void init() {
showLoadingToast();
}
@Override
public void process(Double aDouble) {
SwingUtilities.invokeLater(()->{
if (aDouble == PROCESS_FAILED) {
downloadFailed();
} else if (aDouble == PROCESS_SUCCESS) {
downloadSuccess();
} else if (aDouble == OPENING_FILE) {
openingFile();
}
});
}
public void downloadFailed() {
downloadingToast.setVisible(false);
showFailedToast();
}
public void downloadSuccess() {
downloadingToast.setVisible(false);
}
private void openingFile() {
downloadingToast.setVisible(false);
openingToast = new SimpleToast(AlphaFineHelper.getAlphaFineDialog(), IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/loading.svg"), OPENING_PLEASE_WAIT, true);
openingToast.setVisible(true);
}
private void showLoadingToast() {
downloadingToast = new SimpleToast(AlphaFineHelper.getAlphaFineDialog(), IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/loading.svg"), OPENING_PLEASE_WAIT, false);
downloadingToast.setVisible(true);
}
private void showFailedToast() {
failedToast = new SimpleToast(AlphaFineHelper.getAlphaFineDialog(), IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/caution.svg"), DOWNLOAD_FAILED, true);
failedToast.setVisible(true);
}
}
}

47
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/ProductNews.java

@ -1,8 +1,12 @@
package com.fr.design.mainframe.alphafine.model;
import com.fr.design.i18n.Toolkit;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* 产品动态
@ -17,7 +21,9 @@ public class ProductNews {
private String title;
private Tag tag;
private Target target;
// 推送对象,对象为 list<用户组id>
private List<String> target;
private Status status;
private String url;
@ -26,6 +32,8 @@ public class ProductNews {
private Date pushDate;
public static final String ALL_USER_TARGET = "0";
/**
* 创建cid的用户
*/
@ -58,11 +66,11 @@ public class ProductNews {
return this;
}
public Target getTarget() {
public List<String> getTarget() {
return target;
}
public ProductNews setTarget(Target target) {
public ProductNews setTarget(List<String> target) {
this.target = target;
return this;
}
@ -172,29 +180,18 @@ public class ProductNews {
}
}
public enum Target {
ALL_USER(0);
private final int code;
Target(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static Target parseCode(int code) {
for (Target target : values()) {
if (target.code == code) {
return target;
}
}
throw new IllegalArgumentException();
/**
* 将接口中的target字段转换一下
* 原始数据是字符串例如"1,2,3,4"
* 转换为 List<int>{1,2,3,4}
* */
public static List<String> ParseTarget(String s) {
List<String> list = new ArrayList<>();
if (s != null) {
String[] targets = s.split(",");
list.addAll(Arrays.asList(targets));
}
return list;
}
}

222
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/TemplateResource.java

@ -0,0 +1,222 @@
package com.fr.design.mainframe.alphafine.model;
import com.fr.common.util.Strings;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.alphafine.download.FineMarketConstants;
import com.fr.design.mainframe.alphafine.search.manager.impl.TemplateResourceSearchManager;
import com.fr.general.IOUtils;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.third.jodd.util.StringUtil;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
/**
* 模板资源数据
*/
public class TemplateResource {
/***
* 模板资源类型模板解决方案推荐搜索
*/
public enum Type {
SINGLE_TEMPLATE(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Single_Template")),
SCENARIO_SOLUTION(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Scenario_Solution")),
RECOMMEND_SEARCH;
private String name;
Type() {
}
Type(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 模板资源搜索接口返回值字段名
public static final String ID = "id";
public static final String UUID = "uuid";
public static final String NAME = "name";
public static final String IMAGE_URL = "pic";
public static final String DEMO_URL = "demoUrl";
public static final String PKG_SIZE = "pkgsize";
public static final String FILE_NAME = "fileLoca";
private static final String RECOMMEND_SEARCH_IMG_URL = "com/fr/design/mainframe/alphafine/images/more.png";
// 模板资源属性
private String id;
private String uuid;
private Type type;
private String imageUrl;
private Image image;
private String name;
private String demoUrl;
private String fileName;
private int pkgSize;
private List<String> recommendSearchKey;
private boolean embed;
public static List<TemplateResource> createByJson(JSONArray jsonArray) {
List<TemplateResource> list = new ArrayList<>();
if (jsonArray != null) {
for (int i = jsonArray.length() - 1; i >= 0; i--) {
list.add(createByJson(jsonArray.getJSONObject(i)));
}
}
return list;
}
public static TemplateResource createByJson(JSONObject jsonObject) {
TemplateResource templateResource = new TemplateResource().setId(jsonObject.getString(ID)).setUuid(jsonObject.getString(UUID)).setName(jsonObject.getString(NAME))
.setDemoUrl(jsonObject.getString(DEMO_URL)).setPkgSize(jsonObject.getInt(PKG_SIZE)).setFileName(jsonObject.getString(FILE_NAME));
int pkgSize = templateResource.getPkgSize();
if (pkgSize == 0) {
templateResource.type = Type.SINGLE_TEMPLATE;
} else {
templateResource.type = Type.SCENARIO_SOLUTION;
}
templateResource.setImageUrl(parseUrl(jsonObject));
templateResource.setImage(IOUtils.readImage(templateResource.imageUrl));
return templateResource;
}
/**
* 商城接口传过来的图片url是特殊格式需要特殊处理下
* */
static String parseUrl(JSONObject jsonObject) {
String imgUrl = jsonObject.getString(IMAGE_URL);
int index = imgUrl.indexOf(",");
if (index != -1) {
imgUrl = imgUrl.substring(0, imgUrl.indexOf(","));
}
return imgUrl;
}
public static TemplateResource getRecommendSearch() {
TemplateResource recommend = new TemplateResource();
recommend.setType(Type.RECOMMEND_SEARCH);
recommend.setImageUrl(RECOMMEND_SEARCH_IMG_URL);
recommend.setImage(IOUtils.readImage(RECOMMEND_SEARCH_IMG_URL));
recommend.setRecommendSearchKey(TemplateResourceSearchManager.getInstance().getRecommendSearchKeys());
return recommend;
}
public String getFileName() {
return fileName;
}
public TemplateResource setFileName(String fileName) {
if (Strings.isEmpty(fileName)) {
this.fileName = getName() + FineMarketConstants.ZIP;
} else {
this.fileName = fileName;
}
return this;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public List<String> getRecommendSearchKey() {
return recommendSearchKey;
}
public void setRecommendSearchKey(List<String> recommendSearchKey) {
this.recommendSearchKey = recommendSearchKey;
}
public TemplateResource setImage(Image image) {
this.image = image;
return this;
}
public Image getImage() {
return image;
}
public TemplateResource setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
return this;
}
/**
* 判断是否为内置模板资源
* */
public boolean isEmbed() {
return embed;
}
public void setEmbed(boolean embed) {
this.embed = embed;
}
public String getName() {
return name;
}
public TemplateResource setName(String name) {
this.name = name;
return this;
}
public String getDemoUrl() {
return demoUrl;
}
public boolean hasDemoUrl() {
return !StringUtil.isEmpty(demoUrl);
}
public TemplateResource setDemoUrl(String demoUrl) {
this.demoUrl = demoUrl;
return this;
}
public int getPkgSize() {
return pkgSize;
}
public TemplateResource setPkgSize(int pkgSize) {
this.pkgSize = pkgSize;
return this;
}
public String getId() {
return id;
}
public TemplateResource setId(String id) {
this.id = id;
return this;
}
public String getUuid() {
return uuid;
}
public TemplateResource setUuid(String uuid) {
this.uuid = uuid;
return this;
}
}

239
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/TemplateResourceDetail.java

@ -0,0 +1,239 @@
package com.fr.design.mainframe.alphafine.model;
import com.fr.design.mainframe.alphafine.search.helper.FineMarketClientHelper;
import com.fr.design.mainframe.alphafine.search.manager.impl.TemplateResourceSearchManager;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 模板资源详细数据
*/
public class TemplateResourceDetail {
// 与对应的模板资源关联
private final TemplateResource root;
private String info;
private String vendor;
private String htmlText;
private List<String> detailInfo;
private String[] tagsId;
private List<String> tagsName;
private double price;
private String parentPkgName = "";
private String parentPkgUrl;
private String resourceUrl;
public static final String ID = "id";
public static final String INFO = "description";
public static final String VENDOR = "vendor";
public static final String DETAIL_INFO = "text";
public static final String TAGS_ID = "cid";
public static final String PRICE = "price";
public static final String NAME = "name";
public static final String PARENT_NAME = "parentName";
public static final String PARENT_URL = "parentUrl";
public static final String TAGS_NAME = "tagsName";
public static final String URL = "url";
public TemplateResourceDetail(TemplateResource resource) {
this.root = resource;
}
public String getVendor() {
return vendor;
}
public void setVendor(String vendor) {
this.vendor = vendor;
}
public TemplateResource getRoot() {
return root;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public List<String> getDetailInfo() {
return detailInfo;
}
public void setDetailInfo(List<String> detailInfo) {
this.detailInfo = detailInfo;
}
public String[] getTagsId() {
return tagsId;
}
public void setTagsId(String[] tagsId) {
this.tagsId = tagsId;
}
public List<String> getTagsName() {
return tagsName;
}
public String getTagsString() {
StringBuilder sb = new StringBuilder();
if (tagsName != null) {
for (String tag : tagsName) {
sb.append(tag + " ");
}
}
return sb.toString();
}
public void setTagsName(List<String> tagsName) {
this.tagsName = tagsName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getParentPkgName() {
return parentPkgName;
}
public void setParentPkgName(String parentPkgName) {
if (StringUtils.isEmpty(parentPkgName)) {
this.parentPkgName = "";
} else {
this.parentPkgName = parentPkgName;
}
}
public String getResourceUrl() {
return resourceUrl;
}
public void setResourceUrl(String resourceUrl) {
this.resourceUrl = resourceUrl;
}
public String getHtmlText() {
return htmlText;
}
public void setHtmlText(String htmlText) {
this.htmlText = htmlText;
}
public String getParentPkgUrl() {
return parentPkgUrl;
}
public void setParentPkgUrl(String parentPkgUrl) {
this.parentPkgUrl = parentPkgUrl;
}
public static TemplateResourceDetail createByTemplateResource(TemplateResource root) {
return Builder.buildByResource(root);
}
public static TemplateResourceDetail createFromEmbedResource(TemplateResource root) {
return Builder.buildFromEmbedResource(root);
}
static class Builder {
static FineMarketClientHelper helper = FineMarketClientHelper.getInstance();
static TemplateResourceDetail buildFromEmbedResource(TemplateResource templateResource) {
TemplateResourceDetail detail = new TemplateResourceDetail(templateResource);
String resourceId = templateResource.getId();
JSONArray embedResources = TemplateResourceSearchManager.getInstance().getEmbedResourceJSONArray();
for (int i = 0; i < embedResources.length(); i++) {
JSONObject resource = embedResources.getJSONObject(i);
if (resourceId.equals(resource.getString(ID))) {
detail.setInfo(resource.getString(INFO));
detail.setHtmlText(resource.getString(DETAIL_INFO));
detail.setVendor(resource.getString(VENDOR));
detail.setPrice(resource.getDouble(PRICE));
detail.setResourceUrl(resource.getString(URL));
detail.setParentPkgName(resource.getString(PARENT_NAME));
detail.setParentPkgUrl(resource.getString(PARENT_URL));
detail.setTagsName(Arrays.asList(resource.getString(TAGS_NAME).split(",")));
break;
}
}
return detail;
}
static TemplateResourceDetail buildByResource(TemplateResource templateResource) {
TemplateResourceDetail detail = new TemplateResourceDetail(templateResource);
String resourceId = templateResource.getId();
// 获取模板详情页的信息一共需要三次请求
try {
// 1请求详细信息
JSONObject info = helper.getTemplateInfoById(resourceId);
detail.setInfo(info.getString(INFO));
detail.setHtmlText(info.getString(DETAIL_INFO));
detail.setVendor(info.getString(VENDOR));
detail.setTagsId(info.getString(TAGS_ID).split(","));
detail.setPrice(info.getDouble(PRICE));
detail.setResourceUrl(helper.getTemplateUrlById(templateResource.getId()));
// 2请求所属模板包信息
JSONObject parentPkginfo = helper.getTemplateParentPackageByTemplateId(resourceId);
if (parentPkginfo != null) {
detail.setParentPkgName(parentPkginfo.getString(NAME));
detail.setParentPkgUrl(FineMarketClientHelper.getInstance().getTemplateUrlById(parentPkginfo.getString(ID)));
}
// 3请求标签信息
detail.setTagsName(helper.getTemplateTagsByTemplateTagIds(detail.getTagsId()));
return detail;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
return null;
}
/**
* 这里做下数据转换
* 原始数据是html标签写的如下
* "<ol style="list-style-type: decimal;" class=" list-paddingleft-2"><li><p>该模板需用10.0及以上版本设计器预览<br/></p></li><li><p>该模板为库存场景解决方案的部分内容,全部内容可下载<a href="https://market.fanruan.com/template/20000733" target="_self">库存场景解决方案</a>查看</p></li><li><p>为保障模板预览效果,建议安装<a href="https://help.fanruan.com/finereport10.0/doc-view-3665.html" target="_self">新自适应插件</a>(FR11.0版本插件已内置,无需手动安装),有使用需求或疑问,请联系帆软技术支持咨询<br/></p></li></ol>",
*
* 转换的后的数据 是原始数据中所有<p></p>标签内的包括标签的字符串List<String>,如上字符串会转为如下
* List [<p>该模板需用10.0及以上版本设计器预览<br/></p>,
* <p>该模板为库存场景解决方案的部分内容全部内容可下载<a href="https://market.fanruan.com/template/20000733" target="_self">库存场景解决方案</a>查看</p>,
* <p>为保障模板预览效果建议安装<a href="https://help.fanruan.com/finereport10.0/doc-view-3665.html" target="_self">新自适应插件</a>FR11.0版本插件已内置无需手动安装有使用需求或疑问请联系帆软技术支持咨询<br/></p>
* ]
* */
static final Pattern htmlPattern = Pattern.compile("<p>(.+?)</p>");
static List<String> parseDetailInfo(String htmlDetailInfo) {
List<String> infos = new ArrayList<>();
Matcher matcher = htmlPattern.matcher(htmlDetailInfo);
while (matcher.find()) {
infos.add(matcher.group());
}
return infos;
}
}
}

233
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateResourceDetailPane.java

@ -0,0 +1,233 @@
package com.fr.design.mainframe.alphafine.preview;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.link.MessageWithLink;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.alphafine.AlphaFineConstants;
import com.fr.design.mainframe.alphafine.action.StartUseAction;
import com.fr.design.mainframe.alphafine.component.TemplateResourceImagePanel;
import com.fr.design.mainframe.alphafine.model.TemplateResourceDetail;
import com.fr.design.utils.BrowseUtils;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.LinkStrUtils;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class TemplateResourceDetailPane extends JPanel {
private TemplateResourceDetail data;
private TemplateResourceImagePanel imagePane;
private JPanel contentPane;
private UIScrollPane infoScrollPane;
private JPanel operatePane;
private UIScrollPane detailInfoPane;
private static final int IMAGE_HEIGHT = 170;
private static final int IMAGE_WIDTH = 310;
private static final int SCROLL_PANE_WIDTH = 315;
private static final int SCROLL_PANE_HEIGHT = 135;
private static final int CONTENT_PANE_WIDTH = 320;
private static final int CONTENT_PANE_HEIGHT = 180;
private static final int DETAIL_PANE_HEIGHT = 95;
private static final int TEXT_SCROLL_PANE_HEIGHT = 500;
private static final int PANE_WIDTH = 635;
private static final int BUTTON_WIDTH = 68;
private static final int BUTTON_HEIGHT = 20;
private static final String GOTO_DETAIL = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Detail_GOTO_DETAIL");
private static final String START_USE = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Detail_START_USE");
private static final String VENDOR = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Detail_Vendor");
private static final String TAGS = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Detail_Tags");
private static final String PARENT_PACKAGE = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Detail_Parent_Package");
private static final String DETAIL_INFO = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Detail_Info");
private static final String FREE = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Detail_Price_Free");
private static final String SPACE = " ";
private static final String LF = "<br>";
private static final String RMB = "¥";
private static final Color INFO_PANE_BACKGROUND = new Color(0xf9f9f9);
private static final Color INFO_PANE_FOREGROUND = new Color(0x5b5b5c);
private static final Color MORE_INFO_LINK = new Color(0x419bf9);
private static final Font HTML_FONT = DesignUtils.getDefaultGUIFont().applySize(12);
private static final Color HTML_COLOR = new Color(0x5c5c5d);
private static final String HTML_FORMAT = "<html><style>a {color: #419BF9;text-decoration:none;}</style><body style=\"line-height: 20px;"+ LinkStrUtils.generateStyle(HTML_FONT, HTML_COLOR) +"\">%s</body></html>";
private static final String DETAIL_INFO_HTML_FORMAT = "<html><style>a {color: #419BF9;text-decoration:none;}</style><body style=\"line-height: 20px;" + LinkStrUtils.generateStyle(HTML_FONT, HTML_COLOR) + "\"><p>" + DETAIL_INFO + "</p>%s</body></html>";
private static final String HTML_P_TAG_FORMAT = "<p style=\"margin-top:5pt;\">%s</p>";
public TemplateResourceDetailPane(TemplateResourceDetail detail) {
this.data = detail;
initComponent();
this.setLayout(new FlowLayout(FlowLayout.LEFT));
this.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 20));
this.add(imagePane);
this.add(contentPane);
this.add(detailInfoPane);
this.setBackground(Color.WHITE);
SwingUtilities.invokeLater(()->{scrollToTop();});
}
/**
* scrollPane创建后会拉到最底下初始化的时候手动拉到顶
*/
public void scrollToTop() {
infoScrollPane.getVerticalScrollBar().setValue(0);
detailInfoPane.getVerticalScrollBar().setValue(0);
}
private void initComponent() {
createImagePane();
createContentPane();
createDetailInfoScrollPane();
}
private void createContentPane() {
createInfoScrollPane();
createOperatePane();
contentPane = new JPanel();
contentPane.setLayout(new FlowLayout(FlowLayout.LEFT));
contentPane.setPreferredSize(new Dimension(CONTENT_PANE_WIDTH, CONTENT_PANE_HEIGHT));
contentPane.add(infoScrollPane);
contentPane.add(operatePane);
contentPane.setBackground(Color.WHITE);
}
/**
* 操作区查看详情立即使用
*/
private void createOperatePane() {
operatePane = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel emptyLabel = new JLabel();
emptyLabel.setPreferredSize(new Dimension(145, 25));
JLabel priceLabel = new JLabel();
priceLabel.setForeground(Color.RED);
if (data.getPrice() == 0) {
priceLabel.setText(FREE);
} else {
priceLabel.setText(RMB + SPACE + data.getPrice());
}
operatePane.add(createLinkLabel());
operatePane.add(emptyLabel);
operatePane.add(priceLabel);
operatePane.add(createStartUseButton());
operatePane.setBackground(Color.WHITE);
}
/**
* 查看详情
*/
JLabel createLinkLabel() {
JLabel linkLabel = new JLabel(GOTO_DETAIL);
linkLabel.setBackground(Color.WHITE);
linkLabel.setForeground(MORE_INFO_LINK);
linkLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
openResourceUrl(data.getResourceUrl());
}
});
return linkLabel;
}
/**
* 方便埋点
*/
void openResourceUrl(String url) {
BrowseUtils.browser(url);
}
/**
* 立即使用 按钮
*/
JButton createStartUseButton() {
JButton starUseButton = new JButton(START_USE) {
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(UIConstants.FLESH_BLUE);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 4, 4);
super.paintComponent(g2d);
}
};
starUseButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
starUseButton.setForeground(Color.WHITE);
starUseButton.setFont(AlphaFineConstants.MEDIUM_FONT);
starUseButton.addActionListener(new StartUseAction(data));
starUseButton.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
starUseButton.setContentAreaFilled(false);
return starUseButton;
}
private void createImagePane() {
imagePane = new TemplateResourceImagePanel(data.getRoot(), IMAGE_WIDTH, IMAGE_HEIGHT);
}
/**
* 基本信息页
*/
private void createInfoScrollPane() {
StringBuilder sb = new StringBuilder();
// 开发者
sb.append(String.format(HTML_P_TAG_FORMAT, VENDOR + data.getVendor()));
// 标签
sb.append(String.format(HTML_P_TAG_FORMAT, TAGS + data.getTagsString()));
// 所属模板包
if (!StringUtils.isEmpty(data.getParentPkgName())) {
sb.append(String.format(HTML_P_TAG_FORMAT, PARENT_PACKAGE + LinkStrUtils.generateLinkTagWithoutUnderLine(data.getParentPkgUrl(), data.getParentPkgName())));
}
// 信息
sb.append(String.format(HTML_P_TAG_FORMAT, data.getInfo()));
MessageWithLink content = new MessageWithLink(String.format(HTML_FORMAT, sb));
content.setBackground(INFO_PANE_BACKGROUND);
content.setForeground(INFO_PANE_FOREGROUND);
infoScrollPane = new UIScrollPane(content);
infoScrollPane.setForeground(INFO_PANE_FOREGROUND);
infoScrollPane.setPreferredSize(new Dimension(SCROLL_PANE_WIDTH, SCROLL_PANE_HEIGHT));
infoScrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
}
/**
* 详细信息页
*/
private void createDetailInfoScrollPane() {
MessageWithLink content = new MessageWithLink(String.format(DETAIL_INFO_HTML_FORMAT, data.getHtmlText()));
detailInfoPane = new UIScrollPane(content);
detailInfoPane.setPreferredSize(new Dimension(PANE_WIDTH, DETAIL_PANE_HEIGHT));
detailInfoPane.setBackground(Color.WHITE);
detailInfoPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
}
}

189
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateShopPane.java

@ -0,0 +1,189 @@
package com.fr.design.mainframe.alphafine.preview;
import com.fr.common.util.Strings;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.mainframe.alphafine.AlphaFineConstants;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.component.TemplateResourcePageGridPane;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import com.fr.design.mainframe.alphafine.model.TemplateResourceDetail;
import com.fr.design.mainframe.alphafine.search.manager.impl.TemplateResourceSearchManager;
import com.fr.log.FineLoggerFactory;
import org.jooq.tools.StringUtils;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import java.awt.CardLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
public class TemplateShopPane extends JPanel {
private static final TemplateShopPane INSTANCE = new TemplateShopPane();
public static TemplateShopPane getInstance() {
return INSTANCE;
}
// public 方便埋点
public static final String DEFAULT_PAGE_PANEL = "defaultPagePane";
public static final String PAGE_PANEL = "pagePane";
public static final String DETAIL_PANEL = "detailPane";
public static final String LOADING_PANEL = "loadingPane";
public static final String FAILED_PANEL = "failedPane";
private String currentCard = StringUtils.EMPTY;
private static final String SLASH = "/";
private CardLayout cardLayout = new CardLayout();
private JPanel defaultPagePane;
private JPanel pagePane;
private JPanel detailPane;
private JPanel loadingPane;
private JPanel failedPane;
private TemplateShopPane() {
setLayout(cardLayout);
initComponents();
this.add(defaultPagePane, DEFAULT_PAGE_PANEL);
this.add(loadingPane, LOADING_PANEL);
this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE);
switchCard(DEFAULT_PAGE_PANEL);
}
private void switchCard(String flag) {
cardLayout.show(this, flag);
currentCard = flag;
}
private void initComponents() {
defaultPagePane = createDefaultResourcePane();
loadingPane = createLoadingPane();
}
public void refreshPagePane(List<TemplateResource> resourceList) {
pagePane = createContentPane(resourceList);
this.add(pagePane, PAGE_PANEL);
switchCard(PAGE_PANEL);
}
public void quitSearchResultPane() {
if (currentCard.equals(PAGE_PANEL)) {
switchCard(DEFAULT_PAGE_PANEL);
}
}
public void showResult() {
if (Strings.isEmpty(AlphaFineHelper.getAlphaFineDialog().getSearchText())) {
switchCard(DEFAULT_PAGE_PANEL);
} else {
switchCard(PAGE_PANEL);
}
}
// 打开二级页面,显示详细信息
public void searchAndShowDetailPane(TemplateResource resource) {
changeLabel(resource.getName());
switchCard(LOADING_PANEL);
new SwingWorker<TemplateResourceDetail, Void>() {
@Override
protected TemplateResourceDetail doInBackground(){
// 搜搜
TemplateResourceDetail detail = TemplateResourceSearchManager.getInstance().getDetailSearchResult(resource);
return detail;
}
@Override
protected void done() {
TemplateResourceDetail detail = null;
try {
detail = get();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
if (detail == null) {
setRetryAction(resource);
switchCard(FAILED_PANEL);
} else {
// detailpane初始化
detailPane = new TemplateResourceDetailPane(detail);
// 切换
INSTANCE.add(detailPane, DETAIL_PANEL);
switchCard(DETAIL_PANEL);
}
}
}.execute();
}
private void changeLabel(String resourceName) {
JPanel labelNamePane = AlphaFineHelper.getAlphaFineDialog().getLabelWestPane();
UILabel tabLabel = AlphaFineHelper.getAlphaFineDialog().getTabLabel();
tabLabel.setForeground(AlphaFineConstants.DARK_GRAY);
UILabel slash = new UILabel(SLASH);
slash.setForeground(AlphaFineConstants.DARK_GRAY);
UILabel resourceLabel = new UILabel(resourceName);
resourceLabel.setForeground(AlphaFineConstants.LABEL_SELECTED);
labelNamePane.removeAll();
labelNamePane.add(tabLabel);
labelNamePane.add(slash);
labelNamePane.add(resourceLabel);
tabLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
switchCard(PAGE_PANEL);
tabLabel.setForeground(AlphaFineConstants.LABEL_SELECTED);
labelNamePane.remove(slash);
labelNamePane.remove(resourceLabel);
}
});
}
// 方便埋点,勿删
public String getCurrentCard() {
return currentCard;
}
private JPanel createContentPane(List<TemplateResource> templateResources) {
return new TemplateResourcePageGridPane(templateResources);
}
private JPanel createDefaultResourcePane() {
return createContentPane(TemplateResourceSearchManager.getInstance().getDefaultResourceList());
}
private JPanel createLoadingPane() {
return new SearchLoadingPane();
}
private void setRetryAction(TemplateResource resource) {
if (failedPane != null) {
INSTANCE.remove(failedPane);
}
failedPane = createFailedPane(resource);
INSTANCE.add(failedPane, FAILED_PANEL);
}
private JPanel createFailedPane(TemplateResource resource) {
return new NetWorkFailedPane(()->{this.searchAndShowDetailPane(resource);});
}
}

108
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/TemplateResourceSearchWorkerManager.java

@ -0,0 +1,108 @@
package com.fr.design.mainframe.alphafine.search;
import com.fr.design.mainframe.alphafine.AlphaFineConstants;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.CellType;
import com.fr.design.mainframe.alphafine.component.AlphaFineFrame;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import com.fr.design.mainframe.alphafine.preview.TemplateShopPane;
import com.fr.log.FineLoggerFactory;
import javax.swing.SwingWorker;
import java.util.List;
import java.util.function.Function;
public class TemplateResourceSearchWorkerManager implements SearchManager {
private final CellType cellType;
private SwingWorker<List<TemplateResource>, Void> searchWorker;
private Function<SearchTextBean, List<TemplateResource>> searchFunction;
private AlphaFineFrame alphaFineFrame;
private volatile boolean searchResult = true;
private volatile boolean searchOver = false;
private volatile boolean networkError = false;
public TemplateResourceSearchWorkerManager(CellType cellType, Function<SearchTextBean, List<TemplateResource>> searchFunction, AlphaFineFrame alphaFineFrame) {
this.cellType = cellType;
this.searchFunction = searchFunction;
this.alphaFineFrame = alphaFineFrame;
}
@Override
public void doSearch(SearchTextBean searchTextBean) {
checkSearchWork();
searchOver = false;
this.searchWorker = new SwingWorker<List<TemplateResource>, Void>() {
@Override
protected List<TemplateResource> doInBackground() {
List<TemplateResource> list;
if (!AlphaFineHelper.isNetworkOk()) {
networkError = true;
FineLoggerFactory.getLogger().warn("alphaFine network error");
}
list = searchFunction.apply(searchTextBean);
return list;
}
@Override
protected void done() {
searchOver = true;
if (!isCancelled()) {
try {
List<TemplateResource> list = get();
searchResult = !list.isEmpty();
showResult(list);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
};
this.searchWorker.execute();
}
void showResult(List<TemplateResource> list) {
if (networkError && !searchResult) {
alphaFineFrame.showResult(AlphaFineConstants.NETWORK_ERROR);
return;
}
if (alphaFineFrame.getSelectedType() == cellType) {
if (!searchResult) {
alphaFineFrame.showResult(CellType.NO_RESULT.getFlagStr4None());
} else {
TemplateShopPane.getInstance().refreshPagePane(list);
AlphaFineHelper.getAlphaFineDialog().showResult(cellType.getFlagStr4None());
}
}
}
@Override
public boolean hasSearchResult() {
return searchResult;
}
@Override
public boolean isSearchOver() {
return searchOver;
}
private void checkSearchWork() {
if (this.searchWorker != null && !this.searchWorker.isDone()) {
this.searchWorker.cancel(true);
this.searchWorker = null;
}
}
@Override
public boolean isNetWorkError() {
return networkError;
}
}

347
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java

@ -0,0 +1,347 @@
package com.fr.design.mainframe.alphafine.search.helper;
import com.fr.design.DesignerEnvManager;
import com.fr.design.extra.PluginConstants;
import com.fr.design.mainframe.alphafine.download.FineMarketDownloadManager;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import com.fr.file.FileCommonUtils;
import com.fr.general.CloudCenter;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.market.key.FineMarketPublicKeyHolder;
import com.fr.security.SecurityToolbox;
import com.fr.stable.StableUtils;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.HttpException;
import com.fr.third.org.apache.http.HttpStatus;
import com.fr.third.org.apache.http.client.config.CookieSpecs;
import com.fr.third.org.apache.http.client.config.RequestConfig;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.client.methods.HttpUriRequest;
import com.fr.third.org.apache.http.client.methods.RequestBuilder;
import com.fr.third.org.apache.http.impl.client.BasicCookieStore;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient;
import com.fr.third.org.apache.http.impl.client.HttpClients;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FineMarketClientHelper {
private static final FineMarketClientHelper INSTANCE = new FineMarketClientHelper();
public static FineMarketClientHelper getInstance() {
return INSTANCE;
}
private static final String CERTIFICATE_PUBLIC_KEY = FineMarketPublicKeyHolder.getInstance().getDefaultKey();
public static final String FINE_MARKET_TEMPLATE_INFO = CloudCenter.getInstance().acquireUrlByKind("market.template.info");
public static final String FINE_MARKET_TEMPLATE_URL = CloudCenter.getInstance().acquireUrlByKind("market.template.url");
public static final String FILE_DOWNLOAD = "file/download/";
public static final String PACKAGE_DOWNLOAD = "package/download/";
public static final String TEMPLATES_PARENT_PACKAGE = "parent/";
public static final String TEMPLATES_TAGS = "filter";
public static final String NAME_SEARCH = "?searchKeyword=";
public static final String RESPONSE_STATE = "state";
public static final String RESPONSE_SUCCESS = "ok";
public static final String RESPONSE_RESULT = "result";
public static final String TAGS_KEY = "key";
public static final String TAGS_ITEMS = "items";
public static final String TAG_NAME = "name";
public static final String TAG_ID = "id";
private static final String FILENAME_FORMAT = ".+?(.zip|.rar|.cpt|.frm)";
private static final Pattern FILENAME_PATTERN = Pattern.compile(FILENAME_FORMAT);
// 缓存下所有tag标签
private Map<String, String> tags;
/**
* 获取模板资源的下载链接
* */
public String getResourceDownloadUrl(TemplateResource templateResource) {
if (TemplateResource.Type.SCENARIO_SOLUTION.equals(templateResource.getType())) {
return getPackageDownloadUrl();
} else {
return getFileDownLoadUrl();
}
}
private String getPackageDownloadUrl() {
return FINE_MARKET_TEMPLATE_INFO + PACKAGE_DOWNLOAD;
}
private String getFileDownLoadUrl() {
return FINE_MARKET_TEMPLATE_INFO + FILE_DOWNLOAD;
}
public String download(TemplateResource resource, File destDir, com.fr.design.extra.Process<Double> process) throws Exception {
String resourceId = resource.getId();
CloseableHttpResponse fileRes = getFileResponse(resource, resourceId);
if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
File destFile = createDestFile(destDir, resource);
StableUtils.makesureFileExist(destFile);
InputStream content = null;
FileOutputStream writer = null;
try {
writer = new FileOutputStream(FileCommonUtils.getAbsolutePath(destFile));
HttpEntity entity = fileRes.getEntity();
long totalSize = entity.getContentLength();
content = entity.getContent();
byte[] data = new byte[PluginConstants.BYTES_NUM];
int bytesRead;
int totalBytesRead = 0;
while ((bytesRead = content.read(data)) > 0) {
writer.write(data, 0, bytesRead);
data = new byte[PluginConstants.BYTES_NUM];
totalBytesRead += bytesRead;
process.process(totalBytesRead / (double) totalSize);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
} finally {
content.close();
writer.flush();
writer.close();
}
FineLoggerFactory.getLogger().info("download resource{} success", resourceId);
process.process(FineMarketDownloadManager.PROCESS_SUCCESS);
return FileCommonUtils.getAbsolutePath(destFile);
} else {
FineLoggerFactory.getLogger().info("download resource{} failed", resourceId);
process.process(FineMarketDownloadManager.PROCESS_FAILED);
throw new HttpException();
}
}
private CloseableHttpResponse getFileResponse(TemplateResource resource, String resourceId) throws Exception {
CloseableHttpResponse fileRes = postDownloadHttpResponse(getResourceDownloadUrl(resource), resourceId);
if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) {
fileRes = getDownloadHttpResponse(fileRes.getHeaders("Location")[0].getValue());
}
return fileRes;
}
/**
* 在目标路径下destDir创建与资源名称相同的文件夹 (finalDir)
* 将资源下载到 destDir/finalDir
* 如果文件重复则在文件名前加自增id
* */
private File createDestFile(File destDir, TemplateResource resource) {
String fileName = resource.getName();
File finalDir = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(destDir), fileName));
try {
if (!finalDir.exists()) {
finalDir.mkdir();
}
fileName = resource.getFileName();
fileName = rename(fileName, finalDir);
File destFile = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(finalDir), fileName));
return destFile;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
fileName = UUID.randomUUID() + fileName;
File dest = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(finalDir), fileName));
return dest;
}
/**
* 处理下文件名比如重复下载需要处理重名的情况
* */
String rename(String fileName, File parentDir) throws Exception {
if (!FILENAME_PATTERN.matcher(fileName).matches()) {
throw new Exception("fileName format error: " + fileName);
}
// 获取文件名(含后缀)
String prefix = fileName.substring(0, fileName.length() - 4);
String suffix = fileName.substring(fileName.length() - 4);
File file = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(parentDir), fileName));
// 处理重复文件名
if (file.exists()) {
String fileNameFormat = prefix + "(%d)" + suffix;
Pattern pattern = Pattern.compile(prefix + "\\((\\d)\\)" + suffix);
int cnt = 0;
File[] files = parentDir.listFiles();
for (File f : files) {
Matcher matcher = pattern.matcher(f.getName());
if (matcher.find()) {
cnt = Math.max(cnt, Integer.parseInt(matcher.group(1)));
}
}
cnt++;
fileName = String.format(fileNameFormat, cnt);
}
return fileName;
}
private static CloseableHttpResponse getDownloadHttpResponse(String url) throws Exception {
//先登录一下。不然可能失败
CloseableHttpClient client = createClient();
HttpUriRequest file = RequestBuilder.get()
.setUri(url)
.build();
return client.execute(file);
}
private static CloseableHttpResponse postDownloadHttpResponse(String url, String id) throws Exception {
return postDownloadHttpResponse(url, id, new HashMap<>());
}
private static CloseableHttpResponse postDownloadHttpResponse(String url, String id, Map<String, String> params) throws Exception {
//先登录一下。不然可能失败
CloseableHttpClient client = createClient();
FineLoggerFactory.getLogger().info("login fr-market");
FineLoggerFactory.getLogger().info("start download resource {}", id);
RequestBuilder builder = RequestBuilder.post()
.setHeader("User-Agent", "Mozilla/5.0")
.setUri(url)
.addParameter("id", SecurityToolbox.encrypt(id, CERTIFICATE_PUBLIC_KEY))
.addParameter("userId", String.valueOf(DesignerEnvManager.getEnvManager().getDesignerLoginUid()));
if (params != null) {
Set<String> keys = params.keySet();
for (String key: keys) {
builder.addParameter(key, params.get(key));
}
}
return client.execute(builder.build());
}
private static CloseableHttpClient createClient() {
BasicCookieStore cookieStore = new BasicCookieStore();
return HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.setDefaultCookieStore(cookieStore)
.build();
}
public @Nullable JSONObject getTemplateInfoById(String id) throws IOException {
String url = FINE_MARKET_TEMPLATE_INFO + id;
String jsonString = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(jsonString);
String responseState = (String) jsonObject.get(RESPONSE_STATE);
if (RESPONSE_SUCCESS.equals(responseState)) {
return jsonObject.getJSONObject(RESPONSE_RESULT);
} else {
return null;
}
}
public @Nullable JSONArray getTemplateInfoByName(String name) throws IOException {
String url = FINE_MARKET_TEMPLATE_INFO + NAME_SEARCH + name;
String jsonString = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(jsonString);
String responseState = (String) jsonObject.get(RESPONSE_STATE);
if (RESPONSE_SUCCESS.equals(responseState)) {
return jsonObject.getJSONArray(RESPONSE_RESULT);
}
return null;
}
public String getTemplateUrlById(String id) {
return FINE_MARKET_TEMPLATE_URL + id;
}
public @Nullable JSONObject getTemplateParentPackageByTemplateId(String id) throws IOException {
String url = FINE_MARKET_TEMPLATE_INFO + TEMPLATES_PARENT_PACKAGE + id;
String jsonString = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(jsonString);
String responseState = (String) jsonObject.get(RESPONSE_STATE);
if (RESPONSE_SUCCESS.equals(responseState)) {
JSONArray jsonArray = jsonObject.getJSONArray(RESPONSE_RESULT);
if (!jsonArray.isEmpty()) {
return jsonObject.getJSONArray(RESPONSE_RESULT).getJSONObject(0);
}
}
return null;
}
/**
* 根据模板资源的tagid获取tagName
* */
public List<String> getTemplateTagsByTemplateTagIds(String[] tagIds) throws IOException {
List<String> list = new ArrayList<>();
initTags();
if (tagIds != null) {
for (String tagId : tagIds) {
String tagName = tags.get(tagId);
if (tagName != null) {
list.add(tagName);
}
}
}
return list;
}
/**
* 请求帆软市场获取所有tag信息并构建tagid - tagname的map
* */
private void initTags() throws IOException {
tags = new HashMap<>();
String url = FINE_MARKET_TEMPLATE_INFO + TEMPLATES_TAGS;
String jsonString = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(jsonString);
String responseState = (String) jsonObject.get(RESPONSE_STATE);
if (RESPONSE_SUCCESS.equals(responseState)) {
JSONArray resultArray = jsonObject.getJSONArray(RESPONSE_RESULT);
for (int i = 1; i < resultArray.size(); i++) {
JSONObject result = resultArray.getJSONObject(i);
String key = result.getString(TAGS_KEY);
key = key.substring(key.indexOf('@') + 1);
JSONArray items = result.getJSONArray(TAGS_ITEMS);
for (int j = 0; j < items.length(); j++) {
JSONObject item = items.getJSONObject(j);
String id = item.getString(TAG_ID);
String name = item.getString(TAG_NAME);
tags.put(key + '-' + id, name);
}
}
}
}
}

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

@ -1,6 +1,7 @@
package com.fr.design.mainframe.alphafine.search.manager.impl;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.alphafine.AlphaFineConstants;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.model.ProductNews;
@ -14,6 +15,7 @@ import java.awt.Image;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -90,7 +92,7 @@ public class ProductNewsSearchManager {
setImage(getCoverImage(obj.getString("pic"))).
setUrl(obj.getString("url")).setTag(ProductNews.Tag.parseCode(obj.getInt("tag"))).
setStatus(ProductNews.Status.parseCode(obj.getInt("status"))).setTarget(
ProductNews.Target.parseCode(obj.getInt("target"))).
ProductNews.ParseTarget(obj.getString("target"))).
setCreator(obj.getInt("creator")).setPushDate(new Date(obj.getLong("push_time")));
Date currentDate = new Date(System.currentTimeMillis());
// 推送时间check
@ -99,9 +101,69 @@ public class ProductNewsSearchManager {
idSet.add(productNews.getId());
}
}
productNewsList = filterByDesignerId(productNewsList);
return productNewsList;
}
/**
* 将productNews根据设计器id进行过滤
* productNews有个target字段代表推送对象用户组检查设计器id是否在用户组中来进行过滤
* */
private List<ProductNews> filterByDesignerId(List<ProductNews> list) {
//设计器id
String designId = DesignerEnvManager.getEnvManager().getUUID();
HashMap<String, Set<String>> userGroupInfoCache = new HashMap<>();
//遍历资源,获取target下的所有用户组信息,检查是否包含设计器id
List<ProductNews> newsList = new ArrayList<>();
for (ProductNews productNews : list) {
List<String> targets = productNews.getTarget();
boolean targetsContainDesignerId = false;
// 每条推送可能推送至多个用户组,需要逐一判断
for (String userGroupId : targets) {
// 没有记录的用户组信息需要请求一下
if (!userGroupInfoCache.containsKey(userGroupId)) {
userGroupInfoCache.put(userGroupId, searchUserGroupInfo(userGroupId));
}
// 判断设计器id是否在这个用户组中,在则退出判断,不在则继续
if (userGroupInfoCache.get(userGroupId).contains(designId) || userGroupId.equals(ProductNews.ALL_USER_TARGET)) {
targetsContainDesignerId = true;
break;
}
}
if (targetsContainDesignerId) {
newsList.add(productNews);
}
}
return newsList;
}
/**
* 根据用户组id查询用户组信息改用户组中的所有设计器id
* */
private Set<String> searchUserGroupInfo(String userGroupId) {
String url = AlphaFineConstants.ALPHA_CID_USER_GROUP_INFO + AlphaFineConstants.SEARCH_BY_ID + userGroupId;
Set<String> idSet = new HashSet<>();
try {
String jsonStr = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(jsonStr);
JSONArray idArray = jsonObject.getJSONArray("data");
for (int i = 0; i < idArray.length(); i++) {
idSet.add(idArray.getJSONObject(i).getString("userid"));
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
return idSet;
}
public List<ProductNews> getCachedProductNewsList() {
return productNewsList;
}

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

@ -0,0 +1,102 @@
package com.fr.design.mainframe.alphafine.search.manager.impl;
import com.fr.design.mainframe.alphafine.AlphaFineHelper;
import com.fr.design.mainframe.alphafine.model.TemplateResource;
import com.fr.design.mainframe.alphafine.model.TemplateResourceDetail;
import com.fr.design.mainframe.alphafine.search.helper.FineMarketClientHelper;
import com.fr.general.CloudCenter;
import com.fr.general.IOUtils;
import com.fr.json.JSONArray;
import java.util.ArrayList;
import java.util.List;
public class TemplateResourceSearchManager {
private static final TemplateResourceSearchManager INSTANCE = new TemplateResourceSearchManager();
public static TemplateResourceSearchManager getInstance() {
return INSTANCE;
}
public static final String LOCAL_RESOURCE_URL = "/com/fr/design/mainframe/alphafine/template_resource/local_templates.json";
private static final FineMarketClientHelper helper = FineMarketClientHelper.getInstance();
/**
* 帆软市场暂时没有分页搜索接口先全量搜分页展示
* */
public List<TemplateResource> getSearchResult(String searchText) {
List<TemplateResource> resourceList = new ArrayList<>();
// 联网搜索
try {
JSONArray jsonArray = helper.getTemplateInfoByName(searchText);
if (jsonArray != null && !jsonArray.isEmpty()) {
resourceList.addAll(TemplateResource.createByJson(jsonArray));
}
} catch (Exception e) {
}
// 本地搜索
if (resourceList.isEmpty()) {
List<TemplateResource> localResource = getEmbedResourceList();
localResource.stream().forEach(resource->{
if (resource.getName().toLowerCase().contains(searchText)) {
resourceList.add(resource);
}
});
}
return resourceList;
}
/**
* 返回默认资源
* */
public List<TemplateResource> getDefaultResourceList() {
List<TemplateResource> resourceList = getEmbedResourceList();
// 添加推荐搜索卡片
resourceList.add(TemplateResource.getRecommendSearch());
return resourceList;
}
/**
* 返回内置资源
* */
public List<TemplateResource> getEmbedResourceList() {
List<TemplateResource> resourceList = new ArrayList<>();
JSONArray jsonArray = getEmbedResourceJSONArray();
for (int i = 0; i < jsonArray.size(); i++) {
TemplateResource resource = TemplateResource.createByJson(jsonArray.getJSONObject(i));
resource.setEmbed(true);
resourceList.add(resource);
}
return resourceList;
}
public JSONArray getEmbedResourceJSONArray() {
String jsonString = IOUtils.readResourceAsString(LOCAL_RESOURCE_URL);
return new JSONArray(jsonString);
}
public List<String> getRecommendSearchKeys() {
List<String> searchKey = new ArrayList<>();
String[] keys = CloudCenter.getInstance().acquireConf("alphafine.tempalte.recommend", "跑马灯,填报,地图").split(",");
for (String k : keys) {
searchKey.add(k);
}
return searchKey;
}
public TemplateResourceDetail getDetailSearchResult(TemplateResource resource) {
if (AlphaFineHelper.isNetworkOk()) {
return TemplateResourceDetail.createByTemplateResource(resource);
} else {
return TemplateResourceDetail.createFromEmbedResource(resource);
}
}
}

67
designer-realize/src/main/java/com/fr/market/key/FineMarketDefaultKeyProperties.java

@ -0,0 +1,67 @@
package com.fr.market.key;
import com.fr.general.IOUtils;
import com.fr.io.utils.ResourceIOUtils;
import com.fr.log.FineLoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* @author Link
* @version 11.0
* Created by Yvan on 2022/8/25
*/
public class FineMarketDefaultKeyProperties {
private Properties properties = new Properties();
private Map<String, String> publicKeyMap = new HashMap<>();
private String propertyPath;
private FineMarketDefaultKeyProperties(String propertyPath) {
this.propertyPath = propertyPath;
load();
}
public static FineMarketDefaultKeyProperties create(String propertyPath) {
return new FineMarketDefaultKeyProperties(propertyPath);
}
private void load() {
try (InputStream inputStream = IOUtils.readResource(getPropertyPath())) {
byte[] data = ResourceIOUtils.inputStream2Bytes(inputStream);
properties.load(new ByteArrayInputStream(data));
trims(properties);
publicKeyMap.put(FineMarketPublicKeyConstants.DEFAULT_KEY_KEY, properties.getProperty(FineMarketPublicKeyConstants.DEFAULT_KEY_KEY));
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private String getPropertyPath() {
return this.propertyPath;
}
public String getPublicKey() {
return publicKeyMap.get(FineMarketPublicKeyConstants.DEFAULT_KEY_KEY);
}
/**
* 去除properties中value末尾的空格
* @param properties
*/
public static void trims(Properties properties) {
for (String key : properties.stringPropertyNames()) {
String value = properties.getProperty(key);
if (value != null) {
properties.put(key, value.trim());
}
}
}
}

29
designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyConstants.java

@ -0,0 +1,29 @@
package com.fr.market.key;
/**
* @author Link
* @version 11.0
* Created by Link on 2022/8/25
*/
public class FineMarketPublicKeyConstants {
public static final String DEFAULT_KEY_KEY = "defaultKey";
public static final String DEFAULT_KEY_DIRECTORY = "/com/fr/market/key";
/**
* 公钥第一段
*/
public static final String FIRST_PROPERTY = "76c1/default";
/**
* 公钥第二段
*/
public static final String SECOND_PROPERTY = "943f/default";
/**
* 公钥第三段
*/
public static final String THIRD_PROPERTY = "d8a3/default";
}

48
designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyHolder.java

@ -0,0 +1,48 @@
package com.fr.market.key;
import com.fr.stable.StableUtils;
/**
* 帆软市场公钥Holder
* @author Link
* @version 10.0
* Created by Link on 2022/8/25
*/
public class FineMarketPublicKeyHolder {
private static FineMarketPublicKeyHolder instance = null;
private String defaultKey;
public static FineMarketPublicKeyHolder getInstance() {
if (instance == null) {
synchronized (FineMarketPublicKeyHolder.class) {
if (instance == null) {
instance = new FineMarketPublicKeyHolder();
}
}
}
return instance;
}
private FineMarketPublicKeyHolder() {
init();
}
private void init() {
// 读取三个default.properties文件,组成公钥
String firstPart = FineMarketDefaultKeyProperties.create(StableUtils.pathJoin(FineMarketPublicKeyConstants.DEFAULT_KEY_DIRECTORY, FineMarketPublicKeyConstants.FIRST_PROPERTY)).getPublicKey();
String secondPart = FineMarketDefaultKeyProperties.create(StableUtils.pathJoin(FineMarketPublicKeyConstants.DEFAULT_KEY_DIRECTORY, FineMarketPublicKeyConstants.SECOND_PROPERTY)).getPublicKey();
String thirdPart = FineMarketDefaultKeyProperties.create(StableUtils.pathJoin(FineMarketPublicKeyConstants.DEFAULT_KEY_DIRECTORY, FineMarketPublicKeyConstants.THIRD_PROPERTY)).getPublicKey();
this.defaultKey = firstPart + secondPart + thirdPart;
}
/**
* 获取默认公钥
* @return 公钥
*/
public String getDefaultKey() {
return this.defaultKey;
}
}

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bottom.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.42701 7C3.31655 7 3.22701 7.08954 3.22701 7.2C3.22701 7.24679 3.24341 7.29209 3.27336 7.32804L7.84636 12.8156C7.91707 12.9005 8.04318 12.9119 8.12804 12.8412C8.13733 12.8335 8.1459 12.8249 8.15364 12.8156L12.7266 7.32804C12.7973 7.24318 12.7859 7.11707 12.701 7.04636C12.6651 7.0164 12.6198 7 12.573 7H9V2C9 1.44772 8.55228 1 8 1C7.44772 1 7 1.44772 7 2V7H3.42701ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14H3.5C3.22386 14 3 14.2239 3 14.5C3 14.7761 3.22386 15 3.5 15H12.5Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 672 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bottom_disable.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" opacity=".7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.42701 7C3.31655 7 3.22701 7.08954 3.22701 7.2C3.22701 7.24679 3.24341 7.29209 3.27336 7.32804L7.84636 12.8156C7.91707 12.9005 8.04318 12.9119 8.12804 12.8412C8.13733 12.8335 8.1459 12.8249 8.15364 12.8156L12.7266 7.32804C12.7973 7.24318 12.7859 7.11707 12.701 7.04636C12.6651 7.0164 12.6198 7 12.573 7H9V2C9 1.44772 8.55228 1 8 1C7.44772 1 7 1.44772 7 2V7H3.42701ZM12.5 15C12.7761 15 13 14.7761 13 14.5C13 14.2239 12.7761 14 12.5 14H3.5C3.22386 14 3 14.2239 3 14.5C3 14.7761 3.22386 15 3.5 15H12.5Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 685 B

5
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/caution.svg

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 8C15 11.8656 11.8656 15 8 15C4.13435 15 1 11.8656 1 8C1 4.13435 4.13435 1 8 1C11.8656 1 15 4.13435 15 8Z" fill="#FBB03B"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.43328 10.292C7.27773 10.4476 7.19995 10.6365 7.19995 10.8587C7.19995 11.0809 7.27773 11.2698 7.43328 11.4254C7.58884 11.5809 7.77773 11.6587 7.99995 11.6587C8.22217 11.6587 8.41106 11.5809 8.56662 11.4254C8.72217 11.2698 8.79995 11.0809 8.79995 10.8587C8.79995 10.6365 8.72217 10.4476 8.56662 10.292C8.41106 10.1365 8.22217 10.0587 7.99995 10.0587C7.77773 10.0587 7.58884 10.1365 7.43328 10.292Z" fill="white"/>
<rect x="7.30005" y="4.22144" width="1.4" height="5" rx="0.7" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 820 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/config.svg

@ -0,0 +1,3 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 1C7.17157 1 6.5 1.67157 6.5 2.5V3.2289C6.21745 3.31765 5.9457 3.4308 5.68724 3.56589L5.1716 3.05025C4.58582 2.46447 3.63607 2.46447 3.05028 3.05025C2.4645 3.63604 2.4645 4.58579 3.05028 5.17157L3.56591 5.6872C3.43081 5.94567 3.31765 6.21743 3.2289 6.5H2.5C1.67157 6.5 1 7.17157 1 8C1 8.82843 1.67157 9.5 2.5 9.5H3.2289C3.31765 9.78256 3.43081 10.0543 3.5659 10.3128L3.05026 10.8284C2.46448 11.4142 2.46448 12.364 3.05026 12.9497C3.63605 13.5355 4.5858 13.5355 5.17159 12.9497L5.68722 12.4341C5.94569 12.5692 6.21744 12.6824 6.5 12.7711V13.5C6.5 14.3284 7.17157 15 8 15C8.82843 15 9.5 14.3284 9.5 13.5V12.7711C9.78257 12.6824 10.0543 12.5692 10.3128 12.4341L10.8285 12.9497C11.4142 13.5355 12.364 13.5355 12.9498 12.9497C13.5356 12.364 13.5356 11.4142 12.9498 10.8284L12.4341 10.3128C12.5692 10.0543 12.6824 9.78255 12.7711 9.5H13.5C14.3284 9.5 15 8.82843 15 8C15 7.17157 14.3284 6.5 13.5 6.5H12.7711C12.6824 6.21744 12.5692 5.94569 12.4341 5.68722L12.9498 5.17157C13.5355 4.58579 13.5355 3.63604 12.9498 3.05025C12.364 2.46447 11.4142 2.46447 10.8284 3.05025L10.3128 3.5659C10.0543 3.43081 9.78256 3.31765 9.5 3.2289V2.5C9.5 1.67157 8.82843 1 8 1ZM8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/down.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.42705 9.1124C3.31659 9.1124 3.22705 9.20195 3.22705 9.31241C3.22705 9.35919 3.24345 9.4045 3.27341 9.44044L7.8464 14.928C7.91711 15.0129 8.04322 15.0244 8.12808 14.9536C8.13737 14.9459 8.14594 14.9373 8.15369 14.928L12.7267 9.44044C12.7974 9.35559 12.7859 9.22947 12.7011 9.15876C12.6651 9.12881 12.6198 9.1124 12.573 9.1124H9.00004V2.1124C9.00004 1.56012 8.55233 1.1124 8.00004 1.1124C7.44776 1.1124 7.00004 1.56012 7.00004 2.1124V9.1124H3.42705Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 620 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/down_disable.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" opacity=".7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.42705 9.1124C3.31659 9.1124 3.22705 9.20195 3.22705 9.31241C3.22705 9.35919 3.24345 9.4045 3.27341 9.44044L7.8464 14.928C7.91711 15.0129 8.04322 15.0244 8.12808 14.9536C8.13737 14.9459 8.14594 14.9373 8.15369 14.928L12.7267 9.44044C12.7974 9.35559 12.7859 9.22947 12.7011 9.15876C12.6651 9.12881 12.6198 9.1124 12.573 9.1124H9.00004V2.1124C9.00004 1.56012 8.55233 1.1124 8.00004 1.1124C7.44776 1.1124 7.00004 1.56012 7.00004 2.1124V9.1124H3.42705Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 637 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/loading.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99997 0.615356C3.92156 0.615356 0.615356 3.92156 0.615356 7.99997C0.615356 9.00517 0.816197 9.96346 1.17994 10.8369L2.32206 10.3771C2.0155 9.64576 1.84613 8.84265 1.84613 7.99997C1.84613 4.6013 4.6013 1.84613 7.99997 1.84613C8.58656 1.84613 9.15398 1.9282 9.69137 2.08148L8.55836 4.00142H12.6779C12.678 4.00154 12.6781 4.00165 12.6782 4.00176H14.2096C12.8951 1.96429 10.605 0.615356 7.99997 0.615356ZM14.7714 5.04894L13.6568 5.57321C13.9767 6.31781 14.1538 7.1382 14.1538 7.99997C14.1538 11.3986 11.3986 14.1538 7.99997 14.1538C7.43089 14.1538 6.87986 14.0766 6.35677 13.932L7.49691 12L6.62743 12L3.3233 12L1.79146 12C3.10622 14.0364 5.39566 15.3846 7.99997 15.3846C12.0784 15.3846 15.3846 12.0784 15.3846 7.99997C15.3846 6.95082 15.1658 5.95276 14.7714 5.04894Z" fill="#419BF9"/>
</svg>

After

Width:  |  Height:  |  Size: 936 B

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_template1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_template2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_template3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_template4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 KiB

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/more.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/next.svg

@ -0,0 +1,3 @@
<svg width="6" height="10" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.29289 5L0.646447 8.64645C0.451184 8.84171 0.451184 9.15829 0.646447 9.35355C0.841709 9.54882 1.15829 9.54882 1.35355 9.35355L5.35355 5.35355C5.54882 5.15829 5.54882 4.84171 5.35355 4.64645L1.35355 0.646447C1.15829 0.451184 0.841709 0.451184 0.646447 0.646447C0.451184 0.841709 0.451184 1.15829 0.646447 1.35355L4.29289 5Z" fill="#C2C2C2"/>
</svg>

After

Width:  |  Height:  |  Size: 453 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/prev.svg

@ -0,0 +1,3 @@
<svg width="6" height="10" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.70711 5L5.35355 8.64645C5.54882 8.84171 5.54882 9.15829 5.35355 9.35355C5.15829 9.54882 4.84171 9.54882 4.64645 9.35355L0.646447 5.35355C0.451185 5.15829 0.451185 4.84171 0.646447 4.64645L4.64645 0.646447C4.84171 0.451184 5.15829 0.451184 5.35355 0.646447C5.54882 0.841709 5.54882 1.15829 5.35355 1.35355L1.70711 5Z" fill="#C2C2C2"/>
</svg>

After

Width:  |  Height:  |  Size: 447 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/top.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.42701 9C3.31655 9 3.22701 8.91046 3.22701 8.8C3.22701 8.75321 3.24341 8.70791 3.27336 8.67196L7.84636 3.18437C7.91707 3.09952 8.04318 3.08805 8.12804 3.15877C8.13733 3.16651 8.1459 3.17508 8.15364 3.18437L12.7266 8.67196C12.7973 8.75682 12.7859 8.88293 12.701 8.95364C12.6651 8.9836 12.6198 9 12.573 9H9V14C9 14.5523 8.55228 15 8 15C7.44772 15 7 14.5523 7 14V9H3.42701ZM12.5 1C12.7761 1 13 1.22386 13 1.5C13 1.77614 12.7761 2 12.5 2H3.5C3.22386 2 3 1.77614 3 1.5C3 1.22386 3.22386 1 3.5 1H12.5Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 668 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/top_disable.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" opacity=".7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.42701 9C3.31655 9 3.22701 8.91046 3.22701 8.8C3.22701 8.75321 3.24341 8.70791 3.27336 8.67196L7.84636 3.18437C7.91707 3.09952 8.04318 3.08805 8.12804 3.15877C8.13733 3.16651 8.1459 3.17508 8.15364 3.18437L12.7266 8.67196C12.7973 8.75682 12.7859 8.88293 12.701 8.95364C12.6651 8.9836 12.6198 9 12.573 9H9V14C9 14.5523 8.55228 15 8 15C7.44772 15 7 14.5523 7 14V9H3.42701ZM12.5 1C12.7761 1 13 1.22386 13 1.5C13 1.77614 12.7761 2 12.5 2H3.5C3.22386 2 3 1.77614 3 1.5C3 1.22386 3.22386 1 3.5 1H12.5Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 684 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/up.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.42705 7C3.31659 7 3.22705 6.91046 3.22705 6.8C3.22705 6.75321 3.24345 6.7079 3.27341 6.67196L7.8464 1.18437C7.91711 1.09952 8.04322 1.08805 8.12808 1.15876C8.13737 1.16651 8.14594 1.17508 8.15369 1.18437L12.7267 6.67196C12.7974 6.75682 12.7859 6.88293 12.7011 6.95364C12.6651 6.9836 12.6198 7 12.573 7H9.00004V14C9.00004 14.5523 8.55233 15 8.00004 15C7.44776 15 7.00004 14.5523 7.00004 14V7H3.42705Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 573 B

3
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/up_disable.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" opacity=".7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.42705 7C3.31659 7 3.22705 6.91046 3.22705 6.8C3.22705 6.75321 3.24345 6.7079 3.27341 6.67196L7.8464 1.18437C7.91711 1.09952 8.04322 1.08805 8.12808 1.15876C8.13737 1.16651 8.14594 1.17508 8.15369 1.18437L12.7267 6.67196C12.7974 6.75682 12.7859 6.88293 12.7011 6.95364C12.6651 6.9836 12.6198 7 12.573 7H9.00004V14C9.00004 14.5523 8.55233 15 8.00004 15C7.44776 15 7.00004 14.5523 7.00004 14V7H3.42705Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 589 B

110
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/template_resource/local_templates.json

@ -0,0 +1,110 @@
[
{
"id": 20000770,
"name": "PDCA销售运营闭环管理方案",
"uuid": "7975ad73-9aea-4634-96f1-d33ec1b4283c",
"vendor": "Victoria.",
"sellerId": 202,
"cid": "industry-3,purpose-2,purpose-16,purpose-15",
"tag": null,
"pic": "com/fr/design/mainframe/alphafine/images/local_template1.png",
"price": 0,
"fileLoca": null,
"text": "<ol style=\"list-style-type: decimal;\" class=\" list-paddingleft-2\"><li><p>此方案共包括14张模板,其中12张可视化分析看板、1张分析报表以及1张填报表,需在10.0及以上版本设计器中预览;</p></li><li><p>了解方案详情,可移步-数据分析与可视化指南</p></li><li><p>如果您希望在线体验当前方案,可移步-<a href=\"https://demo.finereport.com/\" target=\"_self\">官方DEMO系统</a>:业务场景应用-&gt;营销管理<br/></p></li><li><p>如果您对此方案感兴趣,希望更加深入了解,可以填写此表单:<a href=\"https://t6ixa9nyl6.jiandaoyun.com/f/60dac9bd282e8e000796eac3\" target=\"_self\">方案需求录入</a>;后续会有帆软行业顾问将与您联系。<br/></p></li></ol>",
"description": "将PDCA循环嵌入销售运营管理的全流程中,从决策层、管理层与执行层三个层级,对目标制定、执行过程、复盘分析、问题跟踪进行全方位精细化管理。",
"updateTime": "2022-06-15T06:36:39.000Z",
"downloadTimes": 1152,
"state": 1,
"designVersion": "10.0",
"involvePlugins": null,
"uploadTime": "2022-06-15T06:36:39.000Z",
"style": null,
"link": "template",
"sellerName": "Victoria.",
"pluginName": [],
"pkgsize": 14,
"material": "方案附件.rar",
"tagsName": "制造加工,营销,组织,管理,经营汇报"
},
{
"id": 20000733,
"name": "库存场景解决方案",
"uuid": "43d1c14b-1a73-41e6-adcc-aaf2872bc8d4",
"vendor": "Victoria.",
"sellerId": 202,
"cid": "industry-3,purpose-5",
"tag": null,
"pic": "com/fr/design/mainframe/alphafine/images/local_template2.png",
"price": 0,
"fileLoca": null,
"text": "<p>当前库存管理面临的现状:库存成本劣势明显、库存周转差距较大。如果对此没有合理有效的解决方案,往往会导致企业库存越来越混乱,经营、资金、成本等问题丛生。</p><p>库存管理解决方案从:“盘”、“析”、“管”三个方向开展,彻底解决库存量大、结构复杂、管理混乱等常见问题</p>",
"description": "库存管理解决方案即从:“盘”、“析”、“管”三个方向开展,对导致库存管理问题的原因逐一击破。",
"updateTime": "2022-05-05T03:53:55.000Z",
"downloadTimes": 816,
"state": 1,
"designVersion": "10.0",
"involvePlugins": null,
"uploadTime": "2022-05-05T03:53:55.000Z",
"style": null,
"link": "template",
"sellerName": "Victoria.",
"pluginName": [],
"pkgsize": 11,
"material": "",
"tagsName":"制造加工,库存"
},
{
"id": 20000581,
"name": "采购场景解决方案",
"uuid": "7994b01f-5069-4554-83cf-9d3506e30767",
"vendor": "Victoria.",
"sellerId": 202,
"cid": "industry-3,purpose-3",
"tag": null,
"pic": "com/fr/design/mainframe/alphafine/images/local_template3.png",
"price": 0,
"fileLoca": null,
"text": "<p>采购场景方案具体细节可参考:<a href=\"https://help.fanruan.com/dvg/doc-view-151.html\" target=\"_self\">可视化指南-采购场景应用</a><br/></p>",
"description": "采购解决方案采用:“自上而下”的分析思路,针对采购相关的不同角色层级及其不同角度发数据分析需求,产出不同的内容",
"updateTime": "2022-03-10T03:50:17.000Z",
"downloadTimes": 2353,
"state": 1,
"designVersion": "10.0",
"involvePlugins": null,
"uploadTime": "2022-03-10T03:50:18.000Z",
"style": null,
"link": "template",
"sellerName": "Victoria.",
"pluginName": [],
"pkgsize": 6,
"material": "",
"tagsName": "制造加工,采购"
},
{
"id": 20000747,
"name": "费用预算系统解决方案",
"uuid": "0776533469c3401a8da78706856b6b02",
"vendor": "finereport",
"sellerId": 1,
"cid": "template_type-1,terminal-1,industry-13,purpose-1",
"tag": null,
"pic": "com/fr/design/mainframe/alphafine/images/local_template4.png",
"price": 0,
"fileLoca": "费用预算系统解决方案.zip",
"text": "<p>模板中使用了数据查询数据集,如果要在本地打开,需要在自己的数据库中建表,并修改数据连接。</p><p>1)建表语句见附件文件夹:SQL语句与表。</p><p><br>2)数据连接默认为 FRDemo,如果用户表所在的数据库连接不是 FRDemo,将模板中数据连接修改为用户默认的数据连接。</p><p><br>3)模板中 SQL 语句为 MYSQL 数据库,若用户使用中数据库语句不匹配,可对应修改为匹配的语句。</p><p><br>4)模板中有大量的超链接,用户存在本地后,预览时注意修改超链接。</p><p><br>5)费用预算系统的平台沿用人事管理系统的平台配置,如果要在本地体验效果,可先下载人事管理系统部署:</span><a href=\"https://help.fanruan.com/dvg/doc-view-6.html?source=0&from=demoshop\" target=\"_blank\" style=\"text-decoration: underline; color: rgb(28, 133, 231); font-family: arial, helvetica, sans-serif;\"><span style=\"font-family: arial, helvetica, sans-serif;\">人事管理系统</span></a><span style=\"font-family: arial, helvetica, sans-serif;\"><br></p><p>模板中图标等背景样式见背景附件。 如果数据替换麻烦,可直接使用内置数据集模板,但内置模板只提供了样式,控件、数据等不能联动。如何制作,可查看帮助文档:</span><a href=\"https://help.fanruan.com/dvg/doc-view-124.html?source=0&from=demoshop\" target=\"_blank\" style=\"text-decoration: underline; color: rgb(28, 133, 231); font-family: arial, helvetica, sans-serif;\"><span style=\"font-family: arial, helvetica, sans-serif;\">费用预算系统</span></a><span style=\"font-family: arial, helvetica, sans-serif;\"></p>",
"description": "费用预算系统是通过 FineReport 填报功能和平台功能结合实现的审批流程系统。能够在线采集数据,提供标准数据模板,解决不同部门、子公司之间数据不统一的问题,\n实现记录预算审批与更改的操作,审批与更改记录留痕等。\n详细内容可查看帮助文档:</span><a href=\"https://help.fanruan.com/dvg/doc-view-124.html?source=0&from=demoshop\" target=\"_blank\" style=\"text-decoration: underline; color: rgb(28, 133, 231); font-family: arial, helvetica, sans-serif;\"><span style=\"font-family: arial, helvetica, sans-serif;\">费用预算系统</span></a><span style=\"font-family: arial, helvetica, sans-serif;\">",
"updateTime": "2022-05-15T05:34:45.000Z",
"downloadTimes": 141,
"state": 1,
"designVersion": "10.0",
"involvePlugins": null,
"uploadTime": "2022-05-15T05:34:45.000Z",
"style": "简约清新",
"link": "template",
"sellerName": "finereport",
"pluginName": [],
"pkgsize": 1,
"material": null,
"tagsName": "IT互联网,财务"
}
]

1
designer-realize/src/main/resources/com/fr/market/key/76c1/default

@ -0,0 +1 @@
defaultKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtsz62CPSWXZE/IYZRiAuTSZkw

1
designer-realize/src/main/resources/com/fr/market/key/943f/default

@ -0,0 +1 @@
defaultKey=1WOwer8+JFktK0uKLAUuQoBr+UjAMFtRA8W7JgKMDwZy/2liEAiXEOSPU/hrdV8D

1
designer-realize/src/main/resources/com/fr/market/key/d8a3/default

@ -0,0 +1 @@
defaultKey=tT541LnGi1X/hXiRwuttPWYN3L2GYm/d5blU+FBNwghBIrdAxXTzYBc6P4KL/oYXnMdTIrkz8tYkG3QoFQIDAQAB
Loading…
Cancel
Save