自定义SQL列表与表单

自定义列表是基于一段查询SQL,快速生产列表页面的强大的快速开发工具, 类似于在navicat中执行查询语句,将数据展现出来, 在自定义列表中, 配合表单可以快速开发增,删,改,查,导出,状态字段变更,等等一系列功能。还能实现自定义按钮,自定义查询条件,多个列表页交互,左树右列表等强大的功能.

1585198867959

配置自定义 SQL 列表

自定义 SQL 列表可以通过一个SQL,生成列表页、报表,支持分页搜索,并且可以添加增删改查、状态变更等操作按钮。

在 表单管理=》自定义列表=》自定义列表中 点击【添加】新增一个自定义SQL

1585198923960

1.解析自定义SQL

在顶部代码编辑框中输入一个 SQL,并点击 【解析】按钮 如:(提示,禁止SQL中出现大文本字段)

SELECT
id AS id,
ah AS ah,
bm AS bm,
bm_id AS bmId,
cjsj AS cjsj,
mz AS mz,
nl AS nl,
sum AS sum,
xb AS xb,
zd1 AS zd1,
zd2 AS zd2,
zjlx AS zjlx
FROM
biz_demo

您可以在 SQL 中使用 以下系统参数

  • ${currentUserId}
  • ${currentUserName}
  • ${curOrgId}
  • ${curTime}
  • ${curDate}
  • ${curDateTime}

如:

select * from org_user where id_ = '${currentUserId}'

除此之外,还可以使用 ${xxx} 作为参数变量,xxx 参数可以从 url 地址传入,也可以从查询栏传入,优先使用查询栏的参数。
url 地址传入作为参数变量具体方法:

  • 1、确定url中有参数穿入,可以使用按钮跳转设置跳转链接/请求地址,在其中带入参数。
    1585198988881
  • 2、设置变量类型:
    • 普通变量 : 直接在SQL后面拼接where条件.无需再写${xxxx}
    • freemaker变量 : 如果是freemaker变量,则会将sql中的${xxxx}替换掉 , 而不是直接在SQL后面拼接where条件,如下:
      1585198988881

2.设置列表字段关键属性

1585198988881

  • 名称:设置自定义Sql列表的 名字(添加菜单时会作为菜单名)
  • 编码: 不能重复
  • 数据源: 指定数据的来源数据库
  • 是否支持导出: 如果选择是, 自会出现导出按钮, 导出时会根据当前的查询条件导出数据
  • 是否默认查询:如果如果否,第一次打开列表页的时候不会触发查询,在点击搜索后才会查询,这会在部分报表的场景非常有用
  • 分页大小: 即指定当前打开列表页的默认分页大小
  • 显示行号/序号: 选择是,第一列默认显示序号列
  • 单选/多选: 选择单选或者多选时, 第一列默认显示单选框或者复选框, 方便全局按钮点击之前,选择对应的数据
  • 表名: 指定当前SQL的默认主表名称, 如果SQL中是多表关联的,需要指定一个主表, 方便自定义按钮修改该表的数据
  • 主键名称: 指定当前SQL的默认主键字段, 这样就可以在自定义按钮触发时 传递该字段的数据到后台.
  • 是否启用: 禁用后, 将无法正常访问该自定义列表, 比如发现自定义列表中的SQL语句,有严重的数据泄露错误时,可以立马禁用该自定义列表
  • 关联在线表单: 自定义SQL列表可以关联一个在线表单,这样可以借助在线表单实现增删改查的需求
  • 展示前脚本: 会在关联的在线表单打开前执行,可以用他初始化表单数据
  • 保存前脚本: 会在关联的在线表单点击保存后,在后端执行,为 Groovy 脚本,可以用来做服务端赋值、校验,如业务对象别名为Demo

     // 给业务对象字段设值,如前置脚本设置默认值流水号
    Demo.put('ddNo',sysScript.getNextSerialNo('dayNo'))

    // 通过sql更新相关联数据 ,Demo.get('code')即从业务对象获取字段值
    sysScript.executeUpdateSql("update xxxxxx set name=? where id =? ",Demo.get('code'))

    // 校验业务对象 User 的account 字段 是否重复
    busDataScript.checkBusDataIsExist(User,'account','账户已存在');
  • 保存后置脚本: 关联表单的业务对象保存成功后执行的 Groovy 脚本,可以用来做业务方面的事情

其他属性都比较见名知意,这里不再赘述

3.列表字段设置

