Browse Source

Merge pull request #11434 in DESIGN/design from final/11.0 to persist/11.0

* commit '39e254e4c6caa809a16cbd4c6ade48c76f0da8d9': (55 commits)
  REPORT-90013 修改实现逻辑
  REPORT-90013 设计器新增不支持的数据连接类型可以保存 【问题原因】远程设计下异常显示内容仍为本地lic信息 【改动思路】增加远程设计下获取支持的数据库类型接口
  REPORT-90013 设计器新增不支持的数据连接类型可以保存 【问题原因】 【改动思路】修改校验方案
  REPORT-90013 设计器新增不支持的数据连接类型可以保存 【问题原因】之前每个空bean对象都是新建的且写equals方法 【改动思路】修改空bean对象,实现equals方法
  REPORT-90013 设计器新增不支持的数据连接类型可以保存 【问题原因】判断逻辑写反了 【改动思路】修改判读逻辑
  REPORT-89957 数据脱敏-本地规则无法保存 【问题原因】还是本地规则这边的问题,有好几个 1. 修改规则触发的updateRule方法,只传入了修改后的规则,修改前的规则未被移除 2. 规则无法保存,ResourceIOUtils.tryWrite接口在远程环境下有问题,会写到服务器上去 3. 所有规则展示的页面,因为之前改动性能,将规则缓存在了页面中,但是没有给刷新缓存的相关逻辑,实际上这个规则展示页面,是可以对本地规则做编辑等操作的,是需要刷新的 【改动思路】 1. updateRule做正确的更新逻辑,删除旧规则,添加新规则 2. ResourceIOUtils.tryWrite换成本地文件系统的IO方法 3. 每次打开所有规则展示的页面之前,刷新一下本地规则缓存 【review建议】
  REPORT-89926 数据脱敏三期增加埋点
  REPORT-89807 切换其他单元格再切换回来,单元格属性-其他会丢失
  REPORT-80693 数据脱敏二期 【问题原因】拼写错误 【改动思路】与前端同学沟通,共同处理一下拼写错误 【review建议】
  REPORT-83849 && REPORT-89327 修改代码质量
  REPORT-83849 && REPORT-89327 【问题原因】未设计远程调用接口;脱敏计算获取的部门id api接口有误,未拼接部分id与职位id 【改动思路】增加远程调用接口;修改获取部分id 的api接口
  修改一下写法
  REPORT-89353 && REPORT-89358 && REPORT-89237 【问题原因】 REPORT-89358:上移下移删除未触发模版保存事件 EPORT-89353:未将脱敏设置list写入到frm决策表 REPORT-89237:预览时单元格格式生效在写入html时,在SE中仅对原始值进行了脱敏;单元格形态计算在脱敏计算后 【解决思路】 EPORT-89358:操作增加触发模版保存事件 EPORT-89353:frm决策报表添加读取写入list信息 REPORT-89237:若单元格设置了格式属性,将在写入html时再进行脱敏;将脱敏计算修改到形态计算后执行
  REPORT-88826 修改类实现
  REPORT-88426 模板数据集和服务器数据集重名时,保存模板会错误校验--修改一下,避免重复获取
  REPORT-88826 修改类名
  REPORT-88426 模板数据集和服务器数据集重名时,保存模板会错误校验
  REPORT-88426 模板数据集和服务器数据集重名时,保存模板会错误校验
  REPORT-87542 复制模板,点击刷新按钮,触发粘贴,会提示没有权限
  REPORT-88826 设计器新增不支持的数据库类型未受到限制 封装DataBaseNotSupportedException用于rpc调用
  ...
fix-lag
superman 2 years ago
parent
commit
7bdc41bf87
  1. 8
      designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java
  2. 32
      designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java
  3. 95
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  4. 1
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java
  5. 59
      designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java
  6. 97
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/TableDataPreviewDesensitizeManager.java
  7. 13
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/PreviewTableDesensitizationPane.java
  8. 42
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/ChooseMark.java
  9. 89
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleChoosePane.java
  10. 16
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java
  11. 11
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRulePane.java
  12. 341
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/setting/TableDataDesensitizationTableModel.java
  13. 99
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/setting/TableDataDesensitizationTablePane.java
  14. 9
      designer-base/src/main/java/com/fr/design/file/DefaultTemplateTreeDefineProcessor.java
  15. 3
      designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java
  16. 20
      designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java
  17. 68
      designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java
  18. 54
      designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java
  19. 92
      designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java
  20. 18
      designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java
  21. 46
      designer-base/src/main/java/com/fr/design/layout/VerticalFlowLayout.java
  22. 2
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  23. 3
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java
  24. 3
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java
  25. 7
      designer-base/src/main/resources/com/fr/design/standard/refresh/refresh_normal.svg
  26. 18
      designer-form/src/main/java/com/fr/design/designer/beans/models/ClipboardProvider.java
  27. 45
      designer-form/src/main/java/com/fr/design/designer/beans/models/DashboardClipboardManager.java
  28. 45
      designer-form/src/main/java/com/fr/design/designer/beans/models/FormSelectionClipboard.java
  29. 26
      designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java
  30. 2
      designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java
  31. 2
      designer-form/src/main/java/com/fr/design/widget/ui/designer/btn/ButtonGroupDefinePane.java
  32. 2
      designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/PluginSearchManager.java
  33. 121
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java
  34. 139
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/CellDesensitizationGroupsPane.java
  35. 108
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/CellDesensitizationTableModel.java
  36. 47
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellEditor.java
  37. 332
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java
  38. 49
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellRender.java
  39. 47
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/UpdateDataWorker.java
  40. 36
      designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java
  41. 5
      designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java

8
designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java

@ -378,12 +378,8 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
protected boolean isDsNameRepeaded(String name) {
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
for (int i = 0; i < allDSNames.length; i++) {
if (ComparatorUtils.equals(name, allDSNames[i])) {
return true;
}
}
return false;
Set<String> allDSNamesWithoutPermissions = DesignTableDataManager.getAllDSNamesWithoutPermissions(tc.getBook());
return allDSNamesWithoutPermissions.contains(name);
}
protected KeyAdapter getTableTreeNodeListener(final UpdateAction editAction, final UpdateAction previewTableDataAction, final UpdateAction removeAction, final TableDataSourceOP op, final TableDataTree dataTree) {

32
designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java

@ -48,6 +48,7 @@ import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@ -295,6 +296,27 @@ public abstract class DesignTableDataManager {
return list.toArray(new String[0]);
}
/**
* 获取所有的数据集名称,无论模板是不是有数据集的权限
*/
public static Set<String> getAllDSNamesWithoutPermissions(TableDataSource source) {
Set<String> names = new HashSet<>();
Map<String, TableDataWrapper> resMap = new HashMap<>();
// 模板数据集
addTemplateData(resMap, source);
// 存储过程
addStoreProcedureData(resMap);
for (Map.Entry<String, TableDataWrapper> entry : resMap.entrySet()) {
names.add(entry.getKey());
}
//服务器数据集
Map<String, TableData> tableDatas = TableDataConfig.getInstance().getTableDatas();
for (Map.Entry<String, TableData> entry : tableDatas.entrySet()) {
names.add(entry.getKey());
}
return names;
}
/**
* 不根据过滤设置返回当前模板数据集服务器数据集存储过程本身是有顺序的
*/
@ -661,4 +683,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);
}
}

