Browse Source

Merge pull request #11265 in DESIGN/design from bugfix/11.0 to release/11.0

* commit '3da82027b991bff829081b3bd6fa8fb1e306f1ab':
  REPORT-88365 决策报表,单元格插入数据列,单元格元素页面有异常 【问题原因】单选时默认将cellDSColumnAdvancedPane的visible设为true,导致显示异常 【改动思路】结合cellDSColumnAdvancedPane的原始visible状态及单元格的单选多选状态再进行设置
  REPORT-88826 设计器新增不支持的数据库类型未受到限制 【问题原因】 【改动思路】新增数据连接时,点击确认后校验是否为受限制的数据库类型
  REPORT-82899 数据脱敏三期 修改增加单元格脱敏属性的实现方式
  数据脱敏三期 【问题原因】rt 【改动思路】rt 顺便过一下开发文档 https://kms.fineres.com/pages/viewpage.action?pageId=576039082
  REPORT-83773 && REPORT-83838 && REPORT-83716 && REPORT-83738 数据脱敏二期迭代bug 【问题原因】rt 【改动思路】主要是: 1. 添加埋点 2. 设计器端限制服务器数据集中脱敏配置的修改 3. 一些逻辑bug修改 【review建议】
  REPORT-84645 lic限制数据库类型-报表配合 【问题原因】rt 【改动思路】设计器中测试数据库连接时,根据lic中数据库类型限制,给出相应的错误提示
  REPORT-83316 && REPORT-83320 && REPORT-83488 && REPORT-83493 数据脱敏一期迭代bug 【问题原因】根据review意见,抽出方法 【改动思路】根据review意见,抽出方法 【review建议】
  REPORT-83316 && REPORT-83320 && REPORT-83488 && REPORT-83493 数据脱敏一期迭代bug 【问题原因】基本都是UI问题 【改动思路】跟产品沟通后,修改 【review建议】
  REPORT-86426-导出excel/pdf 密码支持公式
  REPORT-86259 【导出excel&word】仅限预览下限制复制 REPORT-86426-导出excel/pdf 密码支持公式
  KERNEL-12978 fix: 适配CBB改动
  REPORT-75091 数据脱敏一二期解除功能屏蔽 【问题原因】rt 【改动思路】rt 【review建议】
newui
superman 2 years ago
parent
commit
42187546a2
  1. 3
      designer-base/src/main/java/com/fr/design/actions/file/LocalePane.java
  2. 3
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  3. 10
      designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java
  4. 3
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java
  5. 15
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  6. 26
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java
  7. 59
      designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java
  8. 31
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java
  9. 13
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/PreviewTableDesensitizationPane.java
  10. 42
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/ChooseMark.java
  11. 66
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleChoosePane.java
  12. 10
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java
  13. 273
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/setting/TableDataDesensitizationTableModel.java
  14. 20
      designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java
  15. 68
      designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java
  16. 20
      designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java
  17. 16
      designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java
  18. 18
      designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java
  19. 46
      designer-base/src/main/java/com/fr/design/layout/VerticalFlowLayout.java
  20. 112
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java
  21. 127
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/CellDesensitizationGroupsPane.java
  22. 109
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/CellDesensitizationTableModel.java
  23. 43
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellEditor.java
  24. 304
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java
  25. 49
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellRender.java
  26. 32
      designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java
  27. 5
      designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java

3
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<Locale, String> supportLocaleMap = InterProviderFactory.getProvider().getSupportLocaleMap();
Map<Locale, String> supportLocaleMap = Inter.getSupportLocaleMap();
// richie:暂时去掉设计器中国际化键值对的显示
Map<String, String> map = new HashMap<>();

3
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<Locale> createLanguageComboBox() {
Map<Locale, String> map = InterProviderFactory.getProvider().getSupportLocaleMap();
Map<Locale, String> map = Inter.getSupportLocaleMap();
int size = map.size();
Locale[] keys = new Locale[size];
String[] values = new String[size];

10
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);
}
/**
* 根据数据集名称判断是否为服务器数据集或服务器存储过程
*
* @param tableDataName 数据集名称
* @return
*/
public static boolean isGlobalTableData(String tableDataName) {
return globalDsCache.containsKey(tableDataName);
}
}

3
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);

15
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<ConnectionProvider> pluginCreators = ExtraDesignClassManager.getInstance().getArray(ConnectionProvider.XML_TAG);
for (ConnectionProvider provider : pluginCreators) {
NameObjectCreator creator = new NameObjectCreator(

26
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
}
}
}
}