可以根据实际情况设置 字段备注、对齐方式、是否隐藏、是否导出、字段的超链接,可以拖拽移动顺序

1585199044900

  • 字段备注: 即设置列表页的列头, 导出的excel中的列头也是按照这里设置的.

  • 控件类型:

    • 单行文本框/json/多行文本 : 这三种类型默认都是直接展示数据
    • 日期控件 : 需要设置格式化数据, 如 yyyy-MM-dd, yyyy-MM-dd HH:mm:ss , yyyy/MM/dd 等
    • 下拉框/单选框/复选框 : 需要设置格式化数据, 如 {“1”:”苹果”,”2”:”梨”,”3”:”香蕉”} 列表页将会把1/2/3转为苹果/香蕉/梨.
    • 数据字典/[字典单选框] : 需要设置格式化数据为数据字典KEY, 如 sex
    • [字典复选框] : 需要设置格式化数据为数据字典KEY, 如 fruit , 用在多值的情况下, 比如后台传的数据是1,2 此时列表页会转成 苹果,梨
    • 附件上传 : 格式化附件,点击字段后直接下载附件
    • JSON : 要求数据格式为JSON类型,会通过格式化数据取值对应JSON某个属性值来展示,如果为数组则会取出数组对应字段的逗号分隔形式
  • 格式化数据:

    • 具体格式化参考 控件类型,如数据字典,则当前设置为数据字典key
  • 样式格式化:

    • 状态枚举样式格式化: 数据格式为:{"1":"success","2":"error","3":"primary"},会将值为1的转成 success 风格的 Tag
    • style 源码格式化: 如配置 color:red,则会在字段元素上添加 style= "color:red"
    • class 格式化: 数据格式为 具体 Class的 key ,如 maxlength-300 ,则会在字段元素上添加 class="maxlength-300"
  • 对齐方式 : 可选left/center/right 默认center

  • 是否隐藏 : 如果选择隐藏, 列表页中将不会显示该字段

  • 可导出 : 如果选择否, 导出excel时 将不再导出该字段

  • href : 字段链接 , 在列表页中点击该字段会跳转到该地址 ,

  • 打开方式 : 当设置了href 时, 点击该字段的跳转方式, 可选对话框/tab页/新窗口, 默认是tab标签页 , 选择对话框时,可以设置宽高.

  • 脱敏:脱敏设置为两个数字如 3,3,表示前三个字符,后三个字符保持原值,中间的部分脱敏。

    比如字符:一二三四五六七八
    设置 3,3 后脱敏结果为: 一二三****六七八,
    设置 3 后脱敏结果为: 一二三**

  • 列字段最长长度设置:

目前仅支持以下长度的样式格式化,如需更多,请自行在代码中添加

- 样式格式化设置 `maxlength-100` :最长100px,超长则显示 ...
- 样式格式化设置 `maxlength-120` :最长120px,超长则显示 ...
- 样式格式化设置 `maxlength-150` :最长150px,超长则显示 ...
- 样式格式化设置 `maxlength-200` :最长200px,超长则显示 ...
- 样式格式化设置 `maxlength-300` :最长300px,超长则显示 ...

4.列表查询设置

设置需要用作查询条件的字段

1585199087613

  • 字段备注

  • 条件类型 : 可选< , > , <> , = , <= , >= , in , is null , like , llike , rlike , not in , not null

    1585198748325

  • 控件类型:

    • 单行文本框/json/多行文本 : 这三种类型默认都是单行文本框
    • 日期控件 : 需要设置格式化数据, 如 yyyy-MM-dd, yyyy-MM-dd HH:mm:ss , yyyy/MM/dd 等
    • 下拉框/单选框/复选框 : 需要设置格式化数据, 如 {“1”:”苹果”,”2”:”梨”,”3”:”香蕉”}
    • 数据字典/[字典单选框] : 需要设置格式化数据为数据字典KEY, 如 sex
    • [字典复选框] : 需要设置格式化数据为数据字典KEY, 如 fruit , 用在多值的情况下, 比如后台传的数据是1,2 此时列表页会转成 苹果,梨
    • 自定义对话框:会通过自定义对话框作为入参
      格式化配置如下:
      { "dialogKey": "自定义对话框别名","id":"自定义对话框返回字段中ID字段,用于查询","name":"自定义对话框返回值名字字段,展示选择项","multiple":false,"param":"{设置默认查询条件JSON格式}"}

    1585199191601

  • 显示类型 :

    • 显示 : 默认项
    • 隐藏 : 一般用在默认值-固定类型, 查询时 前端传递该默认参数到后台
    • 禁用 : 一般用在默认值,不允许用户修改该查询条件
    • 移除 : 一般用在默认值-当前日期/当前用户信息等, 查询时,该条件由后台自动封装.
  • 格式化数据 : 配合控件类型使用

  • 是否必传 : 如果选择是, 那么用户在没有输入该查询条件的时候会提示用户必须输入该项才能查询出数据

  • 是否默认 : 如果选是,则需要设置默认值类型

  • 默认值类型 : 配合 默认值格式

    • 固定值 : 默认值格式 设置为具体的值
    • 当前日期 : 默认值格式设置为 如 yyyy-MM-dd, yyyy-MM-dd HH:mm:ss , yyyy/MM/dd 等
    • 当前用户ID
    • 当前用户名称
    • 当前组织ID
    • 当前组织名称
  • 变量类型 :

    • 普通变量 : 直接在SQL后面拼接where条件
    • freemaker变量 : 如果是freemaker变量,则会将sql中的${xxxx}替换掉 , 而不是直接在SQL后面拼接where条件

