桌面端列表类组件

桌面端提供表格、嵌套表格、表格单元格合并、冻结列、单选行、多选行、拖拽行、树形表格、树、列表和嵌套列表等列表形式,界面效果如下面几张图所示

  • 表格支持多列头、总结栏、过滤条

  • 嵌套表格

  • 表格支持单元格合并

  • 表格支持冻结列、列内容的超长省略

  • 单选

  • 多选

  • 表格支持拖拽行(React 表格支持,Vue 表格不支持)

  • 树形表格

  • 树支持过滤

  • 列表支持响应式

  • 嵌套列表

表格组件

表格组件是列表页面中最常用的组件,和数据组件绑定后,显示数据组件中的数据,并实现双向数据绑定。

  • 写入数据:用户录入,或通过代码赋值后,数据会写入数据组件
  • 读取数据:表格组件实时显示数据组件中的数据,数据改变后,会立即显示新的数据

表格组件通过设置“绑定数据集”属性绑定到一个数据组件上,实现双向数据绑定。通过“添加列”设置表格中的显示列,如下图所示。

  • 表格列中不放组件时,以文本的形式显示数据列中的内容。
  • 表格中可以放任意组件,当组件需要设置“绑定数据列”时,必须设置为“表格当前行”的数据列
    • 放表单类组件,表单类组件的“绑定数据列”绑定“表格当前行”的数据列,在表格中可以直接编辑数据
    • 放图片组件,图片的“地址”属性绑定“表格当前行”的数据列,可以显示图片
    • 放按钮组件,按钮的“文本”属性绑定“表格当前行”的数据列,可显示为一个带链接的按钮
  • 在一个表格列中可以放多个组件

数据分页

数据组件有分页能力,表格组件也有分页能力

  • 数据组件的分页是发送请求时携带分页信息,一次请求返回一页数据
  • 表格组件的分页是对内部数据的分页显示

数据组件的分页和表格的分页搭配之后的效果,见下表

数据组件 表格组件 分页 说明
分页 不分页 服务分页 一般情况都使用此方案,数据查询服务支持分页,且一页数据全部显示时使用
不分页 分页 前端分页 数据查询服务不支持分页,且数据需要分页显示时使用
分页 分页 大数据渲染分页 数据查询服务支持分页,但一次请求返回大量数据,这些数据需要分页显示时使用

服务分页

数据组件默认是分页加载的,即数据刷新后,只得到第一页的数据。表格组件显示数据组件中的数据,即显示出第一页的数据,在界面上通过“分页”组件加载第二页、第三页……的数据。分页组件和表格组件要绑定同一个数据集。

前端分页

表格可以显示数据组件中的全部数据,也可以对数据组件中的数据分页显示。例如数据组件中有100条数据,可以设置表格组件的“前端分页”属性为“是”,每页显示20条数据,分成5页显示。表格组件自己提供分页栏。

“前端分页”属性就是原生 Table 组件的 分页属性 pagination,支持设置每页条数、默认每页条数、是否显示 pageSize 切换器、是否显示快速跳转、显示数据总量

例如:设置默认每页条数为4、显示 pageSize 切换器,W 源码如下

pagination="{{{defaultPageSize:4,showSizeChanger:true}}}"

例如:设置每页条数为4,W 源码如下,设计界面如下图所示

pagination="{{{pageSize:4}}}"

img

例如:设置每页条数为4,显示 1 - 10 条/ 共 100 条

{{pageSize:4,showTotal:(total, range)=> `${range[0]} - ${range[1]} 条 / 共 ${total} 条`}}

1740455492261

运行效果,如下图所示

1740455525479

大数据量渲染分页

当数据组件一次返回的数据需要再次分页显示时,例如一次返回100条数据,表格中希望一页显示10条数据时,设置表格组件的“大数据量渲染分页”属性,不需要放分页组件,表格组件自己提供分页栏。

特别注意:这个“大数据量渲染分页”属性的值,必须能被数据组件的 limit 整除,避免出现表格的一页上面有数据组件两页的部分数据

  • limit 默认为20,可以设置的值有1、2、4、5、10
  • limit 设置为-1时,系统使用1000000计算
  • “大数据量渲染分页”属性要设置为6,可以设置 limit 为一个能整除6的数,例如60

“大数据量渲染分页”属性设置,如下图所示

运行效果,如下图所示

滚动加载

表格组件设置“滚动分页”属性为“是”时,不需要使用“分页”组件,通过鼠标滚轮的滚动即可以加载下一页数据。和使用“分页”组件不同的是,使用“分页”组件时,表格中只显示新加载的数据。使用滚动分页时,表格中显示所有加载过的数据。

特别说明

  • Vue 表格组件设置“滚动分页”属性为“是”时,还必须设置“纵向滚动高度”属性,才能实现滚动加载

排序/多列排序

表格组件支持本地数据排序、服务端数据排序、多列排序。

  • 本地数据排序:仅对加载到数据组件中的数据进行排序
  • 服务端数据排序:重新发送请求,按照排序设置,从数据库中重新查询数据
  • 多列排序:设置列的“多列排序优先级”后,即使用多列排序。多列排序优先级中数字大的表示排序顺序在前,数字小的表示排序顺序在后。

单选行/多选行

表格组件使用“选中数据集”记住用户的选择,支持跨页。即用户在第一页选择了两行数据,切换到第二页,选择了三行数据,此时选中数据集中共有五行数据。当用户再次切换到第一页数据时,选择的两行数据还是选中状态。

