diff --git a/designer-base/src/main/java/com/fr/design/actions/file/LocalePane.java b/designer-base/src/main/java/com/fr/design/actions/file/LocalePane.java index 634af28b9..843b3bf72 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/LocalePane.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/LocalePane.java @@ -12,6 +12,7 @@ import com.fr.design.gui.itextfield.UITextField; import com.fr.file.filetree.FileNode; import com.fr.general.GeneralUtils; +import com.fr.general.Inter; import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; import com.fr.stable.ArrayUtils; @@ -121,7 +122,7 @@ public class LocalePane extends BasicPane { private void initPredefinedProperties() { - Map supportLocaleMap = InterProviderFactory.getProvider().getSupportLocaleMap(); + Map supportLocaleMap = Inter.getSupportLocaleMap(); // richie:暂时去掉设计器中国际化键值对的显示 Map map = new HashMap<>(); diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java index 46485409b..840de5867 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java @@ -46,7 +46,6 @@ import com.fr.general.IOUtils; import com.fr.general.Inter; import com.fr.general.log.Log4jConfig; import com.fr.io.attr.ImageExportAttr; -import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; import com.fr.report.ReportConfigManager; import com.fr.stable.Constants; @@ -634,7 +633,7 @@ public class PreferencePane extends BasicPane { } private UIDictionaryComboBox createLanguageComboBox() { - Map map = InterProviderFactory.getProvider().getSupportLocaleMap(); + Map map = Inter.getSupportLocaleMap(); int size = map.size(); Locale[] keys = new Locale[size]; String[] values = new String[size]; diff --git a/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java b/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java index 2ce2a7d82..e18b2a47d 100644 --- a/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java +++ b/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java @@ -661,4 +661,14 @@ public abstract class DesignTableDataManager { public static void setThreadLocal(String value) { threadLocal.set(value); } -} \ No newline at end of file + + /** + * 根据数据集名称判断是否为服务器数据集或服务器存储过程 + * + * @param tableDataName 数据集名称 + * @return + */ + public static boolean isGlobalTableData(String tableDataName) { + return globalDsCache.containsKey(tableDataName); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java index 947cb6e75..635076b59 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java @@ -37,6 +37,9 @@ public class ConnectionListDialogActionAdapter extends DialogActionAdapter { return; } try { + // 校验数据库类型 + connectionManagerPane.validateDatabaseType(connectionConfig); + connectionManagerPane.update(connectionConfig); } catch (Exception e) { connectionListDialog.setDoOKSucceed(false); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java index 23c22144b..eaa4c37d8 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java @@ -22,6 +22,7 @@ import com.fr.file.ConnectionConfig; import com.fr.file.ConnectionOperator; import com.fr.general.NameObject; import com.fr.log.FineLoggerFactory; +import com.fr.regist.FRCoreContext; import com.fr.stable.ArrayUtils; import com.fr.stable.Nameable; import com.fr.stable.StringUtils; @@ -118,17 +119,25 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh * @return 菜单项 */ public NameableCreator[] createNameableCreators() { - NameableCreator[] creators = new NameableCreator[]{new NameObjectCreator( + NameObjectCreator jdbc = new NameObjectCreator( "JDBC", "/com/fr/design/images/data/source/jdbcTableData.png", JDBCDatabaseConnection.class, DatabaseConnectionPane.JDBC.class - ), new NameObjectCreator( + ); + NameObjectCreator jndi = new NameObjectCreator( "JNDI", "/com/fr/design/images/data/source/jdbcTableData.png", JNDIDatabaseConnection.class, DatabaseConnectionPane.JNDI.class - )}; + ); + NameableCreator[] creators; + if (FRCoreContext.getLicense().limitDatabaseType()) { + // 不支持JDNI,屏蔽接口 + creators = new NameableCreator[]{jdbc}; + } else { + creators = new NameableCreator[]{jdbc, jndi}; + } Set pluginCreators = ExtraDesignClassManager.getInstance().getArray(ConnectionProvider.XML_TAG); for (ConnectionProvider provider : pluginCreators) { NameObjectCreator creator = new NameObjectCreator( diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java index 33925dcd3..0c1d88022 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java @@ -1,9 +1,14 @@ package com.fr.design.data.datapane.connect; +import com.fr.data.impl.Connection; import com.fr.design.gui.frpane.LoadingBasicPane; +import com.fr.design.gui.ilist.ListModelElement; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.file.ConnectionConfig; - +import com.fr.general.NameObject; +import com.fr.license.database.DatabaseTypeValidateUtil; +import com.fr.license.exception.DataBaseNotSupportedException; +import com.fr.stable.Nameable; import javax.swing.JPanel; import java.awt.BorderLayout; @@ -61,4 +66,23 @@ public class ConnectionManagerPane extends LoadingBasicPane implements Connectio return connectionListPane.isNamePermitted(); } + /** + * 校验是否支持当前选中连接的数据库类型 + */ + public void validateDatabaseType(ConnectionConfig connectionConfig) { + ListModelElement selectedValue = this.connectionListPane.getSelectedValue(); + if (selectedValue != null) { + Nameable wrapper = selectedValue.wrapper; + try { + Connection connection = (Connection) ((NameObject) wrapper).getObject(); + DatabaseTypeValidateUtil.validateDatabaseType(connection.getDriver(), connection.feature()); + } catch (DataBaseNotSupportedException e) { + // 仅抛出数据库类型不支持异常 + throw e; + } catch (Exception e) { + // ignore + } + } + } + } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java index 027afdf5b..27285850a 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java @@ -33,6 +33,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; import com.fr.design.ui.util.UIUtil; +import com.fr.esd.query.StrategicTableData; import com.fr.function.TIME; import com.fr.general.FRFont; import com.fr.general.data.DataModel; @@ -162,10 +163,8 @@ public class PreviewTablePane extends BasicPane { JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); // 预览行数面板 northPane.add(initPreviewNumberPane(), BorderLayout.CENTER); - /// 迭代延期,暂时屏蔽下功能入口 // 脱敏预览设置面板 -// northPane.add(initDesensitizationPane(), BorderLayout.EAST); - initDesensitizationPane(); + northPane.add(initDesensitizationPane(), BorderLayout.EAST); return northPane; } @@ -225,6 +224,18 @@ public class PreviewTablePane extends BasicPane { * 点击脱敏配置后的操作 */ public void clickDesensitizationLabel() { + // 埋点记录 + recordDesensitization(); + // 判断数据集类型 + if (isGlobalTableData()) { + // 服务器数据集不允许在设计器端修改脱敏配置 + FineJOptionPane.showMessageDialog( + this, + Toolkit.i18nText("Fine-Design_Report_Cannot_Modify_Desensitization_Config_Of_ServerTableData"), + Toolkit.i18nText("Fine-Design_Basic_Alert"), + FineJOptionPane.WARNING_MESSAGE); + return; + } TableDataDesensitizationSettingPane settingPane = new TableDataDesensitizationSettingPane((DesensitizationTableData) tableData); settingPane.populateBean((DesensitizationTableData) tableData); BasicDialog dialog = settingPane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(PreviewTablePane.this), new DialogActionAdapter() { @@ -250,15 +261,41 @@ public class PreviewTablePane extends BasicPane { } /** - * 设置脱敏设置的个数 + * 触发数据脱敏埋点记录 + * + * @return 数据脱敏字段数量 + */ + private int recordDesensitization() { + return getCurrentTableDataDesensitizaitionCount(); + } + + /** + * 当前tableData是否为服务器数据集或服务器存储过程 + * + * @return + */ + public boolean isGlobalTableData() { + return this.tableData instanceof StrategicTableData && + DesignTableDataManager.isGlobalTableData(((StrategicTableData) this.tableData).getDsName()); + } + + /** + * 根据TableData设置脱敏设置的个数 + */ + private void setDesensitizationCountByTableData() { + desensitizationPane.setDesensitizationCount(isDesensitizeOpened(), getCurrentTableDataDesensitizaitionCount()); + desensitizationPane.dealWithTableDataType(isGlobalTableData()); + } + + /** + * 获取当前数据集中设置脱敏规则的个数 * - * @param model + * @return */ - private void setDesensitizationCount(TableModel model) { - desensitizationPane.setDesensitizationCount(isDesensitizeOpened(), - model instanceof DesensitizedPreviewTableModel ? - ((DesensitizedPreviewTableModel) model).getDesensitizeColumnsCount() : - 0); + private int getCurrentTableDataDesensitizaitionCount() { + return this.tableData instanceof DesensitizationTableData ? + ((DesensitizationTableData) this.tableData).getDesensitizationConfig().getDesensitizationItems().size() : + 0; } /** @@ -723,7 +760,7 @@ public class PreviewTablePane extends BasicPane { * @param previewTableModel */ private void setPreviewTableModel(TableModel previewTableModel) { - setDesensitizationCount(previewTableModel); + setDesensitizationCountByTableData(); setModel(previewTableModel); setCurrentRows(previewTableModel.getRowCount()); fireLoadedListener(); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java index 3d3c59331..1fbed9f43 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java @@ -2,6 +2,7 @@ package com.fr.design.data.datapane.preview.desensitization; import com.fr.base.TableData; +import com.fr.data.desensitize.TableDataDesensitizeManager; import com.fr.data.desensitize.base.DesensitizationTableData; import com.fr.data.desensitize.base.TableDataDesensitizationItem; import com.fr.data.desensitize.manage.DesensitizationManager; @@ -77,10 +78,11 @@ public class TableDataPreviewDesensitizeManager implements DesensitizationManage // 获取此数据集的所有脱敏信息 Collection desensitizationItems = ((DesensitizationTableData) tableData).getDesensitizationConfig().getDesensitizationItems(); if (DesentizationUtils.isCollectionNotEmpty(desensitizationItems)) { - // 先对脱敏配置项集合做过滤和排序处理 + // 更新规则 + desensitizationItems = TableDataDesensitizeManager.getInstance().dealWithLastedRules(desensitizationItems); + // 对脱敏配置项集合做过滤和排序处理 List items = desensitizationItems.stream() - .filter(item -> item.getRule().isEnable() && - matchColumnIndex(item, model) >= 0) + .filter(item -> isAvaliableItem4Preview(item, model)) .sorted(Comparator.comparingInt(item -> matchColumnIndex(item, model))) .collect(Collectors.toList()); // 然后转换成Map @@ -92,9 +94,20 @@ public class TableDataPreviewDesensitizeManager implements DesensitizationManage return new DesensitizedPreviewTableModel(model, desensitizationItemMap); } + /** + * 判断是否为有效的用于预览脱敏效果的DesensitizationItem + * + * @param item 脱敏配置项 + * @param model 数据集预览数据 + * @return + */ + private boolean isAvaliableItem4Preview(TableDataDesensitizationItem item, PreviewTableModel model) { + return item.getRule().isEnable() && + matchColumnIndex(item, model) >= 0; + } + /** * 通过TableData获取其列名 - * 实现逻辑有点绕,TableData本身并不能返回列名集合,只能先去获取当前模板所有数据集,然后匹配名称拿到TableDataWrapper再获取列名 * * @param tableData * @return @@ -162,7 +175,7 @@ public class TableDataPreviewDesensitizeManager implements DesensitizationManage * @param positionName * @return */ - public String mergeRoleText(String departmentName, String positionName) { + private String mergeRoleText(String departmentName, String positionName) { return departmentName + positionName; } @@ -173,7 +186,7 @@ public class TableDataPreviewDesensitizeManager implements DesensitizationManage * @param positionId * @return */ - public String mergeRoleId(String departmentId, String positionId) { + private String mergeRoleId(String departmentId, String positionId) { return departmentId + CONNECTOR + positionId; } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/PreviewTableDesensitizationPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/PreviewTableDesensitizationPane.java index 1bf150dd5..01c92e333 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/PreviewTableDesensitizationPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/PreviewTableDesensitizationPane.java @@ -112,9 +112,22 @@ public class PreviewTableDesensitizationPane extends JPanel { return previewToggle; } + /** + * 设置Label的值,主要是需要动态修改配置的脱敏规则的数量 + * + * @param desensitizeOpen + * @param count + */ public void setDesensitizationCount(boolean desensitizeOpen, int count) { desensitizationLabel.setText(desensitizeOpen ? DATA_DESENSITIZATION_CONFIG + LEFT_BRACKET + count + RIGHT_BRACKET + COUNT : DATA_DESENSITIZATION_CONFIG); } + + /** + * 服务器数据集时,Label需要置灰 + */ + public void dealWithTableDataType(boolean globalTableData) { + desensitizationLabel.setForeground(globalTableData ? UIConstants.DISABLED_ICON_COLOR : UIConstants.NORMAL_BLUE); + } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/ChooseMark.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/ChooseMark.java new file mode 100644 index 000000000..099e9a960 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/ChooseMark.java @@ -0,0 +1,42 @@ +package com.fr.design.data.datapane.preview.desensitization.view.common; + +import com.fr.design.gui.ibutton.UIRadioButton; + +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * 标记选中的CellEditor + * + * @author Yvan + * @version 11.0 + * Created by Yvan on 2022/12/20 + */ +public class ChooseMark extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { + + private final UIRadioButton selectedButton; + + public ChooseMark() { + this.selectedButton = new UIRadioButton(); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + selectedButton.setSelected(isSelected); + return selectedButton; + } + + @Override + public Object getCellEditorValue() { + return selectedButton.isSelected(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + selectedButton.setSelected(isSelected); + return selectedButton; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleChoosePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleChoosePane.java index fd627e8cc..3b44c0b18 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleChoosePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleChoosePane.java @@ -4,9 +4,10 @@ import com.fr.base.svg.IconUtils; import com.fr.data.desensitize.rule.DesensitizationRuleManager; import com.fr.data.desensitize.rule.base.DesensitizationRule; import com.fr.data.desensitize.rule.base.DesensitizationRuleSource; +import com.fr.data.desensitize.rule.base.DesensitizationRuleStatus; +import com.fr.design.data.datapane.preview.desensitization.view.common.ChooseMark; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.DialogActionAdapter; -import com.fr.design.gui.ibutton.UIRadioButton; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itableeditorpane.UITableEditAction; import com.fr.design.gui.itableeditorpane.UITableEditorPane; @@ -22,6 +23,7 @@ import javax.swing.SwingUtilities; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import java.awt.CardLayout; +import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.util.LinkedHashSet; @@ -107,18 +109,23 @@ public class DesensitizationRuleChoosePane extends JPanel { super(new String[]{ StringUtils.EMPTY, Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Name"), - Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Description") + Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Description"), + Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status"), }); this.parent = parent; this.debugActionOnly = debugActionOnly; this.setColumnClass(new Class[]{ - RuleChoosePane.class, + ChooseMark.class, UILabel.class, - UILabel.class + UILabel.class, + DesensitizationRuleStatusPane.class }); - this.setDefaultEditor(RuleChoosePane.class, new RuleChoosePane()); - this.setDefaultRenderer(RuleChoosePane.class, new RuleChoosePane()); + this.setDefaultEditor(ChooseMark.class, new ChooseMark()); + this.setDefaultRenderer(ChooseMark.class, new ChooseMark()); + this.setDefaultEditor(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane()); + this.setDefaultRenderer(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane()); this.createTable().getColumnModel().getColumn(0).setMaxWidth(20); + this.createTable().getColumnModel().getColumn(3).setMaxWidth(60); } @Override @@ -134,6 +141,11 @@ public class DesensitizationRuleChoosePane extends JPanel { case 2: // 脱敏规则描述 return DesensitizationRule.getDescription(rule); + case 3: + // 脱敏规则状态 + DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(rule); + // 非正常状态需要标记为异常 + return ruleStatus == DesensitizationRuleStatus.NORMAL ? StringUtils.EMPTY : Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal"); default: return StringUtils.EMPTY; } @@ -161,29 +173,51 @@ public class DesensitizationRuleChoosePane extends JPanel { .collect(Collectors.toSet()); } - private class RuleChoosePane extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { + /** + * 规则状态展示页面 + */ + private class DesensitizationRuleStatusPane extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { - private UIRadioButton selectedButton; + private UILabel ruleStatusLabel; - public RuleChoosePane() { - this.selectedButton = new UIRadioButton(); + DesensitizationRuleStatusPane() { + // 规则状态 + this.ruleStatusLabel = new UILabel(); + this.ruleStatusLabel.setForeground(Color.RED); + } + + /** + * 根据脱敏规则信息,刷新规则状态,主要用于与规则选择器的联动 + * + * @param rule + */ + public void refreshRuleStatus(DesensitizationRule rule) { + DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(rule); + if (ruleStatus == DesensitizationRuleStatus.NORMAL) { + // 正常规则时,重置提示Label + this.ruleStatusLabel.setText(StringUtils.EMPTY); + this.ruleStatusLabel.setToolTipText(null); + } else { + this.ruleStatusLabel.setText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal")); + this.ruleStatusLabel.setToolTipText(ruleStatus.getDescription()); + } } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - selectedButton.setSelected(isSelected); - return selectedButton; + refreshRuleStatus(getList().get(row)); + return ruleStatusLabel; } @Override public Object getCellEditorValue() { - return selectedButton.isSelected(); + return ruleStatusLabel; } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - selectedButton.setSelected(isSelected); - return selectedButton; + refreshRuleStatus(getList().get(row)); + return ruleStatusLabel; } } @@ -298,7 +332,7 @@ public class DesensitizationRuleChoosePane extends JPanel { @Override public void checkEnabled() { - setEnabled(table.getSelectedRow() != -1); + setEnabled(table.getSelectedRow() != -1 && getList().get(table.getSelectedRow()).isEnable()); } @Override diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java index 7354dc0b1..b3c0d2615 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java @@ -2,6 +2,7 @@ package com.fr.design.data.datapane.preview.desensitization.view.rule; import com.fr.data.desensitize.rule.base.DesensitizationCondition; import com.fr.data.desensitize.rule.base.DesensitizationRule; +import com.fr.data.desensitize.rule.base.DesensitizationRuleSource; import com.fr.data.desensitize.rule.base.DesensitizationRuleType; import com.fr.design.beans.BasicBeanPane; import com.fr.design.constants.UIConstants; @@ -271,6 +272,15 @@ public class DesensitizationRuleEditPane extends BasicBeanPane matchRoleNamesByIds(Collection roleIds) { - List result = new ArrayList<>(); + private String matchRoleNamesByIds(Collection roleIds) { + StringBuilder builder = new StringBuilder(); for (String roleId : roleIds) { if (roleMap != null && roleMap.containsKey(roleId)) { - result.add(roleMap.get(roleId)); + builder.append(roleMap.get(roleId)); + builder.append(COMMA); } } - return result; + return builder.length() <= 1 ? StringUtils.EMPTY : builder.substring(0, builder.length() - 1); } @Override public boolean isCellEditable(int row, int col) { - return true; + TableSequences match = TableSequences.match(col); + return match != TableSequences.DesensitizationRuleStatus; } @Override public UITableEditAction[] createAction() { - return new UITableEditAction[]{new AddDesensitizationAction(), new RemoveDesensitizationAction(parent)}; + return new UITableEditAction[]{ + new AddDesensitizationAction(), + new RemoveDesensitizationAction(parent), + new RefreshTableAction(), + }; } /** @@ -166,7 +186,7 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter items = getList(); + Iterator iterator = items.iterator(); + while (iterator.hasNext()) { + TableDataDesensitizationItem item = iterator.next(); + DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(item.getRule()); + if (ruleStatus == DesensitizationRuleStatus.REMOVED) { + // 规则被移除,则删除整条脱敏Item + iterator.remove(); + } else { + // 规则被修改、禁用等,更新一下规则 + item.setRule(DesensitizationRuleManager.getInstance().getLastedDesentizationRule(item.getRule())); + } + } + fireTableDataChanged(); + } + + @Override + public void checkEnabled() {} + } + + /** + * 规则表-列字段编号 + */ + private enum TableSequences { + + /** + * 数据集列名选择 + */ + ColumnName(0), + + /** + * 规则选择 + */ + DesensitizationRule(1), + + /** + * 规则描述 + */ + DesensitizationRuleDescription(2), + + /** + * 规则生效用户组 + */ + EffectedRoles(3), + + /** + * 规则状态 + */ + DesensitizationRuleStatus(4), + + /** + * 未知,用于无法匹配时的返回 + */ + Unknown(100); + + + private int num; + + TableSequences(int num) { + this.num = num; + } + + public int getNum() { + return num; + } + + /** + * 根据列序号匹配列字段 + * + * @param num + * @return + */ + public static TableSequences match(int num) { + for (TableSequences value : TableSequences.values()) { + if (value.getNum() == num) { + return value; + } + } + return Unknown; + } + } + + /** + * 是否需要对异常规则做标记,需要满足 + * 1. 规则非默认空规则 + * 2. 规则本身异常 + * + * @return + */ + private boolean needMarkRule(DesensitizationRule rule) { + return !rule.equals(DesensitizationRule.createDefaultEmptyRule()) && + DesensitizationRuleManager.getInstance().getRuleStatus(rule) != DesensitizationRuleStatus.NORMAL; + } + } diff --git a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java index 3eed2d799..80e7e88bb 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java @@ -37,6 +37,10 @@ public class UICheckListPopup extends UIPopupMenu { private Color mouseEnteredColor = UIConstants.CHECKBOX_HOVER_SELECTED; private int maxDisplayNumber = 8; private boolean supportSelectAll = true; + /** + * 每项数据都有可能因为宽度设置问题,而被省略显示,这个常量代表,是否要给每项数据添加一个值等于其原值的Tooltips + */ + private boolean labelNeedToolTips = false; public static final String COMMIT_EVENT = "commit"; private static final String SELECT_ALL = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Choose_All"); @@ -47,9 +51,14 @@ public class UICheckListPopup extends UIPopupMenu { } public UICheckListPopup(Object[] value, boolean supportSelectAll) { + this(value, supportSelectAll, false); + } + + public UICheckListPopup(Object[] values, boolean supportSelectAll, boolean labelNeedToolTips) { super(); - values = value; + this.values = values; this.supportSelectAll = supportSelectAll; + this.labelNeedToolTips = labelNeedToolTips; initComponent(); } @@ -62,6 +71,11 @@ public class UICheckListPopup extends UIPopupMenu { addCheckboxValues(); } + public UICheckListPopup setLabelNeedToolTips(boolean labelNeedToolTips) { + this.labelNeedToolTips = labelNeedToolTips; + return this; + } + private void initComponent() { checkboxPane = new JPanel(); checkboxPane.setLayout(new GridLayout(checkBoxList.size(), 1, 0, 0)); @@ -111,6 +125,10 @@ public class UICheckListPopup extends UIPopupMenu { checkPane.setBackground(Color.WHITE); checkPane.add(temp); checkPane.add(label); + if (labelNeedToolTips) { + // 设置每项Label的tooltips为其省略前的内容 + label.setToolTipText(checkValue.toString()); + } addMouseListener(temp, label); checkBoxList.add(temp); diff --git a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java index 4dcea229c..ce0a9f869 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java @@ -17,9 +17,6 @@ import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -32,6 +29,9 @@ import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; /** * 设计器下拉复选框组件 @@ -52,7 +52,7 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam //选中的值之间显示的分隔符 private String valueSperator; private static final String DEFAULT_VALUE_SPERATOR = ","; - private static final String OMIT_TEXT = "..."; + protected static final String OMIT_TEXT = "..."; private UIObserverListener uiObserverListener; private GlobalNameListener globalNameListener = null; @@ -60,6 +60,7 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam private boolean showOmitText = true; private boolean supportSelectAll = true; + private String placeHolder = StringUtils.EMPTY; public UIComboCheckBox(Object[] value) { this(value, DEFAULT_VALUE_SPERATOR, true); @@ -112,14 +113,42 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam } private void initComponent() { - this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); this.popup = new UICheckListPopup(values, supportSelectAll); this.popup.addActionListener(new PopupAction()); this.editor = createEditor(); this.arrowButton = createArrowButton(); + setLayoutAndAddComponents(); + setText(); + } + + /** + * 设置布局管理器并且添加组件 + * 默认使用FlowLayout + */ + protected void setLayoutAndAddComponents() { + this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); this.add(editor); this.add(arrowButton); - setText(); + } + + public UICheckListPopup getPopup() { + return popup; + } + + public UITextField getEditor() { + return editor; + } + + public String getPlaceHolder() { + return placeHolder; + } + + public void setPlaceHolder(String placeHolder) { + this.placeHolder = placeHolder; + } + + public UIButton getArrowButton() { + return arrowButton; } private UIButton createArrowButton() { @@ -171,6 +200,9 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { attributeChange(); + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } } @Override @@ -270,6 +302,28 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam String text = builder.length() > 0 ? builder.substring(0, builder.length() - 1) : StringUtils.EMPTY; //计算加省略号后的文本 editor.setText(this.showOmitText ? omitEditorText(editor, text) : text); + // 添加placeHolder + setEditorPlaceHolder(editor); + // tooltips显示原值 + setEditorToolTipText(editor, text); + } + + /** + * 为为添加placeholder + * @param editor + */ + protected void setEditorPlaceHolder(UITextField editor) { + // 默认空实现 + } + + /** + * 为UITextField设置悬浮提示值 + * + * @param editor + * @param text + */ + protected void setEditorToolTipText(JComponent editor, String text) { + // 默认不做设置 } /** @@ -279,7 +333,7 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam * @param text * @return 省略后的文字 */ - private static String omitEditorText(UITextField textEditor, String text) { + protected String omitEditorText(UITextField textEditor, String text) { char[] omitChars = OMIT_TEXT.toCharArray(); //获取字体的大小 FontMetrics fontMetrics = textEditor.getFontMetrics(textEditor.getFont()); diff --git a/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java b/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java index 07756a56b..aca38b28d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java @@ -8,10 +8,12 @@ import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; - -import javax.swing.*; +import javax.swing.JPanel; +import javax.swing.JTable; import javax.swing.event.TableModelListener; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.Insets; import java.util.List; /** @@ -31,25 +33,25 @@ public class UITableEditorPane extends BasicPane { private String leftLabelName; private JPanel buttonPane; - public UITableEditorPane(UITableModelAdapter model) { - this.tableModel = model; - this.initComponent(model.createAction()); - } + public UITableEditorPane(UITableModelAdapter model) { + this.tableModel = model; + this.initComponent(model.createAction()); + } - public UITableEditorPane(UITableModelAdapter model, String s) { - leftLabelName = s; - this.tableModel = model; - this.initComponent(model.createAction()); - } + public UITableEditorPane(UITableModelAdapter model, String s) { + leftLabelName = s; + this.tableModel = model; + this.initComponent(model.createAction()); + } - private void initComponent(UITableEditAction[] action) { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - JPanel pane = new JPanel(new BorderLayout(4, 4)); - this.add(pane, BorderLayout.CENTER); + protected void initComponent(UITableEditAction[] action) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel pane = new JPanel(new BorderLayout(4, 4)); + this.add(pane, BorderLayout.CENTER); - UILabel l = new UILabel(leftLabelName); - editTable = tableModel.createTable(); - editTable.getTableHeader().setBackground(UIConstants.DEFAULT_BG_RULER); + UILabel l = new UILabel(leftLabelName); + editTable = tableModel.createTable(); + editTable.getTableHeader().setBackground(UIConstants.DEFAULT_BG_RULER); UIScrollPane scrollPane = new UIScrollPane(editTable); scrollPane.setBorder(new UIRoundedBorder(UIConstants.TITLED_BORDER_COLOR, 1, UIConstants.ARC)); @@ -62,11 +64,11 @@ public class UITableEditorPane extends BasicPane { } - public UITableModelAdapter getTableModel(){ + public UITableModelAdapter getTableModel() { return tableModel; } - private void initbuttonPane(UITableEditAction[] action) { + protected void initbuttonPane(UITableEditAction[] action) { buttonPane = new JPanel(); if (action != null) { @@ -146,6 +148,14 @@ public class UITableEditorPane extends BasicPane { return buttonPane; } + public JTable getEditTable() { + return editTable; + } + + public void setEditTable(JTable editTable) { + this.editTable = editTable; + } + /** * 停止编辑 */ @@ -157,7 +167,7 @@ public class UITableEditorPane extends BasicPane { /** * 设置表头是否可以改变大小 */ - public void setHeaderResizing(boolean resizingAllowed){ + public void setHeaderResizing(boolean resizingAllowed) { editTable.getTableHeader().setResizingAllowed(resizingAllowed); } diff --git a/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java b/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java index 4506bb9a6..87e21c75b 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java +++ b/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java @@ -219,57 +219,69 @@ public abstract class UITableModelAdapter extends AbstractTableModel implemen protected class DeleteAction extends UITableEditAction { private Component component = null; + // 删除时界面显示的提示语,可自定义 + private String deleteTipText; public DeleteAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Delete")); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); - } - + this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Delete")); + this.setDeleteTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?"); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); + } + public DeleteAction(Component component){ - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Delete")); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); + this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Delete")); + this.setDeleteTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?"); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); this.component = component; } @Override public void actionPerformed(ActionEvent e) { - int[] selectedRow = table.getSelectedRows(); - if (ismultiSelected()) { - FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Multiple_Select_Warn_Text")); - return; - } - if (table.getCellEditor() != null) { - try { - table.getCellEditor().stopCellEditing(); - } catch (Exception ee) { + int[] selectedRow = table.getSelectedRows(); + if (ismultiSelected()) { + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Multiple_Select_Warn_Text")); + return; + } + if (table.getCellEditor() != null) { + try { + table.getCellEditor().stopCellEditing(); + } catch (Exception ee) { FineLoggerFactory.getLogger().error(ee.getMessage(), ee); - } - } - if (getRowCount() < 1) { - return; - } - - if(component == null){ - component = DesignerContext.getDesignerFrame(); - } - int val = FineJOptionPane.showConfirmDialog(component, - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), - JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); - if (val != JOptionPane.OK_OPTION) { - return; - } - for (int i = 0; i < selectedRow.length; i++) { - if (selectedRow[i] - i < 0) { - continue; - } - removeRow(selectedRow[i] - i); - } - fireTableDataChanged(); - int selection = selectedRow[0] > table.getRowCount() ? table.getRowCount() - 1 - : (selectedRow[0] > 1 ? selectedRow[0] - 1 : 0); - table.getSelectionModel().setSelectionInterval(selection, selection); - } + } + } + if (getRowCount() < 1) { + return; + } + + if (component == null) { + component = DesignerContext.getDesignerFrame(); + } + int val = FineJOptionPane.showConfirmDialog(component, getDeleteTipText() + , com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), + JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (val != JOptionPane.OK_OPTION) { + return; + } + for (int i = 0; i < selectedRow.length; i++) { + if (selectedRow[i] - i < 0) { + continue; + } + removeRow(selectedRow[i] - i); + } + fireTableDataChanged(); + int selection = selectedRow[0] > table.getRowCount() ? table.getRowCount() - 1 + : (selectedRow[0] > 1 ? selectedRow[0] - 1 : 0); + table.getSelectionModel().setSelectionInterval(selection, selection); + } + + public String getDeleteTipText() { + return deleteTipText; + } + + public void setDeleteTipText(String deleteTipText) { + this.deleteTipText = deleteTipText; + } - private boolean ismultiSelected(){ + private boolean ismultiSelected() { int[] selectedRow = table.getSelectedRows(); return (selectedRow.length == 1 && (selectedRow[0] > table.getRowCount() - 1 || selectedRow[0] < 0)) || selectedRow.length == 0; } diff --git a/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java b/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java index ce8fdaa9d..417533465 100644 --- a/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java +++ b/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java @@ -607,6 +607,24 @@ public class FRGUIPaneFactory { return jp; } + /** + * 创建垂直流布局,水平填充面板 + * + * @param isAlignLeft 是否左对齐 + * @param align the alignment value + * @param hgap the horizontal gap between components + * @param vgap the vertical gap between components + * @param hfill 水平填充组件 + * @return JPanel对象 + */ + public static JPanel createVerticalFlowLayout_F_Pane(boolean isAlignLeft, int align, int hgap, int vgap, boolean hfill) { + JPanel jp = new JPanel(); + VerticalFlowLayout layout = new VerticalFlowLayout(align, hgap, vgap, hfill); + layout.setAlignLeft(isAlignLeft); + jp.setLayout(layout); + return jp; + } + /** * 创建边框面板L * diff --git a/designer-base/src/main/java/com/fr/design/layout/VerticalFlowLayout.java b/designer-base/src/main/java/com/fr/design/layout/VerticalFlowLayout.java index c857c7301..9f91fee50 100644 --- a/designer-base/src/main/java/com/fr/design/layout/VerticalFlowLayout.java +++ b/designer-base/src/main/java/com/fr/design/layout/VerticalFlowLayout.java @@ -95,6 +95,15 @@ public class VerticalFlowLayout implements LayoutManager, java.io.Serializable { */ protected int vgap; + + /** + * true: 水平填充组件 + * + * @see #isHfill() + * @see #setHfill(boolean) + */ + protected boolean hfill; + /** * Constructs a new FlowLayout with a centered alignment and a * default 5-unit horizontal and vertical gap. @@ -135,6 +144,14 @@ public class VerticalFlowLayout implements LayoutManager, java.io.Serializable { setAlignment(align); } + public VerticalFlowLayout(int align, int hgap, int vgap, boolean fill) { + this.hgap = hgap; + this.vgap = vgap; + this.hfill = fill; + + setAlignment(align); + } + /** * Gets the alignment for this layout. * Possible values are FlowLayout.TOP, @@ -219,6 +236,31 @@ public class VerticalFlowLayout implements LayoutManager, java.io.Serializable { * @param name the name of the component * @param comp the component to be added */ + + /** + * Gets the horizontal filling of components in the + * Container.The default is false. + * + * @return the horizontal filling of components in the + * Container + * @see #setHfill(boolean) + */ + public boolean isHfill() { + return hfill; + } + + /** + * Sets the horizontal filling of components in the + * Container.The default is false. + * + * @param hfill the horizontal filling of components in the + * Container + * @see #isHfill() + */ + public void setHfill(boolean hfill) { + this.hfill = hfill; + } + @Override public void addLayoutComponent(String name, Component comp) { } @@ -379,6 +421,7 @@ public class VerticalFlowLayout implements LayoutManager, java.io.Serializable { Insets insets = target.getInsets(); int maxlen = getMaxLen4LayoutContainer(target, insets); + int maxwidth = target.getWidth() - (insets.left + insets.right); int nmembers = target.getComponentCount(); int x = getX4LayoutContainer(insets), y = getY4LayoutContainer(insets); int roww = 0, start = 0; @@ -390,6 +433,9 @@ public class VerticalFlowLayout implements LayoutManager, java.io.Serializable { Component m = target.getComponent(i); if (m.isVisible()) { Dimension d = getPreferredSize(target, m); + if (hfill) { + d.width = maxwidth; + } m.setSize(d.width, d.height); rs = dealWithDim4LayoutContainer(target, insets, d, x, y, roww, start, maxlen, i, ltr); diff --git a/designer-base/src/main/resources/com/fr/design/standard/refresh/refresh_normal.svg b/designer-base/src/main/resources/com/fr/design/standard/refresh/refresh_normal.svg new file mode 100644 index 000000000..4e3fd9c14 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/standard/refresh/refresh_normal.svg @@ -0,0 +1,7 @@ + + + icon_刷新_normal + + + + \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java index 4cddfea73..bd197d89e 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java @@ -3,6 +3,7 @@ package com.fr.design.mainframe.cell.settingpane; import com.fr.base.Style; import com.fr.design.constants.LayoutConstants; import com.fr.design.constants.UIConstants; +import com.fr.design.dialog.link.MessageWithLink; import com.fr.design.editor.ValueEditorPane; import com.fr.design.editor.ValueEditorPaneFactory; import com.fr.design.file.HistoryTemplateListPane; @@ -21,12 +22,14 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.layout.VerticalFlowLayout; import com.fr.design.mainframe.EastRegionContainerPane; import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.cell.settingpane.desensitization.CellDesensitizationGroupsPane; import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.utils.gui.UIComponentUtils; import com.fr.design.widget.FRWidgetFactory; import com.fr.general.ComparatorUtils; import com.fr.general.FRFont; import com.fr.report.cell.TemplateCellElement; +import com.fr.report.cell.cellattr.CellDesensitizationAttr; import com.fr.report.cell.cellattr.CellGUIAttr; import com.fr.report.cell.cellattr.CellInsertPolicyAttr; import com.fr.report.cell.cellattr.CellPageAttr; @@ -45,10 +48,12 @@ import java.awt.CardLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.FlowLayout; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.util.ArrayList; /** * @author zhou @@ -117,23 +122,85 @@ public class CellOtherSetPane extends AbstractCellAttrPane { private JPanel insertRowPolicyPane; private JPanel defaultValuePane; + // 数据脱敏 + private UILabel scopeLabel; + private UIRadioButton exportButton; + private UIRadioButton previewAndExportButton; + private UIRadioButton[] desensitizationButtons; + private CellDesensitizationGroupsPane groupsPane; + private final int EXPORT_SCOPE = CellDesensitizationAttr.EXPORT_SCOPE; + private final int PREVIEW_AND_EXPORT_SCOPE = CellDesensitizationAttr.PREVIEW_AND_EXPORT_SCOPE; + private static final Color TIPS_FONT_COLOR = new Color(0x8f8f92); + /** * 初始化 * * @return 面板 */ public JPanel createContentPane() { - JPanel downPane = new JPanel(new BorderLayout()); - downPane.add(new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advaced"), HEAD_WDITH, HEAD_HEIGTH, seniorPane()), BorderLayout.NORTH); - downPane.add(new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Pagination"), HEAD_WDITH, HEAD_HEIGTH, pagePane()), BorderLayout.CENTER); - JPanel contentPane = new JPanel(new BorderLayout(0, 0)); - contentPane.add(new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Basic"), HEAD_WDITH, HEAD_HEIGTH, basicPane()), BorderLayout.NORTH); - contentPane.add(downPane, BorderLayout.CENTER); - initAllNames(); + JPanel contentPane = FRGUIPaneFactory.createVerticalFlowLayout_F_Pane(true, VerticalFlowLayout.TOP, 0, 0, true); + + contentPane.add(new UIExpandablePane(Toolkit.i18nText("Fine-Design_Report_Basic"), HEAD_WDITH, HEAD_HEIGTH, basicPane())); + contentPane.add(new UIExpandablePane(Toolkit.i18nText("Fine-Design_Report_Advaced"), HEAD_WDITH, HEAD_HEIGTH, seniorPane())); + contentPane.add(new UIExpandablePane(Toolkit.i18nText("Fine-Design_Report_Pagination"), HEAD_WDITH, HEAD_HEIGTH, pagePane())); + contentPane.add(new UIExpandablePane(Toolkit.i18nText("Fine-Design_Report_Desensitization"), HEAD_WDITH, HEAD_HEIGTH, desensitizePane())); + // VerticalFlowLayout 与 实现的滚动条有冲突,因此再加一层panel + JPanel jPanel = new JPanel(); + jPanel.add(contentPane); + return jPanel; + } + + private JPanel desensitizePane() { + JPanel scopePane = initScopePane(); + + // 带超链的提示信息 + UILabel label = new UILabel(); + MessageWithLink hyperlink = new MessageWithLink( + Toolkit.i18nText("Fine-Design_Report_Desensitization_Tip"), + Toolkit.i18nText("Fine-Design_Report_Desensitization_Hyperlink"), + Toolkit.i18nText("Fine-Design_Report_Desensitization_Help_Document_Url"), + StringUtils.EMPTY, + label.getBackground(), + label.getFont(), + Color.LIGHT_GRAY + ); + + groupsPane = new CellDesensitizationGroupsPane(this); + + JPanel contentPane = FRGUIPaneFactory.createVerticalFlowLayout_F_Pane(true, VerticalFlowLayout.TOP, 0, 0, true); + contentPane.add(scopePane); + contentPane.add(hyperlink); + contentPane.add(groupsPane); + return contentPane; } + /** + * 脱敏设置应用范围panel + * @return + */ + private JPanel initScopePane() { + scopeLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Scope")); + exportButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Report_Desensitization_Export")); + previewAndExportButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Report_Desensitization_Preview_Export")); + desensitizationButtons = new UIRadioButton[]{ + exportButton, previewAndExportButton + }; + + ButtonGroup buttonGroup = new ButtonGroup(); + for (UIRadioButton radioButton : desensitizationButtons) { + buttonGroup.add(radioButton); + } + + JPanel head = new JPanel(); + head.setLayout(new FlowLayout(FlowLayout.LEFT)); + head.add(scopeLabel); + head.add(exportButton); + head.add(previewAndExportButton); + return head; + } + private JPanel basicPane() { defaultAutoRadioButton = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Follow_Paper_Settings")); noAutoRadioButton = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_No_Auto_Adjust")); @@ -211,7 +278,7 @@ public class CellOtherSetPane extends AbstractCellAttrPane { double[] rowSize = {p, p, p}; double[] columnSize = {f}; - Component[][] components = new Component[][] { + Component[][] components = new Component[][]{ new Component[]{insertRowPolicyLabel}, new Component[]{insertRowPolicyButtonGroup}, new Component[]{insertRowPane}, @@ -220,7 +287,7 @@ public class CellOtherSetPane extends AbstractCellAttrPane { } else { double[] rowSize = {p, p}; double[] columnSize = {f, BUTTON_GROUP_WIDTH}; - Component[][] components = new Component[][] { + Component[][] components = new Component[][]{ new Component[]{insertRowPolicyLabel, insertRowPolicyButtonGroup}, new Component[]{null, insertRowPane}, }; @@ -243,7 +310,7 @@ public class CellOtherSetPane extends AbstractCellAttrPane { int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}}; JPanel fileNamePane = createNormal(); - fileNamePane.setBorder(BorderFactory.createEmptyBorder(0,12,0,0)); + fileNamePane.setBorder(BorderFactory.createEmptyBorder(0, 12, 0, 0)); UILabel showContentLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Show_Content"), SwingConstants.LEFT); UIComponentUtils.setLineWrap(showContentLabel); @@ -389,9 +456,9 @@ public class CellOtherSetPane extends AbstractCellAttrPane { currentPageFixedRowDataTipLabel.setBorder(UIConstants.CELL_ATTR_ZEROBORDER); currentPageFixedRowDataTipLabel.setForeground(TIPS_FONT_COLOR); double p = TableLayout.PREFERRED; - double[] rowSize = {p, p, p, p, p, p, p, p, p, p, p,p}; + double[] rowSize = {p, p, p, p, p, p, p, p, p, p, p, p}; double[] columnSize = {p}; - int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},{1,1},{1,1}}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}; Component[][] components = new Component[][]{ new Component[]{null}, new Component[]{pageBeforeRowCheckBox}, @@ -622,6 +689,19 @@ public class CellOtherSetPane extends AbstractCellAttrPane { if (!jTemplate.isJWorkBook()) { //表单中报表块编辑屏蔽掉 插入行策略 insertRowPolicyPane.setVisible(false); } + + populateDesensitizationBean(cellElement); + } + + private void populateDesensitizationBean(TemplateCellElement cellElement) { + CellDesensitizationAttr cellDesensitizationAttr = cellElement.getCellAttr(CellDesensitizationAttr.ATTR_TAG); + if (cellDesensitizationAttr == null) { + cellDesensitizationAttr = new CellDesensitizationAttr(); + } + boolean exportSelected = cellDesensitizationAttr.getScope() == EXPORT_SCOPE; + exportButton.setSelected(exportSelected); + previewAndExportButton.setSelected(!exportSelected); + groupsPane.populate(cellDesensitizationAttr.getDesensitizationBeans()); } /** @@ -714,6 +794,24 @@ public class CellOtherSetPane extends AbstractCellAttrPane { cellElement.setCellGUIAttr(cellGUIAttr); } updatePageAttr(cellElement); + + updateDesensitizationAttr(cellElement); + } + + /** + * 更新数据脱敏设置 + * + * @param cellElement + */ + private void updateDesensitizationAttr(TemplateCellElement cellElement) { + + CellDesensitizationAttr cellDesensitizationAttr = cellElement.getCellAttr(CellDesensitizationAttr.XML_TAG); + if (cellDesensitizationAttr == null) { + cellDesensitizationAttr = new CellDesensitizationAttr(); + } + cellDesensitizationAttr.setScope(exportButton.isSelected() ? EXPORT_SCOPE : PREVIEW_AND_EXPORT_SCOPE); + cellDesensitizationAttr.setDesensitizationBeans(new ArrayList<>(groupsPane.update())); + cellElement.addCellAttr(cellDesensitizationAttr); } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/CellDesensitizationGroupsPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/CellDesensitizationGroupsPane.java new file mode 100644 index 000000000..1c4f200cb --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/CellDesensitizationGroupsPane.java @@ -0,0 +1,127 @@ +package com.fr.design.mainframe.cell.settingpane.desensitization; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.design.mainframe.cell.settingpane.AbstractCellAttrPane; +import com.fr.design.mainframe.cell.settingpane.desensitization.model.CellDesensitizationTableModel; +import com.fr.report.cell.desensitization.CellDesensitizationBean; + +import javax.swing.JPanel; +import javax.swing.JTable; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.util.List; +import java.util.Objects; + +/** + * 数据脱敏规则设置面板 + * + * @author Leo.Qin + * @version 11.0 + * Created by Leo.Qin on 2022/11/15 + */ +public class CellDesensitizationGroupsPane extends JPanel { + private final CellDesensitizationTableModel model; + + // 规则编辑面板 + UITableEditorPane editorPane; + + // 添加规则按钮面板 + private JPanel addRulePane; + + public CellDesensitizationGroupsPane(AbstractCellAttrPane pane) { + model = new CellDesensitizationTableModel(pane, this); + + initComponent(); + } + + private void initComponent() { + this.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 10, true)); + + addRulePane = initAddPane(model); + editorPane = initEditorPane(model); + + this.add(addRulePane); + this.add(editorPane); + } + + /** + * 初始化添加脱敏设置面板 + * + * @param model + * @return + */ + private JPanel initAddPane(CellDesensitizationTableModel model) { + UIButton addButton = new UIButton(model.getAction()); + UILabel addLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Setting")); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] columnSize = {p, f}; + double[] rowSize = {p, p}; + + Component[][] components = new Component[][]{ + new Component[]{addLabel, addButton} + }; + + return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 20, 0); + } + + /** + * 初始化脱敏设置编辑面板 + * + * @param model + * @return + */ + private UITableEditorPane initEditorPane(CellDesensitizationTableModel model) { + UITableEditorPane tableEditorPane = new UITableEditorPane(model) { + @Override + protected void initComponent(UITableEditAction[] action) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JTable editTable = getTableModel().createTable(); + editTable.getTableHeader().setBackground(UIConstants.DEFAULT_BG_RULER); + setEditTable(editTable); + + initbuttonPane(action); + getbuttonPane().setBackground(UIConstants.DEFAULT_BG_RULER); + + JPanel controlPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + controlPane.setBackground(Color.WHITE); + controlPane.add(getbuttonPane(), BorderLayout.WEST); + + JPanel pane = new JPanel(new BorderLayout(4, 4)); + pane.add(editTable, BorderLayout.CENTER); + pane.add(controlPane, BorderLayout.NORTH); + + this.add(pane, BorderLayout.CENTER); + } + }; + return tableEditorPane; + } + + /** + * 更新数据 + */ + public List update() { + return editorPane.update(); + } + + /** + * 填充数据 + */ + public void populate(List desensitizationBeans) { + if (Objects.nonNull(desensitizationBeans)) { + editorPane.populate(desensitizationBeans.toArray(new CellDesensitizationBean[]{})); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/CellDesensitizationTableModel.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/CellDesensitizationTableModel.java new file mode 100644 index 000000000..f73b344a8 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/CellDesensitizationTableModel.java @@ -0,0 +1,109 @@ +package com.fr.design.mainframe.cell.settingpane.desensitization.model; + +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableModelAdapter; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.cell.settingpane.AbstractCellAttrPane; +import com.fr.report.cell.desensitization.CellDesensitizationBean; +import com.fr.stable.StringUtils; + +import java.awt.Component; +import java.awt.event.ActionEvent; + +/** + * 单元格数据脱敏model + * + * @author Leo.Qin + * @version 11.0 + * Created by Leo.Qin on 2023/1/4 + */ +public class CellDesensitizationTableModel extends UITableModelAdapter { + private final int ROW_HEIGHT = 60; + /** + * 属性面板 + */ + private AbstractCellAttrPane attrPane; + /** + * 添加脱敏设置action + */ + private AddDesensitizationAction action; + + public CellDesensitizationTableModel(AbstractCellAttrPane attrPane, Component parent) { + super(new String[]{StringUtils.EMPTY}); + this.attrPane = attrPane; + this.action = new AddDesensitizationAction(); + this.table.getTableHeader().setVisible(false); + this.table.setRowHeight(ROW_HEIGHT); + + setColumnClass(new Class[]{ + DesensitizationCellEditor.class + }); + + this.setDefaultEditor(DesensitizationCellEditor.class, new DesensitizationCellEditor(parent, this)); + this.setDefaultRenderer(DesensitizationCellEditor.class, new DesensitizationCellRender(parent, this)); + } + + @Override + public UITableEditAction[] createAction() { + + return new UITableEditAction[]{ + new MoveUpAction(), + new MoveDownAction(), + new DeleteDesensitizationAction() + }; + } + + public AddDesensitizationAction getAction() { + return action; + } + + /** + * 添加脱敏规则action + */ + public class AddDesensitizationAction extends AddTableRowAction { + + public AddDesensitizationAction() { + this.setName(StringUtils.EMPTY); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + // 添加一条空白数据 + addRow(CellDesensitizationBean.createEmptyBean()); + table.getSelectionModel().setSelectionInterval(table.getRowCount() - 1, table.getRowCount() - 1); + fireTableDataChanged(); + } + + } + + private class DeleteDesensitizationAction extends DeleteAction { + public DeleteDesensitizationAction() { + super(); + this.setDeleteTipText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Remove_Tip")); + } + } + + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + CellDesensitizationBean desensitizationBean = getList().get(rowIndex); + if (desensitizationBean == null) { + desensitizationBean = CellDesensitizationBean.createEmptyBean(); + } + return desensitizationBean; + } + + @Override + public boolean isCellEditable(int row, int col) { + return true; + } + + /** + * 手动触发模版变化,用于更新单元格脱敏设置属性 + */ + public void fireAttrChanged() { + attrPane.attributeChanged(); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellEditor.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellEditor.java new file mode 100644 index 000000000..a20483364 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellEditor.java @@ -0,0 +1,43 @@ +package com.fr.design.mainframe.cell.settingpane.desensitization.model; + +import com.fr.report.cell.desensitization.CellDesensitizationBean; + +import javax.swing.AbstractCellEditor; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.border.LineBorder; +import javax.swing.table.TableCellEditor; +import java.awt.Color; +import java.awt.Component; + +/** + * 脱敏规则设置cellEditor + * @author Leo.Qin + * @version 11.0 + * Created by Leo.Qin on 2023/1/4 + */ +public class DesensitizationCellEditor extends AbstractCellEditor implements TableCellEditor { + private final DesensitizationCellPane editPane; + + DesensitizationCellEditor(Component parent, CellDesensitizationTableModel model) { + editPane = new DesensitizationCellPane(parent, model); + } + + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + + editPane.populate((CellDesensitizationBean) value, row); + + JPanel editPanel = editPane.getEditPanel(); + editPanel.setBorder(new LineBorder(Color.LIGHT_GRAY)); + + return editPanel; + + } + + @Override + public Object getCellEditorValue() { + return editPane.getCellEditorValue(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java new file mode 100644 index 000000000..49d32e7b2 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java @@ -0,0 +1,304 @@ +package com.fr.design.mainframe.cell.settingpane.desensitization.model; + +import com.fr.data.desensitize.rule.DesensitizationRuleManager; +import com.fr.data.desensitize.rule.base.DesensitizationRule; +import com.fr.data.desensitize.rule.base.DesensitizationRuleStatus; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.data.datapane.preview.desensitization.TableDataPreviewDesensitizeManager; +import com.fr.design.data.datapane.preview.desensitization.view.rule.DesensitizationRulePane; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icombocheckbox.UIComboCheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.report.cell.desensitization.CellDesensitizationBean; +import com.fr.stable.StringUtils; +import com.fr.third.org.apache.commons.collections4.map.HashedMap; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.FontMetrics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +/** + * 单元格脱敏规则设置面板 + * + * @author Leo.Qin + * @version 11.0 + * Created by Leo.Qin on 2023/1/5 + */ +public class DesensitizationCellPane extends BasicBeanPane { + private Component parent; + private JPanel editPanel; + private UILabel label; + private UITextField emptyTextField; + private UIButton ruleButton; + private UITextField ruleTextField; + private UIComboCheckBox rolesComboBox; + private static final String APOSTROPHE = "..."; + private Map roleMap; + private DesensitizationRule rule; + private CellDesensitizationTableModel model; + + + DesensitizationCellPane(Component parent, CellDesensitizationTableModel model) { + this.parent = parent; + this.model = model; + + initComponent(); + + addListener(); + } + + private void initComponent() { + editPanel = new JPanel(); + editPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true)); + + label = new UILabel(); + label.setEnabled(false); + editPanel.add(label); + + ruleButton = new UIButton(APOSTROPHE); + + ruleTextField = new UITextField(); + ruleTextField.setEnabled(true); + ruleTextField.setEditable(false); + ruleTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Place_Holder")); + + roleMap = new HashedMap<>(); + rolesComboBox = new RuleUIComboCheckBox(); + rolesComboBox.setPlaceHolder(Toolkit.i18nText("Fine-Design_Report_Desensitization_Role_Place_Holder")); + rolesComboBox.setEnabled(true); + + emptyTextField = new UITextField(); + emptyTextField.setEnabled(false); + emptyTextField.setOpaque(false); + + editPanel.add(initTableCellPanel()); + } + + + /** + * 初始化单元格中的panel + */ + private JPanel initTableCellPanel() { + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + + double[] rowSize = new double[]{f, f}; + double[] columnSize = new double[]{p, f}; + + Component[][] components = new Component[][]{ + new Component[]{ruleButton, ruleTextField}, + new Component[]{emptyTextField, rolesComboBox} + }; + return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 0, 0); + } + + private void addListener() { + ruleButton.addActionListener(chooseRuleListener); + + rolesComboBox.registerChangeListener(uiObserverListener); + } + + + private final UIObserverListener uiObserverListener = new UIObserverListener() { + @Override + public void doChange() { + CellDesensitizationBean selectBean = model.getSelectedValue(); + Set roleIds = generateRolesIdsBySelectedValues(); + if (Objects.nonNull(selectBean) && !selectBean.getRoleIds().equals(roleIds)) { + selectBean.setRoleIds(generateRolesIdsBySelectedValues()); + model.fireAttrChanged(); + } + } + }; + + private final ActionListener chooseRuleListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + CellDesensitizationBean selectBean = model.getSelectedValue(); + DesensitizationRulePane rulePane = new DesensitizationRulePane(); + BasicDialog ruleDialog = rulePane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), new DialogActionAdapter() { + + @Override + public void doOk() { + rule = rulePane.updateBean(); + if (Objects.nonNull(selectBean) && Objects.nonNull(rule) && !selectBean.getDesensitizationRule().equals(rule)) { + selectBean.setDesensitizationRule(rule); + ruleTextField.setText(rule.getRuleName()); + + // 非正常状态需要颜色修改为红色 + refreshRuleState(selectBean); + + model.fireAttrChanged(); + } + rule = null; + } + }, BasicDialog.DEFAULT); + + ruleDialog.setVisible(true); + } + }; + + /** + * 根据当前的规则配置信息,生成选中的rolesMap用来展示 + */ + public Map generateRolesCheckBoxSelectedValues(CellDesensitizationBean bean) { + Map result = new HashMap<>(roleMap.size()); + for (Map.Entry roleEntry : roleMap.entrySet()) { + String roleId = roleEntry.getKey(); + String roleName = roleEntry.getValue(); + result.put(roleName, bean.getRoleIds().contains(roleId)); + } + return result; + } + + /** + * 根据当前的RoleName选择项,生成其对应的RoleId的set存入规则配置信息 + */ + public Set generateRolesIdsBySelectedValues() { + Set result = new LinkedHashSet<>(); + Object[] selectedValues = rolesComboBox.getSelectedValues(); + for (Object selectedValue : selectedValues) { + String selectedRoleName = (String) selectedValue; + if (roleMap.containsValue(selectedRoleName)) { + Optional> matchedEntry = roleMap.entrySet().stream().filter(entry -> StringUtils.equals(entry.getValue(), selectedRoleName)).findFirst(); + matchedEntry.ifPresent(stringStringEntry -> result.add(stringStringEntry.getKey())); + } + } + return result; + } + + public JPanel getEditPanel() { + return editPanel; + } + + /** + * 填充数据 + */ + public void populate(CellDesensitizationBean value, int row) { + + refreshRoles(); + + String ruleName = value.getDesensitizationRule().getRuleName(); + ruleTextField.setText(ruleName); + + // 非正常状态需要颜色修改为红色 + refreshRuleState(value); + + Map map = generateRolesCheckBoxSelectedValues(value); + rolesComboBox.setSelectedValues(map); + + label.setText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Setting") + row); + } + + private void refreshRoles() { + Map roles = TableDataPreviewDesensitizeManager.getInstance().getAllRoles(); + if (!roleMap.equals(roles)) { + roleMap = roles; + rolesComboBox.refreshCombo(roles.values().toArray()); + } + } + + private void refreshRuleState(CellDesensitizationBean value) { + DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(value.getDesensitizationRule()); + if (value.equals(CellDesensitizationBean.createEmptyBean())) { + ruleTextField.setForeground(Color.GRAY); + } else if (ruleStatus != DesensitizationRuleStatus.NORMAL) { + ruleTextField.setForeground(Color.RED); + } else { + ruleTextField.setForeground(Color.BLACK); + } + } + + @Deprecated + @Override + public void populateBean(Object ob) { + } + + @Deprecated + @Override + public Object updateBean() { + return null; + } + + @Deprecated + @Override + protected String title4PopupWindow() { + return null; + } + + public Object getCellEditorValue() { + return ruleTextField.getText(); + } + + + private class RuleUIComboCheckBox extends UIComboCheckBox { + public RuleUIComboCheckBox() { + super(DesensitizationCellPane.this.roleMap.values().toArray(), true); + } + + @Override + protected void setLayoutAndAddComponents() { + // 使用BorderLayout,否则默认使用的FlowLayout会让整个下拉选框使用最小Size,然后TableCell这边会出现空白 + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(getEditor(), BorderLayout.CENTER); + this.add(getArrowButton(), BorderLayout.EAST); + } + + @Override + protected void setEditorToolTipText(JComponent editor, String text) { + // 选项过多时,已选中的值会做省略显示处理,此处添加一个Tooltips,显示完整值 + if (text != null) { + editor.setToolTipText(text); + } + } + + @Override + protected void setEditorPlaceHolder(UITextField editor) { + editor.setPlaceholder(this.getPlaceHolder()); + } + + @Override + protected String omitEditorText(UITextField textEditor, String text) { + char[] omitChars = OMIT_TEXT.toCharArray(); + //获取字体的大小 + FontMetrics fontMetrics = textEditor.getFontMetrics(textEditor.getFont()); + //计算省略号的长度 + int omitLength = fontMetrics.charsWidth(omitChars, 0, omitChars.length); + String omitText = StringUtils.EMPTY; + char[] chars = text.toCharArray(); + + for (int i = 1; i <= chars.length; i++) { + //如果原文本+省略号长度超过文本框 + int width = textEditor.getWidth(); + if (width > 0 && fontMetrics.charsWidth(chars, 0, i) + omitLength > width) { + //从第i-1的位置截断再拼上省略号 + omitText = text.substring(0, i - 2) + OMIT_TEXT; + break; + } + } + + return omitText.equals(StringUtils.EMPTY) ? text : omitText; + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellRender.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellRender.java new file mode 100644 index 000000000..fe04fa5b5 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellRender.java @@ -0,0 +1,49 @@ +package com.fr.design.mainframe.cell.settingpane.desensitization.model; + +import com.fr.report.cell.desensitization.CellDesensitizationBean; + +import javax.swing.BorderFactory; +import javax.swing.JTable; +import javax.swing.border.LineBorder; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.Color; +import java.awt.Component; + +/** + * 脱敏规则设置cellRenderer + * + * @author Leo.Qin + * @version 11.0 + * Created by Leo.Qin on 2023/1/4 + */ +public class DesensitizationCellRender extends DefaultTableCellRenderer { + + private final DesensitizationCellPane editPane; + + + DesensitizationCellRender(Component parent, CellDesensitizationTableModel model) { + editPane = new DesensitizationCellPane(parent, model); + } + + + public Object getCellEditorValue() { + return editPane.getCellEditorValue(); + } + + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + + editPane.populate((CellDesensitizationBean) value, row); + if (table.isCellSelected(row, column)) { + // 设置选中框 + editPane.getEditPanel().setBorder(new LineBorder(Color.LIGHT_GRAY)); + } else { + editPane.getEditPanel().setBorder(BorderFactory.createEmptyBorder()); + } + + return editPane.getEditPanel(); + } + + +} diff --git a/designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java b/designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java index 3714d66a2..5fe52560d 100644 --- a/designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java +++ b/designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java @@ -1,7 +1,6 @@ package com.fr.design.report; import com.fr.base.CustomConfig; -import com.fr.config.Configuration; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.icheckbox.UICheckBox; @@ -11,16 +10,20 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.BrowseUtils; import com.fr.general.CloudCenter; +import com.fr.io.attr.ReportExportAttr; import com.fr.transaction.Configurations; import com.fr.transaction.WorkerFacade; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import javax.swing.BorderFactory; -import javax.swing.JPanel; /** + * 通用 + * * @author hades * @version 11.0 * Created by hades on 2022/5/26 @@ -30,13 +33,15 @@ public class ExportUniversalPane extends BasicPane { private static final String HELP_URL = CloudCenter.getInstance().acquireUrlByKind("help.alt_font.zh_CN", "https://help.fanruan.com/finereport/doc-view-4707.html"); private UICheckBox specialCharacterExport; + // 密码支持公式 + private UICheckBox passwordSupportFormula; public ExportUniversalPane() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - JPanel outerNorthPane =FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Report_Universal_Export_Config")); + JPanel outerNorthPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Report_Universal_Export_Config")); JPanel northPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_M_Pane(); - JPanel specialCharacterExportPane =FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + JPanel specialCharacterExportPane = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); specialCharacterExport = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_Universal_Export_Special_Character")); specialCharacterExport.setSelected(true); specialCharacterExportPane.add(specialCharacterExport); @@ -55,6 +60,11 @@ public class ExportUniversalPane extends BasicPane { labelPane.add(centerLabel, BorderLayout.CENTER); labelPane.add(rightLabel, BorderLayout.EAST); northPane.add(labelPane); + JPanel passwordSupportPane = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + passwordSupportFormula = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_Universal_Export_Password_Support_Formula")); + passwordSupportFormula.setSelected(false); + passwordSupportPane.add(passwordSupportFormula); + northPane.add(passwordSupportPane); outerNorthPane.add(northPane); this.add(outerNorthPane); } @@ -64,15 +74,27 @@ public class ExportUniversalPane extends BasicPane { return "ExportUniversalPane"; } - public void populate() { + /** + * 填充数据 + * + * @param reportExportAttr 报表导出属性 + */ + public void populate(ReportExportAttr reportExportAttr) { this.specialCharacterExport.setSelected(CustomConfig.getInstance().isOptimizedSpecialCharacterExport()); + this.passwordSupportFormula.setSelected(reportExportAttr.isPwdSupportFormula()); } - public void update() { + /** + * 更新界面 + * + * @param reportExportAttr 报表导出属性 + */ + public void update(ReportExportAttr reportExportAttr) { Configurations.modify(new WorkerFacade(CustomConfig.class) { @Override public void run() { CustomConfig.getInstance().setOptimizedSpecialCharacterExport(specialCharacterExport.isSelected()); + reportExportAttr.setPwdSupportFormula(passwordSupportFormula.isSelected()); } }); } diff --git a/designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java b/designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java index 2de520d27..cd992c3fd 100644 --- a/designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java +++ b/designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java @@ -61,7 +61,7 @@ public class ReportExportAttrPane extends BasicPane { } if (this.exportUniversalPane != null) { - this.exportUniversalPane.populate(); + this.exportUniversalPane.populate(reportExportAttr); } if (this.excelExportPane != null) { @@ -84,9 +84,8 @@ public class ReportExportAttrPane extends BasicPane { public ReportExportAttr update() { ReportExportAttr reportExportAttr = new ReportExportAttr(); - if (this.exportUniversalPane != null) { - this.exportUniversalPane.update(); + this.exportUniversalPane.update(reportExportAttr); } if (this.excelExportPane != null) {