5.列表功能按钮

可以点击默认设置的一些快捷按钮快速添加列表按钮,您也可以参考默认按钮去配置特殊按钮。

1585200435761

1585200655655

关键属性

  • 效果 : 当前设置的效果 , 目前默认都用无图标的btn-primary

  • 名称 : 按钮名称

  • 别名 : 按钮别名 , 当前自定义列表中别名不能重复

  • 按钮类型 :

    • 全局按钮 : 会显示到按钮查询栏上面, 这里会判断选中的数据中, 是否满足显示条件
    • 行内按钮 : 会显示在每一行的操作栏上, 这里会根据显示条件判断是否显示
  • 必选 : 这是全局按钮的选项, 如果选择是,那么必须要选择至少一条数据才能触发按钮事件,否则会提示”至少选择一条数据”

  • 图标 : 由于系统统一了列表页的按钮展示风格,暂时没用

  • 样式 : 由于系统统一了列表页的按钮展示风格,暂时没用

  • 提醒内容 : 设置之后, 点击按钮时, 会提示用户是否确认操作, 如果没有设置提醒内容,就会直接触发按钮点击事件

  • 成功提醒 : 按钮操作成功后的提醒

  • 打开方式 :

    • 事件按钮 : 该功能十分强大, 可以修改表的字段的值

      一般配置两个事件按钮来修改某个字段的值

      比如开启,关闭 , 开启按钮将status设置为1, 关闭按钮将status设置为0

      注意: 需要被修改的字段必须在查询SQL中.

      • 数值变化 : 可以修改多个字段 , 用分号;隔开 比如 status=1;isChange=1;,同时也支持系统参数,格式:update_by_=${xxx}

        支持的系统参数

        // 当前用户ID
        ${currentUserId}

        // 当前用户名称
        ${currentUserName}

        // 当前用户部门ID
        ${currentOrgId}

        // 当前用户部门名称
        ${currentOrgName}

        // 当前日期 yyyy-MM-dd
        ${curDate}

        // 当前时间 HH:mm:ss
        ${curTime}

        // 当前日期+时间 yyyy-MM-dd HH:mm:ss
        ${curDateTime}

        // 当前环境变量
        ${env}
      • 关联表 : 配置字段所在的表, 默认使用主表,

      • 关联字段: 配置点击触发该按钮时,前端传递的数据字段. 方便后端根据该字段查询到需要被修改的数据,进行修改.

    • 下面的都需要配置 跳转链接/请求地址

    • 直接请求 : 直接触发一个POST接口请求 , 参数是通过url传递的, 不是postbody.

    • 普通对话框 : 会在当前的IFRAME中打开一个对话框

    • TOP对话框 : 会在当前IFRAME的父级页面打开一个对话框

    • tab页 : 打开一个tab标签页

    • 新页面 : 打开一个新页面

  • 跳转链接/请求地址 :

    可用${xxx} 获取行数据, 比如www.baidu.com?id=${id} , 如果ID为1 , 则会转成www.baidu.com?id=1

    xxx也可以是url中的某个参数

  • 显示条件 :

    1. 默认是true

    2. 也可以根据当前行数据进行判断, 比如 item.xxx == 1

      其中xxx是字段别名

    3. 也可以根据当前URL的参数进行判断 比如 $.getParams()[‘xxx’] == 1

      其中xxx是url中的某个参数

  • 菜单权限控制: 自定义SQL列表的按钮是支持按钮权限控制的,开启该项后,需要以按钮的形式加入菜单管理,鉴权按钮的 code 规则为:customsql_button_自定义SQL列表CODE_按钮CODE

6.左树右列表

当开启左边树时, 自定义列表页会在页面左边初始化一颗树, 点击树节点后,列表数据会级联更新

操作步骤

  1. 开启树 如图所示1586602064218

  2. 数据来源设置

    1. 下拉框 : 比如 {“1”:”下拉项1”,”2”:”下拉项2”,”3”:”下拉项3”} 效果如下

      1586602279249

    2. 数据字典 : 比如 idtype 则会数据字典中获取数据 效果如下

      1586602337511

    3. 系统树 : 比如 flow 则会系统树中获取数据 效果如下

      1586602420908

    4. 自定义列表 : 比如 sysResource 此时还需要设置其他几个参数

      1. 自定义列表-ID: 自定义列表sysResource 中 对应菜单树的ID的字段
      2. 自定义列表-PID: 自定义列表sysResource 中 对应菜单树的PID的字段
      3. 自定义列表-TITLE: 自定义列表sysResource 中 对应菜单树的TITLE的字段

        假如 自定义列表sysResource 的SQL如下

      1586602686526

      这三个字段则配置为 :

      1586602771913

      最终效果如下

      1586602808699

  3. 关联查询字段

    点击树节点时, 自定义列表会获取选中节点的对应的数据, 与关联的查询字段关联, 然后刷新数据

    注意 : 关联查询的字段必须存在于列表查询设置

  4. 是否显示根节点

    如果选是,则会默认显示一个根节点,此时需要配置根节点名称根节点ID

  5. 根节点名称

    比如设置成 组织菜单 则显示效果如下

    1586602808699

  6. 根节点ID

    随便填, 但是要注意该ID不能是数据来源中的任何一个节点的ID. 否则树就会有问题, 一般设置成-9999

完整DEMO演示 : 数据来源于自定义列表sysResource

  1. 左边树设置如下

    1586603382161

  2. 列表查询设置

    1586603435454

  3. 自定义列表sysResource 的设置

    1586602686526

  4. 最终效果

    1586603527332

7.配置表单权限

可以在自定义SQL列表关联的在线表单中配置表单字段权限,限制不同角色的人只能看到、编辑指定的内容。

8.国际化

需要做国际化的地方加上$:xxxxxx 即可

xxxxxx是国际化翻译的key值

自定义列表中需要用到国际化的地方

  1. 列表基础设置
    1. 名称
  2. 列表字段设置
    1. 字段备注
  3. 列表查询设置
    1. 字段备注
  4. 列表功能按钮设置
    1. 名称
    2. 提醒内容
    3. 成功提醒
  5. 左边树设置
    1. 根节点名称

后面有很多好玩的东西,敬请期待

我们可以单独去用自定义表单组件去渲染一个业务对象的JSON
一个业务对象的JSON 也可以提交到业务表单的保存接口去持久化
业务对象可以生成代码,代码也可以生成业务对象

小彩蛋

1 添加别名

会自动将SQL加上别名

比如

select
ID_,
PROC_DEF_ID_,
PROC_INST_ID_,
EXECUTION_ID_,
ACT_ID_,
TASK_ID_,
CALL_PROC_INST_ID_,
ACT_NAME_,
ACT_TYPE_,
ASSIGNEE_,
START_TIME_,
END_TIME_,
DURATION_,
TENANT_ID_
from
act_hi_actinst

会自动变成

SELECT
ID_ AS id,
PROC_DEF_ID_ AS procDefId,
PROC_INST_ID_ AS procInstId,
EXECUTION_ID_ AS executionId,
ACT_ID_ AS actId,
TASK_ID_ AS taskId,
CALL_PROC_INST_ID_ AS callProcInstId,
ACT_NAME_ AS actName,
ACT_TYPE_ AS actType,
ASSIGNEE_ AS assignee,
START_TIME_ AS startTime,
END_TIME_ AS endTime,
DURATION_ AS duration,
TENANT_ID_ AS tenantId
FROM
act_hi_actinst

2 数据权限控制

通过 ${currentUserId} 或者 ${curOrgId} 可以控制数据权限. 使用户只能看到特定的数据.

3 复杂查询

理论上只要SQL语句没问题, 自定义列表中的SQL是支持任意复杂的SQL查询 比如