表格组件“开启选择功能”后,会在表格左边第一列显示一个单选列或多选列。

在选择功能中,选择“单选”或“多选”,决定表格的选择方式,选择多选时,列头显示全选按钮。

准备一个选中数据集,和表格绑定的数据集一样,清空“自动模式”属性

在表格的“选中数据集”属性中绑定上一步添加的数据集,用户选择行后,选择的行数据会复制到这个选中数据集中

表格多选时的行数据,存入选中数据集,运行效果如下

特别说明

  • 选中数据集为树形数据时,编辑该数据组件,取消勾选“树形数据”,作为普通数据使用

1739159409361

用代码控制选中状态

表格组件使用选中数据集存储选中行;也使用选中数据集中的数据,设置行的选中状态。因此通过修改选中数据集中的数据,可以实现选中和取消选中

案例一:选中或取消选中表格当前行

react 代码如下

    onSelectCurrentRowBtnClick = (event) => {
        let mainData = this.comp("mainData");       //获取表格组件绑定的数据集
        let selectData = this.comp("selectData");   //获取表格组件绑定的选中数据集
        let selectedRowKeys = selectData.getIDs();  //获取当前选中的数据的主键列表
        let rowId = mainData.getCurrentRowID();     //获取数据组件当前行的主键值
        if(selectedRowKeys.indexOf(rowId) > -1){    //已选中,取消选中
            selectData.removeData(rowId);           //取消选中
        }else{
            mainData.copyRows(rowId,"selectData");  //未选中,设置为选中
        }
    }

vue 代码如下

    let $page = usePage();
    let mainData= useData('mainData');              //获取表格组件绑定的数据集
    let selectData = useData('selectData');         //获取表格组件绑定的选中数据集

    onSelectCurrentRowBtnClick = (event) => {
        let selectedRowKeys = selectData.getIDs();  //获取当前选中的数据的主键列表
        let rowId = mainData.getCurrentRowID();     //获取数据组件当前行的主键值
        if(selectedRowKeys.indexOf(rowId) > -1){    //已选中,取消选中
            selectData.removeData(rowId);           //取消选中
        }else{
            mainData.copyRows(rowId,"selectData");  //未选中,设置为选中
        }
    }

案例二:点击表格行时,实现选中或取消选中

react 代码如下

    onMultiSelectTableRowClick = ({event,record,index}) => {
        let mainData = this.comp("mainData");       //获取表格组件绑定的数据集
        let selectData = this.comp("selectData");   //获取表格组件绑定的选中数据集
        let selectedRowKeys = selectData.getIDs();  //获取当前选中的数据的主键列表
        let idColumn = selectData.getIdColumn();    //获取选中数据集的主键列名
        let rowId = record[idColumn];               //从表格当前行 record 中获取主键值
        if(selectedRowKeys.indexOf(rowId) > -1){    //已选中,取消选中
            selectData.removeData(rowId);           //取消选中
        }else{
            mainData.copyRows(rowId,"selectData");  //未选中,设置为选中
        }
    }

vue 代码如下

    let $page = usePage();
    let mainData= useData('mainData');              //获取表格组件绑定的数据集
    let selectData = useData('selectData');         //获取表格组件绑定的选中数据集

    onMultiSelectTableRowClick = ({event,record,index}) => {
        let selectedRowKeys = selectData.getIDs();  //获取当前选中的数据的主键列表
        let idColumn = selectData.getIdColumn();    //获取选中数据集的主键列名
        let rowId = record[idColumn];               //从表格当前行 record 中获取主键值
        if(selectedRowKeys.indexOf(rowId) > -1){    //已选中,取消选中
            selectData.removeData(rowId);           //取消选中
        }else{
            mainData.copyRows(rowId,"selectData");  //未选中,设置为选中
        }
    }

特别说明:删除选中数据集的数据使用 removeData 方法,不能使用 deleteData 方法

  • removeData 方法是前端删除数据组件中数据的方法,仅删除前端数据,不删除数据库中的数据
  • deleteData 方法是删除数据集中数据的方法,即会发送请求从数据库中删除数据

删除选中的数据

删除选中时,选中数据集中的数据都是要删除的数据,通过"选中数据集"的"ID列表"方法获取要删除数据的主键列表,作为删除方法的参数,删除后清空选中数据集

操作设置如下图所示

用 JS 代码实现,代码如下

react 代码

    onDeleteSelectBtnClick = (event) => {
        let mainData = this.comp("mainData");       //获取表格组件绑定的数据集
        let selectData = this.comp("selectData");   //获取表格组件绑定的选中数据集
        mainData.deleteData(selectData.getIDs()).then(()=>{   //获取选中数据集的主键列表,删除数据
            selectData.clear();                     //删除后,清除选中数据集的数据
        },()=>{});
    }

vue 代码

let $page = usePage();
let mainData= useData('mainData');              //获取表格组件绑定的数据集
let selectData = useData('selectData');         //获取表格组件绑定的选中数据集

let onDeleteSelectBtnClick = (event) => {
    mainData.deleteData(selectData.getIDs()).then(()=>{   //获取选中数据集的主键列表,删除数据
        selectData.clear();     //删除后,清除选中数据集的数据  
    },()=>{});
}

冻结列(固定列)

对于列数很多的数据,可以固定前后的列,横向滚动查看其它数据,和“横向滚动宽度”配合使用。“横向滚动宽度”需要输入一个值,如下图所示。

