Browse Source
* commit 'b09cf5abd277f3a9a14838a088e122e0cfb886e7': (287 commits) REPORT-136473 & EPORT-136480 fix: 懒加载导致控件输入框事件异常 REPORT-135233 调整VcsOperator REPORT-135233 调整AuthorityOperator REPORT-135233 调整DecisionOperator REPORT-135233 调整TplOperator REPORT-135233 调整DataBaseTypeOperator REPORT-135233 调整TemplateExportOperator REPORT-135233 调整OrganizationOperator REPORT-135233 调整TemplateChecker REPORT-135233 调整VcsAutoCleanOperator REPORT-135233 调整DataFetcher,CommitHelper REPORT-135233 调整LockInfoOperator REPORT-135233 调整ShareEmbeddedConverter REPORT-135233 调整TableDataOperator和ConnectionOperator REPORT-135233 调整FileNodes REPORT-135996 fix: 视觉二次验收问题修复 REPORT-136212 fix: 图表创建面板优化 REPORT-136120 fix: 本地设计器启动日志级别需要全部配置保持一致 REPORT-135874 fix: 修复无法获取远程环境脱敏规则的问题 修改拖拽条颜色 ...fbp/master
634 changed files with 8104 additions and 7947 deletions
@ -0,0 +1,127 @@
|
||||
package com.fine.theme.icon.plugin; |
||||
|
||||
import com.fine.theme.icon.AbstractIconSet; |
||||
import com.fine.theme.icon.IconSet; |
||||
import com.fine.theme.icon.IconType; |
||||
import com.fine.theme.icon.JsonIconSet; |
||||
import com.fine.theme.icon.UrlIconResource; |
||||
import com.formdev.flatlaf.FlatLaf; |
||||
import com.fr.design.fun.LazyIconProvider; |
||||
import com.fr.general.GeneralContext; |
||||
import com.fr.plugin.manage.PluginFilter; |
||||
import com.fr.plugin.observer.PluginEvent; |
||||
import com.fr.plugin.observer.PluginEventListener; |
||||
import com.fr.plugin.observer.PluginEventType; |
||||
import com.fr.stable.AssistUtils; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.jetbrains.annotations.Nullable; |
||||
|
||||
import javax.swing.Icon; |
||||
import javax.swing.LookAndFeel; |
||||
import javax.swing.UIManager; |
||||
import java.awt.Dimension; |
||||
import java.util.ArrayList; |
||||
import java.util.Set; |
||||
import java.util.function.Consumer; |
||||
|
||||
|
||||
/** |
||||
* 管理插件 iconSet |
||||
* @author lemon |
||||
* @since |
||||
* Created on |
||||
*/ |
||||
public class PluginIconSet extends AbstractIconSet { |
||||
|
||||
private static final String NAME = "Plugin Icon Set"; |
||||
private static final ArrayList<IconSet> PLUGIN_ICON_SETS = new ArrayList<>(); |
||||
|
||||
public PluginIconSet() { |
||||
name = NAME; |
||||
listenPluginIcons(); |
||||
} |
||||
|
||||
/** |
||||
* 适配插件图标 Icon |
||||
*/ |
||||
public static void listenPluginIcons() { |
||||
//注册插件监听
|
||||
PluginFilter filter = context -> context.contain(LazyIconProvider.MARK_STRING); |
||||
|
||||
PluginEventListener insert = new PluginEventListener() { |
||||
@Override |
||||
public void on(PluginEvent event) { |
||||
handlePluginEvent(event, (provider) -> PLUGIN_ICON_SETS.add(generateJsonIconSet(provider))); |
||||
} |
||||
}; |
||||
|
||||
PluginEventListener remove = new PluginEventListener() { |
||||
@Override |
||||
public void on(PluginEvent event) { |
||||
handlePluginEvent(event, (provider) -> PLUGIN_ICON_SETS.removeIf(iconSet -> iconSet.getId().equals(provider.pluginId()))); |
||||
} |
||||
}; |
||||
|
||||
GeneralContext.listenPlugin(PluginEventType.AfterRun, insert, filter); |
||||
GeneralContext.listenPlugin(PluginEventType.AfterInstall, insert, filter); |
||||
GeneralContext.listenPlugin(PluginEventType.AfterForbid, remove, filter); |
||||
GeneralContext.listenPlugin(PluginEventType.AfterUninstall, remove, filter); |
||||
} |
||||
|
||||
private static void handlePluginEvent(PluginEvent event, Consumer<LazyIconProvider> consumer) { |
||||
Set<LazyIconProvider> set = event.getContext().getRuntime().get(LazyIconProvider.MARK_STRING); |
||||
for (LazyIconProvider provider : set) { |
||||
consumer.accept(provider); |
||||
} |
||||
} |
||||
|
||||
private static JsonIconSet generateJsonIconSet(LazyIconProvider provider) { |
||||
LookAndFeel laf = UIManager.getLookAndFeel(); |
||||
boolean dark = ((FlatLaf) laf).isDark(); |
||||
String jsonPath = dark ? provider.darkJsonPath() : provider.lightJsonPath(); |
||||
return new JsonIconSet(new UrlIconResource(jsonPath)) { |
||||
@Override |
||||
public @NotNull String getId() { |
||||
return provider.pluginId(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
@Override |
||||
public @Nullable Icon findIcon(@NotNull String id, @NotNull Dimension dimension, IconType type) { |
||||
Icon icon; |
||||
for (IconSet iconSet : PLUGIN_ICON_SETS) { |
||||
icon = iconSet.findIcon(id, dimension, type); |
||||
if (icon != null) { |
||||
return icon; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* 根据 id 匹配 icon set |
||||
* @param id 对于 plugin icon set, id 是 plugin_id |
||||
* @return icon set |
||||
*/ |
||||
public static IconSet getIconSet(@NotNull final String id ) { |
||||
for (IconSet iconSet : PLUGIN_ICON_SETS) { |
||||
if (iconSet.getId().equals(id)) { |
||||
return iconSet; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
return obj instanceof PluginIconSet |
||||
&& AssistUtils.equals(this.name, ((PluginIconSet) obj).name); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return AssistUtils.hashCode(name); |
||||
} |
||||
} |
@ -0,0 +1,59 @@
|
||||
package com.fine.theme.light.ui; |
||||
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils; |
||||
import com.fr.design.gui.date.UICalendarPanel; |
||||
|
||||
import javax.swing.JComponent; |
||||
import javax.swing.UIManager; |
||||
import javax.swing.border.LineBorder; |
||||
import javax.swing.plaf.ComponentUI; |
||||
import javax.swing.plaf.PanelUI; |
||||
import java.awt.Color; |
||||
|
||||
|
||||
/** |
||||
* {@link UICalendarPanel} 的 UI 样式 |
||||
* |
||||
* @author lemon |
||||
* @since 12.0 |
||||
* Created on 2024/09/22 |
||||
*/ |
||||
public class FineCalendarPaneUI extends PanelUI { |
||||
protected Color defaultBackground; |
||||
|
||||
/** |
||||
* @param shared |
||||
* @since 2 |
||||
*/ |
||||
protected FineCalendarPaneUI() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* 创建UI |
||||
* |
||||
* @param c 组件 |
||||
* @return ComponentUI |
||||
*/ |
||||
public static ComponentUI createUI(JComponent c) { |
||||
return FlatUIUtils.createSharedUI(FineCalendarPaneUI.class, FineCalendarPaneUI::new); |
||||
} |
||||
|
||||
/** |
||||
* @param c the component where this UI delegate is being installed |
||||
*/ |
||||
public void installUI(JComponent c) { |
||||
super.installUI(c); |
||||
defaultBackground = UIManager.getColor("Calendar.background"); |
||||
|
||||
//renderer this
|
||||
c.setBackground(defaultBackground); |
||||
c.setBorder(new LineBorder(FlatUIUtils.getUIColor("defaultBorderColor", Color.BLACK))); |
||||
} |
||||
|
||||
@Override |
||||
public void uninstallUI(JComponent c) { |
||||
super.uninstallUI(c); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,37 @@
|
||||
package com.fine.theme.light.ui; |
||||
|
||||
import com.formdev.flatlaf.ui.FlatComboBoxUI; |
||||
|
||||
import javax.swing.JComponent; |
||||
import javax.swing.UIManager; |
||||
import javax.swing.plaf.ComponentUI; |
||||
|
||||
|
||||
/** |
||||
* {@link com.fr.design.gui.icombocheckbox.UIComboCheckBox} 的 UI 样式 |
||||
* |
||||
* @author lemon |
||||
* @since 12.0 |
||||
* Created on 2024/09/27 |
||||
*/ |
||||
public class FineComboCheckBoxUI extends FlatComboBoxUI { |
||||
|
||||
public FineComboCheckBoxUI() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* 创建UI |
||||
*/ |
||||
public static ComponentUI createUI(JComponent c) { |
||||
return new FineComboCheckBoxUI(); |
||||
} |
||||
|
||||
@Override |
||||
public void installUI(JComponent c) { |
||||
super.installUI(c); |
||||
c.setBackground(UIManager.getColor("ComboCheckBox.background")); |
||||
c.setBorder(UIManager.getBorder("ComboCheckBox.border")); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,140 @@
|
||||
package com.fine.theme.light.ui; |
||||
|
||||
import com.formdev.flatlaf.ui.FlatLabelUI; |
||||
import com.formdev.flatlaf.ui.FlatRoundBorder; |
||||
import com.formdev.flatlaf.ui.FlatUIUtils; |
||||
import com.fr.design.gui.date.UIDayLabel; |
||||
|
||||
import javax.swing.JComponent; |
||||
import javax.swing.UIManager; |
||||
import javax.swing.plaf.ComponentUI; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.FontMetrics; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
|
||||
/** |
||||
* {@link UIDayLabel} 的 UI 样式 |
||||
* |
||||
* @author lemon |
||||
* @since 12.0 |
||||
* Created on 2024/09/22 |
||||
*/ |
||||
public class FineDayLabelUI extends FlatLabelUI { |
||||
protected Color defaultBackground; |
||||
protected Color selectedBackground; |
||||
protected Color hoverBackground; |
||||
protected Color pressedBackground; |
||||
protected Color otherMonthForeground; |
||||
|
||||
protected int arc; |
||||
|
||||
/** |
||||
* @since 2 |
||||
*/ |
||||
protected FineDayLabelUI() { |
||||
super(false); |
||||
} |
||||
|
||||
/** |
||||
* 创建UI |
||||
* |
||||
* @param c 组件 |
||||
* @return ComponentUI |
||||
*/ |
||||
public static ComponentUI createUI(JComponent c) { |
||||
return FlatUIUtils.createSharedUI(FineDayLabelUI.class, FineDayLabelUI::new); |
||||
} |
||||
|
||||
/** |
||||
* @param c the component where this UI delegate is being installed |
||||
*/ |
||||
public void installUI(JComponent c) { |
||||
super.installUI(c); |
||||
selectedBackground = UIManager.getColor("Calendar.day.selectedBackground"); |
||||
hoverBackground = UIManager.getColor("Calendar.day.hoverBackground"); |
||||
pressedBackground = UIManager.getColor("Calendar.day.pressedBackground"); |
||||
defaultBackground = UIManager.getColor("Calendar.background"); |
||||
otherMonthForeground = UIManager.getColor("Calendar.dayOtherMonth.foreground"); |
||||
|
||||
arc = UIManager.getInt("Calendar.day.arc"); |
||||
} |
||||
|
||||
@Override |
||||
public void uninstallUI(JComponent c) { |
||||
super.uninstallUI(c); |
||||
} |
||||
|
||||
/** |
||||
* UICalendarPanel paint, 目前只对 {@link UIDayLabel} 样式自定义,其余使用默认样式 |
||||
* |
||||
* @param g the <code>Graphics</code> context in which to paint |
||||
* @param c the component being painted; |
||||
* this argument is often ignored, |
||||
* but might be used if the UI object is stateless |
||||
* and shared by multiple components |
||||
*/ |
||||
public void paint(Graphics g, JComponent c) { |
||||
super.paint(g, c); |
||||
if (c instanceof UIDayLabel) { |
||||
paintDayLabel((UIDayLabel) c); |
||||
} |
||||
} |
||||
|
||||
private void paintDayLabel(UIDayLabel label) { |
||||
if (!label.isSmallLabel()) { |
||||
label.setBackground(getBackgroundColor(label)); |
||||
return; |
||||
} |
||||
|
||||
label.setBorder(new DayLabelRoundedBorder()); |
||||
|
||||
if (!label.isCurrentMonth()) { |
||||
label.setForeground(otherMonthForeground); |
||||
} |
||||
} |
||||
|
||||
private Color getBackgroundColor(UIDayLabel dayLabel) { |
||||
if (dayLabel.isSelected()) { |
||||
return selectedBackground; |
||||
} |
||||
if (dayLabel.isHovered()) { |
||||
return hoverBackground; |
||||
} |
||||
if (dayLabel.isPressed()) { |
||||
return pressedBackground; |
||||
} |
||||
return defaultBackground; |
||||
} |
||||
|
||||
/** |
||||
* {@link UIDayLabel} 的 border 样式 |
||||
*/ |
||||
private class DayLabelRoundedBorder extends FlatRoundBorder { |
||||
|
||||
public DayLabelRoundedBorder() { |
||||
} |
||||
|
||||
@Override |
||||
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { |
||||
Graphics2D g2 = (Graphics2D) g.create(); |
||||
|
||||
try { |
||||
FlatUIUtils.setRenderingHints(g2); |
||||
g2.setColor(getBackgroundColor((UIDayLabel) c)); |
||||
g2.fillRoundRect(0, 0, width, height, arc, arc); |
||||
|
||||
// 避免文字被背景色覆盖
|
||||
UIDayLabel dayLabel = (UIDayLabel) c; |
||||
g2.setColor(dayLabel.getForeground()); |
||||
FontMetrics metrics = g2.getFontMetrics(dayLabel.getFont()); |
||||
int x1 = (width - metrics.stringWidth(dayLabel.getText())) / 2; |
||||
int y1 = ((height - metrics.getHeight()) / 2) + metrics.getAscent(); |
||||
g2.drawString(dayLabel.getText(), x1, y1); |
||||
} finally { |
||||
g2.dispose(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,214 @@
|
||||
package com.fr.design; |
||||
|
||||
import com.fr.concurrent.FineExecutors; |
||||
import com.fr.concurrent.NamedThreadFactory; |
||||
import com.fr.design.mainframe.SiteCenterToken; |
||||
import com.fr.design.metric.AbstractDesignerMetric; |
||||
import com.fr.general.CloudCenter; |
||||
import com.fr.general.http.HttpToolbox; |
||||
import com.fr.json.JSONArray; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.workspace.Workspace; |
||||
import com.fr.workspace.WorkspaceSwitchProcess; |
||||
import com.fr.workspace.WorkspaceSwitchStatics; |
||||
import com.fr.workspace.switcher.WorkspaceSwitchHistory; |
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
import java.util.Comparator; |
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
import java.util.Map; |
||||
import java.util.TreeSet; |
||||
import java.util.concurrent.ExecutorService; |
||||
|
||||
/** |
||||
* 设计器环境切换埋点提交 |
||||
* |
||||
* @author Bruce.Deng |
||||
* @since 11.0 |
||||
* Created on 2024/9/5 |
||||
*/ |
||||
public class EnvSwitcherSubmitTask extends AbstractDesignerMetric { |
||||
|
||||
private static final String TAG_MODULE = "module"; |
||||
private static final String TAG_SELF_USED = "selfUsed"; |
||||
private static final String TAG_SUB = "sub"; |
||||
private static final String WORK_DIRECTORY_TYPE_BEFORE_SWITCHING = "workDirectoryTypeBeforeSwitching"; |
||||
private static final String WORK_DIRECTORY_TYPE_AFTER_SWITCHING = "workDirectoryTypeAfterSwitching"; |
||||
private static final String SWITCH_COMPLETED = "switchCompleted"; |
||||
private static final String EXCHANGE_TIME = "exchangeTime"; |
||||
private static final String START_SLOW_MODULE_NAME = "startSlowModuleName"; |
||||
private static final String STOP_SLOW_MODULE_NAME = "stopSlowModuleName"; |
||||
private static final int MIN_LIMIT = 100; |
||||
private static final String SWITCH_TABLE_SUFFIX = "record_of_fbp_remoteSwitch/single"; |
||||
private final ExecutorService service; |
||||
|
||||
private EnvSwitcherSubmitTask() { |
||||
service = FineExecutors.newSingleThreadExecutor(new NamedThreadFactory("DesignEnvSwitchMetricSubmit")); |
||||
} |
||||
|
||||
/** |
||||
* 异步提交环境切换的埋点 |
||||
*/ |
||||
public static void asyncSubmit() { |
||||
new EnvSwitcherSubmitTask().run(); |
||||
} |
||||
|
||||
/** |
||||
* 执行任务 |
||||
*/ |
||||
private void run() { |
||||
|
||||
WorkspaceSwitchHistory.consume(workspaceSwitchProcesses -> { |
||||
Iterator<WorkspaceSwitchProcess> workspaceSwitchProcessIterator = workspaceSwitchProcesses.descendingIterator(); |
||||
while (workspaceSwitchProcessIterator.hasNext()) { |
||||
WorkspaceSwitchProcess next = workspaceSwitchProcessIterator.next(); |
||||
// 过滤掉 source 为空的启动过程
|
||||
if (next != null && next.getSource() != null) { |
||||
submitProcess(next); |
||||
} |
||||
// 提交之后要移除掉
|
||||
workspaceSwitchProcessIterator.remove(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void submitProcess(WorkspaceSwitchProcess process) { |
||||
service.submit(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
collectAndSubmit(process); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void collectAndSubmit(WorkspaceSwitchProcess process) { |
||||
Map<String, Object> para = new HashMap<>(); |
||||
para.put("token", SiteCenterToken.generateToken()); |
||||
para.put("content", collect(process)); |
||||
try { |
||||
HttpToolbox.post(getUrl(), para); |
||||
FineLoggerFactory.getLogger().debug("[EnvSwitcher] submit env switcher metric to cloud."); |
||||
} catch (Throwable t) { |
||||
FineLoggerFactory.getLogger().debug(t,"[EnvSwitcher] failed to submit env switcher metric to cloud."); |
||||
} |
||||
} |
||||
|
||||
private JSONObject collect(WorkspaceSwitchProcess process) { |
||||
JSONObject info = new JSONObject(); |
||||
addDefaultMetric(info); |
||||
addMeta(info, process); |
||||
addStatics(info, process.getStatics()); |
||||
return info; |
||||
} |
||||
|
||||
private static void addMeta(JSONObject info, WorkspaceSwitchProcess process) { |
||||
Workspace source = process.getSource(); |
||||
info.put(WORK_DIRECTORY_TYPE_BEFORE_SWITCHING, workspaceType(source)); |
||||
Workspace target = process.getTarget(); |
||||
info.put(WORK_DIRECTORY_TYPE_AFTER_SWITCHING, workspaceType(target)); |
||||
info.put(SWITCH_COMPLETED, switchCompleted(process)); |
||||
} |
||||
|
||||
@NotNull |
||||
private static String switchCompleted(WorkspaceSwitchProcess process) { |
||||
|
||||
return process.isSwitchSuccess() ? "yes" : "no"; |
||||
} |
||||
|
||||
@NotNull |
||||
private static String workspaceType(Workspace workspace) { |
||||
|
||||
return workspace.isLocal() ? "local" : "remote"; |
||||
} |
||||
|
||||
private void addStatics(JSONObject info, WorkspaceSwitchStatics statics) { |
||||
info.put(EXCHANGE_TIME, statics.getElapsed()); |
||||
JSONObject startSlowModuleName = convert2CloudModel(statics.getStartModuleUsed()); |
||||
info.put(START_SLOW_MODULE_NAME, startSlowModuleName); |
||||
JSONObject stopSlowModuleName = convert2CloudModel(statics.getStopModuleUsed()); |
||||
info.put(STOP_SLOW_MODULE_NAME, stopSlowModuleName); |
||||
} |
||||
|
||||
/* convert */ |
||||
|
||||
@NotNull |
||||
private JSONObject convert2CloudModel(JSONObject moduleUsedJO) { |
||||
|
||||
TreeSet<Entry> entries = convert2SortSet(moduleUsedJO); |
||||
return convert2JO(entries); |
||||
} |
||||
|
||||
@NotNull |
||||
private static JSONObject convert2JO(TreeSet<Entry> startEntries) { |
||||
|
||||
JSONObject moduleNames = new JSONObject(); |
||||
startEntries.stream() |
||||
.filter((e) -> e.getSelfUsed() > MIN_LIMIT) |
||||
.forEach((e) -> moduleNames.put(e.getModuleName(), e.getSelfUsed())); |
||||
return moduleNames; |
||||
} |
||||
|
||||
@NotNull |
||||
private TreeSet<Entry> convert2SortSet(JSONObject moduleUsedJO) { |
||||
|
||||
TreeSet<Entry> entries = new TreeSet<>(Comparator.comparingInt(Entry::getSelfUsed)); |
||||
sortBySelfUsed(moduleUsedJO, entries); |
||||
return entries; |
||||
} |
||||
|
||||
/** |
||||
* 循环处理 JSON, 并降序排序 |
||||
* |
||||
* @param moduleUsed 模块用时 {@link com.fr.module.engine.FineModule} |
||||
* @param entries 降序排序的树集合 |
||||
*/ |
||||
private void sortBySelfUsed(JSONObject moduleUsed, TreeSet<Entry> entries) { |
||||
|
||||
if (moduleUsed == null || moduleUsed.isEmpty()) { |
||||
return; |
||||
} |
||||
|
||||
String moduleName = moduleUsed.optString(TAG_MODULE); |
||||
int selfUsed = moduleUsed.optInt(TAG_SELF_USED); |
||||
entries.add(new Entry(moduleName, selfUsed)); |
||||
|
||||
JSONArray subModules = moduleUsed.optJSONArray(TAG_SUB); |
||||
if (subModules != null) { |
||||
int length = subModules.length(); |
||||
for (int i = 0; i < length; i++) { |
||||
JSONObject subModuleUsed = subModules.optJSONObject(i); |
||||
sortBySelfUsed(subModuleUsed, entries); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private String getUrl() { |
||||
String monitorEntry = CloudCenter.getInstance().acquireUrlByKind("cloud.monitor.api.entrypoint"); |
||||
String url = (StringUtils.isNotEmpty(monitorEntry) ? monitorEntry : DEFAULT_MONITOR_URL) |
||||
+ SWITCH_TABLE_SUFFIX; |
||||
return url; |
||||
} |
||||
|
||||
private static class Entry { |
||||
|
||||
private final String moduleName; |
||||
|
||||
private final Integer selfUsed; |
||||
|
||||
public Entry(String moduleName, Integer selfUsed) { |
||||
this.moduleName = moduleName; |
||||
this.selfUsed = selfUsed; |
||||
} |
||||
|
||||
public String getModuleName() { |
||||
return moduleName; |
||||
} |
||||
|
||||
public Integer getSelfUsed() { |
||||
return selfUsed; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,235 @@
|
||||
package com.fr.design.data.datapane.preview; |
||||
|
||||
import com.fr.base.DataSetProcessors; |
||||
import com.fr.base.Parameter; |
||||
import com.fr.base.ParameterHelper; |
||||
import com.fr.base.ParameterTypeHandler; |
||||
import com.fr.base.StoreProcedureParameter; |
||||
import com.fr.base.TableData; |
||||
import com.fr.data.impl.Connection; |
||||
import com.fr.data.impl.DBTableData; |
||||
import com.fr.data.impl.NameDatabaseConnection; |
||||
import com.fr.data.impl.storeproc.StoreProcedure; |
||||
import com.fr.decision.fun.UniversalServerTableDataProvider; |
||||
import com.fr.decision.webservice.bean.dataset.ParameterBean; |
||||
import com.fr.decision.webservice.bean.dataset.ParameterExternal; |
||||
import com.fr.decision.webservice.bean.dataset.SQLDataSetBean; |
||||
import com.fr.decision.webservice.bean.dataset.ServerDataSetBean; |
||||
import com.fr.decision.webservice.bean.dataset.StoreProcedureBean; |
||||
import com.fr.decision.webservice.bean.dataset.StrategyConfigBean; |
||||
import com.fr.decision.webservice.v10.datasource.dataset.processor.impl.SQLDataSetProcessor; |
||||
import com.fr.decision.webservice.v10.datasource.dataset.processor.impl.StoreProcedureProcessor; |
||||
import com.fr.esd.core.strategy.config.StrategyConfig; |
||||
import com.fr.general.GeneralUtils; |
||||
import com.fr.general.sql.SqlUtils; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.script.Calculator; |
||||
import com.fr.security.encryption.transmission.TransmissionEncryptionManager; |
||||
import com.fr.stable.ParameterProvider; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.workspace.server.repository.connection.ConnectionRepository; |
||||
import com.fr.workspace.server.repository.tabledata.DataEncryptionHelper; |
||||
import com.fr.workspace.server.repository.tabledata.TableDataRepository; |
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 数据集bean工具类 |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2024/8/9 |
||||
*/ |
||||
public class TableDataBeanHelper { |
||||
|
||||
/** |
||||
* 获取服务器数据集 |
||||
*/ |
||||
public static Map<String, TableData> getServerTableDatas() { |
||||
final List<ServerDataSetBean> beans = TableDataRepository.getInstance().getAllTableData(); |
||||
final Map<String, Connection> connectionMap = ConnectionInfoBeanHelper.createConnectionMap(ConnectionRepository.getInstance().getAll()); |
||||
final Map<String, TableData> tableDataMap = new HashMap<>(); |
||||
try { |
||||
for (ServerDataSetBean bean : beans) { |
||||
tableDataMap.put(bean.getDatasetName() , TableDataBeanHelper.getTableDataSet(connectionMap, bean.getDatasetType(), bean.getDatasetData())); |
||||
} |
||||
} catch (Exception e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
return tableDataMap; |
||||
} |
||||
|
||||
/** |
||||
* 根据序列化数据生成tabledata |
||||
*/ |
||||
public static TableData getTableDataSet(Map<String, Connection> connectionMap, String type, String tableDataSetData) throws Exception { |
||||
if (DataSetProcessors.getProcessors().containsKey(type)) { |
||||
if (StringUtils.equals(SQLDataSetProcessor.TYPE, type)) { |
||||
return deserialize4SQL(connectionMap, null, new JSONObject(tableDataSetData)); |
||||
} else if (StringUtils.equals(StoreProcedureProcessor.TYPE, type)) { |
||||
return deserialize4Procedure(connectionMap, null, new JSONObject(tableDataSetData)); |
||||
} else { |
||||
UniversalServerTableDataProvider processor = DataSetProcessors.getProcessors().get(type); |
||||
return (TableData) processor.deserialize(null, new JSONObject(tableDataSetData)); |
||||
} |
||||
|
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private static TableData deserialize4Procedure(Map<String, Connection> connectionMap, DBTableData oldDataSet, JSONObject object) { |
||||
StoreProcedure storeProcedure = new StoreProcedure(); |
||||
StoreProcedureBean bean = object.mapTo(StoreProcedureBean.class); |
||||
storeProcedure.setShare(bean.isShare()); |
||||
storeProcedure.setMaxMemRowCount(bean.getMaxMemRowCount()); |
||||
storeProcedure.setQuery(bean.getQuery()); |
||||
if (StringUtils.isNotEmpty(bean.getDatabase())) { |
||||
Connection connection = connectionMap.get(bean.getDatabase()); |
||||
if (connection != null) { |
||||
storeProcedure.setDatabaseConnection(new NameDatabaseConnection(bean.getDatabase())); |
||||
} else { |
||||
FineLoggerFactory.getLogger().info("not find conn by {}", bean.getDatabase()); |
||||
} |
||||
} |
||||
Parameter[] parameters = new Parameter[bean.getParameters().size()]; |
||||
for (int i = 0; i < parameters.length; i++) { |
||||
ParameterBean parameterBean = bean.getParameters().get(i); |
||||
parameters[i] = (Parameter) ParameterTypeHandler.getInstance().parseParameter(parameterBean, new Parameter(parameterBean.getName())); |
||||
} |
||||
List<ParameterExternal> externals = bean.getStoreProcedureParameterBeanList(); |
||||
StoreProcedureParameter[] procedureParameters = new StoreProcedureParameter[bean.getParameters().size()]; |
||||
for (int i = 0; i < procedureParameters.length; i++) { |
||||
StoreProcedureParameter storeProcedureParameter = new StoreProcedureParameter(); |
||||
storeProcedureParameter.setName(parameters[i].getName()); |
||||
storeProcedureParameter.setValue(parameters[i].getValue()); |
||||
storeProcedureParameter.setSchema(externals.get(i).getSchema()); |
||||
storeProcedureParameter.setType(externals.get(i).getTypeInt()); |
||||
procedureParameters[i] = storeProcedureParameter; |
||||
} |
||||
storeProcedure.setParameters(procedureParameters); |
||||
return storeProcedure; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 获取服务器数据集传输的bean |
||||
*/ |
||||
public static ServerDataSetBean getServerDataSetBean(String name, TableData tableData) { |
||||
for (UniversalServerTableDataProvider processor : DataSetProcessors.getProcessors().values()) { |
||||
if (SQLDataSetProcessor.KEY.classForTableData() == tableData.getClass()) { |
||||
return serialize4SQL(name, tableData); |
||||
} else if (processor.classForTableData() == tableData.getClass()) { |
||||
ServerDataSetBean bean = new ServerDataSetBean(); |
||||
try { |
||||
bean.setDatasetData(processor.serialize(tableData).toString()); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
bean.setDatasetData(StringUtils.EMPTY); |
||||
} |
||||
bean.setDatasetName(name); |
||||
bean.setDatasetId(name); |
||||
bean.setDatasetType(processor.nameForTableData()); |
||||
return bean; |
||||
} |
||||
} |
||||
return new ServerDataSetBean(name); |
||||
} |
||||
|
||||
private static ServerDataSetBean serialize4SQL(String name, TableData tableData) { |
||||
ServerDataSetBean bean = new ServerDataSetBean(); |
||||
try { |
||||
bean.setDatasetData(serialize4SQL0((DBTableData) tableData).toString()); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
bean.setDatasetData(StringUtils.EMPTY); |
||||
} |
||||
bean.setDatasetName(name); |
||||
bean.setDatasetId(name); |
||||
bean.setDatasetType(SQLDataSetProcessor.KEY.nameForTableData()); |
||||
return bean; |
||||
} |
||||
|
||||
private static Object serialize4SQL0(DBTableData dataSet) { |
||||
SQLDataSetBean bean = new SQLDataSetBean(); |
||||
if (dataSet.getDatabase() instanceof NameDatabaseConnection) { |
||||
bean.setDatabase(((NameDatabaseConnection) dataSet.getDatabase()).getName()); |
||||
} |
||||
bean.setQuery(DataEncryptionHelper.encrypt(dataSet.getQuery())); |
||||
List<ParameterBean> parameterBeans = new ArrayList<>(); |
||||
ParameterProvider[] parameters = dataSet.getParameters(Calculator.createCalculator()); |
||||
for (ParameterProvider parameter : parameters) { |
||||
parameterBeans.add(new ParameterBean(parameter.getValue().getClass().getSimpleName(), parameter.getName(), GeneralUtils.objectToString(parameter.getValue()))); |
||||
} |
||||
bean.setParameters(parameterBeans); |
||||
StrategyConfig config = dataSet.getStrategyConfig(); |
||||
if (config != null) { |
||||
StrategyConfigBean strategyConfigBean = new StrategyConfigBean(); |
||||
strategyConfigBean.setUseGlobal(config.isUseGlobal()); |
||||
strategyConfigBean.setShouldMonitor(config.shouldMonitor()); |
||||
strategyConfigBean.setShouldEvolve(config.shouldEvolve()); |
||||
strategyConfigBean.setScheduleBySchema(config.isScheduleBySchema()); |
||||
strategyConfigBean.setTimeToLive(config.getTimeToLive()); |
||||
strategyConfigBean.setTimeToIdle(config.getTimeToIdle()); |
||||
strategyConfigBean.setUpdateInterval(config.getUpdateInterval()); |
||||
strategyConfigBean.setTerminalTime(config.getTerminalTime()); |
||||
strategyConfigBean.setUpdateSchema(config.getUpdateSchema()); |
||||
strategyConfigBean.setActiveInitiation(config.isActiveInitiation()); |
||||
strategyConfigBean.setShare(config.enabled()); |
||||
bean.setStrategyConfig(strategyConfigBean); |
||||
} |
||||
return JSONObject.mapFrom(bean); |
||||
} |
||||
|
||||
|
||||
private static TableData deserialize4SQL(Map<String, Connection> connectionMap, DBTableData oldDataSet, JSONObject object) { |
||||
DBTableData tableData = new DBTableData(); |
||||
SQLDataSetBean bean = object.mapTo(SQLDataSetBean.class); |
||||
tableData.setQuery(DataEncryptionHelper.decrypt(bean.getQuery())); |
||||
Connection connection = connectionMap.get(bean.getDatabase()); |
||||
if (connection != null) { |
||||
tableData.setDatabase(new NameDatabaseConnection(bean.getDatabase())); |
||||
} else { |
||||
FineLoggerFactory.getLogger().info("not find conn by {}", bean.getDatabase()); |
||||
} |
||||
String sql = SqlUtils.clearSqlComments(DataEncryptionHelper.decrypt(bean.getQuery())); |
||||
Parameter[] parameters = new Parameter[bean.getParameters().size()]; |
||||
for (int i = 0; i < parameters.length; i++) { |
||||
ParameterBean parameterBean = bean.getParameters().get(i); |
||||
parameters[i] = (Parameter) ParameterTypeHandler.getInstance().parseParameter(parameterBean, new Parameter(parameterBean.getName())); |
||||
} |
||||
tableData.setParameters(ParameterHelper.analyzeAndUnionSameParameters(new String[]{sql}, parameters)); |
||||
if (oldDataSet != null) { |
||||
tableData.setMaxMemRowCount(oldDataSet.getMaxMemRowCount()); |
||||
tableData.setPageQuerySql(oldDataSet.getPageQuerySql()); |
||||
tableData.setShare(oldDataSet.isShare()); |
||||
tableData.setDataQueryProcessor(oldDataSet.getDataQueryProcessor()); |
||||
} |
||||
StrategyConfig config = getStrategyConfig(bean.getStrategyConfig()); |
||||
tableData.setStrategyConfig(config); |
||||
return tableData; |
||||
} |
||||
|
||||
private static StrategyConfig getStrategyConfig(StrategyConfigBean bean) { |
||||
if (bean == null) { |
||||
return new StrategyConfig(); |
||||
} |
||||
StrategyConfig config = new StrategyConfig(); |
||||
config.setEnable(bean.isShare()); |
||||
config.setUseGlobal(bean.isUseGlobal()); |
||||
config.setShouldMonitor(bean.isShouldMonitor()); |
||||
config.setShouldEvolve(bean.isShouldEvolve()); |
||||
config.setScheduleBySchema(bean.isScheduleBySchema()); |
||||
config.setTimeToLive(bean.getTimeToLive()); |
||||
config.setTimeToIdle(bean.getTimeToIdle()); |
||||
config.setUpdateInterval(bean.getUpdateInterval()); |
||||
config.setTerminalTime(bean.getTerminalTime()); |
||||
config.setUpdateSchema(bean.getUpdateSchema()); |
||||
config.setActiveInitiation(bean.isActiveInitiation()); |
||||
return config; |
||||
} |
||||
} |
@ -0,0 +1,107 @@
|
||||
package com.fr.design.data.tabledata; |
||||
|
||||
import com.fanruan.config.impl.data.ConnectionConfigProviderFactory; |
||||
import com.fanruan.config.impl.data.TableDataConfigProviderFactory; |
||||
import com.fr.base.TableData; |
||||
import com.fr.decision.webservice.bean.dataset.FileDataSetBean; |
||||
import com.fr.decision.webservice.bean.dataset.ServerDataSetBean; |
||||
import com.fr.decision.webservice.bean.entry.FileNodeBean; |
||||
import com.fr.decision.webservice.v10.datasource.dataset.processor.impl.FileProcessor; |
||||
import com.fr.decision.webservice.v10.file.FileNodeService; |
||||
import com.fr.design.data.datapane.preview.TableDataBeanHelper; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.CommonUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.project.ProjectConstants; |
||||
import com.fr.workspace.server.repository.tabledata.BaseTableDataSource; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashSet; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* LocalTableDataSource |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2024/5/29 |
||||
*/ |
||||
public class LocalTableDataSource extends BaseTableDataSource { |
||||
@Override |
||||
public Set<String> getAllNames(String username) { |
||||
Set<String> authServerDataSetNames = new HashSet<>(); |
||||
for (String authServerDataSetName : TableDataConfigProviderFactory.getInstance().getTableDatas().keySet()) { |
||||
authServerDataSetNames.add(authServerDataSetName); |
||||
} |
||||
return authServerDataSetNames; |
||||
} |
||||
|
||||
@Override |
||||
public boolean lock(String str) { |
||||
// 本地默认锁定成功,让其执行后续动作
|
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean unlock(String str) { |
||||
// 本地默认解锁成功
|
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isLock(String str) { |
||||
// 本地默认未锁定
|
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public List<FileNodeBean> getFileList(String fileType) { |
||||
return FileProcessor.KEY.getFileList(fileType, StringUtils.EMPTY); |
||||
} |
||||
|
||||
@Override |
||||
public boolean testFilePath(FileDataSetBean fileDataSetBean) { |
||||
try { |
||||
return FileProcessor.KEY.testFilePath(fileDataSetBean); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public List<FileNodeBean> getCertificatesFile(String keyword) throws Exception { |
||||
String pPath = CommonUtils.pathJoin(ProjectConstants.RESOURCES_NAME, ProjectConstants.CERTIFICATES_DIRECTORY); |
||||
return FileNodeService.getInstance().getAllRecursiveFileNodes(pPath, ProjectConstants.RESOURCES_NAME, keyword); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public List<ServerDataSetBean> getAllTableData() { |
||||
|
||||
List<ServerDataSetBean> beans = new ArrayList<>(); |
||||
TableData[] tableDatas = TableDataConfigProviderFactory.getInstance().getTableDatas().values().toArray(new TableData[0]); |
||||
for (TableData data : tableDatas) { |
||||
beans.add(TableDataBeanHelper.getServerDataSetBean(data.getName(), data)); |
||||
} |
||||
return beans; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void add(ServerDataSetBean bean) throws Exception { |
||||
TableDataConfigProviderFactory.getInstance().addTableData(bean.getDatasetName(), TableDataBeanHelper.getTableDataSet(ConnectionConfigProviderFactory.getConfigProvider().getConnections(), bean.getDatasetType(), bean.getDatasetData())); |
||||
} |
||||
|
||||
@Override |
||||
public void delete(ServerDataSetBean bean) throws Exception { |
||||
TableDataConfigProviderFactory.getInstance().removeTableData(bean.getDatasetName()); |
||||
} |
||||
|
||||
@Override |
||||
public void update(ServerDataSetBean bean) throws Exception { |
||||
TableDataConfigProviderFactory.getInstance().updateTableData(bean.getDatasetName(), TableDataBeanHelper.getTableDataSet(ConnectionConfigProviderFactory.getConfigProvider().getConnections(), bean.getDatasetType(), bean.getDatasetData())); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,46 @@
|
||||
package com.fr.design.data.tabledata.tabledatapane; |
||||
|
||||
import com.fr.base.AbstractTableData; |
||||
import com.fr.design.data.tabledata.datacenter.DCTableDataPane; |
||||
import com.fr.third.guava.collect.Sets; |
||||
|
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* 数据集面板帮助类 |
||||
* |
||||
* @author vito |
||||
* @since 11.0 |
||||
* Created on 2024/9/10 |
||||
*/ |
||||
public class TableDataPaneHelper { |
||||
/** |
||||
* 标记优先使用带名称的构造方法 |
||||
*/ |
||||
private final static Set<Class<? extends AbstractTableDataPane<? extends AbstractTableData>>> NAMED_TABLE_DATA_PANE = |
||||
Sets.newHashSet( |
||||
MultiTDTableDataPane.class, |
||||
GlobalMultiTDTableDataPane.class, |
||||
TreeTableDataPane.class, |
||||
GlobalTreeTableDataPane.class, |
||||
DCTableDataPane.class); |
||||
|
||||
/** |
||||
* 是否为带名称的数据集面板 |
||||
* |
||||
* @param tableDataPaneClass 数据集面板类 |
||||
* @return 是否为带名称的数据集面板 |
||||
*/ |
||||
public static boolean isNamedTableDataPane(Class<?> tableDataPaneClass) { |
||||
return NAMED_TABLE_DATA_PANE.contains(tableDataPaneClass); |
||||
} |
||||
|
||||
/** |
||||
* 注册需要名称的数据集面板 |
||||
* |
||||
* @param tableDataPaneClass 数据集面板类 |
||||
*/ |
||||
public static void registerNamedTableDataPane(Class<? extends AbstractTableDataPane<? extends AbstractTableData>> tableDataPaneClass) { |
||||
NAMED_TABLE_DATA_PANE.add(tableDataPaneClass); |
||||
} |
||||
} |
@ -1,42 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.design.dialog.UIDialog; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.stable.StableUtils; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
|
||||
/** |
||||
* Created by vito on 2017/5/5. |
||||
*/ |
||||
public class LoginDialog extends UIDialog { |
||||
private static final Dimension DEFAULT_SHOP = new Dimension(401, 301); |
||||
|
||||
public LoginDialog(Frame frame, Component pane) { |
||||
super(frame); |
||||
init(pane); |
||||
} |
||||
|
||||
public LoginDialog(Dialog dialog, Component pane) { |
||||
super(dialog); |
||||
init(pane); |
||||
} |
||||
|
||||
private void init(Component pane) { |
||||
if (StableUtils.getMajorJavaVersion() >= 8) { |
||||
setUndecorated(true); |
||||
} |
||||
JPanel panel = (JPanel) getContentPane(); |
||||
panel.setLayout(new BorderLayout()); |
||||
add(pane, BorderLayout.CENTER); |
||||
setSize(DEFAULT_SHOP); |
||||
GUICoreUtils.centerWindow(this); |
||||
setResizable(false); |
||||
} |
||||
|
||||
@Override |
||||
public void checkValid() throws Exception { |
||||
// do nothing
|
||||
} |
||||
} |
@ -1,200 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fanruan.carina.Carina; |
||||
import com.fanruan.cloud.FanruanCloud; |
||||
import com.fanruan.config.bbs.FineBBSConfigProvider; |
||||
import com.fr.concurrent.NamedThreadFactory; |
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.dialog.UIDialog; |
||||
import com.fr.design.extra.exe.PluginLoginExecutor; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.locale.impl.BbsRegisterMark; |
||||
import com.fr.design.locale.impl.BbsResetMark; |
||||
import com.fr.design.login.service.DesignerLoginClient; |
||||
import com.fr.design.login.service.DesignerLoginResult; |
||||
import com.fr.general.CloudCenter; |
||||
import com.fr.general.http.HttpClient; |
||||
import com.fr.general.locale.LocaleCenter; |
||||
import com.fr.general.locale.LocaleMark; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.StringUtils; |
||||
import javafx.concurrent.Task; |
||||
import javafx.scene.web.WebEngine; |
||||
import netscape.javascript.JSObject; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
import java.net.URI; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.Executors; |
||||
|
||||
/** |
||||
* @author vito |
||||
*/ |
||||
public class LoginWebBridge { |
||||
|
||||
//最低消息的条数
|
||||
private static final int MIN_MESSAGE_COUNT = 0; |
||||
//网络连接失败
|
||||
private static final String NET_FAILED = "-4"; |
||||
//用户名,密码为空
|
||||
private static final String LOGIN_INFO_EMPTY = "-5"; |
||||
private static final Color LOGIN_BACKGROUND = new Color(184, 220, 242); |
||||
private static LoginWebBridge helper; |
||||
//消息条数
|
||||
private int messageCount; |
||||
private UIDialog uiDialog; |
||||
private UIDialog qqDialog; |
||||
private UILabel uiLabel; |
||||
private WebEngine webEngine; |
||||
|
||||
private LoginWebBridge() { |
||||
} |
||||
|
||||
public static LoginWebBridge getHelper() { |
||||
if (helper != null) { |
||||
return helper; |
||||
} |
||||
synchronized (LoginWebBridge.class) { |
||||
if (helper == null) { |
||||
helper = new LoginWebBridge(); |
||||
} |
||||
return helper; |
||||
} |
||||
} |
||||
|
||||
public static LoginWebBridge getHelper(WebEngine webEngine) { |
||||
getHelper(); |
||||
helper.setWebEngine(webEngine); |
||||
return helper; |
||||
} |
||||
|
||||
public void setWebEngine(WebEngine webEngine) { |
||||
this.webEngine = webEngine; |
||||
} |
||||
|
||||
public int getMessageCount() { |
||||
return messageCount; |
||||
} |
||||
|
||||
/** |
||||
* 设置获取的消息长度,并设置显示 |
||||
* |
||||
* @param count |
||||
*/ |
||||
public void setMessageCount(int count) { |
||||
if (count == MIN_MESSAGE_COUNT) { |
||||
Carina.config(FineBBSConfigProvider.class).setBbsUsername(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()); |
||||
return; |
||||
} |
||||
this.messageCount = count; |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append(StringUtils.BLANK).append(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()) |
||||
.append("(").append(this.messageCount) |
||||
.append(")").append(StringUtils.BLANK); |
||||
Carina.config(FineBBSConfigProvider.class).setBbsUsername(sb.toString()); |
||||
} |
||||
|
||||
public void setQQDialog(UIDialog qqDialog) { |
||||
closeQQWindow(); |
||||
this.qqDialog = qqDialog; |
||||
} |
||||
|
||||
public void setDialogHandle(UIDialog uiDialog) { |
||||
closeWindow(); |
||||
this.uiDialog = uiDialog; |
||||
} |
||||
|
||||
public void setUILabel(UILabel uiLabel) { |
||||
this.uiLabel = uiLabel; |
||||
} |
||||
|
||||
/** |
||||
* 测试论坛网络连接 |
||||
* |
||||
* @return |
||||
*/ |
||||
private boolean testConnection() { |
||||
HttpClient client = new HttpClient(CloudCenter.getInstance().acquireUrlByKind("bbs.test")); |
||||
return client.isServerAlive(); |
||||
} |
||||
|
||||
/** |
||||
* 注册页面 |
||||
*/ |
||||
public void registerHref() { |
||||
try { |
||||
LocaleMark<String> registerMark = LocaleCenter.getMark(BbsRegisterMark.class); |
||||
Desktop.getDesktop().browse(new URI(registerMark.getValue())); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 忘记密码 |
||||
*/ |
||||
public void forgetHref() { |
||||
try { |
||||
LocaleMark<String> resetMark = LocaleCenter.getMark(BbsResetMark.class); |
||||
Desktop.getDesktop().browse(new URI(resetMark.getValue())); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 设计器端的用户登录 |
||||
* |
||||
* @param username 用户名 |
||||
* @param password 密码 |
||||
* @return 登录信息标志 |
||||
*/ |
||||
public void defaultLogin(String username, String password, final JSObject callback) { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new PluginLoginExecutor(username, password)); |
||||
ExecutorService es = Executors.newSingleThreadExecutor(new NamedThreadFactory("bbsDefaultLogin")); |
||||
es.submit(task); |
||||
es.shutdown(); |
||||
} |
||||
|
||||
/** |
||||
* 登录操作 |
||||
* |
||||
* @param userInfo 登录信息 |
||||
* @param password 密码 |
||||
* @return 登录信息标志 |
||||
*/ |
||||
public String login(String userInfo, String password) { |
||||
DesignerLoginClient client = new DesignerLoginClient(); |
||||
DesignerLoginResult result = client.login(userInfo, password); |
||||
int uid = result.getUid(); |
||||
if (uid > 0) { |
||||
closeWindow(); |
||||
} |
||||
return String.valueOf(uid); |
||||
} |
||||
|
||||
/** |
||||
* 关闭窗口 |
||||
*/ |
||||
public void closeWindow() { |
||||
if (uiDialog != null) { |
||||
uiDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); |
||||
uiDialog.setVisible(false); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 关闭QQ授权窗口 |
||||
*/ |
||||
public void closeQQWindow() { |
||||
if (qqDialog != null) { |
||||
qqDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); |
||||
qqDialog.setVisible(false); |
||||
} |
||||
} |
||||
|
||||
public void openUrlAtLocalWebBrowser(WebEngine eng, String url) { |
||||
// do nothing
|
||||
} |
||||
} |
@ -1,54 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import javafx.application.Platform; |
||||
import javafx.embed.swing.JFXPanel; |
||||
import javafx.event.EventHandler; |
||||
import javafx.scene.Scene; |
||||
import javafx.scene.layout.BorderPane; |
||||
import javafx.scene.web.WebEngine; |
||||
import javafx.scene.web.WebEvent; |
||||
import javafx.scene.web.WebView; |
||||
import netscape.javascript.JSObject; |
||||
|
||||
import javax.swing.*; |
||||
|
||||
/** |
||||
* Created by zhaohehe on 16/7/26. |
||||
*/ |
||||
public class LoginWebPane extends JFXPanel { |
||||
|
||||
public LoginWebPane(final String installHome) { |
||||
Platform.setImplicitExit(false); |
||||
Platform.runLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
BorderPane root = new BorderPane(); |
||||
Scene scene = new Scene(root); |
||||
LoginWebPane.this.setScene(scene); |
||||
WebView webView = new WebView(); |
||||
WebEngine webEngine = webView.getEngine(); |
||||
webEngine.load("file:///" + installHome + "/scripts/login.html"); |
||||
webEngine.setOnAlert(new EventHandler<WebEvent<String>>() { |
||||
@Override |
||||
public void handle(WebEvent<String> event) { |
||||
showAlert(event.getData()); |
||||
} |
||||
}); |
||||
JSObject obj = (JSObject) webEngine.executeScript("window"); |
||||
obj.setMember("LoginHelper", LoginWebBridge.getHelper(webEngine)); |
||||
webView.setContextMenuEnabled(false);//屏蔽右键
|
||||
root.setCenter(webView); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void showAlert(final String message) { |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
FineJOptionPane.showMessageDialog(LoginWebPane.this, message); |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -1,601 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fanruan.carina.Carina; |
||||
import com.fanruan.cloud.FanruanCloud; |
||||
import com.fanruan.config.bbs.FineBBSConfigProvider; |
||||
import com.fr.config.MarketConfig; |
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.RestartHelper; |
||||
import com.fr.design.bridge.exec.JSCallback; |
||||
import com.fr.design.dialog.UIDialog; |
||||
import com.fr.design.extra.exe.GetInstalledPluginsExecutor; |
||||
import com.fr.design.extra.exe.GetPluginCategoriesExecutor; |
||||
import com.fr.design.extra.exe.GetPluginFromStoreExecutor; |
||||
import com.fr.design.extra.exe.GetPluginPrefixExecutor; |
||||
import com.fr.design.extra.exe.PluginLoginExecutor; |
||||
import com.fr.design.extra.exe.ReadUpdateOnlineExecutor; |
||||
import com.fr.design.extra.exe.SearchOnlineExecutor; |
||||
import com.fr.design.locale.impl.BbsRegisterMark; |
||||
import com.fr.design.locale.impl.BbsResetMark; |
||||
import com.fr.design.locale.impl.BbsSpaceMark; |
||||
import com.fr.design.login.DesignerLoginSource; |
||||
import com.fr.design.plugin.DesignerPluginContext; |
||||
import com.fr.design.utils.concurrent.ThreadFactoryBuilder; |
||||
import com.fr.general.locale.LocaleCenter; |
||||
import com.fr.general.locale.LocaleMark; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.plugin.context.PluginMarker; |
||||
import com.fr.stable.ArrayUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import javafx.concurrent.Task; |
||||
import javafx.scene.web.WebEngine; |
||||
import javafx.stage.FileChooser; |
||||
import javafx.stage.Stage; |
||||
import netscape.javascript.JSObject; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
import java.util.concurrent.ThreadPoolExecutor; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
/** |
||||
* 开放给Web组件的接口,用于安装,卸载,更新以及更改插件可用状态 |
||||
*/ |
||||
public class PluginWebBridge { |
||||
private static final String THREAD_NAME_TEMPLATE = "pluginbridge-thread-%s"; |
||||
private static final String ACTION = "action"; |
||||
private static final String KEYWORD = "keyword"; |
||||
private static final String PLUGIN_INFO = "pluginInfo"; |
||||
private static final int COREPOOLSIZE = 3; |
||||
private static final int MAXPOOLSIZE = 5; |
||||
|
||||
private static PluginWebBridge helper; |
||||
|
||||
private UIDialog uiDialog; |
||||
private ACTIONS actions; |
||||
|
||||
private Map<String, Object> config; |
||||
private WebEngine webEngine; |
||||
|
||||
private ExecutorService threadPoolExecutor = new ThreadPoolExecutor(COREPOOLSIZE, MAXPOOLSIZE, |
||||
0L, TimeUnit.MILLISECONDS, |
||||
new LinkedBlockingQueue<Runnable>(COREPOOLSIZE), |
||||
new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); |
||||
|
||||
private PluginWebBridge() { |
||||
} |
||||
|
||||
public static PluginWebBridge getHelper() { |
||||
if (helper != null) { |
||||
return helper; |
||||
} |
||||
synchronized (PluginWebBridge.class) { |
||||
if (helper == null) { |
||||
helper = new PluginWebBridge(); |
||||
} |
||||
return helper; |
||||
} |
||||
} |
||||
|
||||
public static PluginWebBridge getHelper(WebEngine webEngine) { |
||||
getHelper(); |
||||
helper.setEngine(webEngine); |
||||
return helper; |
||||
} |
||||
|
||||
/** |
||||
* 获取打开动作配置 |
||||
* |
||||
* @return 配置信息 |
||||
*/ |
||||
public String getRunConfig() { |
||||
if (actions != null) { |
||||
JSONObject jsonObject = new JSONObject(); |
||||
try { |
||||
jsonObject.put(ACTION, actions.getContext()); |
||||
Set<String> keySet = config.keySet(); |
||||
for (String key : keySet) { |
||||
jsonObject.put(key, config.get(key).toString()); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
return jsonObject.toString(); |
||||
} |
||||
return StringUtils.EMPTY; |
||||
} |
||||
|
||||
/** |
||||
* 配置打开动作 |
||||
* |
||||
* @param action 动作 |
||||
* @param config 参数 |
||||
*/ |
||||
public void setRunConfig(ACTIONS action, Map<String, Object> config) { |
||||
this.actions = action; |
||||
this.config = config; |
||||
} |
||||
|
||||
/** |
||||
* 清楚打开动作 |
||||
*/ |
||||
public void clearRunConfig() { |
||||
this.actions = null; |
||||
this.config = null; |
||||
} |
||||
|
||||
/** |
||||
* 打开时搜索 |
||||
* |
||||
* @param keyword 关键词 |
||||
*/ |
||||
|
||||
public void openWithSearch(String keyword) { |
||||
HashMap<String, Object> map = new HashMap<String, Object>(2); |
||||
map.put(KEYWORD, keyword); |
||||
setRunConfig(ACTIONS.SEARCH, map); |
||||
} |
||||
|
||||
/** |
||||
* 根据插件信息跳转到应用中心 |
||||
* |
||||
* @param keyword |
||||
* @param pluginInfo |
||||
*/ |
||||
public void showResultInStore(String keyword, String pluginInfo) { |
||||
HashMap<String, Object> map = new HashMap<>(); |
||||
map.put(KEYWORD, keyword); |
||||
map.put(PLUGIN_INFO, pluginInfo); |
||||
setRunConfig(ACTIONS.SHOW_RESULT, map); |
||||
} |
||||
|
||||
public void setEngine(WebEngine webEngine) { |
||||
this.webEngine = webEngine; |
||||
} |
||||
|
||||
public void setDialogHandle(UIDialog uiDialog) { |
||||
closeWindow(); |
||||
this.uiDialog = uiDialog; |
||||
} |
||||
|
||||
/** |
||||
* 从插件服务器上安装插件 |
||||
* |
||||
* @param pluginInfo 插件的ID |
||||
* @param callback 回调函数 |
||||
*/ |
||||
public void installPluginOnline(final String pluginInfo, final JSObject callback) { |
||||
JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); |
||||
PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo); |
||||
PluginOperateUtils.installPluginOnline(pluginMarker, jsCallback); |
||||
} |
||||
|
||||
/** |
||||
* 从磁盘上选择插件安装包进行安装 |
||||
* |
||||
* @param filePath 插件包的路径 |
||||
*/ |
||||
public void installPluginFromDisk(final String filePath, final JSObject callback) { |
||||
JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); |
||||
File file = new File(filePath); |
||||
PluginOperateUtils.installPluginFromDisk(file, jsCallback); |
||||
} |
||||
|
||||
/** |
||||
* 卸载当前选中的插件 |
||||
* |
||||
* @param pluginInfo 插件信息 |
||||
*/ |
||||
public void uninstallPlugin(final String pluginInfo, final boolean isForce, final JSObject callback) { |
||||
JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); |
||||
PluginOperateUtils.uninstallPlugin(pluginInfo, isForce, jsCallback); |
||||
} |
||||
|
||||
/** |
||||
* 从插件服务器上更新选中的插件 |
||||
* |
||||
* @param pluginIDs 插件集合 |
||||
*/ |
||||
public void updatePluginOnline(JSObject pluginIDs, final JSObject callback) { |
||||
JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); |
||||
String[] pluginInfos = jsObjectToStringArray(pluginIDs); |
||||
List<PluginMarker> pluginMarkerList = new ArrayList<PluginMarker>(); |
||||
for (int i = 0; i < pluginInfos.length; i++) { |
||||
pluginMarkerList.add(PluginUtils.createPluginMarker(pluginInfos[i])); |
||||
} |
||||
PluginOperateUtils.updatePluginOnline(pluginMarkerList, jsCallback); |
||||
} |
||||
|
||||
/** |
||||
* 从磁盘上选择插件安装包进行插件升级 |
||||
* |
||||
* @param filePath 插件包的路径 |
||||
*/ |
||||
public void updatePluginFromDisk(String filePath, final JSObject callback) { |
||||
JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); |
||||
File file = new File(filePath); |
||||
PluginOperateUtils.updatePluginFromDisk(file, jsCallback); |
||||
} |
||||
|
||||
/** |
||||
* 修改选中的插件的活跃状态 |
||||
* |
||||
* @param pluginID 插件ID |
||||
*/ |
||||
public void setPluginActive(String pluginID, final JSObject callback) { |
||||
JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); |
||||
PluginOperateUtils.setPluginActive(pluginID, jsCallback); |
||||
} |
||||
|
||||
/** |
||||
* 已安装插件检查更新 |
||||
*/ |
||||
public void readUpdateOnline(final JSObject callback) { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new ReadUpdateOnlineExecutor()); |
||||
threadPoolExecutor.submit(task); |
||||
} |
||||
|
||||
/** |
||||
* 选择文件对话框 |
||||
* |
||||
* @return 选择的文件的路径 |
||||
*/ |
||||
public String showFileChooser() { |
||||
return showFileChooserWithFilter(StringUtils.EMPTY, StringUtils.EMPTY); |
||||
} |
||||
|
||||
/** |
||||
* 选择文件对话框 |
||||
* |
||||
* @param des 过滤文件描述 |
||||
* @param filter 文件的后缀 |
||||
* @return 选择的文件的路径 |
||||
* 这里换用JFileChooser会卡死,不知道为什么 |
||||
*/ |
||||
public String showFileChooserWithFilter(String des, String filter) { |
||||
FileChooser fileChooser = new FileChooser(); |
||||
|
||||
if (StringUtils.isNotEmpty(filter)) { |
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(des, filter)); |
||||
} |
||||
|
||||
File selectedFile = fileChooser.showOpenDialog(new Stage()); |
||||
if (selectedFile == null) { |
||||
return null; |
||||
} |
||||
return selectedFile.getAbsolutePath(); |
||||
} |
||||
|
||||
/** |
||||
* 选择文件对话框 |
||||
* |
||||
* @param des 过滤文件描述 |
||||
* @param args 文件的后缀 |
||||
* @return 选择的文件的路径 |
||||
*/ |
||||
public String showFileChooserWithFilters(String des, JSObject args) { |
||||
FileChooser fileChooser = new FileChooser(); |
||||
String[] filters = jsObjectToStringArray(args); |
||||
if (ArrayUtils.isNotEmpty(filters)) { |
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(des, filters)); |
||||
} |
||||
|
||||
File selectedFile = fileChooser.showOpenDialog(new Stage()); |
||||
if (selectedFile == null) { |
||||
return null; |
||||
} |
||||
return selectedFile.getAbsolutePath(); |
||||
} |
||||
|
||||
/** |
||||
* 获取已经安装的插件的数组 |
||||
* |
||||
* @return 已安装的插件组成的数组 |
||||
*/ |
||||
public void getInstalledPlugins(final JSObject callback) { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new GetInstalledPluginsExecutor()); |
||||
threadPoolExecutor.submit(task); |
||||
} |
||||
|
||||
private String[] jsObjectToStringArray(JSObject obj) { |
||||
if (obj == null) { |
||||
return ArrayUtils.EMPTY_STRING_ARRAY; |
||||
} |
||||
int len = (int) obj.getMember("length"); |
||||
List<String> list = new ArrayList<>(); |
||||
for (int i = 0; i < len; i++) { |
||||
list.add(obj.getSlot(i).toString()); |
||||
} |
||||
return list.toArray(new String[len]); |
||||
} |
||||
|
||||
/** |
||||
* 搜索在线插件 |
||||
* |
||||
* @param keyword 关键字 |
||||
*/ |
||||
public void searchPlugin(String keyword, final JSObject callback) { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new SearchOnlineExecutor(keyword)); |
||||
threadPoolExecutor.submit(task); |
||||
} |
||||
|
||||
/** |
||||
* 根据条件获取在线插件的 |
||||
* |
||||
* @param category 分类 |
||||
* @param seller 卖家性质 |
||||
* @param fee 收费类型 |
||||
* @param callback 回调函数 |
||||
*/ |
||||
public void getPluginFromStore(String category, String seller, String fee, final JSObject callback) { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new GetPluginFromStoreExecutor(category, seller, fee, "")); |
||||
threadPoolExecutor.submit(task); |
||||
} |
||||
|
||||
/** |
||||
* 根据条件获取在线插件 |
||||
* |
||||
* @param info 插件信息 |
||||
* @param callback 回调函数 |
||||
*/ |
||||
public void getPluginFromStoreNew(String info, final JSObject callback) { |
||||
try { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new GetPluginFromStoreExecutor(new JSONObject(info))); |
||||
threadPoolExecutor.submit(task); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
|
||||
public void getPluginPrefix(final JSObject callback) { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new GetPluginPrefixExecutor()); |
||||
threadPoolExecutor.submit(task); |
||||
} |
||||
|
||||
/** |
||||
* 在线获取插件分类 |
||||
* |
||||
* @param callback 回调函数 |
||||
*/ |
||||
public void getPluginCategories(final JSObject callback) { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new GetPluginCategoriesExecutor()); |
||||
threadPoolExecutor.submit(task); |
||||
} |
||||
|
||||
/** |
||||
* 展示一个重启的对话框(少用,莫名其妙会有bug) |
||||
* |
||||
* @param message 展示的消息 |
||||
*/ |
||||
public void showRestartMessage(String message) { |
||||
int rv = JOptionPane.showOptionDialog( |
||||
null, |
||||
message, |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), |
||||
JOptionPane.YES_NO_OPTION, |
||||
JOptionPane.INFORMATION_MESSAGE, |
||||
null, |
||||
new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Restart_Designer"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Restart_Designer_Later")}, |
||||
null |
||||
); |
||||
if (rv == JOptionPane.OK_OPTION) { |
||||
RestartHelper.restart(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 关闭窗口 |
||||
*/ |
||||
public void closeWindow() { |
||||
if (uiDialog != null) { |
||||
uiDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); |
||||
uiDialog.setVisible(false); |
||||
} |
||||
if (uiDialog == DesignerPluginContext.getPluginDialog()) { |
||||
DesignerPluginContext.setPluginDialog(null); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 窗口是否无装饰(判断是否使用系统标题栏) |
||||
*/ |
||||
public boolean isCustomTitleBar() { |
||||
if (uiDialog != null) { |
||||
return uiDialog.isUndecorated(); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* 获取系统登录的用户名 |
||||
* |
||||
* @param callback |
||||
*/ |
||||
public String getLoginInfo(final JSObject callback) { |
||||
registerLoginInfo(callback); |
||||
return DesignerEnvManager.getEnvManager().getDesignerLoginUsername(); |
||||
} |
||||
|
||||
/** |
||||
* 系统登录注册 |
||||
* |
||||
* @param callback |
||||
*/ |
||||
public void registerLoginInfo(final JSObject callback) { |
||||
JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); |
||||
PluginOperateUtils.getLoginInfo(jsCallback); |
||||
} |
||||
|
||||
/** |
||||
* 打开论坛消息界面 |
||||
*/ |
||||
public void getPriviteMessage() { |
||||
try { |
||||
LocaleMark<String> spaceMark = LocaleCenter.getMark(BbsSpaceMark.class); |
||||
Desktop.getDesktop().browse(new URI(spaceMark.getValue())); |
||||
} catch (Exception exp) { |
||||
FineLoggerFactory.getLogger().info(exp.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 打开登录页面 |
||||
*/ |
||||
public void loginContent() { |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
UserLoginContext.fireLoginContextListener(DesignerLoginSource.NORMAL); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 在本地浏览器里打开url |
||||
* tips:重载的时候,需要给js调用的方法需要放在前面,否则可能不会被调用(此乃坑) |
||||
* 所以最好的是不要重载在js可以访问的接口文件中 |
||||
* |
||||
* @param url 要打开的地址 |
||||
*/ |
||||
public void openShopUrlAtWebBrowser(String url) { |
||||
openUrlAtLocalWebBrowser(webEngine, url); |
||||
} |
||||
|
||||
/** |
||||
* 在本地浏览器里打开url |
||||
* |
||||
* @param eng web引擎 |
||||
* @param url 要打开的地址 |
||||
*/ |
||||
public void openUrlAtLocalWebBrowser(WebEngine eng, String url) { |
||||
if (Desktop.isDesktopSupported()) { |
||||
try { |
||||
//创建一个URI实例,注意不是URL
|
||||
URI uri = URI.create(url); |
||||
//获取当前系统桌面扩展
|
||||
Desktop desktop = Desktop.getDesktop(); |
||||
//判断系统桌面是否支持要执行的功能
|
||||
if (desktop.isSupported(Desktop.Action.BROWSE)) { |
||||
//获取系统默认浏览器打开链接
|
||||
desktop.browse(uri); |
||||
} |
||||
} catch (NullPointerException e) { |
||||
//此为uri为空时抛出异常
|
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} catch (IOException e) { |
||||
//此为无法获取系统默认浏览器
|
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 注册页面 |
||||
*/ |
||||
public void registerHref() { |
||||
try { |
||||
LocaleMark<String> registerMark = LocaleCenter.getMark(BbsRegisterMark.class); |
||||
Desktop.getDesktop().browse(new URI(registerMark.getValue())); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().info(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
|
||||
/*-------------------------------登录部分的处理----------------------------------*/ |
||||
|
||||
/** |
||||
* 忘记密码 |
||||
*/ |
||||
public void forgetHref() { |
||||
try { |
||||
LocaleMark<String> resetMark = LocaleCenter.getMark(BbsResetMark.class); |
||||
Desktop.getDesktop().browse(new URI(resetMark.getValue())); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().info(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 设计器端的用户登录 |
||||
* |
||||
* @param username 用户名 |
||||
* @param password 密码 |
||||
* @return 登录信息标志 |
||||
*/ |
||||
public void defaultLogin(String username, String password, final JSObject callback) { |
||||
Task<Void> task = new PluginTask<>(webEngine, callback, new PluginLoginExecutor(username, password)); |
||||
threadPoolExecutor.submit(task); |
||||
} |
||||
|
||||
/** |
||||
* 通过QQ登录后通知登录 |
||||
*/ |
||||
public void ucsynLogin(long uid, String username, String password, final JSONObject callback) { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 清除用户信息 |
||||
*/ |
||||
public void clearUserInfo() { |
||||
Carina.config(FineBBSConfigProvider.class).setBbsUsername(StringUtils.EMPTY); |
||||
} |
||||
|
||||
public void getPackInfo(final JSObject callback){ |
||||
JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); |
||||
jsCallback.execute(StringUtils.EMPTY); |
||||
} |
||||
|
||||
/** |
||||
* 初始化设计器部分 |
||||
*/ |
||||
public void initExtraDiff(final JSObject callback) { |
||||
//todo 初始化设计器其他部分
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* 国际化(用来做兼容,暂时不删) |
||||
*/ |
||||
public String parseI18(final String key) { |
||||
return com.fr.design.i18n.Toolkit.i18nText(key); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 是否是在设计器中操作 |
||||
*/ |
||||
public boolean isDesigner() { |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 动作枚举 |
||||
*/ |
||||
public enum ACTIONS { |
||||
SEARCH("search"), SHOW_RESULT("showResult"); |
||||
private String context; |
||||
|
||||
ACTIONS(String context) { |
||||
this.context = context; |
||||
} |
||||
|
||||
public String getContext() { |
||||
return context; |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,112 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.base.TemplateUtils; |
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.general.GeneralContext; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.EncodeConstants; |
||||
import com.fr.stable.StableUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import javafx.application.Platform; |
||||
import javafx.embed.swing.JFXPanel; |
||||
import javafx.event.EventHandler; |
||||
import javafx.scene.Scene; |
||||
import javafx.scene.layout.BorderPane; |
||||
import javafx.scene.web.WebEngine; |
||||
import javafx.scene.web.WebEvent; |
||||
import javafx.scene.web.WebView; |
||||
import netscape.javascript.JSObject; |
||||
|
||||
import javax.swing.JOptionPane; |
||||
import javax.swing.SwingUtilities; |
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.net.URLEncoder; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Created by richie on 16/3/19. |
||||
*/ |
||||
public class PluginWebPane extends JFXPanel { |
||||
private static final String RESOURCE_URL = "resourceURL"; |
||||
private static final String LANGUAGE = "language"; |
||||
private static final String URL_PLUS = "+"; |
||||
private static final String URL_SPACING = "%20"; |
||||
private static final String URL_PREFIX = "file:///"; |
||||
private WebEngine webEngine; |
||||
|
||||
public PluginWebPane(final String installHome, final String mainJs) { |
||||
Platform.setImplicitExit(false); |
||||
Platform.runLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
BorderPane root = new BorderPane(); |
||||
Scene scene = new Scene(root); |
||||
PluginWebPane.this.setScene(scene); |
||||
WebView webView = new WebView(); |
||||
webEngine = webView.getEngine(); |
||||
try{ |
||||
String htmlString = getRenderedHtml(installHome, mainJs); |
||||
webEngine.loadContent(htmlString); |
||||
webEngine.setOnAlert(new EventHandler<WebEvent<String>>() { |
||||
@Override |
||||
public void handle(WebEvent<String> event) { |
||||
showAlert(event.getData()); |
||||
} |
||||
}); |
||||
JSObject obj = (JSObject) webEngine.executeScript("window"); |
||||
obj.setMember("PluginHelper", PluginWebBridge.getHelper(webEngine)); |
||||
webView.setContextMenuEnabled(false);//屏蔽右键
|
||||
root.setCenter(webView); |
||||
}catch (Exception e){ |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
|
||||
} |
||||
}); |
||||
} |
||||
|
||||
private String getRenderedHtml(String installHome, String mainJs) throws IOException { |
||||
InputStream inp = IOUtils.readResource(StableUtils.pathJoin(installHome, mainJs)); |
||||
if (inp == null) { |
||||
throw new IOException("Not found template: " + mainJs); |
||||
} |
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inp, StableUtils.RESOURCE_ENCODER)); |
||||
BufferedReader read = new BufferedReader(reader); |
||||
StringBuffer sb = new StringBuffer(); |
||||
String line; |
||||
Map<String, Object> map4Tpl = new HashMap<String, Object>(); |
||||
//URL中关于空格的编码与空格所在位置相关:空格被编码成+的情况只能在查询字符串部分出现,而被编码成%20则可以出现在路径和查询字符串中
|
||||
//URLEncoder会将空格转成+,这边需要+转成%20
|
||||
map4Tpl.put(RESOURCE_URL, URL_PREFIX + URLEncoder.encode(installHome, EncodeConstants.ENCODING_UTF_8).replace(URL_PLUS, URL_SPACING)); |
||||
map4Tpl.put(LANGUAGE, GeneralContext.getLocale().toString()); |
||||
while ((line = read.readLine()) != null) { |
||||
if (sb.length() > 0) { |
||||
sb.append('\n'); |
||||
} |
||||
sb.append(line); |
||||
} |
||||
String htmlString = StringUtils.EMPTY; |
||||
try{ |
||||
htmlString = TemplateUtils.renderParameter4Tpl(sb.toString(), map4Tpl); |
||||
}catch (Exception e){ |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
reader.close(); |
||||
inp.close(); |
||||
return htmlString; |
||||
} |
||||
|
||||
private void showAlert(final String message) { |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
FineJOptionPane.showMessageDialog(PluginWebPane.this, message); |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -1,32 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.design.dialog.UIDialog; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
|
||||
/** |
||||
* Created by zhaohehe on 16/7/28. |
||||
*/ |
||||
public class QQLoginDialog extends UIDialog { |
||||
private static final Dimension DEFAULT_SHOP = new Dimension(700, 500); |
||||
|
||||
public QQLoginDialog(Frame frame, Component pane) { |
||||
super(frame); |
||||
setUndecorated(true); |
||||
JPanel panel = (JPanel) getContentPane(); |
||||
panel.setLayout(new BorderLayout()); |
||||
add(pane, BorderLayout.CENTER); |
||||
setSize(DEFAULT_SHOP); |
||||
GUICoreUtils.centerWindow(this); |
||||
setResizable(false); |
||||
setTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Manager")); |
||||
} |
||||
|
||||
@Override |
||||
public void checkValid() throws Exception { |
||||
// do nothing
|
||||
} |
||||
|
||||
} |
@ -1,46 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.design.dialog.BasicPane; |
||||
import com.fr.design.dialog.UIDialog; |
||||
import com.fr.design.jdk.JdkVersion; |
||||
import com.fr.design.plugin.DesignerPluginContext; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.stable.StableUtils; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
|
||||
/** |
||||
* Created by vito on 16/4/18. |
||||
*/ |
||||
public class ShopDialog extends UIDialog { |
||||
|
||||
public ShopDialog(Frame frame, BasicPane pane) { |
||||
super(frame); |
||||
if (StableUtils.getMajorJavaVersion() >= 8) { |
||||
setUndecorated(true); |
||||
} |
||||
JPanel panel = (JPanel) getContentPane(); |
||||
panel.setLayout(new BorderLayout()); |
||||
add(pane, BorderLayout.CENTER); |
||||
setSize(createDefaultDimension()); |
||||
GUICoreUtils.centerWindow(this); |
||||
setResizable(false); |
||||
DesignerPluginContext.setPluginDialog(this); |
||||
} |
||||
|
||||
private Dimension createDefaultDimension() { |
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); |
||||
// jdk11 分辨率较低 缩放较大时 屏幕高度小于或接近设定的高度 需要调整下
|
||||
if (JdkVersion.GE_9.support() && screenSize.height - 700 < 50) { |
||||
return new Dimension(900, screenSize.height - 100); |
||||
} else { |
||||
return new Dimension(900, 700); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void checkValid() throws Exception { |
||||
// do nothing
|
||||
} |
||||
} |
@ -1,31 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.design.dialog.BasicPane; |
||||
|
||||
|
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
|
||||
/** |
||||
* @author richie |
||||
* @date 2015-03-09 |
||||
* @since 8.0 |
||||
* 应用中心的构建采用JavaScript代码来动态实现,但是不总是依赖于服务器端的HTML |
||||
* 采用JDK提供的JavaScript引擎,实际是用JavaScript语法实现Java端的功能,并通过JavaScript引擎动态调用 |
||||
* JavaScript放在安装目录下的scripts/store目录下,检测到新版本的时候,可以通过更新这个目录下的文件实现热更新 |
||||
* 不直接嵌入WebView组件的原因是什么呢? |
||||
* 因为如果直接嵌入WebView,和设计器的交互就需要预先设定好,这样灵活性会差很多,而如果使用JavaScript引擎, |
||||
* 就可以直接在JavaScript中和WebView组件做交互,而同时JavaScript中可以调用任何的设计器API. |
||||
*/ |
||||
public class ShopManagerPane extends BasicPane { |
||||
|
||||
public ShopManagerPane(Component webPane) { |
||||
setLayout(new BorderLayout()); |
||||
add(webPane, BorderLayout.CENTER); |
||||
} |
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Manager"); |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue