),如上字符串会转为如下
+ * List [该模板需用10.0及以上版本设计器预览
,
+ * 该模板为库存场景解决方案的部分内容,全部内容可下载库存场景解决方案查看
,
+ * 为保障模板预览效果,建议安装新自适应插件(FR11.0版本插件已内置,无需手动安装),有使用需求或疑问,请联系帆软技术支持咨询
+ * ]
+ * */
+ static final Pattern htmlPattern = Pattern.compile("(.+?)
");
+ static List parseDetailInfo(String htmlDetailInfo) {
+ List infos = new ArrayList<>();
+ Matcher matcher = htmlPattern.matcher(htmlDetailInfo);
+ while (matcher.find()) {
+ infos.add(matcher.group());
+ }
+ return infos;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateResourceDetailPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateResourceDetailPane.java
new file mode 100644
index 000000000..8d0ef703b
--- /dev/null
+++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateResourceDetailPane.java
@@ -0,0 +1,228 @@
+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.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.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 = "
";
+ 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 String HTML_FORMAT = "%s";
+ private static final String DETAIL_INFO_HTML_FORMAT = "" + DETAIL_INFO + "
%s";
+ private static final String HTML_P_TAG_FORMAT = "%s
";
+
+
+
+ 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.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));
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateShopPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateShopPane.java
new file mode 100644
index 000000000..fb0181ddd
--- /dev/null
+++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/TemplateShopPane.java
@@ -0,0 +1,183 @@
+package com.fr.design.mainframe.alphafine.preview;
+
+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 com.fr.third.apache.logging.log4j.util.Strings;
+
+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 = Strings.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 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 showPagePane() {
+ switchCard(PAGE_PANEL);
+ }
+
+ // 打开二级页面,显示详细信息
+ public void searchAndShowDetailPane(TemplateResource resource) {
+
+ changeLabel(resource.getName());
+
+ switchCard(LOADING_PANEL);
+
+ new SwingWorker() {
+ @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 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);});
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/TemplateResourceSearchWorkerManager.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/TemplateResourceSearchWorkerManager.java
new file mode 100644
index 000000000..ac1ef39a7
--- /dev/null
+++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/TemplateResourceSearchWorkerManager.java
@@ -0,0 +1,109 @@
+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, Void> searchWorker;
+
+ private Function> searchFunction;
+
+ private AlphaFineFrame alphaFineFrame;
+
+ private volatile boolean searchResult = true;
+
+ private volatile boolean searchOver = false;
+
+ private volatile boolean networkError = false;
+
+ public TemplateResourceSearchWorkerManager(CellType cellType, Function> searchFunction, AlphaFineFrame alphaFineFrame) {
+ this.cellType = cellType;
+ this.searchFunction = searchFunction;
+ this.alphaFineFrame = alphaFineFrame;
+ }
+
+ @Override
+ public void doSearch(SearchTextBean searchTextBean) {
+ checkSearchWork();
+ searchOver = false;
+ networkError = false;
+
+ this.searchWorker = new SwingWorker, Void>() {
+ @Override
+ protected List doInBackground() {
+ List list;
+ if (!AlphaFineHelper.isNetworkOk() && cellType.isNeedNetWork()) {
+ networkError = true;
+ FineLoggerFactory.getLogger().warn("alphaFine network error");
+ }
+ list = searchFunction.apply(searchTextBean);
+ return list;
+ }
+
+ @Override
+ protected void done() {
+ searchOver = true;
+ if (!isCancelled()) {
+ try {
+ List list = get();
+ searchResult = !list.isEmpty();
+ showResult(list);
+ } catch (Exception e) {
+ FineLoggerFactory.getLogger().error(e.getMessage(), e);
+ }
+ }
+ }
+ };
+ this.searchWorker.execute();
+ }
+
+ void showResult(List 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;
+ }
+}
\ No newline at end of file
diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java
new file mode 100644
index 000000000..52e7e3a80
--- /dev/null
+++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java
@@ -0,0 +1,325 @@
+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.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";
+
+ // 缓存下所有tag标签
+ private Map 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 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();
+ try {
+ File finalDir = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(destDir), fileName));
+ if (!finalDir.exists()) {
+ finalDir.mkdir();
+ }
+
+ // 获取文件名(含后缀)
+ fileName = resource.getFileName();
+
+ // 处理重复文件名
+ String fileNameFormat = "(%d)" + fileName;
+ Pattern pattern = Pattern.compile("\\((\\d)\\)" + fileName);
+ int cnt = 0;
+
+ File[] files = finalDir.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);
+
+
+
+ File destFile = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(finalDir), fileName));
+ destFile.createNewFile();
+ return destFile;
+ } catch (Exception e) {
+ FineLoggerFactory.getLogger().error(e, e.getMessage());
+ }
+ return null;
+ }
+
+ 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 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 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 getTemplateTagsByTemplateTagIds(String[] tagIds) throws IOException {
+ List 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);
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ProductNewsSearchManager.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ProductNewsSearchManager.java
index 205735ab3..961121758 100644
--- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ProductNewsSearchManager.java
+++ b/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;
@@ -12,17 +13,18 @@ import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import org.jetbrains.annotations.Nullable;
+import javax.imageio.ImageIO;
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;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import javax.imageio.ImageIO;
public class ProductNewsSearchManager {
@@ -91,7 +93,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
@@ -100,9 +102,69 @@ public class ProductNewsSearchManager {
idSet.add(productNews.getId());
}
}
+
+ productNewsList = filterByDesignerId(productNewsList);
+
return productNewsList;
}
+
+ /**
+ * 将productNews根据设计器id进行过滤
+ * productNews有个target字段,代表推送对象用户组,检查设计器id是否在用户组中来进行过滤
+ * */
+ private List filterByDesignerId(List list) {
+ //设计器id
+ String designId = DesignerEnvManager.getEnvManager().getUUID();
+
+ HashMap> userGroupInfoCache = new HashMap<>();
+ //遍历资源,获取target下的所有用户组信息,检查是否包含设计器id
+ List newsList = new ArrayList<>();
+ for (ProductNews productNews : list) {
+ List 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 searchUserGroupInfo(String userGroupId) {
+ String url = AlphaFineConstants.ALPHA_CID_USER_GROUP_INFO + AlphaFineConstants.SEARCH_BY_ID + userGroupId;
+ Set 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 getCachedProductNewsList() {
return productNewsList;
}
diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/TemplateResourceSearchManager.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/TemplateResourceSearchManager.java
new file mode 100644
index 000000000..2a8c76751
--- /dev/null
+++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/TemplateResourceSearchManager.java
@@ -0,0 +1,100 @@
+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 getSearchResult(String searchText) {
+ List 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 localResource = getEmbedResourceList();
+ localResource.stream().forEach(resource->{
+ if (resource.getName().toLowerCase().contains(searchText)) {
+ resourceList.add(resource);
+ }
+ });
+ }
+ return resourceList;
+ }
+
+
+ /**
+ * 返回默认资源
+ * */
+ public List getDefaultResourceList() {
+ List resourceList = getEmbedResourceList();
+ // 添加推荐搜索卡片
+ resourceList.add(TemplateResource.getRecommendSearch());
+ return resourceList;
+ }
+
+ /**
+ * 返回内置资源
+ * */
+ public List getEmbedResourceList() {
+ List resourceList = new ArrayList<>();
+ JSONArray jsonArray = getEmbedResourceJSONArray();
+ for (int i = 0; i < jsonArray.size(); i++) {
+ resourceList.add(TemplateResource.createByJson(jsonArray.getJSONObject(i)));
+ }
+ return resourceList;
+ }
+
+ public JSONArray getEmbedResourceJSONArray() {
+ String jsonString = IOUtils.readResourceAsString(LOCAL_RESOURCE_URL);
+ return new JSONArray(jsonString);
+ }
+
+ public List getRecommendSearchKeys() {
+ List 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);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/designer-realize/src/main/java/com/fr/market/key/FineMarketDefaultKeyProperties.java b/designer-realize/src/main/java/com/fr/market/key/FineMarketDefaultKeyProperties.java
new file mode 100644
index 000000000..d17a61727
--- /dev/null
+++ b/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 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());
+ }
+ }
+ }
+}
diff --git a/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyConstants.java b/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyConstants.java
new file mode 100644
index 000000000..cab87bec3
--- /dev/null
+++ b/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";
+}
diff --git a/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyHolder.java b/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyHolder.java
new file mode 100644
index 000000000..b37493559
--- /dev/null
+++ b/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;
+ }
+}
diff --git a/designer-realize/src/main/java/com/fr/start/DesignerSubListener.java b/designer-realize/src/main/java/com/fr/start/DesignerSubListener.java
index 52d364f6c..50134622d 100644
--- a/designer-realize/src/main/java/com/fr/start/DesignerSubListener.java
+++ b/designer-realize/src/main/java/com/fr/start/DesignerSubListener.java
@@ -8,6 +8,7 @@ import com.fr.exit.DesignerExiter;
import com.fr.process.engine.core.CarryMessageEvent;
import com.fr.process.engine.core.FineProcessContext;
import com.fr.process.engine.core.FineProcessEngineEvent;
+import com.fr.start.common.DesignerStartupContext;
/**
* @author hades
@@ -31,6 +32,10 @@ public class DesignerSubListener {
FineProcessContext.getParentPipe().listen(FineProcessEngineEvent.READY, new Listener() {
@Override
public void on(Event event, Null param) {
+ // 如果是在起始页的等待过程中
+ if (DesignerStartupContext.getInstance().isOnWaiting()) {
+ return;
+ }
if (DesignerContext.getDesignerFrame() == null || !DesignerContext.getDesignerFrame().isShowing()) {
DesignerExiter.getInstance().exitUnexpectedly(() -> {
diff --git a/designer-realize/src/main/java/com/fr/start/MainDesigner.java b/designer-realize/src/main/java/com/fr/start/MainDesigner.java
index 9d4d3eb14..122f5f918 100644
--- a/designer-realize/src/main/java/com/fr/start/MainDesigner.java
+++ b/designer-realize/src/main/java/com/fr/start/MainDesigner.java
@@ -11,6 +11,7 @@ import com.fr.design.actions.server.ServerConfigManagerAction;
import com.fr.design.actions.server.TemplateThemeManagerAction;
import com.fr.design.actions.server.WidgetManagerAction;
import com.fr.design.base.mode.DesignModeContext;
+import com.fr.design.carton.SwitchForSwingChecker;
import com.fr.design.constants.UIConstants;
import com.fr.design.deeplink.DeepLinkManager;
import com.fr.design.file.HistoryTemplateListCache;
@@ -74,9 +75,8 @@ import com.fr.start.server.ServerTray;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
import com.fr.van.chart.map.server.ChartMapEditorAction;
import com.fr.workspace.WorkContext;
-
-import javax.swing.JComponent;
import javax.swing.JPanel;
+import javax.swing.JComponent;
import javax.swing.border.MatteBorder;
import java.awt.Component;
import java.awt.Dimension;
@@ -123,12 +123,13 @@ public class MainDesigner extends BaseDesigner {
showSplash();
startPreload0();
- DeepLinkManager.getInstance().start(args);
StopWatch watch = new StopWatch();
watch.start();
DesignerLifecycleMonitorContext.getMonitor().beforeStart();
//启动运行时
FineRuntime.start();
+ //等 FineRuntime 启动后启动
+ DeepLinkManager.getInstance().start(args);
startPreload1();
@@ -156,6 +157,8 @@ public class MainDesigner extends BaseDesigner {
}
FineLoggerFactory.getLogger().info("Designer started.Time used {} ms", watch.getTime());
watch.stop();
+
+ SwitchForSwingChecker.initThreadMonitoring();
}
/**
@@ -238,8 +241,13 @@ public class MainDesigner extends BaseDesigner {
if (WorkContext.getCurrent().isRoot()) {
menuDef.addShortCut(
- new ServerConfigManagerAction(),
- new TemplateThemeManagerAction(),
+ new ServerConfigManagerAction()
+ );
+ JTemplate, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
+ if (JTemplate.isValid(jt)) {
+ menuDef.addShortCut(new TemplateThemeManagerAction());
+ }
+ menuDef.addShortCut(
new WidgetManagerAction()
);
menuDef.addShortCut(new ChartPreStyleAction(), new ChartEmptyDataStyleAction(),new ChartMapEditorAction());
@@ -401,7 +409,7 @@ public class MainDesigner extends BaseDesigner {
@Override
protected void refreshLargeToolbarState() {
JTemplate, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
- if (jt == null) {
+ if (!JTemplate.isValid(jt)) {
return;
}
saveButton.setEnabled(!jt.isSaved() && !DesignModeContext.isVcsMode() && jt.checkEnable());
diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java b/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java
index ff7962f61..4a4fbac2b 100644
--- a/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java
+++ b/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java
@@ -33,6 +33,7 @@ import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.start.DesignerProcessType;
import com.fr.start.ServerStarter;
+import com.fr.start.common.DesignerStartupContext;
import com.fr.start.event.LazyStartupEvent;
import com.fr.start.preload.PreLoadService;
import com.fr.start.server.FineEmbedServer;
@@ -120,7 +121,7 @@ public class DesignerStartup extends Activator {
|| FineEmbedServer.isRunning()) {
return;
}
- if (DaoSelectorFactory.getDaoSelector().useCacheDao()) {
+ if (DaoSelectorFactory.getDaoSelector().useCacheDao() || DesignerStartupContext.getInstance().isOnStartup()) {
listenEvent(LazyStartupEvent.INSTANCE, new Listener(Integer.MIN_VALUE) {
@Override
public void on(Event event, Null param) {
diff --git a/designer-realize/src/main/java/com/fr/start/module/optimized/DesignUpdateActivator.java b/designer-realize/src/main/java/com/fr/start/module/optimized/DesignUpdateActivator.java
new file mode 100644
index 000000000..b6ad5ce2a
--- /dev/null
+++ b/designer-realize/src/main/java/com/fr/start/module/optimized/DesignUpdateActivator.java
@@ -0,0 +1,25 @@
+package com.fr.start.module.optimized;
+
+import com.fr.start.common.DesignerStartupContext;
+import com.fr.update.activator.BasicUpdateActivator;
+import com.fr.update.base.FineUpdateUnit;
+
+/**
+ * created by Harrison on 2022/08/11
+ **/
+public class DesignUpdateActivator extends BasicUpdateActivator {
+
+ @Override
+ public void start() {
+
+ if (DesignerStartupContext.getInstance().onWarmup()) {
+ try {
+ prepare4Start();
+ FineUpdateUnit.makeNew();
+ } catch (Throwable ignore) {
+ }
+ } else {
+ super.start();
+ }
+ }
+}
diff --git a/designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java b/designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java
index 12e1e1f7c..568b51293 100644
--- a/designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java
+++ b/designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java
@@ -1,5 +1,7 @@
package com.fr.start.module.optimized;
+import com.fr.design.DesignerEnvManager;
+import com.fr.design.mainframe.DesignerContext;
import com.fr.design.ui.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import com.fr.module.Activator;
@@ -8,8 +10,11 @@ import com.fr.start.common.DesignerStartupContext;
import com.fr.start.module.StartupArgs;
import com.fr.start.util.DesignerStartupPageUtil;
import com.fr.start.warmup.DesignerPreWarmTask;
+import com.fr.startup.metric.DesignerMetrics;
+import com.fr.startup.metric.DesignerStartupModel;
import com.fr.startup.ui.StartupPageModel;
import com.fr.startup.ui.StartupPageWindow;
+import com.fr.startup.ui.StartupWorkspaceBean;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
import com.fr.value.NotNullLazyValue;
import org.jetbrains.annotations.NotNull;
@@ -56,8 +61,8 @@ public class DesignerStartupPageActivator extends Activator {
warmTask.start();
// 即时暂停
- DesignerStartupContext.getRecorder().suspend();
-
+ suspendRecorder(context);
+
UIUtil.invokeLaterIfNeeded(() -> {
StartupPageModel model = StartupPageModel.create();
@@ -66,24 +71,48 @@ public class DesignerStartupPageActivator extends Activator {
// selectAndOpenLast
model.setOpenLastTemplateRunnable(() -> {
context.setOpenLastFile(true);
+ handleModel(model);
launchAfterWarmup(warmTask);
});
// selectAndOpenEmpty
model.setOpenEmptyTemplateRunnable(() -> {
context.setOpenEmpty(true);
+ handleModel(model);
launchAfterWarmup(warmTask);
});
// selectAndCreateNew
model.setCreateNewTemplateRunnable(() -> {
context.setCreateNew(true);
+ handleModel(model);
launchAfterWarmup(warmTask);
});
StartupPageWindow window = new StartupPageWindow(model);
window.setVisible(true);
context.setOnWaiting(true);
+
+ });
+ }
+
+ private void suspendRecorder(DesignerStartupContext context) {
+
+ DesignerMetrics designerMetrics = context.getDesignerMetrics();
+ DesignerStartupModel designerStartupModel = designerMetrics.getModel();
+ StopWatch recorder = DesignerStartupContext.getRecorder();
+ recorder.suspend();
+ long time = recorder.getTime(TimeUnit.MILLISECONDS);
+ designerStartupModel.setLandingTime(time);
+ }
+
+ private void handleModel(StartupPageModel model) {
+
+ // 将选中的环境设置为当前环境
+ StartupWorkspaceBean selectWorkspaceInfo = model.getSelectWorkspaceInfo();
+ DesignerEnvManager.getEnvManager().setCurEnvName(selectWorkspaceInfo.getName());
+ UIUtil.invokeLaterIfNeeded(() -> {
+ DesignerContext.getDesignerFrame().setTitle();
});
}
@@ -106,12 +135,22 @@ public class DesignerStartupPageActivator extends Activator {
UIUtil.invokeLaterIfNeeded(() -> {
// 换到 awt 线程中关闭,不然异步会出现问题。
DesignerStartupContext.getInstance().setOnStartup(false);
+ recordStartupEnd(stopWatch);
});
}
-
+
FineLoggerFactory.getLogger().debug("designer-startup-page started cost {} ms", DesignerStartupContext.getRecorder().getTime(TimeUnit.MILLISECONDS));
}
+ private void recordStartupEnd(StopWatch stopWatch) {
+
+ DesignerStartupContext context = DesignerStartupContext.getInstance();
+ DesignerMetrics designerMetrics = context.getDesignerMetrics();
+ DesignerStartupModel model = designerMetrics.getModel();
+ model.setStartingTime(stopWatch.getTime(TimeUnit.MILLISECONDS));
+ model.fill();
+ }
+
@Override
public void stop() {
diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bottom.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bottom.svg
new file mode 100644
index 000000000..ef489cdce
--- /dev/null
+++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bottom.svg
@@ -0,0 +1,3 @@
+