列的“固定列”属性设置为“居左”,表示固定在表格左边,设置为“居右”,表示固定在表格右边。

如果设置了多选或单选,要控制多选或单选也固定,可以在表格组件的“选择功能配置”中设置“固定”为“是”,如下图所示

隐藏列

表格的列有动态隐藏属性,通过一个表达式控制列是显示还是隐藏,设计界面如下图所示

动态渲染列(48)

从48版本开始,表格组件增加渲染前事件,可用于动态渲染列,如下图所示,其中岗位工资、绩效工资、税、工龄工资4列是在渲染前事件中渲染出来的

1737098966708

设计界面如下图所示,备注说明后面就是操作列

1737099086926

岗位工资、绩效工资、税、工龄工资4列的数据在从表中,通过输出数据集返回 JSON 数据,如下图所示

1737099753195

JSON 数据格式如下图所示

1737099237658

渲染前事件代码如下,props.dataSource 就是返回的 JSON 数据,Column 的 dataIndex 指向 dataSource 中的 key 可以直接渲染出数据

    onTableRender = (event) => {
        let {detail:{props}} = event;
        //完整遍历从表,获得动态渲染的列名,并将从表数据写入 dataSource 以便通过 dataIndex 的指定进行渲染
        let itemName = [];
        props.dataSource.map((item)=>{
            item.detail && item.detail.map((item2)=>{
                item[item2.itemName]=item2.money;
                if (itemName.indexOf(item2.itemName) == -1) {
                    itemName.push(item2.itemName);
                }
            })
        })
        //在操作列前,插入列
        for (let i in itemName) {
            let index = props.children.length - 1;
            props.children.splice(index,0,<Column title={itemName[i]} dataIndex={itemName[i]} key={itemName[i]} width={120}/>)
        }
    }

渲染前事件中 props 数据格式如下图所示

1737100126262

执行5到12行的代码后,将从表数据写入 dataSource ,数据如下图所示

1737100401118

Column 的 dataIndex 指向 dataSource 中的 key (例如:岗位工资),表格中就会显示出岗位工资列及数据

多列头

多列头使用列组实现,在表格中“添加列组”,在列组中“添加列”,即可显示为多列头。

总结栏

在表格中“添加总结栏”,在表格的下方出现一个空行,在行内的单元格中,可以放文本组件显示相关内容,也支持放其它组件。

显示数据组件中的记录数、某列的总和、平均值可以使用数据组件的函数,也可以自定义函数实现复杂计算,参考《页面表达式

总结栏如果需要一直显示在表格底部,如下图所示

1720410571951

需要设置表格组件的“纵向滚动高度”,如下图所示,如果要实现表格充满的效果,参考《页面布局》中的充满布局

1720410444448

总结栏行的列合并

总结栏行列默认是跟表格上的列一一对应,如下显示

1728386487460

可以通过总结栏列上提供的跨列设置列合并,如设置为3即从第1列开始往后列表3列,需要注意设计时需要把总结栏中的第2列和第3列删除

1728386519900

设置后的运行效果如下:

1728386563468

固定表头

表格组件设置“纵向滚动高度”属性,实现表头固定效果。表头固定通常是页面在使用充满布局时的常见做法,关于页面使用充满布局,参考《页面布局》中讲解的充满布局,里面介绍了表格组件表头固定的实现方法。

嵌套表格

嵌套表格将两个或多个数据组件的数据,以嵌入在行下方的方式显示,支持展开和收起。

  • 在外层表格中“添加子表格”

  • 子表格绑定数据集、添加列、设置“过滤条件”

  • 过滤条件中的行记录是子表格的数据

  • 过滤条件设置为:子表格中的某列数据等于外层表格中的某列数据

特别说明:如果嵌套表格关联的两个数据组件,在后端设置了主从关系,必须清空页面上从数据组件的“主从选项”属性

  • 主从选项使得从数据的数据,跟随主数据当前行的变化而重新加载,即从数据中只会显示一条主数据的从数据
  • 去掉主从关系,使得从数据可以加载任意数据,表格中才能显示出多主多从的效果

表格单元格合并

在表格列的渲染函数中设置行合并数 rowSpan 的值,rowSpan 为2表示合并两行。

本例提供一个单元格合并的完整案例,合并数据中的“一级分类”列 c1_name、“二级分类”列 c2_name 和“三级分类”列 c3_name

  • 在数据组件的刷新后事件中,根据数据组件中的数据,计算每行的一级分类、二级分类和三级分类需要合并的行数,形成 JSON 对象,存储到计算列 spanCount 中
  • 在需要合并行的列(“一级分类”列、“二级分类”列和“三级分类”列)的渲染方法中,获取合并行数 spanCount,赋值给渲染方法返回值 rowSpan

开发过程如下:

计算合并列

  • 数据组件添加计算列:spanCount,文本类型,要存储 JSON 字符串

  • 在数据组件的刷新后事件中,根据数据计算合并行数