95
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java

@ -21,6 +21,9 @@ import com.fr.event.EventDispatcher;
import com.fr.file.ConnectionConfig;
import com.fr.file.ConnectionOperator;
import com.fr.general.NameObject;
import com.fr.license.database.BaseDataBaseTypePoint;
import com.fr.license.database.DBTypes;
import com.fr.license.exception.DataBaseNotSupportedException;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Nameable;
@ -29,17 +32,22 @@ import com.fr.stable.core.PropertyChangeAdapter;
import com.fr.transaction.Configurations;
import com.fr.transaction.WorkerFacade;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.database.DataBaseTypeOperator;
import org.jetbrains.annotations.NotNull;
import javax.swing.SwingWorker;
import java.awt.Window;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
/**
* Connection List Pane.
@ -49,6 +57,7 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
private boolean isNamePermitted = true;
private final HashMap<String, String> renameMap = new HashMap<>();
private final Map<String, Connection> populatedConnectionsSnapshot = new LinkedHashMap<>();
private static List<String> supportedDatabaseTypes = new ArrayList<>();
public ConnectionListPane() {
renameMap.clear();
@ -62,6 +71,30 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
rename(selectedName, getEditingName());
}
});
getSupportedTypes();
}
/**
* 获取本地远程环境lic中未受限制的数据库类型信息
*/
private static void getSupportedTypes() {
SwingWorker<List<String>, Void> getSupportedTypesWorker = new SwingWorker<List<String>, Void>() {
@Override
protected List<String> doInBackground() {
return WorkContext.getCurrent().get(DataBaseTypeOperator.class).getSupportedDatabaseTypes();
}
@Override
protected void done() {
try {
supportedDatabaseTypes = get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
};
getSupportedTypesWorker.execute();
}
@Override
@ -114,21 +147,31 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
/**
* 创建菜单项
* <p>
* 方法中获取limitDatabaseType使用了远程rpc调用可能会比较耗时
*
* @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 (WorkContext.getCurrent().get(DataBaseTypeOperator.class).limitDatabaseType()) {
// 不支持JNDI,屏蔽接口
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(
@ -221,10 +264,56 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
}
});
this.validateDatabaseType(addedOrUpdatedConnections);
this.validateConnections(addedOrUpdatedConnections);
this.alterConnections(removedConnNames, addedOrUpdatedConnections);
}
/**
* 校验是否支持所有新增和修改数据连接的数据库类型
*/
public void validateDatabaseType(@NotNull List<ConnectionBean> addedOrUpdatedConnections) {
Set<String> notSupportedConnections = new HashSet<>();
if (!addedOrUpdatedConnections.isEmpty()) {
for (ConnectionBean bean : addedOrUpdatedConnections) {
Connection connection = bean.getConnection();
// 仅校验jdbc连接,其他插件数据连接不进行校验
if (connection instanceof JDBCDatabaseConnection) {
BaseDataBaseTypePoint dataBaseTypePoint = BaseDataBaseTypePoint.getDataBaseTypePoint(connection.getDriver(), connection.feature());
if (connectionIsNotSupported(connection, dataBaseTypePoint)) {
notSupportedConnections.addAll(dataBaseTypePoint.getDataBaseType());
}
}
}
}
if (!notSupportedConnections.isEmpty()) {
throw new DataBaseNotSupportedException(notSupportedConnections, supportedDatabaseTypes);
}
}
/**
* 校验当前数据连接是否被限制
*/
private static boolean connectionIsNotSupported(Connection connection, BaseDataBaseTypePoint dataBaseTypePoint) {
return !validateFRDemo(connection.getDriver(), connection.feature()) &&
(dataBaseTypePoint != null && !supportedDatabaseTypes.containsAll(dataBaseTypePoint.getDatabaseType()));
}
/**
* 校验当前是否为FRDemo不对其进行限制
*/
private static boolean validateFRDemo(String driver, String url) {
if (DBTypes.Sqlite.getDriver().equals(driver) && url.contains(DBTypes.Sqlite.getUrlKey())) {
// 产品:对sqlite类型只允许示例连接FRDemo
String databaseName = url.substring(url.lastIndexOf("/") + 1);
return StringUtils.equals("FRDemo.db", databaseName);
}
return false;
}
private void validateConnections(List<ConnectionBean> addedOrUpdatedConnections) throws Exception {

1
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java

@ -4,7 +4,6 @@ import com.fr.design.gui.frpane.LoadingBasicPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.file.ConnectionConfig;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.util.HashMap;

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 getCurrentTableDataDesensitizationCount();
}
/**
* 当前tableData是否为服务器数据集或服务器存储过程
*
* @return
*/
public boolean isGlobalTableData() {
return this.tableData instanceof StrategicTableData &&
DesignTableDataManager.isGlobalTableData(((StrategicTableData) this.tableData).getDsName());
}
/**
* 根据TableData设置脱敏设置的个数
*/
private void setDesensitizationCountByTableData() {
desensitizationPane.setDesensitizationCount(isDesensitizeOpened(), getCurrentTableDataDesensitizationCount());
desensitizationPane.dealWithTableDataType(isGlobalTableData());
}
/**
* 获取当前数据集中设置脱敏规则的个数
*
* @param model
* @return
*/
private void setDesensitizationCount(TableModel model) {
desensitizationPane.setDesensitizationCount(isDesensitizeOpened(),
model instanceof DesensitizedPreviewTableModel ?
((DesensitizedPreviewTableModel) model).getDesensitizeColumnsCount() :
0);
private int getCurrentTableDataDesensitizationCount() {
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();

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

@ -2,6 +2,8 @@ package com.fr.design.data.datapane.preview.desensitization;
import com.fr.base.TableData;
import com.fr.data.TableDataSource;
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;
@ -14,11 +16,14 @@ import com.fr.decision.webservice.v10.user.PositionService;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.preview.PreviewTableModel;
import com.fr.design.data.datapane.preview.desensitization.model.DesensitizedPreviewTableModel;
import com.fr.esd.query.StrategicTableData;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
@ -77,10 +82,11 @@ public class TableDataPreviewDesensitizeManager implements DesensitizationManage
// 获取此数据集的所有脱敏信息
Collection<TableDataDesensitizationItem> desensitizationItems = ((DesensitizationTableData) tableData).getDesensitizationConfig().getDesensitizationItems();
if (DesentizationUtils.isCollectionNotEmpty(desensitizationItems)) {
// 先对脱敏配置项集合做过滤和排序处理
// 更新规则
desensitizationItems = TableDataDesensitizeManager.getInstance().dealWithlatestRules(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
@ -93,88 +99,29 @@ public class TableDataPreviewDesensitizeManager implements DesensitizationManage
}
/**
* 通过TableData获取其列名
* 实现逻辑有点绕TableData本身并不能返回列名集合只能先去获取当前模板所有数据集然后匹配名称拿到TableDataWrapper再获取列名
* 判断是否为有效的用于预览脱敏效果的DesensitizationItem
*
* @param tableData
* @param item 脱敏配置项
* @param model 数据集预览数据
* @return
*/
public List<String> getColumnNamesByTableData(TableData tableData) {
return DesignTableDataManager.getColumnNamesByTableData(tableData);
private boolean isAvaliableItem4Preview(TableDataDesensitizationItem item, PreviewTableModel model) {
return item.getRule().isEnable() &&
matchColumnIndex(item, model) >= 0;
}
/**
* 这个api会返回 部门职位 + 自定义角色 的Map
* 其中 key为 "pid" + "_" + "id"value为 "ptext" + "text"
* 通过TableData获取其列名,理论上一定存在缓存值
*
* @param tableData
* @return
*/
public Map<String, String> getAllRoles() {
Map<String, String> rolesMap = new LinkedHashMap<>();
// 处理部门职位相关的用户组
addDepartmentAndPositionRoles2Map(rolesMap);
// 处理自定义角色相关的用户组
addCustomRoles2Map(rolesMap);
return rolesMap;
}
/**
* 获取所有的部门职位按照 key为 "pid" + "_" + "id"value为 "ptext" + "text"的格式添加到参数Map中
*
* @param rolesMap
*/
private void addDepartmentAndPositionRoles2Map(Map<String, String> rolesMap) {
try {
List<DepartmentPostBean> postBeans = PositionService.getInstance().getDepartmentPostNameList();
for (DepartmentPostBean postBean : postBeans) {
String department = postBean.getpText();
String position = postBean.getText();
String departmentId = postBean.getpId();
String positionId = postBean.getId();
if (!ComparatorUtils.equals(DecisionServiceConstants.DECISION_DEP_ROOT, postBean.getId()) && StringUtils.isNotEmpty(position)) {
// 只添加部门和职位同时存在的
rolesMap.put(mergeRoleId(departmentId, positionId), mergeRoleText(department, position));
}
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "[Desensitization] failed to add department and position roles to map for {}", e.getMessage());
}
}
/**
* 获取所有的自定义角色按照 id - name添加到参数map里
*
* @param rolesMap
*/
private void addCustomRoles2Map(Map<String, String> rolesMap) {
try {
List<RoleBean> allCustomRole = CustomRoleService.getInstance().getAllCustomRoleNameList(null);
allCustomRole.forEach(roleBean -> rolesMap.put(roleBean.getId(), roleBean.getText()));
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "[Desensitization] failed to add custom role to map for {}", e.getMessage());
public List<String> getColumnNamesByTableData(TableData tableData) {
TableDataSource editingTableDataSource = DesignTableDataManager.getEditingTableDataSource();
if (editingTableDataSource != null && tableData instanceof StrategicTableData) {
return Arrays.asList(DesignTableDataManager.getSelectedColumnNames(editingTableDataSource, ((StrategicTableData) tableData).getDsName()));
}
}
/**
* 合并部门 + 职位的名称
*
* @param departmentName
* @param positionName
* @return
*/
public String mergeRoleText(String departmentName, String positionName) {
return departmentName + positionName;
}
/**
* 合并部门 + 职位的id
*
* @param departmentId
* @param positionId
* @return
*/
public String mergeRoleId(String departmentId, String positionId) {
return departmentId + CONNECTOR + positionId;
return Collections.EMPTY_LIST;
}
/**

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

89
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,10 +23,12 @@ 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;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@ -46,7 +49,10 @@ public class DesensitizationRuleChoosePane extends JPanel {
private DesensitizationRuleSource currentRuleSource;
public DesensitizationRuleChoosePane() {
private Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules;
public DesensitizationRuleChoosePane(Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules) {
this.latestRules = latestRules;
this.cardLayout = new CardLayout();
this.setLayout(cardLayout);
serverRuleEditPane = new UITableEditorPane<>(new DesensitizationRuleChooseTableModel(this, true));
@ -74,8 +80,8 @@ public class DesensitizationRuleChoosePane extends JPanel {
* 展示当前规则
*/
private void populateDesensitizationRules() {
serverRuleEditPane.populate(DesensitizationRuleManager.getInstance().getRules(DesensitizationRuleSource.SERVER));
customRuleEditPane.populate(DesensitizationRuleManager.getInstance().getRules(DesensitizationRuleSource.CUSTOM));
serverRuleEditPane.populate(latestRules.get(DesensitizationRuleSource.SERVER).values().toArray(new DesensitizationRule[0]));
customRuleEditPane.populate(latestRules.get(DesensitizationRuleSource.CUSTOM).values().toArray(new DesensitizationRule[0]));
}
/**
@ -107,18 +113,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 +145,11 @@ public class DesensitizationRuleChoosePane extends JPanel {
case 2:
// 脱敏规则描述
return DesensitizationRule.getDescription(rule);
case 3:
// 脱敏规则状态
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(rule, latestRules);
// 非正常状态需要标记为异常
return ruleStatus == DesensitizationRuleStatus.NORMAL ? StringUtils.EMPTY : Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal");
default:
return StringUtils.EMPTY;
}
@ -161,29 +177,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 UILabel ruleStatusLabel;
private UIRadioButton selectedButton;
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, latestRules);
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;
}
}
@ -237,18 +275,25 @@ public class DesensitizationRuleChoosePane extends JPanel {
@Override
public void actionPerformed(ActionEvent e) {
// 获取当前选中规则
DesensitizationRule selectedValue = getSelectedValue();
// 获取当前选中规则的副本
DesensitizationRule selectedValue = null;
try {
selectedValue = (DesensitizationRule) getSelectedValue().clone();
} catch (CloneNotSupportedException ex) {
throw new RuntimeException(ex);
}
DesensitizationRuleEditPane editPane = new DesensitizationRuleEditPane(getCurrentExistRuleNames(selectedValue.getRuleName()));
editPane.populateBean(selectedValue);
final DesensitizationRule finalRule = selectedValue;
BasicDialog basicDialog = editPane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(parent), new DialogActionAdapter() {
@Override
public void doOk() {
DesensitizationRule rule = editPane.updateBean();
// 修改同步到RuleManager中
if (DesensitizationRule.valid(rule)) {
DesensitizationRuleManager.getInstance().updateRule(rule);
DesensitizationRuleManager.getInstance().updateRule(finalRule, rule);
}
setSelectedValue(rule);
fireTableDataChanged();
}
@ -298,7 +343,7 @@ public class DesensitizationRuleChoosePane extends JPanel {
@Override
public void checkEnabled() {
setEnabled(table.getSelectedRow() != -1);
setEnabled(table.getSelectedRow() != -1 && getList().get(table.getSelectedRow()).isEnable());
}
@Override

16
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;
@ -158,15 +159,15 @@ public class DesensitizationRuleEditPane extends BasicBeanPane<DesensitizationRu
ruleConditionPane = new JPanel(cardLayout);
// 字符替换
JPanel characterReplacePane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane();
UILabel retainFrontLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Retain_Front") + StringUtils.BLANK);
UILabel retainFrontLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_One") + StringUtils.BLANK);
retainFrontTextField = new UINumberField(5);
retainFrontTextField.addFocusListener(retainFrontListener);
UILabel retainBackLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Count_And_Back") + StringUtils.BLANK);
UILabel retainBackLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Two") + StringUtils.BLANK);
retainBackTextField = new UINumberField(5);
retainBackTextField.addFocusListener(retainBackListener);
UILabel replaceLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Count_And_Other_Character_Replace_By") + StringUtils.BLANK);
UILabel replaceLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Three") + StringUtils.BLANK);
firstSymbolTextField = new UITextField(10);
firstSymbolTextField.addFocusListener(firstSymbolListener);
@ -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;
}

11
designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRulePane.java

@ -9,6 +9,7 @@ import com.fr.design.layout.FRGUIPaneFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.util.Map;
/**
* 脱敏规则展示页
@ -29,13 +30,19 @@ public class DesensitizationRulePane extends BasicBeanPane<DesensitizationRule>
*/
private DesensitizationRuleChoosePane ruleChoosePane;
/**
* 最新的所有规则
*/
private Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules;
/**
* 内容面板
*/
private JPanel contentPane;
public DesensitizationRulePane() {
public DesensitizationRulePane(Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.latestRules = latestRules;
initPane();
}
@ -47,7 +54,7 @@ public class DesensitizationRulePane extends BasicBeanPane<DesensitizationRule>
// 规则来源选择Pane
ruleSourceChoosePane = new DesensitizationRuleSourceChoosePane(this);
// 规则选择Pane
ruleChoosePane = new DesensitizationRuleChoosePane();
ruleChoosePane = new DesensitizationRuleChoosePane(latestRules);
contentPane.add(ruleSourceChoosePane, BorderLayout.NORTH);
contentPane.add(ruleChoosePane, BorderLayout.CENTER);
}

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

@ -2,8 +2,10 @@ 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.design.data.datapane.preview.desensitization.TableDataPreviewDesensitizeManager;
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.rule.DesensitizationRulePane;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
@ -15,12 +17,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,12 +32,16 @@ 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.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@ -52,39 +60,46 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
private static final String APOSTROPHE = "...";
private DesensitizationTableData tableData;
private static final String COMMA = ",";
/**
* 当前数据集的所有列名
*/
private List<String> columnNames;
private List<String> columnNames = new ArrayList<>();
/**
* key为用户组唯一标识id拼接value为用户组名称
*/
private Map<String, String> roleMap;
private Map<String, String> roleMap = new LinkedHashMap<>();
private Component parent;
private DesensitizationRuleChooser ruleChooser;
/**
* 当前最新的所有规则
*/
private Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules = new LinkedHashMap<>();
private DesensitizationRuleDescriptionPane descriptionPane;
private Component parent;
public TableDataDesensitizationTableModel(DesensitizationTableData tableData, Component parent) {
public TableDataDesensitizationTableModel(DesensitizationTableData tableData, Component parent, List<String> columnNames, Map<String, String> roleMap, Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules) {
// 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;
// 获取当前数据集的所有列名
this.columnNames = TableDataPreviewDesensitizeManager.getInstance().getColumnNamesByTableData(tableData);
// 获取当前所有用户组
this.roleMap = TableDataPreviewDesensitizeManager.getInstance().getAllRoles();
this.parent = parent;
this.columnNames = columnNames;
this.roleMap = roleMap;
this.latestRules = latestRules;
initTable();
}
/**
* 初始化Table
*/
private void initTable() {
this.setColumnClass(new Class[]{
// 列名选择
ColumnNamesComboBox.class,
@ -93,62 +108,77 @@ 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();
ColumnNamesComboBox columnNamesComboBox = new ColumnNamesComboBox();
this.setDefaultEditor(ColumnNamesComboBox.class, columnNamesComboBox);
this.setDefaultEditor(DesensitizationRuleChooser.class, new DesensitizationRuleChooser());
this.setDefaultEditor(DesensitizationRuleDescriptionPane.class, new DesensitizationRuleDescriptionPane());
this.setDefaultEditor(EffectedRolesChooser.class, new EffectedRolesChooser());
EffectedRolesChooser effectedRolesChooser = new EffectedRolesChooser();
this.setDefaultEditor(EffectedRolesChooser.class, 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:
// 规则状态
return needMarkRule(desensitizationItem.getRule()) ? 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
public UITableEditAction[] createAction() {
return new UITableEditAction[]{new AddDesensitizationAction(), new RemoveDesensitizationAction(parent)};
return new UITableEditAction[]{
new AddDesensitizationAction(),
new RemoveDesensitizationAction(parent),
new RefreshTableAction(),
};
}
/**
@ -166,7 +196,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;
@ -190,7 +220,6 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
});
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
columnNameComboBox.setSelectedItem(getList().get(row).getColumnName());
@ -202,15 +231,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 +246,27 @@ 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();
// 重新获取一下本地规则缓存
refreshCustomRuleCache();
DesensitizationRulePane rulePane = new DesensitizationRulePane(latestRules);
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();
if (Objects.nonNull(desensitizationItem) && Objects.nonNull(rule)) {
DesensitizationRule rule = rulePane.updateBean();
if (Objects.nonNull(desensitizationItem) && DesensitizationRule.valid(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 +279,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 +298,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 +316,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 +331,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,15 +421,58 @@ 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) {
DesensitizationRule rule = currentItem.getRule();
if (needMarkRule(rule)) {
// 非正常规则,根据规则状态展示不同提示文字
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(rule, latestRules);
this.ruleStatusLabel.setText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Rule_Status_Abnormal"));
this.ruleStatusLabel.setToolTipText(ruleStatus.getDescription());
} else {
// 正常规则,重置提示Label
this.ruleStatusLabel.setText(StringUtils.EMPTY);
this.ruleStatusLabel.setToolTipText(null);
}
}
@Override
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) {
rolesCheckBox.setSelectedValues(generateRolesCheckBoxSelectedValues(getList().get(row)));
return rolesCheckBox;
refreshRuleStatus(getList().get(row));
return ruleStatusLabel;
}
}
private class AddDesensitizationAction extends AddTableRowAction {
public AddDesensitizationAction() {
@ -439,4 +504,116 @@ public class TableDataDesensitizationTableModel extends UITableModelAdapter<Tabl
}
}
private class RefreshTableAction extends UITableEditAction {
public RefreshTableAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Refresh"));
this.setSmallIcon("/com/fr/design/standard/refresh/refresh", false);
}
@Override
public void actionPerformed(ActionEvent e) {
// 刷新TableData的规则,主要是为了自动替换掉平台中被修改的规则
List<TableDataDesensitizationItem> items = getList();
Iterator<TableDataDesensitizationItem> iterator = items.iterator();
while (iterator.hasNext()) {
TableDataDesensitizationItem item = iterator.next();
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(item.getRule(), latestRules);
if (ruleStatus == DesensitizationRuleStatus.REMOVED) {
// 规则被移除,则删除整条脱敏Item
iterator.remove();
} else {
// 规则被修改、禁用等,更新一下规则
item.setRule(DesensitizationRuleManager.getInstance().getLastedDesentizationRule(item.getRule(), latestRules));
}
}
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, latestRules) != DesensitizationRuleStatus.NORMAL;
}
/**
* 刷新当前页面的本地规则缓存查询最新本地规则的逻辑也是使用了缓存因此无需考虑耗时
*/
private void refreshCustomRuleCache() {
Map<String, DesensitizationRule> customRules = DesensitizationRuleManager.getInstance().getRulesBySource(DesensitizationRuleSource.CUSTOM);
latestRules.put(DesensitizationRuleSource.CUSTOM, customRules);
}
}

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

@ -1,14 +1,28 @@
package com.fr.design.data.datapane.preview.desensitization.view.setting;
import com.fr.base.operator.org.OrganizationOperator;
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.DesensitizationRuleSource;
import com.fr.design.data.datapane.preview.desensitization.TableDataPreviewDesensitizeManager;
import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane;
import com.fr.design.gui.itableeditorpane.UITableEditorPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.workspace.WorkContext;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 脱敏字段设置页面中的Table
@ -34,6 +48,15 @@ public class TableDataDesensitizationTablePane extends JPanel {
*/
private UITableEditorPane<TableDataDesensitizationItem> editorPane;
private static final String LOADING_PANE = "loading";
private static final String CONTENT_PANE = "content";
private CardLayout card;
private JPanel loadingPane;
private JPanel contentPane;
public TableDataDesensitizationTablePane(DesensitizationTableData tableData, Component parent) {
this.tableData = tableData;
this.parent = parent;
@ -41,10 +64,65 @@ public class TableDataDesensitizationTablePane extends JPanel {
}
private void initComponent() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.editorPane = new UITableEditorPane<>(new TableDataDesensitizationTableModel(tableData, parent));
this.editorPane.setHeaderResizing(false);
this.add(editorPane, BorderLayout.CENTER);
card = new CardLayout();
this.setLayout(card);
// 初始化Loading面板
loadingPane = new TipsPane(true);
this.add(LOADING_PANE, loadingPane);
switchTo(LOADING_PANE);
// 在SwingWorker中初始化Content面板并切换
initContent();
}
/**
* 初始化内容面板
* 考虑到远程设计下的性能需要限制查询数据库的次数所以这里查一次之后子面板内复用
*/
private void initContent() {
final List<String> columnNames = new ArrayList<>();
final Map<String, String> roleMap = new LinkedHashMap<>();
final Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules = new LinkedHashMap<>();
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
// 获取当前数据集的所有列名
columnNames.addAll(TableDataPreviewDesensitizeManager.getInstance().getColumnNamesByTableData(tableData));
// 获取当前所有用户组
roleMap.putAll(WorkContext.getCurrent().get(OrganizationOperator.class).getAllRoles4Desensitization());
// 获取当前最新的所有规则
latestRules.putAll(DesensitizationRuleManager.getInstance().getAllRules());
return null;
}
@Override
protected void done() {
contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
editorPane = new UITableEditorPane<>(new TableDataDesensitizationTableModel(tableData, parent, columnNames, roleMap, latestRules));
editorPane.setHeaderResizing(false);
editorPane.populate(tableData.getDesensitizationConfig().getDesensitizationItems().toArray(new TableDataDesensitizationItem[0]));
contentPane.add(editorPane, BorderLayout.CENTER);
add(CONTENT_PANE, contentPane);
switchTo(CONTENT_PANE);
}
}.execute();
}
/**
* 切换面板
*
* @param panelName
*/
public void switchTo(String panelName) {
try {
if (panelName != null) {
card.show(this, panelName);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
/**
@ -54,13 +132,22 @@ public class TableDataDesensitizationTablePane extends JPanel {
*/
public void populateDesensitizationSetting(DesensitizationTableData tableData) {
this.tableData = tableData;
editorPane.populate(tableData.getDesensitizationConfig().getDesensitizationItems().toArray(new TableDataDesensitizationItem[0]));
if (editorPane != null) {
// editorPane的初始化在SwingWorker中完成,这里做个判空
editorPane.populate(tableData.getDesensitizationConfig().getDesensitizationItems().toArray(new TableDataDesensitizationItem[0]));
}
}
/**
* 获取当前对TableData的配置脱敏规则信息
*/
public List<TableDataDesensitizationItem> updateDesensitizationSetting() {
return editorPane.update();
return editorPane == null ?
new ArrayList<>() :
editorPane.update()
.stream()
.filter(item -> TableDataDesensitizationItem.valid(item))
.collect(Collectors.toList());
}
}

9
designer-base/src/main/java/com/fr/design/file/DefaultTemplateTreeDefineProcessor.java

@ -28,6 +28,7 @@ import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.collections.CollectionUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
@ -229,7 +230,13 @@ public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefi
}
//确定目标目录并检查权限
FileOperations selectedOperation = DesignerFrameFileDealerPane.getInstance().getSelectedOperation();
if (!selectedOperation.access()) {
boolean rootAuthority = true;
if (selectedOperation.getFileNode() == null && selectedOperation instanceof TemplateTreePane) {
//没有选中文件节点时,默认粘贴到根目录下,所以直接检测根目录是否有权限
ExpandMutableTreeNode root = (ExpandMutableTreeNode) ((TemplateTreePane) selectedOperation).getTemplateFileTree().getModel().getRoot();
rootAuthority = root.hasFullAuthority();
}
if (!rootAuthority && !selectedOperation.access()) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Template_Permission_Denied"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),

3
designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java

@ -307,10 +307,11 @@ public class TemplateTreePane extends JPanel implements FileOperations {
if (reportletsTree.getSelectionCount() == 0) {
//没选中文件刷新根目录
reportletsTree.refresh();
return;
}
reportletsTree.refreshParent(Objects.requireNonNull(reportletsTree.getSelectionPath()));
DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(null);
FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Template_File_Tree_Refresh_Successfully") + "!");
FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Template_File_Tree_Refresh_Successfully"));
}

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

54
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<T> extends BasicPane {
private String leftLabelName;
private JPanel buttonPane;
public UITableEditorPane(UITableModelAdapter<T> model) {
this.tableModel = model;
this.initComponent(model.createAction());
}
public UITableEditorPane(UITableModelAdapter<T> model) {
this.tableModel = model;
this.initComponent(model.createAction());
}
public UITableEditorPane(UITableModelAdapter<T> model, String s) {
leftLabelName = s;
this.tableModel = model;
this.initComponent(model.createAction());
}
public UITableEditorPane(UITableModelAdapter<T> 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<T> extends BasicPane {
}
public UITableModelAdapter<T> getTableModel(){
public UITableModelAdapter<T> 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<T> extends BasicPane {
return buttonPane;
}
public JTable getEditTable() {
return editTable;
}
public void setEditTable(JTable editTable) {
this.editTable = editTable;
}
/**
* 停止编辑
*/
@ -157,7 +167,7 @@ public class UITableEditorPane<T> extends BasicPane {
/**
* 设置表头是否可以改变大小
*/
public void setHeaderResizing(boolean resizingAllowed){
public void setHeaderResizing(boolean resizingAllowed) {
editTable.getTableHeader().setResizingAllowed(resizingAllowed);
}

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

@ -219,57 +219,69 @@ 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.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 (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);
}
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);
}
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;
}

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

2
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -329,7 +329,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
/**
* 为另存的模板创建新的模板id
*/
private void generateNewTemplateIdForSaveAs() {
protected void generateNewTemplateIdForSaveAs() {
generateTemplateId();
}

3
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java

@ -18,6 +18,7 @@ import com.fr.event.Null;
import com.fr.intelli.metrics.Compute;
import com.fr.intelli.record.Focus;
import com.fr.intelli.record.PerformancePoint;
import com.fr.jvm.assist.FineAssist;
import com.fr.module.Activator;
import com.fr.module.extension.Prepare;
import com.fr.record.analyzer.AnalyzerConfiguration;
@ -57,7 +58,7 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare {
List<AnalyzerConfiguration> backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY);
if (!CollectionUtils.isEmpty(backwardsConfigurations)) {
// 直接初始化,不添加默认值,防止和下面的冲突
FineAnalyzer.initDirectly(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0]));
FineAnalyzer.initDirectly(FineAssist.findInstrumentation(), basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0]));
}
// 等页面完全打开后,再进行 retransform, 别影响了启动速度

3
designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java

@ -11,6 +11,7 @@ import com.fr.intelli.record.Measurable;
import com.fr.intelli.record.MeasureObject;
import com.fr.intelli.record.MeasureUnit;
import com.fr.log.FineLoggerFactory;
import com.fr.log.message.AbstractMessage;
import com.fr.measure.DBMeterFactory;
import com.fr.stable.StringUtils;
import com.fr.third.net.bytebuddy.asm.Advice;
@ -75,7 +76,7 @@ public class MonitorAdvice implements DesignerAnalyzerAdvice {
List<Object> newArgs = new ArrayList<>(Arrays.asList(args));
newArgs.add(id);
recordSQLDetail(id);
Object message = null;
AbstractMessage message = null;
try {
message = measurable.durableEntity(measureObject, newArgs.toArray());
} catch (Throwable throwable) {

7
designer-base/src/main/resources/com/fr/design/standard/refresh/refresh_normal.svg

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon_刷新_normal</title>
<g id="icon_刷新_normal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M13.0593807,1 C13.4802225,1 13.8213822,1.34115968 13.8213822,1.76200147 L13.8213822,1.76200147 L13.8213822,5.2534957 C13.8213822,5.67433749 13.4802225,6.01549717 13.0593807,6.01549717 L13.0593807,6.01549717 L9.56788646,6.01549717 C9.14704467,6.01549717 8.80588499,5.67433749 8.80588499,5.2534957 C8.80588499,4.83265391 9.14704467,4.49149423 9.56788646,4.49149423 L9.56788646,4.49149423 L11.169634,4.48959417 C10.8434607,4.27112237 10.4895308,4.09123525 10.1125367,3.95402064 C7.56533579,3.02691531 4.74885407,4.34026231 3.82174874,6.88746326 C2.89464341,9.43466421 4.20799041,12.2511459 6.75519136,13.1782513 C9.30239231,14.1053566 12.118874,12.7920096 13.0459794,10.2448086 C13.1899157,9.84934672 13.6271844,9.64544497 14.0226464,9.78938133 C14.4181083,9.9333177 14.62201,10.3705864 14.4780737,10.7660483 C13.2630956,14.1041731 9.57207646,15.8253236 6.23395166,14.6103456 C2.89582685,13.3953675 1.17467636,9.70434836 2.38965442,6.36622356 C3.60463249,3.02809876 7.29565164,1.30694826 10.6337764,2.52192632 C11.3047108,2.76612647 11.9217951,3.11486447 12.467588,3.55405023 L12.297,3.423 L12.2973792,1.76200147 C12.2973792,1.37622983 12.5840481,1.05741329 12.9559816,1.00695618 Z" id="Combined-Shape" fill="#333334" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

18
designer-form/src/main/java/com/fr/design/designer/beans/models/ClipboardProvider.java

@ -0,0 +1,18 @@
package com.fr.design.designer.beans.models;
public interface ClipboardProvider {
/**
* 剪切到剪贴板
*
* @param o 剪切对象
*/
void cut2Clipboard(Object o);
/**
* 复制到剪贴板
*
* @param o 复制对象
*/
void copy2Clipboard(Object o);
}

45
designer-form/src/main/java/com/fr/design/designer/beans/models/DashboardClipboardManager.java

@ -0,0 +1,45 @@
package com.fr.design.designer.beans.models;
import java.util.ArrayList;
import java.util.List;
/**
* 用来管理不同剪贴板以及之间的数据同步
*/
public class DashboardClipboardManager {
private static class Holder {
private static final DashboardClipboardManager HOLDER = new DashboardClipboardManager();
}
private static final List<ClipboardProvider> CLIPBOARD_LIST = new ArrayList<>();
public void registerDashboardClipboard(ClipboardProvider clipboard) {
CLIPBOARD_LIST.add(clipboard);
}
public void removeDashboardClipboard(ClipboardProvider clipboard) {
CLIPBOARD_LIST.remove(clipboard);
}
public static DashboardClipboardManager getInstance() {
return Holder.HOLDER;
}
private DashboardClipboardManager() {
}
public void cut2Clipboard(Object o) {
for (ClipboardProvider clipboard : CLIPBOARD_LIST) {
//同步其他剪贴板
clipboard.cut2Clipboard(o);
}
}
public void copy2Clipboard(Object o) {
for (ClipboardProvider clipboard : CLIPBOARD_LIST) {
//同步其他剪贴板
clipboard.copy2Clipboard(o);
}
}
}

45
designer-form/src/main/java/com/fr/design/designer/beans/models/FormSelectionClipboard.java

@ -0,0 +1,45 @@
package com.fr.design.designer.beans.models;
import com.fr.design.mainframe.FormSelection;
public class FormSelectionClipboard implements ClipboardProvider {
private static final FormSelection FRM_CLIPBOARD = new FormSelection();
static {
DashboardClipboardManager.getInstance().registerDashboardClipboard(FormSelectionClipboard.getInstance());
}
private static class Holder {
private static final FormSelectionClipboard HOLDER = new FormSelectionClipboard();
}
public static FormSelectionClipboard getInstance() {
return Holder.HOLDER;
}
private FormSelectionClipboard() {
}
public boolean isEmpty() {
return FRM_CLIPBOARD.isEmpty();
}
public FormSelection getClipboard() {
return FRM_CLIPBOARD;
}
@Override
public void cut2Clipboard(Object o) {
if (o instanceof FormSelection) {
((FormSelection) o).cut2ClipBoard(FRM_CLIPBOARD);
}
}
@Override
public void copy2Clipboard(Object o) {
if (o instanceof FormSelection) {
((FormSelection) o).copy2ClipBoard(FRM_CLIPBOARD);
}
}
}

26
designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java

@ -46,12 +46,14 @@ public class SelectionModel {
//被粘贴组件在所选组件位置处往下、往右各错开20像素。执行多次粘贴时,在上一次粘贴的位置处错开20像素。
private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离
private static final double OFFSET_RELATIVE = 0.80;
private static FormSelection clipboard = new FormSelection();
private static FormSelectionClipboard formClipboard = FormSelectionClipboard.getInstance();
private FormDesigner designer;
private FormSelection selection;
private Rectangle hotspotBounds;
private FormWidgetOptionProvider provider;
public SelectionModel(FormDesigner designer) {
this.designer = designer;
selection = new FormSelection();
@ -71,7 +73,7 @@ public class SelectionModel {
* @return 是否为空
*/
public static boolean isEmpty() {
return clipboard.isEmpty();
return formClipboard.isEmpty();
}
/**
@ -161,7 +163,7 @@ public class SelectionModel {
if (hasSelectionComponent()) {
FormSelection cutSelection = ClipboardFilter.cut(selection);
if (cutSelection != null) {
cutSelection.cut2ClipBoard(clipboard);
DashboardClipboardManager.getInstance().cut2Clipboard(cutSelection);
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED);
setSelectedCreator(hasSelectedParaComponent() ? designer.getParaComponent() : designer.getRootComponent());
designer.repaint();
@ -192,7 +194,7 @@ public class SelectionModel {
if (!selection.isEmpty()) {
FormSelection copySelection = ClipboardFilter.copy(selection);
if (copySelection != null) {
copySelection.copy2ClipBoard(clipboard);
DashboardClipboardManager.getInstance().copy2Clipboard(copySelection);
}
}
}
@ -203,7 +205,7 @@ public class SelectionModel {
* @return
*/
public boolean pasteFromClipBoard() {
FormSelection pasteSelection = ClipboardFilter.paste(clipboard);
FormSelection pasteSelection = ClipboardFilter.paste(formClipboard.getClipboard());
if (pasteSelection != null && !pasteSelection.isEmpty()) {
if (!hasSelectedPasteSource()) {
//未选
@ -240,7 +242,7 @@ public class SelectionModel {
//编辑器外面还有两层容器,使用designer.getRootComponent()获取到的是编辑器中层的容器,不是编辑器表层
//当前选择的就是编辑器表层
FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(),
clipboard,
formClipboard.getClipboard(),
DELTA_X_Y,
DELTA_X_Y);
}
@ -248,7 +250,7 @@ public class SelectionModel {
//cpt本地组件复用,编辑器就一层,是最底层,使用designer.getRootComponent()就可以获取到
//使用selection.getSelectedCreator()也应该是可以获取到的。
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(),
clipboard,
formClipboard.getClipboard(),
DELTA_X_Y,
DELTA_X_Y);
}
@ -266,7 +268,7 @@ public class SelectionModel {
if (hasSelectedPasteSource()) {
selectedPaste();
} else {
FormSelectionUtils.paste2Container(designer, container, clipboard,
FormSelectionUtils.paste2Container(designer, container, formClipboard.getClipboard(),
rectangle.x + rectangle.width / 2,
rectangle.y + DELTA_X_Y);
}
@ -281,7 +283,7 @@ public class SelectionModel {
selectedPaste();
} else {
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(),
clipboard,
formClipboard.getClipboard(),
rectangle.x + rectangle.width / 2,
rectangle.y + DELTA_X_Y);
}
@ -314,13 +316,13 @@ public class SelectionModel {
positionX = selectionRec.x - containerRec.x + selectionRec.width / 2;
positionY = (int) (selectionRec.y - containerRec.y + selectionRec.height * OFFSET_RELATIVE);
}
FormSelectionUtils.paste2Container(designer, container, clipboard, positionX, positionY);
FormSelectionUtils.paste2Container(designer, container, formClipboard.getClipboard(), positionX, positionY);
} else if (container != null && selection.getSelectedCreator().getParent() instanceof XWAbsoluteLayout) {
//绝对布局
Rectangle rec = selection.getSelctionBounds();
FormSelectionUtils.paste2Container(designer, container, clipboard, rec.x + DELTA_X_Y, rec.y + DELTA_X_Y);
FormSelectionUtils.paste2Container(designer, container, formClipboard.getClipboard(), rec.x + DELTA_X_Y, rec.y + DELTA_X_Y);
} else if (isExtraContainer(container)) {
provider.paste2Container(clipboard);
provider.paste2Container(formClipboard.getClipboard());
}
}

2
designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java

@ -68,7 +68,7 @@ public class LabelDefinePane extends AbstractDataModify<Label> {
int[][] rowCount = {{1, 3}, {1, 1}, {1, 1}, {1, 1}, {1, 1}};
UILabel widgetValueLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Estate_Widget_Value"));
widgetValueLabel.setVerticalAlignment(SwingConstants.TOP);
UILabel fontLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Font_Size"));
UILabel fontLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Font"));
fontLabel.setVerticalAlignment(SwingConstants.TOP);
Component[][] components = new Component[][]{
new Component[]{widgetValueLabel, formWidgetValuePane},

2
designer-form/src/main/java/com/fr/design/widget/ui/designer/btn/ButtonGroupDefinePane.java

@ -44,7 +44,7 @@ public abstract class ButtonGroupDefinePane<T extends ButtonGroup> extends Field
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Label_Name")), labelNameTextField},
new Component[]{widgetValueLabel, formWidgetValuePane},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_DS_Dictionary")), dictionaryEditor},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FR_Font")), fontSizePane},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Font_Size")), fontSizePane},
new Component[]{buttonGroupDictPane, null}
};
double[] rowSize = {p, p, p, p, p, p, p};

2
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/PluginSearchManager.java

@ -214,7 +214,7 @@ public class PluginSearchManager implements AlphaFineSearchProvider {
}
return time;
}
}));
}).reversed());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}

121
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,86 @@ 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);
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);
initAllNames();
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 +279,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 +288,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 +311,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 +457,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 +690,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 +795,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);
}

139
designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/CellDesensitizationGroupsPane.java

@ -0,0 +1,139 @@
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)) {
// 记录埋点数据
if (!desensitizationBeans.isEmpty()) {
recordDesensitization(desensitizationBeans);
}
editorPane.populate(desensitizationBeans.toArray(new CellDesensitizationBean[]{}));
}
}
/**
* 记录预览导出脱敏埋点
*/
private int recordDesensitization(List<CellDesensitizationBean> desensitizationBeans) {
return desensitizationBeans.size();
}
}

