如何实现移动列表自定义筛选—以页签展示为例原创
金蝶云社区-时空蔷薇
时空蔷薇
5人赞赏了该文章 3,861次浏览 未经作者许可,禁止转载编辑于2022年04月15日 11:19:03
summary-icon摘要由AI智能服务提供

### 文本阅读理解摘要 本文描述了如何自定义开发一个移动列表页面,以替代标准产品的移动列表过滤条件实现样式。主要步骤包括:继承标准移动列表模板,实现自定义的移动列表模板,并在其中添加自定义筛选页签控件。根据筛选维度(如单据状态)设置页签数和标识,通过移动列表插件实现筛选页签的展示数据及点击页签时列表页面数据的切换逻辑。文中还详细说明了实现过程,包括页面开发、继承移动列表插件并实现自定义逻辑、数据初始化及页签展示控制等关键代码段。此外,还提及了为保障功能实用性,建议自定义筛选应归纳为少数(3~5个)散列值的字段。

关键词:

页面开发,移动列表

一、需求

图片1.png 

1

这(图1)是标准产品移动列表过滤条件的实现样式,我不想要,想要改成图2这样一排页签展示,要怎么实现呢?

图片2.png

2

 

二、思路与方案

    首先,继承标准产品的移动列表模板(bos_moblist),实现二开自定义的移动列表模板,在自定义的列表模板依照需求原型添加自定义筛选页签控件,根据筛选维度添加页签数及设置标识(如图3),通过移动列表插件实现筛选页签的展示数据及点击页签时列表页面数据切换逻辑。

    为保障功能实用性,建议可归纳为少数(3~5)个散列值的字段才可用自定义筛选。

 

图片3.png

3

    然后,在业务单据(如【自定义筛选单据】)的移动列表配置列表表单模板为二开自定义的移动列表模板,如图四。

 

图片4.png

4

 

三、实现过程

1. 页面开发

继承标准产品的移动列表模板(bos_moblist)实现二开自定义的移动列表模板【自定义筛选移动列表】(kded_bos_moblist_inh),所作修改内容:

   (1) 隐藏标准继承的移动筛选排序控件(mobfiltersortap);

    (2) 添加自定义筛选页签kded_customfiltertab),并添加标签页。本案例根据单据状态(billsatus)自定义筛选,其枚举值有保存、已提交、已审核,故在此添加三个页签,标题可不设置在插件中维护,本案例不考虑多语言场景,有需要可自行实现;

    (3) 添加Flex面板控件,如图5,用于列表无数据时的前端提示。

 

图片5.png

5

2. 继承AbstractMobListPlugin实现自定义的移动列表模板逻辑

关键代码:

/** 保存页签的状态值集 */
private static final List<String> saveStateList = Collections.unmodifiableList(Lists.newArrayList("A"));
/** 已提交页签的状态值集 */
private static final List<String> submitStateList = Collections.unmodifiableList(Lists.newArrayList("B"));
/** 审核页签的状态值集 */
private static final List<String> auditStateList = Collections.unmodifiableList(Lists.newArrayList("C"));
private Map<String, MobileListStateInfo> paramMap;
private static final MobileListStateInfo saveStateInfo;
private static final MobileListStateInfo submitStateInfo;
private static final MobileListStateInfo auditStateInfo;
private static final List<MobileListStateInfo> stateInfoList;
 
static {
//定义每个状态页签-标题名称-值集
saveStateInfo = new MobileListStateInfo("kded_savetab", "暂存", saveStateList);
submitStateInfo = new MobileListStateInfo("kded_submittab", "已提交", submitStateList);
auditStateInfo = new MobileListStateInfo("kded_audittab", "已审核", auditStateList);
stateInfoList = Lists.newArrayListWithExpectedSize(3);
 
stateInfoList.add(saveStateInfo);
stateInfoList.add(submitStateInfo);
stateInfoList.add(auditStateInfo);
}
public CustomeFilterListMobile() {
//初始化移动列表自定义筛选页签数据
this.paramMap = (Map<String, MobileListStateInfo>)stateInfoList.stream().collect(Collectors.toMap(MobileListStateInfo::getTabNum, Function.identity()));
}

 

3. 数据初始化

页面加载在afterCreateNewData事件初始化每个页签数据,根据自定义筛选条件及特殊数据权限(可根据业务需要自行调整)查询数据,并设置页签展示内容和列表展示数据。