JS 代码如下:

    onRowSpanDataAfterRefresh = (event) => {
        // 初始化计算列 spanCount
        let data = event.source;
        // spanCols 指定要合并的列,支持多列,列的合并行数会记录在计算列 spanCount 中
        let spanCols = ["c1_name","c2_name","c3_name"];
        let firstRow = {};
        // 解析并写入计算列 spanCount = "{c1_name:4,c2_name:2,c3_name:1}"
        function setSpanCount(row, col, count) {
            let spanCount = {};
            if (row.spanCount) {
                spanCount = JSON.parse(row.spanCount);
            }
            spanCount[col] = count;
            data.setValue("spanCount", JSON.stringify(spanCount), row);
        }
        // 遍历数据
        data.each(function(params){
            let row = params.row;
            for (let i = 0; i < spanCols.length; i++) {
                let spanCol = spanCols[i];
                let value = row[spanCol];
                if (firstRow[spanCol] && (value == firstRow[spanCol].value)) {
                    // 如果当前列的值在 firstRow 已存在,首行的合并数 + 1,当前行的合并数 = 0
                    firstRow[spanCol].count = firstRow[spanCol].count + 1;
                    setSpanCount(row, spanCol, 0);
                } else {
                    // 如果当前列的值在 firstRow 不存在
                    if (firstRow[spanCol]) {
                        // 记录前一个值的首行合并数
                        setSpanCount(firstRow[spanCol].firstRow, spanCol, firstRow[spanCol].count)
                    }
                    // 开始记录下一个值的首行
                    firstRow[spanCol] = {
                        "firstRow": row,
                        "value": value,
                        "count": 1
                    }
                }
            }
        })
        // 遍历后记录最后的首行
        for (let i = 0; i < spanCols.length; i++) {
            let spanCol = spanCols[i];
            setSpanCount(firstRow[spanCol].firstRow, spanCol, firstRow[spanCol].count)
        }
    }

react 列渲染

  • 添加“一级分类”列、“二级分类”列、“三级分类”列的渲染方法

JS 代码如下:

    //一级分类列的渲染方法
    tableColumn26RenderRender = (text, record, index) => {
        return this.columnRender(text, record, index, "c1_name");
    }

    //二级分类列的渲染方法
    tableColumn27RenderRender = (text, record, index) => {
        return this.columnRender(text, record, index, "c2_name");
    }

    //三级分类列的渲染方法
    tableColumn28RenderRender = (text, record, index) => {
        return this.columnRender(text, record, index, "c3_name");
    }

    //合并列的渲染
    columnRender(text, record, index, col) {
        // 获取表格当前行-指定列的合并数
        let spanCount = this.comp("rowSpanData").getValue("spanCount", record);
        return {
            children: text,
            props: {
                rowSpan: spanCount ? JSON.parse(spanCount)[col] : 1
            }
        };
    }

特别说明 渲染方法用于返回 ReactNode,表格列渲染方法返回 JSON 数据,因此需要手工修改 w 文件

将系统生成的代码,<attr:render/>

<antdpro:Table.Column class="column c-columnMiddle" dataIndex="c1_name" id="tableColumn26" width="120px" xmlns:attr="http://www.wex5.com/attr">
    <attr:title id="default68">
        <antdpro:Typography.Text id="typographyText31" text="一级分类"/>
    </attr:title>
    <attr:render d_canAddChild="false" designer_child_type="code" id="default75">
        <Fragment id="fragment0">{$page.tableColumn26RenderRender(text, record, index)}</Fragment>
    </attr:render>
</antdpro:Table.Column>

修改为 render 属性

<antdpro:Table.Column class="column c-columnMiddle" dataIndex="c1_name" id="tableColumn26" render="{$page.tableColumn26RenderRender(text, record, index)}" width="120px" xmlns:attr="http://www.wex5.com/attr">
    <attr:title id="default68">
        <antdpro:Typography.Text id="typographyText31" text="一级分类"/>
    </attr:title>
</antdpro:Table.Column>

vue 列渲染

切换到源码,在“一级分类”列、“二级分类”列、“三级分类”列中添加 customRender="{columnRender}",添加后完整代码如下

<antdv:Table.Column class="column" customRender="{columnRender}" dataIndex="c1_name" id="tableColumn27" width="120px" xmlns:attr="http://www.wex5.com/attr">
    <attr:title d_canAddChild="true" id="default70">
        <antdv:Typography.Text content="一级分类" id="typographyText30"/>
    </attr:title>
</antdv:Table.Column>

在 js 文件中添加 columnRender 方法,代码如下

//合并列的渲染
let columnRender = ({text, record, index, column}) => {
    // 获取表格当前行-指定列的合并数
    let spanCount = rowSpanData.getValue("spanCount", record);
    return {
        children: text,
        props: {
            rowSpan: spanCount ? JSON.parse(spanCount)[column.dataIndex] : 1
        }
    };
}

拖拽行(React 表格支持,Vue 表格不支持)

React 表格支持拖拽行,实现调整行顺序的效果。设置表格的“拖拽行排序”属性为是,表格左边第一列会显示一个三横图标,用鼠标拖拽这个图标,实现拖拽行的效果。拖动到期望的位置后松开鼠标,触发“行拖拽后事件”。

在“行拖拽后事件”中,调用数据组件的 moveTo 方法移动行,界面上就显示出移动的效果。

