@ -0,0 +1,203 @@
|
||||
package com.fr.design.data.tabledata.datacenter; |
||||
|
||||
import com.fr.base.BaseFormula; |
||||
import com.fr.datacenters.tabledata.bean.DCFilterQueryBean; |
||||
import com.fr.datacenters.tabledata.bean.DCTableDataBean; |
||||
import com.fr.datacenters.tabledata.filter.DCFilter; |
||||
import com.fr.design.bridge.exec.JSBridge; |
||||
import com.fr.design.dialog.DialogActionListener; |
||||
import com.fr.design.dialog.UIDialog; |
||||
import com.fr.design.formula.FormulaFactory; |
||||
import com.fr.design.formula.UIFormula; |
||||
import com.fr.design.jxbrowser.JxUIPane; |
||||
import com.fr.json.revise.EmbedJson; |
||||
import com.fr.locale.InterProviderFactory; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.script.Calculator; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.third.antlr.ANTLRException; |
||||
import com.fr.workspace.WorkContext; |
||||
import com.teamdev.jxbrowser.js.JsAccessible; |
||||
import com.teamdev.jxbrowser.js.JsFunction; |
||||
import com.teamdev.jxbrowser.js.JsObject; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
import java.awt.Window; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
import java.util.concurrent.CompletableFuture; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* 数据中心JS对象方法桥接类 |
||||
* |
||||
* @author vito |
||||
* @since 11.0 |
||||
* Created on 2024/6/17 |
||||
*/ |
||||
@JsAccessible |
||||
public class DatacentersJSBridge { |
||||
private static final String EVENT_FORMULA_UPDATE = "OK"; |
||||
private static final String EVENT_FORMULA_CANCEL = "CANCEL"; |
||||
|
||||
/** |
||||
* 获取数据中心JS对象方法桥接实例 |
||||
* |
||||
* @param window js环境的window对象 |
||||
* @return 桥接实例 |
||||
*/ |
||||
public static DatacentersJSBridge getBridge(JsObject window) { |
||||
return new DatacentersJSBridge(window); |
||||
} |
||||
|
||||
private final JsObject window; |
||||
|
||||
|
||||
private DatacentersJSBridge(JsObject window) { |
||||
this.window = window; |
||||
} |
||||
|
||||
private static DatacentersPane relationPanel; |
||||
|
||||
/** |
||||
* 设置窗口,用于打开对话框的层级 |
||||
* |
||||
* @param panel 面板 |
||||
*/ |
||||
public static void relationPanel(DatacentersPane panel) { |
||||
relationPanel = panel; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* i18n方法 |
||||
* |
||||
* @param text key文本 |
||||
* @return 国际化文本 |
||||
* @throws Exception 异常 |
||||
*/ |
||||
@JSBridge |
||||
public void i18nText(String text, final JsFunction callback) { |
||||
JxUIPane.DEFAULT_EXECUTOR.submit(() -> |
||||
callback.invoke(window, InterProviderFactory.getProvider().getLocText(text))); |
||||
} |
||||
|
||||
/** |
||||
* 获取登录的凭证 token |
||||
* 同步方法,非耗时方法 |
||||
*/ |
||||
@JSBridge |
||||
public String fetchToken() { |
||||
return WorkContext.getCurrent().getConnection().getToken(); |
||||
} |
||||
|
||||
/** |
||||
* 判断是否远程环境 |
||||
* |
||||
* @return 是远程环境返回true,反之false |
||||
*/ |
||||
@JSBridge |
||||
public boolean isRemote() { |
||||
return !WorkContext.getCurrent().isLocal(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 判断是否设计器环境 |
||||
* |
||||
* @return 是设计器环境返回true,反之false |
||||
*/ |
||||
@JSBridge |
||||
public boolean isDesigner() { |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 调用公式面板 |
||||
*/ |
||||
@JSBridge |
||||
public void showFormulaPane(String content, final JsFunction callback) { |
||||
final UIFormula formulaPane = FormulaFactory.createFormulaPaneWhenReserveFormula(); |
||||
formulaPane.populate(BaseFormula.createFormulaBuilder().build(StringUtils.alwaysNotNull(content))); |
||||
formulaPane.showLargeWindow(SwingUtilities.getWindowAncestor(relationPanel), new DialogActionListener() { |
||||
@Override |
||||
public void doOk() { |
||||
BaseFormula formula = formulaPane.update(); |
||||
SwingUtilities.invokeLater(() -> callback.invoke(window, EVENT_FORMULA_UPDATE, formula.getPureContent())); |
||||
} |
||||
|
||||
@Override |
||||
public void doCancel() { |
||||
SwingUtilities.invokeLater(() -> callback.invoke(window, EVENT_FORMULA_CANCEL)); |
||||
} |
||||
}).setVisible(true); |
||||
} |
||||
|
||||
/** |
||||
* 解析公式参数 |
||||
*/ |
||||
@JSBridge |
||||
public void parseFormulaParameters(String content, final JsFunction callback) { |
||||
|
||||
JxUIPane.DEFAULT_EXECUTOR.submit(() -> { |
||||
try { |
||||
List<String> list = Arrays.stream(Calculator.relatedParameters(content)) |
||||
.map(p -> p.substring(1)) |
||||
.collect(Collectors.toList()); |
||||
callback.invoke(window, EmbedJson.encode(list)); |
||||
} catch (ANTLRException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 解析过滤结构 |
||||
*/ |
||||
@JSBridge |
||||
public void transFilter4Query(String tableData, final JsFunction callback) { |
||||
|
||||
JxUIPane.DEFAULT_EXECUTOR.submit(() -> { |
||||
try { |
||||
DCTableDataBean decoded = EmbedJson.decodeValue(tableData, DCTableDataBean.class); |
||||
DCFilter dcFilter = decoded.getFilter().evalValue(decoded.getParameters(), Calculator.createCalculator()); |
||||
DCFilterQueryBean queryBean = dcFilter.toQueryBean(); |
||||
String encode = EmbedJson.encode(queryBean); |
||||
callback.invoke(window, encode); |
||||
} catch (Exception e) { |
||||
callback.invoke(window, EmbedJson.encode(new DCFilterQueryBean())); |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 对话框确定动作 |
||||
*/ |
||||
@JSBridge |
||||
public void okAction() { |
||||
CompletableFuture |
||||
.runAsync(() -> relationPanel.updateNamePane()) |
||||
.thenRunAsync(() -> { |
||||
Window ancestor = SwingUtilities.getWindowAncestor(relationPanel); |
||||
if (ancestor instanceof UIDialog) { |
||||
try { |
||||
((UIDialog) ancestor).doOK(); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 对话框取消动作 |
||||
*/ |
||||
@JSBridge |
||||
public void cancelAction() { |
||||
Window ancestor = SwingUtilities.getWindowAncestor(relationPanel); |
||||
if (ancestor instanceof UIDialog) { |
||||
((UIDialog) ancestor).doCancel(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,128 @@
|
||||
package com.fr.design.data.tabledata.datacenter; |
||||
|
||||
import com.fr.datacenters.tabledata.DCTableData; |
||||
import com.fr.datacenters.tabledata.bean.DCNameBean; |
||||
import com.fr.datacenters.tabledata.bean.DCTableDataBean; |
||||
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; |
||||
import com.fr.design.dialog.DialogActionListener; |
||||
import com.fr.design.dialog.UIDialog; |
||||
import com.fr.design.jxbrowser.JxEngine; |
||||
import com.fr.design.jxbrowser.JxUIPane; |
||||
import com.fr.json.revise.EmbedJson; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.third.guava.collect.ImmutableMap; |
||||
import com.fr.workspace.WorkContext; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Window; |
||||
|
||||
/** |
||||
* 数据中心数据集面板 |
||||
* |
||||
* @author vito |
||||
* @since 11.0 |
||||
* Created on 2024/6/17 |
||||
*/ |
||||
public class DatacentersPane extends AbstractTableDataPane<DCTableData> { |
||||
|
||||
private static final JxEngine JX_ENGINE = JxEngine.newInstance(false); |
||||
|
||||
private static final String DATA_CENTER = "dc"; |
||||
private static final String DATA_CENTER_HELPER = "dcHelper"; |
||||
private final JxUIPane<String> dataCenterJxUIPane; |
||||
private JxTableDataNamePane namePane; |
||||
// 用于复制粘贴场景
|
||||
private DCTableData dcTableData; |
||||
|
||||
/** |
||||
* 借用,只运行一次 |
||||
*/ |
||||
private void addDialogActionListener() { |
||||
|
||||
// 保证在窗口加载完成后执行
|
||||
SwingUtilities.invokeLater(() -> { |
||||
Window ancestor = SwingUtilities.getWindowAncestor(DatacentersPane.this); |
||||
if (ancestor instanceof UIDialog) { |
||||
((UIDialog) ancestor).addDialogActionListener(new DialogActionListener() { |
||||
@Override |
||||
public void doOk() { |
||||
dataCenterJxUIPane.disposeBrowser(); |
||||
} |
||||
|
||||
@Override |
||||
public void doCancel() { |
||||
dataCenterJxUIPane.disposeBrowser(); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public DatacentersPane() { |
||||
setLayout(new BorderLayout()); |
||||
dataCenterJxUIPane = getJxUIPane(); |
||||
add(dataCenterJxUIPane, BorderLayout.CENTER); |
||||
dataCenterJxUIPane.addXHRHeaders(ImmutableMap.of("Authorization", |
||||
WorkContext.getCurrent().getConnection().getToken())); |
||||
} |
||||
|
||||
private static JxUIPane<String> getJxUIPane() { |
||||
return new JxUIPane.Builder<String>() |
||||
.engine(JX_ENGINE) |
||||
.namespace(DATA_CENTER) |
||||
.bindWindow(DATA_CENTER_HELPER, DatacentersJSBridge::getBridge) |
||||
.withEMB("com/fr/design/data/tabledata/datacenter/web/data-choose.prod.html", |
||||
ImmutableMap.of("fineServletURL", getDatacentersUrl())) |
||||
.build(); |
||||
} |
||||
|
||||
private static String getDatacentersUrl() { |
||||
if (!WorkContext.getCurrent().isLocal()) { |
||||
String path = WorkContext.getCurrent().getPath(); |
||||
return path.endsWith("/") ? path + "bi" : path + "/bi"; |
||||
} |
||||
return StringUtils.EMPTY; |
||||
} |
||||
|
||||
@Override |
||||
public NamePane asNamePane() { |
||||
return namePane = new JxTableDataNamePane(this); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void populateBean(DCTableData ob) { |
||||
DatacentersJSBridge.relationPanel(this); |
||||
dcTableData = ob; |
||||
dataCenterJxUIPane.populate(EmbedJson.encode(ob.toBean())); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public DCTableData updateBean() { |
||||
String data = dataCenterJxUIPane.update(); |
||||
if (StringUtils.isNotEmpty(data)) { |
||||
DCTableDataBean tableDataBean = EmbedJson.decodeValue(data, DCTableDataBean.class); |
||||
namePane.setObjectName(tableDataBean.getDsName()); |
||||
return DCTableData.fromBean(tableDataBean); |
||||
} else { |
||||
// 复制的场景下,不打开界面需要返回数据集
|
||||
return dcTableData; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 为了兼容之前的面板,编辑时更新模板的数据集,需要在updateBean之前更新到名称 |
||||
*/ |
||||
public void updateNamePane() { |
||||
String data = dataCenterJxUIPane.update(); |
||||
DCNameBean nameBean = EmbedJson.decodeValue(data, DCNameBean.class); |
||||
namePane.setObjectName(nameBean.getDsName()); |
||||
} |
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return ""; |
||||
} |
||||
} |
@ -0,0 +1,72 @@
|
||||
package com.fr.design.data.tabledata.datacenter; |
||||
|
||||
import com.fr.design.dialog.BasicDialog; |
||||
import com.fr.design.dialog.BasicPane; |
||||
import com.fr.design.dialog.BasicPane.NamePane; |
||||
import com.fr.design.dialog.DialogActionListener; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.DesignerFrame; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import java.awt.BorderLayout; |
||||
import java.awt.Dimension; |
||||
import java.awt.Window; |
||||
|
||||
/** |
||||
* 1. 覆盖namePane里面的名字组件 |
||||
* 2. 重写Dialog组件大小 |
||||
* |
||||
* @author vito |
||||
* @since 11.0 |
||||
* Created on 2024/7/20 |
||||
*/ |
||||
public class JxTableDataNamePane extends NamePane { |
||||
// 持有窗口对象,操作按钮状态
|
||||
private BasicDialog dialog; |
||||
private String dsName = StringUtils.EMPTY; |
||||
|
||||
public JxTableDataNamePane(BasicPane tableDataPane) { |
||||
super(tableDataPane); |
||||
setLayout(new BorderLayout()); |
||||
add(tableDataPane, BorderLayout.CENTER); |
||||
} |
||||
|
||||
public String getObjectName() { |
||||
return dsName; |
||||
} |
||||
|
||||
public void setObjectName(String name) { |
||||
dsName = name; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 显示窗口,重写尺寸 |
||||
* |
||||
* @param window 窗口 |
||||
* @param l 对话框监听器 |
||||
* @return 对话框 |
||||
*/ |
||||
@Override |
||||
public BasicDialog showLargeWindow(Window window, DialogActionListener l) { |
||||
this.dialog = showWindowWithCustomSize(window, l, calculatePaneDimension(), false); |
||||
return this.dialog; |
||||
} |
||||
|
||||
private static final int MIN_WIDTH = 1000; |
||||
private static final int MIN_HEIGHT = 600; |
||||
|
||||
/** |
||||
* 计算数据集窗口大小 |
||||
* 宽:80%,高:90% |
||||
* |
||||
* @return 宽高 |
||||
*/ |
||||
public static Dimension calculatePaneDimension() { |
||||
DesignerFrame parent = DesignerContext.getDesignerFrame(); |
||||
int width = Math.max((int) (parent.getWidth() * 0.8), MIN_WIDTH); |
||||
int height = Math.max((int) (parent.getHeight() * 0.9), MIN_HEIGHT); |
||||
return new Dimension(width, height); |
||||
} |
||||
} |
||||
|
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 804 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 834 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 588 B |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 582 B |
After Width: | Height: | Size: 588 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 617 B |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 182 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 182 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 931 B |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 983 B |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 737 B |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 242 B |
After Width: | Height: | Size: 6.9 KiB |