关键代码:

@Override
public void afterCreateNewData(EventObject e) {
    super.afterCreateNewData(e);
    //初始化自定义筛选页签展示数据
    Map<String, Integer> tabCountMap = this.initTabLabelCount();
    Tab tab = (Tab)this.getView().getControl("kded_customfiltertab");
    if (tab != null) {
        String currentTab = tab.getCurrentTab();
        boolean hasCount = (Integer)tabCountMap.get(currentTab) > 0;
        //根据当前激活页签是否存在数据控制展示列表或者用户提示
        this.showDefaultViewInfo(hasCount);
    }
}
/**
 * 初始化自定义筛选页签展示数据
 * @return
 */
protected Map<String, Integer> initTabLabelCount() {
    //根据页签标识获取自定义过滤
    List<QFilter> commonFilters = this.getCommonFilters((String[])this.paramMap.keySet().toArray(new String[0]));
    //获取列表标准筛选过滤
    List<QFilter> metaDataFilters = this.getFilterFromMetaData();
    if (metaDataFilters != null && !metaDataFilters.isEmpty()) {
        commonFilters.addAll(metaDataFilters);
    }
    //获取每个页签纬度值的数据集,这里根据单据状态
    Map<String, Integer> countMap = this.getStateCount(commonFilters);
    //根据saveStateList集合值计算每个页签的数值
    Map<String, Integer> tabCountMap = this.totalCount(countMap);
     
    Iterator<Entry<String, MobileListStateInfo>> iterator = this.paramMap.entrySet().iterator();
    while(iterator.hasNext()) {
        Entry<String, MobileListStateInfo> entryinfo = iterator.next();
        MobileListStateInfo stateInfo = entryinfo.getValue();
        int count = 0;
        if (tabCountMap.get(entryinfo.getKey()) != null) {
            count = (Integer)tabCountMap.get(entryinfo.getKey());
        }
        TabPage tabPage = (TabPage)this.getControl((String)entryinfo.getKey());
        //设置页签标签值
        if (tabPage != null) {
            tabPage.setMessage(stateInfo.getTabName() + "(" + count + ")");
            this.getPageCache().put((String)entryinfo.getKey(), String.valueOf(count));
        }
    }
    return tabCountMap;
}
/**
 * 根据页签标识获取自定义过滤
 * @param currentTab
 * @return
 */
private List<QFilter> getCommonFilters(String... tabName) {
    //可扩容队列,可根据实际需要设置
    ArrayList<Object> stateList = Lists.newArrayListWithCapacity(3);
    String[] tabNameArray = tabName;
    int length = tabNameArray.length;
    for(int i=0; i<length; i++) {
        String currentTab = tabNameArray[i];
        MobileListStateInfo mobileListStateInfo = paramMap.get(currentTab);
        if(mobileListStateInfo != null) {
            stateList.addAll(mobileListStateInfo.getStateList());
        }
    }
    QFilter statusFilter = new QFilter("billstatus", QCP.in, stateList);
    QFilter specialDataPermFilter = getSpecialDataPermFilter();
    return Lists.newArrayList(statusFilter, specialDataPermFilter);
}
/**
 * 获取特殊数据权限过滤
 * @return
 */
private QFilter getSpecialDataPermFilter(){
    IFormView view = this.getView();
    String appId = view.getFormShowParameter().getAppId();
     
    if (StringUtils.isEmpty(appId)) {
       String appNum = view.getFormShowParameter().getFormConfig().getAppId();
       appId = BizAppServiceHelp.getAppIdByAppNumber(appNum);
    }
    PermissionService permissionService = (PermissionService)ServiceFactory.getService(PermissionService.class);
    String bizAppId = null;
    if (StringUtils.isNotBlank(appId)) {
        AppInfo app = AppMetadataCache.getAppInfo(appId);
        if (app != null) {
        bizAppId = app.getId();
        }
    }
    return permissionService.getOperationRuleFilter(bizAppId, getEntityName(), "view", new StringBuilder());
}
/**
 * 获取列表筛选过滤
 * @return
 */