-- 子查询
SELECT
t1.`id` AS id1,
t1.`dhwb` AS dh456wb,
t1.`duohwb` AS duohwb,
t1.`riqiymd` AS riqiymd,
t1.`riqiymdhms` AS riqiymdhms,
t1.`xialakuang` AS xialakuang,
t1.`zidian` AS zidian,
t1.`danxuankuang` AS danxuankuang,
t1.`zidiandanxuankuang` AS zidiandanxuankuang,
t1.`fuxuankuang` AS fuxuankuang,
t1.`zidianfuxuankuang` AS zidianfuxuankuang,
t1.`json` AS json,
t1.`status` AS statusAlias,
(select id from test_ctltype_2 t3 where t3.id = t1.id and t3.id = t2.id ) as subSelectId
FROM
test_ctltype t1
left join test_ctltype_2 t2 on t1.id = t2.id
-- 分组查询 排序查询
SELECT
`status` AS statusAlias
FROM
test_ctltype
WHERE
STATUS = 1
GROUP BY
statusAlias
ORDER BY
statusAlias desc

4 自定义列表导出和导入

可以先在测试环境配置自定义SQL, 然后导出. 再导入到生产环境中

5 调试SQL

管理员可以在每个自定义列表页面看到一个调试SQL的按钮, 点击该按钮时, 会打印当前待执行的SQL语句到F12控制台, 方便开发人员调试SQL

1585203072937

6 SQL查询引擎 - 查询条件封装

这是自定义SQL最核心的部分, 查询条件会智能的自动拼接到where条件之后, 而不会直接包裹一层select 再拼接where条件 , 这样就大大提升了查询效率.

比如 :

-- 子查询
SELECT
t1.`id` AS id1,
t1.`xialakuang` AS xialakuang,
t1.`zidian` AS zidian,
t1.`status` AS statusAlias,
t2.`status` AS statusAlias2,
(select id from test_ctltype_2 t3 where t3.id = t1.id and t3.id = t2.id ) as subSelectId
FROM
test_ctltype t1
left join test_ctltype_2 t2 on t1.id = t2.id
where t1.zidian !=1
group by t1.xialakuang
order by t1.xialakuang
1. 如果此时前端传递了statusAlias参数为1

那么执行的SQL将变成如下

-- 查询总数的SQL
SELECT
count(1) as count
FROM
test_ctltype t1
left join test_ctltype_2 t2 on t1.id = t2.id
where t1.zidian !=1 and t1.`status` = 1
group by t1.xialakuang
order by t1.xialakuang
-- 查询数据的SQL
SELECT
t1.`id` AS id1,
t1.`xialakuang` AS xialakuang,
t1.`zidian` AS zidian,
t1.`status` AS statusAlias,
t2.`status` AS statusAlias2,
(select id from test_ctltype_2 t3 where t3.id = t1.id and t3.id = t2.id ) as subSelectId
FROM
test_ctltype t1
left join test_ctltype_2 t2 on t1.id = t2.id
where t1.zidian !=1 and t1.`status` = 1
group by t1.xialakuang
order by t1.xialakuang
2. 如果此时前端传递了statusAlias2参数为1

那么执行的SQL将变成如下

-- 查询总数的SQL
SELECT
count(1) as count
FROM
test_ctltype t1
left join test_ctltype_2 t2 on t1.id = t2.id
where t1.zidian !=1 and t2.`status` = 1
group by t1.xialakuang
order by t1.xialakuang
-- 查询数据的SQL
SELECT
t1.`id` AS id1,
t1.`xialakuang` AS xialakuang,
t1.`zidian` AS zidian,
t1.`status` AS statusAlias,
t2.`status` AS statusAlias2,
(select id from test_ctltype_2 t3 where t3.id = t1.id and t3.id = t2.id ) as subSelectId
FROM
test_ctltype t1
left join test_ctltype_2 t2 on t1.id = t2.id
where t1.zidian !=1 and t2.`status` = 1
group by t1.xialakuang
order by t1.xialakuang
3. 如果此时前端传递了subSelectId参数为1

由于subSelectId 是子查询的字段, 那么执行的SQL将变成如下

-- 查询总数的SQL
select count(1) as count
from (
原始SQL
) as temp where subSelectId = 1
-- 查询数据的SQL
select
id1,
xialakuang,
idian,
statusAlias,
statusAlias2,
subSelectId
from (
原始SQL
) as temp where subSelectId = 1