Skip to content

JDL增强

BegCode在JHipster的基础上,对JDL的注解进行了增强,主要体现在以下几个方面。

3. 对field增加多个注解

3.1 @endUsed注解

本注解主要用来定制前端的显示或编辑组件。

系统中默认字段类型对应的组件分别如下:

md
LOCATE_DATE: DatePicker
ZONED_DATE_TIME: DatePicker
ENUM: Select
DOUBLE: InputNumber
FLOAT: InputNumber
INTEGER: InputNumber
LONG: InputNumber
BIG_DECIMAL: InputNumber
BOOLEAN: Switch
STRING: Input
TEXTBLOB: Editor

通过@endUsed注解可以调整为其他组件。

示例如下:

md
    @endUsed(iconPicker)
    @importDataField
    @columnWidth(50)
    icon String /** 图标 */

示例中使用icon图标选择组件。

@endUsed支持的组件有:

md
    fileUrl: 文件上传并接收Url
    imageUrl: 图片上传并接收Url
    videoUrl: 文件上传并接收Url
    audioUrl: 文件上传并接收Url
    editor: 富文本编辑器
    codeEditor: 代码编辑器
    select: 下接选择框
    checkbox: 多选框
    radio: 单选框
    radioButton: 按钮样式的单选组合
    rate: 评分
    slider: 滑动输入条
    switch: 开关
    textArea: 文本域
    avatar: 头像
    iconPicker: ICON选择器
    selectModal: 高级弹窗选择器(高级组件)

3.2 @skipCriteria注解

表示该字段不在条件参数类中。

示例:

md
@skipCriteria
@skipDto
@fieldColumnName(password_hash)
@importDataField
password String /\*_ 密码 _/

表示password不出现在条件查询类(UserCriteria)中

3.3 @skipDto注解

表示该字段不在Api接口输出类中。示例同3.2

3.4 @fieldColumnName注解

指定数据库表中列名,一般情况下不使用,可能有时属性名无法转换为数据库表中列名时可用。示例同3.2

3.5 @columnWidth注解

指定前端列表显示时字段宽度。一般情况下,不同类型字段有默认宽度,但需要指定时使用此注解。

示例如下:

md
    @endUsed(iconPicker)
    @importDataField
    @columnWidth(50)
    icon String /** 图标 */

3.6 @fieldConfig注解

这是一个比较复杂的注解,支持多种参数,使用-分隔。

支持的参数有:

md
hideInList: 前端列表中不显示
hideInForm:前端编辑中不显示
editInList:前端列表中直接编辑
searchForm:前端列表中显示在查询表单中(默认都显示,但此项靠前)
filter:前端列表列是否可筛选

示例如下:

md
    @fieldConfig(hideInList-hideInForm)
    @ownerEntityName
    ownerEntityName String /** 实体名称 */

3.6 @sortField注解

该字段是排序字段,前端显示排序组件,后端生成相应的排序接口。 支持三种排序操作方式:拖拽、上下移动、填写数值。

示例如下:

md
    @sortField(asc)
    sortValue Integer /** 排序 */

3.6.1 java接口文件

java
    @PutMapping("/sort-value/{id}/{type}")
    @Operation(tags = "更新排序字段值", description = "根据移动记录ID和插入点前后记录ID更新排序值")
    @AutoLog(value = "更新排序字段值", logType = LogType.OPERATE, operateType = OperateType.EDIT)
    public ResponseEntity<Boolean> updateSortValue(
        @PathVariable(value = "id", required = false) final Long id,
        @PathVariable(value = "type") SortValueOperateType type,
        @RequestParam(value = "beforeId", required = false) Long beforeId,
        @RequestParam(value = "afterId", required = false) Long afterId,
        @RequestParam(value = "newSortValue", required = false) Integer newSortValue,
        @RequestBody(required = false) PositionCriteria criteria
    ) {
        log.debug("REST request to update SortValue : {}, {}, {}", id, beforeId, afterId);
        if (ObjectUtils.allNull(beforeId, afterId) && !type.equals(SortValueOperateType.VALUE)) {
            throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
        }
        if (positionRepository.findById(id).isEmpty()) {
            throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound");
        }
        QueryWrapper<Position> queryWrapper = null;
        if (type.equals(SortValueOperateType.DROP)) {
            queryWrapper = positionQueryService.createQueryWrapper(criteria);
        }
        Boolean result = positionService.updateSortValue(id, beforeId, afterId, newSortValue, queryWrapper, type);
        return ResponseEntity.ok().body(result);
    }