本例移动后修改相关行的序号列的值,“行拖拽后事件”的 JS 代码如下:

    constructor(props, context) {
        super(props, context);
        this.sortDataId = "mainData";//拖拽排序数据组件id
        this.sortDataIdCol = "fid";//拖拽排序数据组件主键列名
        this.sortNoCol = "sortNo";//拖拽排序数据组件序号列名
    }

    /*-------------------拖拽排序-------------------*/
    onTable6DragSort = ({active,over}) => {
        let mainData = this.comp(this.sortDataId);
        //获得移动行
        let srcRow = mainData.getRowByID(active.id);
        //获得目标行
        let tarRow = mainData.getRowByID(over.id);
        //获得id数组,移动行索引,目标行索引
        let idArr = active.data.current.sortable.items;
        let begin = active.data.current.sortable.index;
        let end = over.data.current.sortable.index;
        //获得移动方向
        let up = begin > end;
        //移动
        mainData.moveTo(srcRow,tarRow,up?"BEFORE":"AFTER");
        //备份目标行的序号
        let sortEnd = this.getSortById(idArr[end]);

    if(up){
            //从over到active-1的新序号 是下一行的序号
    for(let i=end;i<begin;i++){
                let sort = this.getSortById(idArr[i+1]);
                mainData.setValueByID(this.sortNoCol,sort,idArr[i]);
            }
        }else{
            //从over到active-1的新序号 是上一行的序号
    for(let i=end;i>begin;i--){
                let sort = this.getSortById(idArr[i-1]);
                mainData.setValueByID(this.sortNoCol,sort,idArr[i]);
            }
        }
        //active的新序号 是 over的序号
        mainData.setValueByID(this.sortNoCol,sortEnd,idArr[begin]);
    }

    getSortById = (id) => {
        let row = this.comp(this.sortDataId).find([this.sortDataIdCol],[id]);
        if(row.length > 0){
            return row[0].sortNo;
        }
    }

表格布局属性

列内容不换行,会导致列宽被撑宽,影响列的布局,如下图所示

1721802618795

设置“表格元素的 table-layout”属性为“固定”表示内容不会影响列的布局,设计界面如下图所示

1721818238357

运行效果如下图所示

1721818089967

树形表格

表格组件绑定树形数据,会在第一列显示展开箭头,用于逐级展开树形数据,如下图所示

树组件

树和表格组件不同,树只展示一列,且不显示列头,如下图所示

树展示哪一列数据,由树组件的“显示列”属性指定

默认展开

树支持默认展开全部和默认展开根

  • “默认展开”属性设置为“展开全部”:树组件显示数据组件中的全部数据,如果数据组件中数据不全,不会发送请求取数据,即树组件仅在加载全部数据后,才能呈现展开全部的效果
  • “默认展开”属性设置为“展开根”:树组件发送请求,加载第一个节点的数据,并展开显示,如下图所示

树过滤

树组件绑定的数据组件配置了全路径ID和全路径名称时,搭配智能过滤组件,可以实现树过滤,运行效果如下图所示

多选

树支持勾选和级联勾选

  • “勾选”属性设置为“是”:树的展开箭头右侧显示一个多选框,用于多选,和表格多选一样,在设置“选中数据集”属性后,选中的数据写入选中数据集
  • “级联勾选”属性设置为“是”:选中父节点,自动选中全部子节点;选中全部子节点,自动选中父节点
  • “级联勾选”属性设置为“否”:选中节点,不自动选中其他节点

特别说明

  • 选中数据集为树形数据时,编辑该数据组件,取消勾选“树形数据”,作为普通数据使用

1739159409361

显示图标

树组件除了展开/折叠图标以外,在标题前面还可以显示一个图标,运行效果如下图所示

1739331772678

设置“显示图标”属性为“是”,在“节点图标”属性中根据不同的数据显示不同的图标,设计界面如下图所示

1739326964014

使用单色图标(线框风格和实底风格)时,使用下面的写法定义图标颜色,引号必须使用 \" 转义

"css:{"color":"orange"}@gift,outlined"

1739331544637

使用双色图标时,在设计界面中可以选择主色,如下图所示

1739327065728

另外还提供“节点样式”属性,为节点(包括图标和标题)设置 class 名称

1739331727824

例如:给图标设置颜色,vue 的 css 定义如下

:deep {
    .x-orange .ant-tree-iconEle {
        color: orange;
    }
}

用代码选中虚根

写 JS 代码选中虚根,代码如下

    let tree = this.comp("tree"); 
    tree.setSelection("__VIRTUAL_ROOT__")

列表组件

列表组件和表格组件一样,同样是展示数据组件的全部数据,不同的是,表格组件一行显示一条数据,列表组件则没有限制,即可以一行显示一条数据、也可以一行显示多条数据(如下图所示)、还可以多行显示一条数据。

列表项

列表组件提供一种固定格式:列表项。包括图标、标题、描述、内容区、扩展区、操作栏,支持垂直和水平两种布局方式。组件层次结构,如下图所示

垂直布局,展示效果示意图,如下图所示

水平布局,展示效果示意图,如下图所示

垂直布局,实际运行效果,如下图所示

水平布局,实际运行效果,如下图所示

布局方式

列表组件组件除了支持列表项,也支持在列表中添加任意组件。

  • 列表模板中只有一个组件时
    • 组件是行级元素,则一行显示一个
    • 组件是行内元素,则流式布局,一行显示多个
  • 列表模板中超过一个组件时,列表的展示方向支持“水平”和“垂直”

垂直列表

列表的“方向”属性设置为“垂直”,系统自动增加一个 div 节点,用于实现行级元素效果,如下图所示

水平列表

列表的“方向”属性设置为“水平”,系统自动增加一个 span 节点,用于实现行内元素效果,如下图所示

固定列数

在列表的“列表栅格配置-列数”属性中设置数字,列表显示为一行显示多个数据的效果,设置界面如下图所示