59
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();

31
designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java

@ -5,6 +5,7 @@ import com.fr.base.TableData;
import com.fr.data.desensitize.base.DesensitizationTableData;
import com.fr.data.desensitize.base.TableDataDesensitizationItem;
import com.fr.data.desensitize.manage.DesensitizationManager;
import com.fr.data.desensitize.rule.DesensitizationRuleManager;
import com.fr.data.desensitize.util.DesentizationUtils;
import com.fr.decision.webservice.bean.user.DepartmentPostBean;
import com.fr.decision.webservice.bean.user.RoleBean;
@ -77,10 +78,11 @@ public class TableDataPreviewDesensitizeManager implements DesensitizationManage
// 获取此数据集的所有脱敏信息
Collection<TableDataDesensitizationItem> desensitizationItems = ((DesensitizationTableData) tableData).getDesensitizationConfig().getDesensitizationItems();
if (DesentizationUtils.isCollectionNotEmpty(desensitizationItems)) {
// 先对脱敏配置项集合做过滤和排序处理
// 更新规则
dealWithLastedRules(desensitizationItems);
// 对脱敏配置项集合做过滤和排序处理
List<TableDataDesensitizationItem> 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,30 @@ 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;
}
/**
* 在预览计算前将Item中的规则替换为最新规则防止平台规则被临时修改
*/
private void dealWithLastedRules(Collection<TableDataDesensitizationItem> desensitizationItems) {
desensitizationItems.forEach(item -> {
// 获取最新的规则
item.setRule(DesensitizationRuleManager.getInstance().getLastedDesentizationRule(item.getRule()));
});
}
/**
* 通过TableData获取其列名
* 实现逻辑有点绕TableData本身并不能返回列名集合只能先去获取当前模板所有数据集然后匹配名称拿到TableDataWrapper再获取列名
*
* @param tableData
* @return

13
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);
}
}

42
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;
}
}

66
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;
DesensitizationRuleStatusPane() {
// 规则状态
this.ruleStatusLabel = new UILabel();
this.ruleStatusLabel.setForeground(Color.RED);
}
public RuleChoosePane() {
this.selectedButton = new UIRadioButton();
/**
* 根据脱敏规则信息刷新规则状态主要用于与规则选择器的联动
*
* @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

10
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<DesensitizationRu
@Override
public DesensitizationRule updateBean() {
rule.setRuleName(this.ruleNameTextField.getText());
rule.setRuleSource(DesensitizationRuleSource.CUSTOM);
DesensitizationRuleType ruleType = DesensitizationRuleType.matchByTypeName(String.valueOf(this.ruleTypeComboBox.getSelectedItem()));
rule.setRuleType(ruleType);
rule.getCondition().setRetainFront((int) this.retainFrontTextField.getValue());
rule.getCondition().setRetainBack((int) this.retainBackTextField.getValue());
rule.getCondition().setSymbol(ruleType == DesensitizationRuleType.CHARACTER_REPLACE ?
this.firstSymbolTextField.getText() :
this.secondSymbolTextField.getText());
rule.setEnable(true);
return rule;
}

273
designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/setting/TableDataDesensitizationTableModel.java

@ -2,11 +2,14 @@ package com.fr.design.data.datapane.preview.desensitization.view.setting;
import com.fr.data.desensitize.base.DesensitizationTableData;
import com.fr.data.desensitize.base.TableDataDesensitizationItem;
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.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.dialog.FineJOptionPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombocheckbox.UIComboCheckBox;
@ -15,12 +18,14 @@ import com.fr.design.gui.itableeditorpane.UITableEditAction;
import com.fr.design.gui.itableeditorpane.UITableModelAdapter;
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.stable.StringUtils;
import org.jetbrains.annotations.Nullable;
import javax.swing.AbstractCellEditor;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
@ -28,10 +33,11 @@ import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
@ -52,6 +58,8 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
private static final String APOSTROPHE = "...";
private static final String COMMA = ",";
private DesensitizationTableData tableData;
/**
@ -66,17 +74,14 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
private Component parent;
private DesensitizationRuleChooser ruleChooser;
private DesensitizationRuleDescriptionPane descriptionPane;
public TableDataDesensitizationTableModel(DesensitizationTableData tableData, Component parent) {
// table相关
super(new String[]{
Toolkit.i18nText("Fine-Design_Report_Desensitization_Column"),
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule"),
StringUtils.EMPTY,
Toolkit.i18nText("Fine-Design_Report_Desensitization_Effected_Roles")
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Description"),
Toolkit.i18nText("Fine-Design_Report_Desensitization_Effected_Roles"),
Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status"),
});
// 一些数据相关
this.tableData = tableData;
@ -93,57 +98,69 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
// 规则详情展示
DesensitizationRuleDescriptionPane.class,
// 生效用户组选择
EffectedRolesChooser.class
EffectedRolesChooser.class,
// 规则状态
DesensitizationRuleStatusPane.class
});
this.setDefaultEditor(ColumnNamesComboBox.class, new ColumnNamesComboBox());
this.ruleChooser = new DesensitizationRuleChooser();
this.setDefaultEditor(DesensitizationRuleChooser.class, ruleChooser);
this.setDefaultRenderer(DesensitizationRuleChooser.class, ruleChooser);
this.descriptionPane = new DesensitizationRuleDescriptionPane();
this.setDefaultEditor(DesensitizationRuleChooser.class, new DesensitizationRuleChooser());
this.setDefaultEditor(DesensitizationRuleDescriptionPane.class, new DesensitizationRuleDescriptionPane());
this.setDefaultEditor(EffectedRolesChooser.class, new EffectedRolesChooser());
this.setDefaultEditor(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane());
this.setDefaultRenderer(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane());
this.createTable().getColumnModel().getColumn(TableSequences.DesensitizationRuleStatus.getNum()).setMaxWidth(60);
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
TableDataDesensitizationItem desensitizationItem = this.getList().get(rowIndex);
switch (columnIndex) {
case 0:
TableSequences match = TableSequences.match(columnIndex);
switch (match) {
case ColumnName:
// 选中的数据集字段名称
return desensitizationItem.getColumnName();
case 1:
case DesensitizationRule:
// 脱敏规则名称
return desensitizationItem.getRule().getRuleName();
case 2:
case DesensitizationRuleDescription:
// 脱敏规则详情
return DesensitizationRule.getDescription(desensitizationItem.getRule());
case 3:
case EffectedRoles:
// 生效用户组
return matchRoleNamesByIds(desensitizationItem.getRoleIds());
case DesensitizationRuleStatus:
// 规则状态
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(desensitizationItem.getRule());
// 非正常状态需要标记为异常
return ruleStatus == DesensitizationRuleStatus.NORMAL ? StringUtils.EMPTY : Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal");
default:
return StringUtils.EMPTY;
}
}
/**
* 通过id匹配此用户组对应的部门职位名称或者说自定义角色名称
* 通过id匹配此用户组对应的部门职位名称或者说自定义角色名称并拼接成字符串返回
*
* @param roleIds
* @return
*/
private List<String> matchRoleNamesByIds(Collection<String> roleIds) {
List<String> result = new ArrayList<>();
private String matchRoleNamesByIds(Collection<String> 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
@ -166,7 +183,7 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
/**
* 列名选择下拉框
*/
private class ColumnNamesComboBox extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private class ColumnNamesComboBox extends AbstractCellEditor implements TableCellEditor {
private UIComboBox columnNameComboBox;
@ -202,15 +219,9 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
Object selectedItem = columnNameComboBox.getSelectedItem();
return Objects.isNull(selectedItem) ? StringUtils.EMPTY : selectedItem.toString();
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
columnNameComboBox.setSelectedItem(getList().get(row).getColumnName());
return columnNameComboBox;
}
}
private class DesensitizationRuleChooser extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private class DesensitizationRuleChooser extends AbstractCellEditor implements TableCellEditor {
/**
* 规则选择页面
*/
@ -223,26 +234,25 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
* 规则选择按钮
*/
private UIButton chooseButton;
/**
* 规则
*/
private DesensitizationRule rule;
private ActionListener chooseRuleListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DesensitizationRulePane rulePane = new DesensitizationRulePane();
TableDataDesensitizationItem desensitizationItem = getCurrentSelectBean();
int selectedRow = table.getSelectedRow();
BasicDialog ruleDialog = rulePane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), new DialogActionAdapter() {
@Override
public void doOk() {
rule = rulePane.updateBean();
TableDataDesensitizationItem desensitizationItem = getCurrentSelectBean();
DesensitizationRule rule = rulePane.updateBean();
if (Objects.nonNull(desensitizationItem) && Objects.nonNull(rule)) {
desensitizationItem.setRule(rule);
desensitizationItem.setRuleName(rule.getRuleName());
// 刷新规则名称、描述、状态
ruleNameTextField.setText(rule.getRuleName());
fireTableDataChanged();
table.getSelectionModel().setSelectionInterval(selectedRow, selectedRow);
}
rule = null;
}
}, BasicDialog.DEFAULT);
ruleDialog.setVisible(true);
@ -255,29 +265,13 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
ruleNameTextField.setEnabled(false);
// 规则选择按钮
chooseButton = new UIButton(APOSTROPHE);
chooseButton.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Click_To_Choose_Rule"));
chooseButton.addActionListener(chooseRuleListener);
// 规则选择页面
Component[][] templateChooserComponent = {{ruleNameTextField, chooseButton}};
double[] rowSize = {TableLayout.PREFERRED};
double[] columnSize = {TableLayout.FILL, 22};
choosePane = TableLayoutHelper.createCommonTableLayoutPane(templateChooserComponent, rowSize, columnSize, 0);
this.addCellEditorListener(new CellEditorListener() {
@Override
public void editingCanceled(ChangeEvent e) {
}
@Override
public void editingStopped(ChangeEvent e) {
TableDataDesensitizationItem desensitizationItem = getCurrentSelectBean();
if (Objects.nonNull(desensitizationItem) && Objects.nonNull(rule)) {
desensitizationItem.setRule(rule);
desensitizationItem.setRuleName(rule.getRuleName());
fireTableDataChanged();
}
}
});
}
@Override
@ -290,12 +284,6 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
public Object getCellEditorValue() {
return ruleNameTextField.getText();
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
ruleNameTextField.setText((String) value);
return choosePane;
}
}
private class DesensitizationRuleDescriptionPane extends AbstractCellEditor implements TableCellEditor {
@ -314,6 +302,7 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
*/
public void refreshDescription(DesensitizationRule desensitizationRule) {
this.descriptionLabel.setText(DesensitizationRule.getDescription(desensitizationRule));
this.descriptionLabel.setToolTipText(this.descriptionLabel.getText());
}
@Override
@ -328,12 +317,31 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
}
}
private class EffectedRolesChooser extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
/**
* 生效用户组复选框
*/
private class EffectedRolesChooser extends AbstractCellEditor implements TableCellEditor {
private UIComboCheckBox rolesCheckBox;
EffectedRolesChooser() {
this.rolesCheckBox = new UIComboCheckBox(roleMap.values().toArray(), true);
this.rolesCheckBox = new UIComboCheckBox(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);
}
}
};
this.addCellEditorListener(new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
@ -399,14 +407,85 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
public Object getCellEditorValue() {
return rolesCheckBox.getSelectedValues();
}
}
/**
* 规则状态展示页面
*/
private class DesensitizationRuleStatusPane extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private UILabel ruleStatusLabel;
DesensitizationRuleStatusPane() {
// 规则状态
this.ruleStatusLabel = new UILabel();
this.ruleStatusLabel.setForeground(Color.RED);
}
/**
* 根据脱敏规则信息刷新规则状态主要用于与规则选择器的联动
*
* @param currentItem
*/
public void refreshRuleStatus(TableDataDesensitizationItem currentItem) {
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(currentItem.getRule());
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());
}
}
/**
* 标签点击后处理原规则
*/
private void ruleStatusLabelClick(TableDataDesensitizationItem currentItem) {
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(currentItem.getRule());
if (ruleStatus == DesensitizationRuleStatus.NORMAL) {
return;
}
// 点击Label后,弹窗提示
int option = FineJOptionPane.showConfirmDialog(
parent,
ruleStatus.getDescription(),
Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"),
FineJOptionPane.OK_CANCEL_OPTION,
FineJOptionPane.INFORMATION_MESSAGE);
if (option == FineJOptionPane.OK_OPTION && table.getSelectedRow() != -1) {
int selectedRow = table.getSelectedRow();
// 点击确定后,根据规则状态对规则做处理
if (ruleStatus == DesensitizationRuleStatus.REMOVED || ruleStatus == DesensitizationRuleStatus.WRONG) {
// 规则被删除或读取错误时,直接删掉
removeRow(selectedRow);
} else if (ruleStatus == DesensitizationRuleStatus.MODIFIED) {
// 规则被修改时,用新规则替换
DesensitizationRule lastedRule = DesensitizationRuleManager.getInstance().getLastedDesentizationRule(currentItem.getRule());
currentItem.setRule(lastedRule);
setRowAt(currentItem, selectedRow);
}
}
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
rolesCheckBox.setSelectedValues(generateRolesCheckBoxSelectedValues(getList().get(row)));
return rolesCheckBox;
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
refreshRuleStatus(getList().get(row));
return ruleStatusLabel;
}
@Override
public Object getCellEditorValue() {
return ruleStatusLabel;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
refreshRuleStatus(getList().get(row));
return ruleStatusLabel;
}
}
private class AddDesensitizationAction extends AddTableRowAction {
@ -439,4 +518,66 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
}
}
/**
* 规则表-列字段编号
*/
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;
}
}
}