3.6.2 后端service类

sort_value_service.png

3.6.3 前端效果

上下移动: sort_value.png

拖拽: sort_value_drag.png

3.7 @showBy注解

条件显示,主要用在form中,根据条件进行显示。 支持简单的比较操作符:

javascript
const operators = ['!=', '>=', '<=', '==', '<>', '>', '<', '='];

示例如下:

md
    @showBy("type=MENU")
    link String /** 路由 */

前端生成代码如下:

javascript
const config = [
  {
    label: '隐藏面包屑',
    field: 'hideInBreadcrumb',
    show: ({ values }) => {
      return values && values.type === 'MENU';
    },
    component: 'Switch',
    componentProps: { placeholder: '请选择隐藏面包屑' },
    rules: [],
  },
  {
    label: '快捷菜单项',
    field: 'shortcut',
    show: ({ values }) => {
      return values && values.type === 'MENU';
    },
    component: 'Switch',
    componentProps: { placeholder: '请选择快捷菜单项' },
    rules: [],
  },
  {
    label: '菜单根节点',
    field: 'shortcutRoot',
    show: ({ values }) => {
      return values && values.type === 'MENU';
    },
    component: 'Switch',
    componentProps: { placeholder: '请选择菜单根节点' },
    rules: [],
  },
];

3.8 @collectIdByRelationFrom注解

这是一个复杂而不常用的注解,实现的功能是收集与某一实体(A)有关联关系的其他实体(B/C/D)的id,通过其他实体(B/C/D)的id由后端去获得所有相关的A实体的id列表。 通过示例具体说明。

示例如下:

md
/\*\*

- 通告对象类型
  _(USER:指定用户,ALL:全体用户)
  _/
  receiverType ReceiverType required  
  @showBy("receiverType!=ALL")
  @endUsed(selectModal)
  @collectIdByRelationFrom("User=receiverType")
  receiverIds TextBlob /\*_ 指定接收者id _/

本示例中,在消息通知编辑页面,通过receiverType来确定给哪一类人发消息,类型有:全部、指定用户、部门、角色、岗位五种, 如果指定为全部则不显示选择组件,其他形式下显示相应的弹窗组件并支持选择。

前端代码:

javascript
const config = [
  {
    label: '指定接收者id',
    field: 'receiverIds',
    show: ({ values }) => {
      return values && values.receiverType !== 'ALL';
    },
    component: 'SelectModal',
    componentProps: ({ formModel }) => {
      let componentName = '';
      if (formModel.receiverType === 'USER') {
        componentName = 'UserRelation';
      } else if (formModel.receiverType === 'DEPARTMENT') {
        componentName = 'DepartmentRelation';
      } else if (formModel.receiverType === 'POSITION') {
        componentName = 'PositionRelation';
      } else if (formModel.receiverType === 'AUTHORITY') {
        componentName = 'AuthorityRelation';
      }
      return {
        placeholder: '请选择指定接收者id',
        style: 'width: 100%',
        componentName,
        updateType: 'emitSelected',
        showComponentName: 'Avatar',
        queryNames: ['id.in'],
        rowIdField: 'value.id',
        valueType: 'splitString',
      };
    },
    rules: [],
  },
];

运行效果: announcement.png