运行效果如下图所示

响应式

列表通过“列表栅格配置”实现响应式布局,即在不同的分辨率下,列表中一行显示的个数可以不同,且不受24栅格的影响,个数支持任意整数。设置界面如下图所示

运行效果如下图所示

嵌套列表

嵌套列表和嵌套表格一样,都是内层列表或表格设置“过滤条件”即可。因此对于嵌套需求,支持表格嵌套表格、表格嵌套列表、列表嵌套列表、列表嵌套表格

  • 在外层列表中添加“列表”组件,作为内层列表
  • 内层列表绑定数据集、设置“过滤条件”
  • 过滤条件中的行记录是内层列表的数据

  • 过滤条件设置为:内层列表中的某列数据等于外层列表中的某列数据

运行效果如下图所示

特别说明:如果嵌套列表关联的两个数据组件,在后端设置了主从关系,必须清空页面上从数据组件的“主从选项”属性

  • 主从选项使得从数据的数据,跟随主数据当前行的变化而重新加载,即从数据中只会显示一条主数据的从数据
  • 去掉主从关系,使得从数据可以加载任意数据,列表中才能显示出多主多从的效果

加载方式

数据组件加载下一页数据时,有两种方式,一种是清空现有数据,加载新数据,另一种是保留现有数据,追加新数据。

  • 列表组件不设置“加载方式”,配合“分页”组件,实现第一种加载效果
  • 列表组件设置“加载方式”为“点击加载”,不需要使用“分页”组件,运行时,在列表最后显示“加载更多”按钮,点击“加载更多”按钮,追加下一页数据

  • 列表组件设置“加载方式”为“滚动加载”,不需要使用“分页”组件,运行时,通过鼠标滚轮的向下滚动,追加下一页数据。滚动分页需要在列表上增加 height 和 overflow 两个样式,设置界面如下图所示

样式代码如下

    .c-scroll-list{
        height: calc(100vh - var(--x-portal-header-height) - 80px);
        overflow: auto;;
    }

使用案例

表格-显示序号

表格组件中可以显示两种序号,一种是每页都从1开始,另一种是所有数据大排序,第一页从1开始,第二页继续前一页的序号,如下面两张图所示

表格序号

使用表格当前序号实现,在列渲染中添加文本组件,设置“文本”属性为:表格当前序号 + 1

跨页序号

跨页序号使用数据组件的跨页序号方法实现。

  • 给数据组件添加一个计算列,用于计算、存储、显示跨页序号

  • 设置计算列的计算规则,为数据组件的跨页序号方法,数据组件为每一行的计算列写入一个递增的序号

  • 在表格中添加计算列,显示跨页序号

表格-控制显示加载中

在页面中执行数据加载、通过 this.request 发送请求时,页面组件会根据执行时间,自动显示加载遮罩,一般情况不需要开发者关心加载遮罩。如果确实需要自己控制表格的加载遮罩,在表格中增加“加载中配置”,将“加载中”属性绑定一个数据列,根据数据列中的值控制是否显示加载遮罩。

表格-行内按钮事件

使用表格当前行数据

在表格组件的列渲染中的按钮,在添加事件前,开启扩展参数,设置“参数名称”,选择“参数值”。

参数值可以选择“渲染”中的“文本”、“行对象”、“索引”、“表格当前序号”、“表格当前行”。其中“行对象”和“表格当前行”是一样的,前者是 Antd 提供的渲染回调方法的参数,后者是平台提供的语法糖。

事件跳转后生成 JS 方法,包括扩展参数,代码如下:

    onEditBtnClick = ({row}) => (event) => {
        message.info(row.name);     //获取行对象中name列的值
        event.stopPropagation();    //阻止冒泡
    }

阻止冒泡

在表格组件中,即设置了列渲染中按钮的点击事件,也设置了行点击事件,运行时点击按钮,会前后触发按钮的点击事件和行点击事件,这种事件向父节点传递称为冒泡,在事件中执行 event.stopPropagation(); 语句可以阻止向上冒泡,代码如下

    onEditBtnClick = ({row}) => (event) => {
        message.info(row.name);     //获取行对象中name列的值
        event.stopPropagation();    //阻止冒泡
    }

表格-当前行样式

有些时候,表格组件上需要显示出刚点击过的行。例如主从两个表格,点击主表格的某行,从表格中显示主数据对应的从数据,此时需要在主表格中明确显示出从数据对应的主数据。

表格组件提供“当前行类名”属性,可以设置为“高亮效果”或自定义的类名,高亮效果使用的是表格组件的选中类名 ant-table-row-selected

ant-table-row-selected 类运行效果如下图所示

如果需要修改系统默认的样式,有两种方法,一种是使用 css 代码修改样式,另一种是使用主题配置修改样式,推荐使用第二种方法。

react 使用 css 代码修改样式

使用下面的 css 代码,全局修改选中行的背景色

    :global{
        .ant-table-wrapper .ant-table-tbody .ant-table-row.ant-table-row-selected >.ant-table-cell{
            background-color: pink;
        }
    }

使用下面的 css 代码,修改具有 c-custom 样式的节点下的表格选中行的背景色

    .c-custom{
        :global{
            .ant-table-wrapper .ant-table-tbody .ant-table-row.ant-table-row-selected >.ant-table-cell{
                background-color: pink;
            }
        }
    }

