After Width: | Height: | Size: 197 KiB |
@ -0,0 +1,21 @@
|
||||
package com.fr.startup.ui; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class StartupPageUtilTest { |
||||
|
||||
@Test |
||||
public void testGetRemoteAddress() throws Exception { |
||||
String remoteAddress = StartupPageUtil.getRemoteAddress("https://localhost:9090/webroot"); |
||||
Assert.assertEquals("localhost:9090", remoteAddress); |
||||
|
||||
String remoteAddress1 = StartupPageUtil.getRemoteAddress("https://localhost/webroot"); |
||||
Assert.assertEquals("localhost", remoteAddress1); |
||||
|
||||
String remoteAddress2 = StartupPageUtil.getRemoteAddress(null); |
||||
Assert.assertEquals("", remoteAddress2); |
||||
} |
||||
} |
@ -0,0 +1,29 @@
|
||||
package com.fr.design.mainframe.alphafine.action; |
||||
|
||||
import com.fr.design.mainframe.alphafine.model.TemplateResourceDetail; |
||||
import com.fr.design.mainframe.alphafine.search.helper.FineMarketClientHelper; |
||||
|
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
|
||||
/** |
||||
* 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) { |
||||
FineMarketClientHelper.getInstance().openBrowserAndDownload(resourceDetail.getRoot()); |
||||
} |
||||
} |
@ -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(getSouthPane(), BorderLayout.SOUTH); |
||||
} |
||||
|
||||
private void initComponent() { |
||||
createNorthPane(); |
||||
createSouthPane(); |
||||
} |
||||
|
||||
|
||||
private void createSouthPane() { |
||||
setSouthPane(new JPanel(new FlowLayout(FlowLayout.LEFT))); |
||||
JPanel southPane = getSouthPane(); |
||||
southPane.setBackground(Color.WHITE); |
||||
JLabel recommend = new JLabel(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Recommend_For_You")); |
||||
southPane.add(recommend); |
||||
|
||||
List<String> searchKeys = getTemplateResource().getRecommendSearchKey(); |
||||
|
||||
for (String key : searchKeys) { |
||||
JLabel keyLabel = new SearchKeyLabel(key); |
||||
southPane.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); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,74 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.base.GraphHelper; |
||||
import com.fr.design.mainframe.alphafine.model.TemplateResource; |
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import javax.swing.JPanel; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
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(116, 181, 249); |
||||
|
||||
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.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.drawString(tagName, x, getHeight() - 5); |
||||
} |
||||
g2.setColor(defaultColor); |
||||
} |
||||
|
||||
@Override |
||||
public Dimension getPreferredSize() { |
||||
return new Dimension(width, height); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,225 @@
|
||||
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); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 分页panel,borderlayout布局,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); |
||||
} |
||||
|
||||
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)); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,122 @@
|
||||
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.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.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
|
||||
public class TemplateResourcePanel extends JPanel { |
||||
|
||||
private JPanel northPane; |
||||
private JPanel southPane; |
||||
private TemplateResource templateResource; |
||||
|
||||
private static final Color PANEL_BORDER_COLOR = new Color(0xe8e8e9); |
||||
private static final Color DEMO_LABEL_FOREGROUND = new Color(0x419bf9); |
||||
|
||||
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(southPane, BorderLayout.SOUTH); |
||||
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 getSouthPane() { |
||||
return southPane; |
||||
} |
||||
public TemplateResource getTemplateResource() { |
||||
return templateResource; |
||||
} |
||||
|
||||
public void setNorthPane(JPanel northPane) { |
||||
this.northPane = northPane; |
||||
} |
||||
|
||||
public void setSouthPane(JPanel southPane) { |
||||
this.southPane = southPane; |
||||
} |
||||
|
||||
public void setTemplateResource(TemplateResource templateResource) { |
||||
this.templateResource = templateResource; |
||||
} |
||||
|
||||
private void initComponent() { |
||||
createNorthPane(); |
||||
createSouthPane(); |
||||
} |
||||
|
||||
protected void createNorthPane() { |
||||
northPane = new TemplateResourceImagePanel(templateResource); |
||||
} |
||||
|
||||
private void createSouthPane() { |
||||
JLabel nameLabel = new JLabel(templateResource.getName()); |
||||
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()); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
southPane = new JPanel(new BorderLayout()); |
||||
southPane.setBackground(Color.WHITE); |
||||
southPane.add(nameLabel, BorderLayout.WEST); |
||||
southPane.add(demoLabel, BorderLayout.EAST); |
||||
} |
||||
|
||||
@Override |
||||
public Dimension getPreferredSize() { |
||||
return new Dimension(180, 90); |
||||
} |
||||
} |
@ -0,0 +1,191 @@
|
||||
package com.fr.design.mainframe.alphafine.model; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
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"; |
||||
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 int pkgSize; |
||||
private List<String> recommendSearchKey; |
||||
|
||||
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)); |
||||
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 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 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; |
||||
} |
||||
} |
@ -0,0 +1,208 @@
|
||||
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 List<String> detailInfo; |
||||
private String[] tagsId; |
||||
private List<String> tagsName; |
||||
private double price; |
||||
private String parentPkgName; |
||||
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 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 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 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.setDetailInfo(parseDetailInfo(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.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.setDetailInfo(parseDetailInfo(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)); |
||||
} |
||||
|
||||
// 3请求标签信息
|
||||
detail.setTagsName(helper.getTemplateTagsByTemplateTagIds(detail.getTagsId())); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e, e.getMessage()); |
||||
} |
||||
|
||||
return detail; |
||||
} |
||||
|
||||
/** |
||||
* 这里做下数据转换 |
||||
* 原始数据是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; |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,196 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.i18n.Toolkit; |
||||
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 javax.swing.BorderFactory; |
||||
import javax.swing.JLabel; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.awt.FlowLayout; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import java.util.List; |
||||
|
||||
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 = 320; |
||||
private static final int SCROLL_PANE_HEIGHT = 150; |
||||
private static final int CONTENT_PANE_WIDTH = 320; |
||||
private static final int CONTENT_PANE_HEIGHT = 180; |
||||
private static final int DETAIL_PANE_HEIGHT = 110; |
||||
private static final int TEXT_SCROLL_PANE_HEIGHT = 500; |
||||
private static final int PANE_WIDTH = 640; |
||||
|
||||
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); |
||||
|
||||
|
||||
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); |
||||
} |
||||
|
||||
public void refresh() { |
||||
|
||||
} |
||||
|
||||
private void initComponent() { |
||||
createImagePane(); |
||||
createContentPane(); |
||||
createDetailInfoPane(); |
||||
} |
||||
|
||||
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(140, 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(Color.BLUE); |
||||
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); |
||||
} |
||||
|
||||
UIButton createStartUseButton() { |
||||
UIButton starUseButton = new UIButton(START_USE); |
||||
starUseButton.addActionListener(new StartUseAction(data)); |
||||
return starUseButton; |
||||
} |
||||
|
||||
|
||||
private void createInfoScrollPane() { |
||||
JLabel content = new JLabel(); |
||||
content.setHorizontalAlignment(SwingConstants.LEFT); |
||||
content.setVerticalAlignment(SwingConstants.TOP); |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("<html><body><p>"); |
||||
|
||||
sb.append(VENDOR + data.getVendor() + LF); |
||||
|
||||
List<String> tags = data.getTagsName(); |
||||
sb.append(TAGS); |
||||
for (String tag : tags) { |
||||
sb.append(tag + SPACE); |
||||
} |
||||
sb.append(LF); |
||||
|
||||
sb.append(PARENT_PACKAGE + data.getParentPkgName() + LF); |
||||
sb.append(data.getInfo()); |
||||
sb.append("</p></body></html>"); |
||||
content.setText(sb.toString()); |
||||
content.setBackground(INFO_PANE_BACKGROUND); |
||||
content.setForeground(INFO_PANE_FOREGROUND); |
||||
content.setPreferredSize(new Dimension(SCROLL_PANE_WIDTH - 10, TEXT_SCROLL_PANE_HEIGHT)); |
||||
infoScrollPane = new UIScrollPane(content); |
||||
infoScrollPane.setPreferredSize(new Dimension(SCROLL_PANE_WIDTH, SCROLL_PANE_HEIGHT - 25)); |
||||
infoScrollPane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0)); |
||||
} |
||||
|
||||
|
||||
|
||||
private void createImagePane() { |
||||
imagePane = new TemplateResourceImagePanel(data.getRoot(), IMAGE_WIDTH, IMAGE_HEIGHT); |
||||
} |
||||
|
||||
private void createDetailInfoPane() { |
||||
|
||||
JLabel content = new JLabel(); |
||||
content.setHorizontalAlignment(SwingConstants.LEFT); |
||||
content.setVerticalAlignment(SwingConstants.TOP); |
||||
|
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("<html><body><p>"); |
||||
sb.append(DETAIL_INFO + LF); |
||||
|
||||
List<String> detailInfos = data.getDetailInfo(); |
||||
for (String info : detailInfos) { |
||||
sb.append(info); |
||||
} |
||||
sb.append("</p></body></html>"); |
||||
content.setText(sb.toString()); |
||||
content.setPreferredSize(new Dimension(PANE_WIDTH - 20, TEXT_SCROLL_PANE_HEIGHT)); |
||||
content.setBackground(Color.WHITE); |
||||
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)); |
||||
} |
||||
} |
@ -0,0 +1,158 @@
|
||||
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"; |
||||
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 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 showPagePane() { |
||||
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()); |
||||
} |
||||
// 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.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(); |
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -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<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; |
||||
networkError = false; |
||||
|
||||
this.searchWorker = new SwingWorker<List<TemplateResource>, Void>() { |
||||
@Override |
||||
protected List<TemplateResource> doInBackground() { |
||||
List<TemplateResource> 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<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; |
||||
} |
||||
} |
@ -0,0 +1,178 @@
|
||||
package com.fr.design.mainframe.alphafine.search.helper; |
||||
|
||||
import com.fr.design.mainframe.alphafine.model.TemplateResource; |
||||
import com.fr.design.utils.BrowseUtils; |
||||
import com.fr.general.CloudCenter; |
||||
import com.fr.general.http.HttpToolbox; |
||||
import com.fr.json.JSONArray; |
||||
import com.fr.json.JSONObject; |
||||
import org.jetbrains.annotations.Nullable; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
public class FineMarketClientHelper { |
||||
private static final FineMarketClientHelper INSTANCE = new FineMarketClientHelper(); |
||||
public static FineMarketClientHelper getInstance() { |
||||
return INSTANCE; |
||||
} |
||||
|
||||
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 LOGIN_FINE_CLUB_AND_REDIRECT_SHOP = CloudCenter.getInstance().acquireUrlByKind("af.login.redirect.market"); |
||||
public static final String FILE_DOWNLOAD = "file/"; |
||||
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<String, String> tags; |
||||
|
||||
|
||||
/** |
||||
* 获取模板资源的下载链接 |
||||
* */ |
||||
public String getResourceDownloadUrl(TemplateResource templateResource) { |
||||
if (TemplateResource.Type.SCENARIO_SOLUTION.equals(templateResource.getType())) { |
||||
return getPackageDownloadUrl(templateResource.getId()); |
||||
} else { |
||||
return getFileDownLoadUrl(templateResource.getId()); |
||||
} |
||||
|
||||
} |
||||
|
||||
public void openBrowserAndDownload(TemplateResource templateResource) { |
||||
String url = LOGIN_FINE_CLUB_AND_REDIRECT_SHOP; |
||||
if (TemplateResource.Type.SCENARIO_SOLUTION.equals(templateResource.getType())) { |
||||
url += getPackageDownloadUrl(templateResource.getId()); |
||||
} else { |
||||
url += getFileDownLoadUrl(templateResource.getId()); |
||||
} |
||||
BrowseUtils.browser(url); |
||||
} |
||||
|
||||
/** |
||||
* 暂时没有package的下载接口,需要用户在浏览器点击下载 |
||||
* */ |
||||
private String getPackageDownloadUrl(String id) { |
||||
return getTemplateUrlById(id); |
||||
} |
||||
|
||||
/** |
||||
* 打开浏览器,下载单一模板 |
||||
* */ |
||||
private String getFileDownLoadUrl(String id) { |
||||
return FINE_MARKET_TEMPLATE_INFO + FILE_DOWNLOAD + id; |
||||
} |
||||
|
||||
|
||||
|
||||
/** |
||||
* 获取帆软市场模板资源页面链接 |
||||
* */ |
||||
public String getFineMarketTemplateUrl() { |
||||
return FINE_MARKET_TEMPLATE_URL; |
||||
} |
||||
|
||||
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); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -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<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++) { |
||||
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<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); |
||||
} |
||||
} |
||||
|
||||
} |
After Width: | Height: | Size: 672 B |
After Width: | Height: | Size: 685 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 620 B |
After Width: | Height: | Size: 637 B |
After Width: | Height: | Size: 424 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 206 KiB |
After Width: | Height: | Size: 591 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 453 B |
After Width: | Height: | Size: 447 B |
After Width: | Height: | Size: 668 B |
After Width: | Height: | Size: 684 B |
After Width: | Height: | Size: 573 B |
After Width: | Height: | Size: 589 B |
@ -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>:业务场景应用->营销管理<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互联网,财务" |
||||
} |
||||
] |