20
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);

68
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());

20
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;
/**
@ -42,7 +44,7 @@ public class UITableEditorPane<T> extends BasicPane {
this.initComponent(model.createAction());
}
private void initComponent(UITableEditAction[] action) {
protected void initComponent(UITableEditAction[] action) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel pane = new JPanel(new BorderLayout(4, 4));
this.add(pane, BorderLayout.CENTER);
@ -66,7 +68,7 @@ public class UITableEditorPane<T> extends BasicPane {
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<T> extends BasicPane {
return buttonPane;
}
public JTable getEditTable() {
return editTable;
}
public void setEditTable(JTable editTable) {
this.editTable = editTable;
}
/**
* 停止编辑
*/

16
designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java

@ -219,13 +219,17 @@ public abstract class UITableModelAdapter<T> 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.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.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;
}
@ -251,8 +255,8 @@ public abstract class UITableModelAdapter<T> extends AbstractTableModel implemen
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"),
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;
@ -269,6 +273,14 @@ public abstract class UITableModelAdapter<T> extends AbstractTableModel implemen
table.getSelectionModel().setSelectionInterval(selection, selection);
}
public String getDeleteTipText() {
return deleteTipText;
}
public void setDeleteTipText(String deleteTipText) {
this.deleteTipText = deleteTipText;
}
private boolean ismultiSelected() {
int[] selectedRow = table.getSelectedRows();
return (selectedRow.length == 1 && (selectedRow[0] > table.getRowCount() - 1 || selectedRow[0] < 0)) || selectedRow.length == 0;

18
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
*

46
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 <code>FlowLayout</code> 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 <code>FlowLayout.TOP</code>,
@ -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
* <code>Container</code>.The default is false.
*
* @return the horizontal filling of components in the
* <code>Container</code>
* @see #setHfill(boolean)
*/
public boolean isHfill() {
return hfill;
}
/**
* Sets the horizontal filling of components in the
* <code>Container</code>.The default is false.
*
* @param hfill the horizontal filling of components in the
* <code>Container</code>
* @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);

112
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"));
@ -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);
}

127
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<CellDesensitizationBean> 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<CellDesensitizationBean> initEditorPane(CellDesensitizationTableModel model) {
UITableEditorPane<CellDesensitizationBean> tableEditorPane = new UITableEditorPane<CellDesensitizationBean>(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<CellDesensitizationBean> update() {
return editorPane.update();
}
/**
* 填充数据
*/
public void populate(List<CellDesensitizationBean> desensitizationBeans) {
if (Objects.nonNull(desensitizationBeans)) {
editorPane.populate(desensitizationBeans.toArray(new CellDesensitizationBean[]{}));
}
}
}

109
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<CellDesensitizationBean> {
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();
}
}

43
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();
}
}

304
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<String, String> 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<String> 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<Object, Boolean> generateRolesCheckBoxSelectedValues(CellDesensitizationBean bean) {
Map<Object, Boolean> result = new HashMap<>(roleMap.size());
for (Map.Entry<String, String> 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<String> generateRolesIdsBySelectedValues() {
Set<String> result = new LinkedHashSet<>();
Object[] selectedValues = rolesComboBox.getSelectedValues();
for (Object selectedValue : selectedValues) {
String selectedRoleName = (String) selectedValue;
if (roleMap.containsValue(selectedRoleName)) {
Optional<Map.Entry<String, String>> 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<Object, Boolean> map = generateRolesCheckBoxSelectedValues(value);
rolesComboBox.setSelectedValues(map);
label.setText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Setting") + row);
}
private void refreshRoles() {
Map<String, String> 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;
}
}
}

49
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();
}
}

32
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,6 +33,8 @@ 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());
@ -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());
}
});
}

5
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) {

Loading…
Cancel
Save