108
designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/CellDesensitizationTableModel.java

@ -0,0 +1,108 @@
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;
}
@Override
public void fireTableDataChanged() {
super.fireTableDataChanged();
attrPane.attributeChanged();
}
}

47
designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellEditor.java

@ -0,0 +1,47 @@
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.SwingWorker;
import javax.swing.border.LineBorder;
import javax.swing.table.TableCellEditor;
import java.awt.Color;
import java.awt.Component;
import java.util.Map;
/**
* 脱敏规则设置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) {
// 点击脱敏设置时刷新用户组信息和所有规则
SwingWorker<Map<String, Object>, Void> updateDateWorker = new UpdateDataWorker();
updateDateWorker.execute();
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();
}
}

332
designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java

@ -0,0 +1,332 @@
package com.fr.design.mainframe.cell.settingpane.desensitization.model;
import com.fr.base.operator.org.OrganizationOperator;
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.beans.BasicBeanPane;
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.file.HistoryTemplateListCache;
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.design.mainframe.JTemplate;
import com.fr.design.mainframe.JTemplateActionListener;
import com.fr.report.cell.desensitization.CellDesensitizationBean;
import com.fr.stable.StringUtils;
import com.fr.third.org.apache.commons.collections4.map.HashedMap;
import com.fr.workspace.WorkContext;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
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;
import java.util.concurrent.ExecutionException;
/**
* 单元格脱敏规则设置面板
*
* @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 DesensitizationRule rule;
private static Map<String, String> roleMap;
private static Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules;
private CellDesensitizationTableModel model;
private static final CellDesensitizationBean EMPTY_BEAN = CellDesensitizationBean.createEmptyBean();
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);
latestRules = new HashMap<>();
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.fireTableDataChanged();
}
}
};
private final ActionListener chooseRuleListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CellDesensitizationBean selectBean = model.getSelectedValue();
DesensitizationRulePane rulePane = new DesensitizationRulePane(latestRules);
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);
model.fireTableDataChanged();
}
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();
refreshRuleText(value);
// 非正常状态需要颜色修改为红色
refreshRuleState(value);
Map<Object, Boolean> map = generateRolesCheckBoxSelectedValues(value);
rolesComboBox.setSelectedValues(map);
label.setText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Setting") + (row + 1));
}
/**
* 刷新规则文本
*
* @param value
*/
private void refreshRuleText(CellDesensitizationBean value) {
ruleTextField.setText(StringUtils.EMPTY);
DesensitizationRule desensitizationRule = value.getDesensitizationRule();
if (desensitizationRule != null) {
String ruleName = desensitizationRule.getRuleName();
ruleTextField.setText(ruleName);
}
}
/**
* combobox组件刷新用户组信息
*/
private void refreshRoles() {
rolesComboBox.clearText();
rolesComboBox.refreshCombo(roleMap.values().toArray());
}
private void refreshRuleState(CellDesensitizationBean value) {
DesensitizationRuleStatus ruleStatus = DesensitizationRuleManager.getInstance().getRuleStatus(value.getDesensitizationRule(), latestRules);
if (EMPTY_BEAN.equals(value)) {
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;
}
}
/**
* 更新用户组和平台规则
*/
public static void updateData(Map<String, String> roleMap, Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> latestRules) {
DesensitizationCellPane.roleMap = roleMap;
DesensitizationCellPane.latestRules = latestRules;
}
}

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