private List<QFilter> getFilterFromMetaData() {
    List<QFilter> qFilters = null;
    BillList billList = (BillList)this.getControl("billlistap");
    FilterCondition filterCondition = billList.getFilter();
    if (filterCondition != null) {
        FilterBuilder filterBuilder = new FilterBuilder((MainEntityType)billList.getEntityType(), billList.getFilter(), this.getModel());
        filterBuilder.buildFilter();
        qFilters = filterBuilder.getQFilters();
    }
    return qFilters;
}
/**
 * 获取每个页签纬度值的数据集
 * @param commonFilters
 * @return
 */
protected Map<String, Integer> getStateCount(List<QFilter> commonFilters) {
   Map<String, Integer> countMap = Maps.newHashMapWithExpectedSize(10);
   ORM orm = ORM.create();
   try {
       DataSet dataset = orm.queryDataSet(this.getClass().getName(), this.getEntityName(), "billstatus", (QFilter[])commonFilters.toArray(new QFilter[0]));
       if (null != dataset) {
           try{
               //根据billsatatus进行分组
               DataSet groupSet = dataset.groupBy(new String[]{"billstatus"}).count("num").finish();
               Iterator<Row> iterator = groupSet.iterator();
               while(iterator.hasNext()) {
                   Row row = (Row)iterator.next();
                   countMap.put(row.getString("billstatus"), row.getInteger("num"));
               }
           } finally {
               //关闭dataset
               dataset.close();
           }
       }
   } catch (Exception ex) {
      logger.info("getStateCount query error", ex);
   }
   return countMap;
}
/**
 * 根据stateList集合值计算每个页签的数值
 * @param countMap
 * @return
 */
private Map<String, Integer> totalCount(Map<String, Integer> countMap) {
    Map<String, Integer> totalCount = Maps.newHashMapWithExpectedSize(this.paramMap.size());
    Iterator<Entry<String, MobileListStateInfo>> iterator = this.paramMap.entrySet().iterator();
    while(iterator.hasNext()) {
        Entry<String, MobileListStateInfo> entry = iterator.next();
        List<String> stateList = ((MobileListStateInfo)entry.getValue()).getStateList();
        Integer sum = 0;
        String state;
        for(Iterator<String> stateIterator = stateList.iterator(); stateIterator.hasNext(); sum = sum + (Integer)countMap.getOrDefault(state, 0)) {
            state = (String)stateIterator.next();
        }
        totalCount.put(entry.getKey(), sum);
    }
    return totalCount;
}

 

4. setFilter事件增加二开自定义筛选条件对列表数据进行过滤

关键代码:

@Override
public void setFilter(SetFilterEvent e) {
    super.setFilter(e);
    Tab tab = getControl("kded_customfiltertab");
    if(tab != null) {
        String currentTab = tab.getCurrentTab();
        List<QFilter> qFilters = e.getQFilters();
        qFilters.addAll(getCommonFilters(currentTab));
    }
}

 

5. registerListener事件给自定义筛选页签kded_customfiltertab)添加TabSelect监听,在tabSelected事件中响应,调用BillList.refresh()触发setFilter事件刷新列表数据展示

关键代码:

@Override
public void registerListener(EventObject e) {
    super.registerListener(e);
    Tab tab = (Tab)this.getControl("kded_customfiltertab");
    if (tab != null) {
        tab.addTabSelectListener(this);
    }
}
@Override
public void tabSelected(TabSelectEvent paramTabSelectEvent) {
    BillList billList = (BillList)this.getControl("billlistap");
    billList.refresh();
    String tabKey = paramTabSelectEvent.getTabKey();
    //判断列表是否存在数据展示列表或无数据提示
    this.showDefaultViewInfo(this.getTabCount(tabKey) > 0);
}

 

6. 新建二开单据【自定义筛选单据】(kded_cusfilterbill),修改移动列表,配置“列表表单模板”为步骤1的【自定义筛选移动列表】(kded_bos_moblist_inh),如图6

 

图片6.png

6

 

四、效果图

1. 当前页签列表无数据时提示,如图2

图片7.png

7 列表无数据时提示

 

2. 移动列表自定义筛选页签根据列表数据分页签正确展示。

图片8.png

8

图片9.png

9

 

3. 点击切换页签列表即时刷新展示当前页面数据。

图片10.png

10

图片11.png

11

五、开发环境版本

COSMICV4.0.014.0

 

、参考资料

【开发平台】指导手册

学习成长中心

 

、附件

图标赞 5
5人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!