运行效果如下图所示

  • 当前应用若是从门户应用打开的,且需要修改全局样式,请使用主题配置修改样式
  • 当前应用若是独立运行,可以将上面的 css 代码写在 UI2/pcx/common.css 文件中,在 UI2/pcx/common.js 文件中引用 common.css,代码如下。系统运行时会自动引用 common.js,从而引用了 common.css,使得运行系统后,样式立即生效
  import "./common.css";

vue 使用 css 代码修改样式

使用下面的 css 代码,修改当前页面所有表格组件的选中行的背景色

.x-page {
    :deep{
        .ant-table-wrapper .ant-table-tbody >tr.ant-table-row-selected >td{
            background-color: pink;
        }
    }
}

具体组件样式的修改可以参考《页面样式》中的说明

使用主题配置修改样式

系统支持主题(皮肤)配置,在主题配置中定义 Antd 全局 Token、组件的 Token、组件的样式、非组件的样式、iframe 嵌入页面的样式,具体使用参考《主题配置》中的“表格当前行样式修改案例”。

表格-接管列头排序

点击表格的某列,对该列进行排序。如果该列关联的是 restData 的实体列,则系统可对其进行排序处理。如果该列没有对应 restData 的某个实体列,或者关联的是 serviceData,则需要写代码实现排序。例如:下图中“二级+三级”列是数据集中“二级”列和“三级”列组合起来的

二级+三级的列定义如下

<antdv:Table.Column xmlns:attr="http://www.wex5.com/attr" class="column" dataIndex="fself" id="tableColumn3" width="120px" sorter="{{"compare":false}}">
    <attr:title id="default8">
        <antdv:Typography.Text content="二级+三级" id="typographyText3"/>
    </attr:title>
    <attr:render id="default9"/>
</antdv:Table.Column>

接管表格组件的“配置改变” onChange 事件,从事件参数中获取点击的列 sorter.field,以及排序方式 sorter.order。

其他列的排序由系统处理,本事件中只处理点击二级+三级列的排序,代码如下:

import { reactive, ref, watch } from "vue";
import { usePage, useData } from "vue_addon/core";
let $page = usePage();
let data = useData("restData0");//restData0是表格绑定的数据集的id
let onTable0Change = ({pagination,filters,sorter,extra}) => {
        // 只处理fself字段的排序
        if(sorter.field != "fself") return;  
        // 获取数据集上定义的排序
        if(!$page.cloneOrd){
            let baseOrders = data.getOderBysObj();
            if (baseOrders && baseOrders.length > 0) {
                $page.cloneOrd = [...baseOrders]
            }
        }
        // 清空排序
        data.clearOrderBy();
        let order = sorter.order;
        order = 'ascend' === order ? 1 : ('descend' === order ? 0 : undefined);
        data.setOrderBy("ferji", order);
        data.setOrderBy("fsanji", order);
        // 把数据集上定义的排序追加在后面
        if ($page.cloneOrd && $page.cloneOrd.length > 0) {
            for (let i in $page.cloneOrd) {
                data.setOrderBy($page.cloneOrd[i].name,$page.cloneOrd[i].type);
            }
        }
        data.refreshData();
}

表格-表头固定、总结栏固定

表头和总结栏如果需要一直显示在表格头部和底部,如下图所示

1720410891460

需要设置表格组件的“纵向滚动高度”,如下图所示,如果要实现表格充满的效果,参考《页面布局》中的充满布局

1720410444448

表格-设置空图片

当表格无数据时,Antd 默认显示为下图

希望改为自定义的图片和文字内容,如下图所示

通过设置 css 实现,隐藏原来的图片和文字,通过设置背景图显示新的图片,通过增加 after 伪类显示新的文字内容。实现步骤如下

  • 上传图片

依次点击“页面-设置-素材库”,打开素材库对话框,上传图片至 UI2/pcx/images 目录下。

本例中上传 empty.svg 文件.

  • 在 css 文件中,增加下面的 css
.custom{
    :deep{
            .ant-empty.ant-empty-normal .ant-empty-image {
                background-image: url(./images/empty.svg);
                background-repeat: no-repeat;
                background-position: top center;
                background-size: 276px 128px;
                margin-bottom: 16px;
                height: 128px;
            }

            .ant-empty.ant-empty-normal .ant-empty-description,
            .ant-empty.ant-empty-normal .ant-empty-image svg{
                display: none
            }

            .ant-empty.ant-empty-normal:after {
                content: "暂无内容";
                font-size: 14px;
                color: rgba(0, 0, 0, 0.45);
            }
        }
    }
}

在页面组件的预定义样式上添加 custom,实现自定义空图片和文字的效果

  • 不同的表格显示不同的空图片

上面的写法是当前页面中全局生效的,要实现不同的表格显示不同的空图片,使用下面的方式定义 css

.task-table{
    :global(.ant-empty.ant-empty-normal .ant-empty-image){
            background-image: url(./images/empty.svg);
            background-repeat: no-repeat;
            background-position: top center;
            background-size: 276px 128px;
            margin-bottom: 16px;
            height: 128px;
    }

    :global(.ant-empty.ant-empty-normal .ant-empty-description,
    .ant-empty.ant-empty-normal .ant-empty-image svg){
            display: none
        }

    :global(.ant-empty.ant-empty-normal:after) {
            content: "暂无内容";
            font-size: 14px;
            color: rgba(0, 0, 0, 0.45);
    }
}
.notice-table{
    :global(.ant-empty.ant-empty-normal .ant-empty-image){
            background-image: url(./images/empty.svg);
            background-repeat: no-repeat;
            background-position: top center;
            background-size: 276px 128px;
            margin-bottom: 16px;
            height: 128px;
    }

    :global(.ant-empty.ant-empty-normal .ant-empty-description,
    .ant-empty.ant-empty-normal .ant-empty-image svg){
            display: none
        }

    :global(.ant-empty.ant-empty-normal:after) {
            content: "暂无内容";
            font-size: 14px;
            color: rgba(0, 0, 0, 0.45);
    }
}