47
designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/UpdateDataWorker.java

@ -0,0 +1,47 @@
package com.fr.design.mainframe.cell.settingpane.desensitization.model;
import com.fr.base.operator.org.OrganizationOperator;
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.workspace.WorkContext;
import javax.swing.SwingWorker;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
/**
* 刷新脱敏设置全局 roles rules SwingWorker
*
* @author Leo.Qin
* @version 11.0
* Created by Leo.Qin on 2023/1/5
*/
public class UpdateDataWorker extends SwingWorker<Map<String, Object>, Void> {
private final String ROLE_KEY = "Roles";
private final String RULE_KEY = "Rules";
@Override
protected Map<String, Object> doInBackground() {
Map<String, Object> result = new HashMap<>();
Map<String, String> allRoles = WorkContext.getCurrent().get(OrganizationOperator.class).getAllRoles4Desensitization();
Map<DesensitizationRuleSource, Map<String, DesensitizationRule>> allRules = DesensitizationRuleManager.getInstance().getAllRules();
result.put(ROLE_KEY, allRoles);
result.put(RULE_KEY, allRules);
return result;
}
@Override
protected void done() {
try {
Map<String, Object> result = get();
DesensitizationCellPane.updateData((Map<String, String>) result.get(ROLE_KEY), (Map<DesensitizationRuleSource, Map<String, DesensitizationRule>>) result.get(RULE_KEY));
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}

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

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