Merge in DESIGN/design from ~LINK.ZHAO/design:feature/x to feature/x * commit '5313422fc914853947bf34970104469034994a4d': REPORT-75093 运营产品化二期 pr修改 REPORT-75093 运营产品化二期 pr修改 REPORT-75093 运营产品化二期 pr修改 REPORT-75093 运营产品化二期 pr修改 REPORT-75093 运营产品化二期 pr修改 REPORT-75093 运营产品化二期 pr修改 REPORT-75093 运营产品化二期 pr修改 REPORT-75093 运营产品化二期 1、alphafine设置页修改 2、alphafine新增模板资源页面 3、原来的tab页修改了名字feature/x
@ -0,0 +1,32 @@
|
||||
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 com.fr.design.utils.BrowseUtils; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
|
||||
/** |
||||
* alphaFine - 模板资源 - 二级界面 - 开始使用按钮的绑定事件 |
||||
* |
||||
* 点击后跳转至帆软市场下载对应模板资源 |
||||
* */ |
||||
public class StartUseAction implements ActionListener { |
||||
|
||||
TemplateResourceDetail resourceDetail; |
||||
|
||||
public StartUseAction(TemplateResourceDetail detail) { |
||||
this.resourceDetail = detail; |
||||
} |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
String url = FineMarketClientHelper.getInstance().getTemplateDownLoadUrl(resourceDetail.getRoot()); |
||||
if (url == null) { |
||||
// 如果获取失败,跳转到所有模板页面
|
||||
url = FineMarketClientHelper.getInstance().getFineMarketTemplateUrl(); |
||||
} |
||||
BrowseUtils.browser(url); |
||||
} |
||||
} |
@ -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,203 @@
|
||||
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 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) { |
||||
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,191 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
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.JButton; |
||||
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(115, 25)); |
||||
JLabel priceLabel = new JLabel(); |
||||
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); |
||||
String url = data.getResourceUrl(); |
||||
BrowseUtils.browser(url); |
||||
} |
||||
}); |
||||
return linkLabel; |
||||
} |
||||
|
||||
JButton createStartUseButton() { |
||||
JButton starUseButton = new JButton(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,118 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
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.util.List; |
||||
|
||||
public class TemplateShopPane extends JPanel { |
||||
|
||||
private static final TemplateShopPane INSTANCE = new TemplateShopPane(); |
||||
public static TemplateShopPane getInstance() { |
||||
return INSTANCE; |
||||
} |
||||
|
||||
|
||||
private static final String DEFAULT_PAGE_PANEL = "defaultPagePane"; |
||||
private static final String PAGE_PANEL = "pagePane"; |
||||
private static final String DETAIL_PANEL = "detailPane"; |
||||
private static final String LOADING_PANEL = "loadingPane"; |
||||
private String currentCard = Strings.EMPTY; |
||||
|
||||
|
||||
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) { |
||||
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 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,149 @@
|
||||
package com.fr.design.mainframe.alphafine.search.helper; |
||||
|
||||
import com.fr.design.mainframe.alphafine.model.TemplateResource; |
||||
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", "https://market.fanruan.com/templates/"); |
||||
public static final String FINE_MARKET_TEMPLATE_URL = CloudCenter.getInstance().acquireUrlByKind("market.template.url", "https://market.fanruan.com/template/"); |
||||
public static final String FILE_DOWNLOAD = "file/"; |
||||
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 getTemplateDownLoadUrl(TemplateResource templateResource) { |
||||
String url = FINE_MARKET_TEMPLATE_INFO + FILE_DOWNLOAD; |
||||
if (templateResource != null) { |
||||
return url + templateResource.getId(); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取帆软市场模板资源页面链接 |
||||
* */ |
||||
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().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: 219 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 5.5 MiB |
After Width: | Height: | Size: 2.6 MiB |
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,106 @@
|
||||
[ |
||||
{ |
||||
"id": 20000736, |
||||
"name": "库存变动分析看板", |
||||
"uuid": "eee73cbe-441f-48a3-8b08-f27445a922df", |
||||
"cid": "terminal-1,industry-3,purpose-3", |
||||
"description": "通过存货变动看板,财务分析人员或者管理会计可以根据指标的趋势、数据对比等进行分析。", |
||||
"vendor": "Victoria.", |
||||
"pic": "com\\fr\\design\\mainframe\\alphafine\\images\\local_template1.png", |
||||
"fileLoca": "库存变动分析看板.frm", |
||||
"uploadTime": "2022-05-07T09:11:54.000Z", |
||||
"tag": null, |
||||
"sellerId": 202, |
||||
"style": "2", |
||||
"price": 0, |
||||
"downloadTimes": 3931, |
||||
"updateTime": "2022-05-07T09:11:54.000Z", |
||||
"designVersion": "10.0", |
||||
"involvePlugins": "none", |
||||
"pkgsize": 0, |
||||
"link": "template", |
||||
"score": 16.519018, |
||||
"url": "https://market.fanruan.com/template/20000736", |
||||
"text": "<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>", |
||||
"parentName": "库存场景解决方案", |
||||
"tagsName": "制造加工,采购" |
||||
}, |
||||
{ |
||||
"id": 20000578, |
||||
"name": "采购综合分析", |
||||
"uuid": "6dff455a-3a78-461e-8534-0a092fdf60ef", |
||||
"cid": "terminal-1,industry-3,purpose-3", |
||||
"description": "综合分析看板中,主要从采购全流程销量监控、重点模块独立分析的角度进行数据分析。决策者可以直接根据看板中的数据进行采购全流程的全面把控、定位责任模块,释放管理压力。", |
||||
"vendor": "Victoria.", |
||||
"pic": "com\\fr\\design\\mainframe\\alphafine\\images\\local_template2.png", |
||||
"fileLoca": "采购综合分析.frm", |
||||
"uploadTime": "2022-05-07T09:15:07.000Z", |
||||
"tag": null, |
||||
"sellerId": 202, |
||||
"style": "1", |
||||
"price": 0, |
||||
"downloadTimes": 2715, |
||||
"updateTime": "2022-05-07T09:15:07.000Z", |
||||
"designVersion": "10.0", |
||||
"involvePlugins": "none", |
||||
"pkgsize": 0, |
||||
"link": "template", |
||||
"score": 16.519018, |
||||
"url": "https://market.fanruan.com/template/20000578", |
||||
"text": "<ol style=\\\"list-style-type: decimal;\\\" class=\\\" list-paddingleft-2\\\"><li><p>看板包括采购流程中的主要节点、预算分析、降本分析、物料消耗情况等。</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>", |
||||
"parentName": "采购场景解决方案", |
||||
"tagsName": "制造加工,采购" |
||||
}, |
||||
{ |
||||
"id": 20000780, |
||||
"name": "仓储物流综合管理平台", |
||||
"uuid": "d94fcc7e61b44af4bde68a7aa769df3e", |
||||
"cid": "template_type-2,terminal-1,industry-4,purpose-5,purpose-6,purpose-4", |
||||
"description": "仓储物流综合管理平台包含园区内的车流、人流、物流监控,仓库内景工作状态监控,码头集装箱监控三大场景。实现仓储物流全方位动态管理。", |
||||
"vendor": "finereport", |
||||
"pic": "com\\fr\\design\\mainframe\\alphafine\\images\\local_template3.png", |
||||
"fileLoca": "仓储物流综合管理.zip", |
||||
"uploadTime": "2022-06-29T06:07:16.000Z", |
||||
"tag": null, |
||||
"sellerId": 1, |
||||
"style": "简约清新", |
||||
"price": 0, |
||||
"downloadTimes": 149, |
||||
"updateTime": "2022-06-29T06:07:16.000Z", |
||||
"designVersion": "10.0", |
||||
"involvePlugins": "1162", |
||||
"pkgsize": 0, |
||||
"link": "template", |
||||
"score": 18.520216, |
||||
"url": "https://market.fanruan.com/template/20000780", |
||||
"text": "<p>1.本大屏场景要求使用FR11.0正式发布版本,且必须将“fvs大屏编辑模式”插件更新到1.4版本,设置方法请查看帮助文档:<a href=\\\"https://help.fanruan.com/finereport/doc-view-4188.html?source=0&from=demoshop\\\"target=\\\"_blank\\\">FVS插件安装及配置要求</a></p>\\n<p>2.压缩包内包含仓储物流综合管理模板以及三个钻取页面的文件。需要把两个弹窗内容文件和主文件一起放在报表目录文件夹下,设置对应的预览链接。弹窗和网页链接的设置方法参考:<a href=\\\"https://help.fanruan.com/finereport/doc-view-4400.html?source=0&from=demoshop\\\"target=\\\"_blank\\\">FVS点击跳出弹出框</a> 、<a href=\\\"https://help.fanruan.com/finereport/doc-view-4399.html?source=0&from=demoshop\\\"target=\\\"_blank\\\">FVS点击跳转网页链接</a></p>\\n<p>3.仓储物流综合管理模板使用了自定义模型组件,并设置了模型动画。详情请查看文档:<a href=\\\"https://help.fanruan.com/finereport/doc-view-4496.html?source=0&from=demoshop\\\"target=\\\"_blank\\\">FVS自定义模型组件</a></p>", |
||||
"parentName": "", |
||||
"tagsName": "交通运输,库存,物流生产" |
||||
}, |
||||
{ |
||||
"id": 20000779, |
||||
"name": "考勤异常提醒", |
||||
"uuid": "b0c0bc3ba3f744a6b2299c69d4d55f31", |
||||
"cid": "template_type-3,terminal-2,industry-7,purpose-8", |
||||
"description": "考勤异常提醒场景通过 FineReport 移动端微信集成和移动端推送,实现每月考勤周期末将考勤异常数据推送给企业员工。\n员工可以在手机上打开异常报表预览,及时处理异常数据,降低企业HR部门的沟通成本。\n其中异常报表包括员工当月出勤汇总情况和异常记录情况。\n详细说明见文档:考勤异常提醒-https://help.fanruan.com/dvg/doc-view-212.html?source=0&from=shopdemo\n", |
||||
"vendor": "finereport", |
||||
"pic": "com\\fr\\design\\mainframe\\alphafine\\images\\local_template4.png", |
||||
"fileLoca": "考勤异常提醒.rar", |
||||
"uploadTime": "2022-06-27T02:55:34.000Z", |
||||
"tag": null, |
||||
"sellerId": 1, |
||||
"style": "简约清新", |
||||
"price": 0, |
||||
"downloadTimes": 46, |
||||
"updateTime": "2022-06-27T02:55:34.000Z", |
||||
"designVersion": "10.0", |
||||
"involvePlugins": null, |
||||
"pkgsize": 0, |
||||
"link": "template", |
||||
"score": 18.520168, |
||||
"url": "https://market.fanruan.com/template/20000779", |
||||
"text": "<p>一、附件内容说明</p>\\n<p>1)04考勤异常提醒.frm:模板,数据为「数据库查询」数据集,可使用 2) 的语句将数据导入自己的数据库后,连接数据查看。</p>\\n<p>2)Hr_考勤早晚卡记录.sql:Hr_考勤早晚卡记录表的 DDL 语句,可以直接在自己的数据库中还原Hr_考勤早晚卡记录表。</p>\\n<p>3)内置数据集模板:内置数据的模板,不替换数据的情况可查看样式,涉及数据变化,如参数查询等功能不支持</p>\\n<p>4)素材:模板中用到的素材</p>\\n<p>二、使用说明</p>\\n<p>1)下载后先在个人数据库表中准备数据,打开模板后替换数据连接即可查看,不想替换可使用内置数据集的模板。</p>\\n<p>2)注意附件只提供模板,推送效果需要将自己的工程与微信集成,在工程上设置定时调度后使用,相关内容可查看文档。</p>\",\"description\":\"<p>考勤异常提醒场景通过 FineReport 移动端微信集成和移动端推送,实现每月考勤周期末将考勤异常数据推送给企业员工。\\n员工可以在手机上打开异常报表预览,及时处理异常数据,降低企业HR部门的沟通成本。</p>\\n<p>其中异常报表包括员工当月出勤汇总情况和异常记录情况。</p>\\n<p>详细说明见文档:考勤异常提醒-https://help.fanruan.com/dvg/doc-view-212.html?source=0&from=shopdemo</p>", |
||||
"parentName": "", |
||||
"tagsName": "批发零售,人力资源" |
||||
} |
||||
] |