在表格外层增加区块组件,设置自定义样式为 task-table,使用 task-table 里面的样式;定义为 notice-table,使用 notice-table 里面的样式。

树形表格-展开

树形表格的展开需要使用系统组件 ExpandedData 提供的展开全部 expandAll 和收起全部 collapseAll 两个方法。需要说明的是,展开全部方法不发送请求,只是将数据组件中的数据全部显示,即有多少数据显示多少数据

使用 ExpandedData 组件,需要引用,代码如下

import ExpandedData from "$UI/wxsys/comps/expandedData/ExpandedData";

ExpandedData 组件提供 getInstance 方法获取数据组件的展开数据实例,说明如下

方法:
    getInstance ({Data: refData})
描述:
    获取组件实例
参数:
    refData:{Data} - 数据组件对象
返回值:
    ExpandedData

ExpandedData 组件提供 expandAll 方法展开全部数据,说明如下

方法:
    expandAll ()
描述:
    将数据组件中的数据全部展开显示

ExpandedData 组件提供 collapseAll 方法收起全部数据,说明如下

方法:
    collapseAll ()
描述:
    收起后,只显示根节点

示例代码

import ExpandedData from "$UI/wxsys/comps/expandedData/ExpandedData";
//展开所有
onExpandAllBtnClick = (event) => {
        ExpandedData.getInstance({refData:this.comp('restData1')}).expandAll();
}
//关闭所有
onCollapseAllBtnClick = (event) => {
        ExpandedData.getInstance({refData:this.comp('restData1')}).collapseAll();
}

运行效果如下图所示

1722333830736

树形表格-自定义展开图标

树形表格默认的展开图标是箭头,在“树形展开配置”提供的有“展开图标”的设置可以自定义展开图标

1739432056200

"展开图标"是点击"跳转"生产js函数,通过js实现的。需要在js中引入需要使用的图标,如下:

react代码

import {PlusSquareOutlined, MinusSquareOutlined } from '@ant-design/icons';

vue代码

import {PlusSquareOutlined, MinusSquareOutlined} from '@ant-design/icons-vue';

具体"展开图标"函数的实现如下:

react代码

tableExpandable0ExpandIconFn = (props) => {
    if (!props.expandable) {
        return <span className={"antd-table-tree-expand-icon"} />;
    }

    if (props.expanded) {
        return <MinusSquareOutlined className={"antd-table-tree-expand-icon"} onClick={e => {
            props.onExpand(props.record, e);
            e.stopPropagation();
        }}/>;

    } else {
        return <PlusSquareOutlined className={"antd-table-tree-expand-icon"} onClick={e => {
            props.onExpand(props.record, e);
            e.stopPropagation();
        }}/>;
    }
}

vue代码

let tableExpandable0ExpandIconFn = (props) => {
    if (!props.expandable) {
        return <span class={"antd-table-tree-expand-icon"} />;
    }

    if (props.expanded) {
        return <MinusSquareOutlined class={"antd-table-tree-expand-icon"} onClick={e => {
            props.onExpand(props.record, e);
            e.stopPropagation();
        }} />;

    } else {
        return <PlusSquareOutlined class={"antd-table-tree-expand-icon"} onClick={e => {
            props.onExpand(props.record, e);
            e.stopPropagation();
        }} />;
    }
}

运行效果如下:

1739431756612

树-展开

树组件提供展开全部和展开某行的方法

  • 展开全部

树组件提供 expandAll 方法显示数据组件中的全部数据,调用示例代码如下:

react 代码

let onButton5Click = (event) => {
    this.comp("tree0").expandAll();
}

vue 代码

let onButton5Click = (event) => {
    $page.comp("tree0").expandAll();
}

特别说明

  • 如果要全展开就需要数据组件加载全部数据,如果只加载了根数据只会显示根,即加载了多少数据就会显示多少数据
  • 展开具体的行

树组件提供 expandNode(id) 方法展开行,参数是行的主键值,调用示例代码如下

react 代码

let onButton6Click = (event) => {
    this.comp("tree0").expandNode("CA8A602D66400001D1DC1C10E5109CC0");
}

vue 代码

let onButton6Click = (event) => {
    $page.comp("tree0").expandNode("CA8A602D66400001D1DC1C10E5109CC0");
}

特别说明

  • 如果数据组件中没有展开行数据,显示不出展开的效果,即不能展开一个不在树上的节点

列表类组件

列表类组件提供很多属性用于界面展现和用户交互,鉴于官网介绍的比较详细,本文不再赘述。

组件 用途 Antd 官网 Antd Vue 官网
表格 展示行列数据 表格 表格
多层次的结构列表
列表 最基础的列表展示,可承载文字、列表、图片、段落 列表 列表
分页 分页器用于分隔长列表,每次只加载一个页面 分页 分页

案例位置

桌面-页面-列表表单组件-表格组件.w、列表组件.w、树形组件.w

results matching ""

    No results matching ""