本文讨论了在苍穹平台上动态加载进度条控件的需求背景、思路与方案、实现过程以及实现效果。在实际开发中,进度条控件数量和属性需根据动态数据加载。实现方案包括向前端动态添加控件配置、注册到后端、添加编程模型实例并侦听插件事件,以及根据业务数据为进度条赋值。通过重写多个方法(如loadCustomControlMetas、beforeBindData、onGetControl、afterBindData),在表单插件中动态创建和配置进度条控件,并根据项目任务完成情况动态更新进度条。文章还提供了开发环境版本和参考资料。
关键词:动态,进度条控件
一、需求背景
说到进度条控件,这个是苍穹标准支持的控件。但往往在实际开发中,控件的数量或者控件的属性是根据实际的数据动态加载的。
比如要统计一个项目的任务完成度,这个项目又有多条任务线,这个需要通过进度条控件来实现。其中的难点是任务线和任务完成情况都是需要根据实际情况动态计算得出的无法提前在单据设计器中预置出来。大家可以通过下面的案例来学习苍穹是如何实现动态加载进度条的
二、思路与方案
向前端动态添加控件配置
将前端动态增加的控件注册到后端
向表单添加控件添加编程模型实例,并侦听控件的插件事件
根据实际的业务数据为动态创建的进度条赋值
三、实现过程
1、表单注册插件,该插件继承AbstractFormPlugin
2、重写loadCustomControlMetas:向前端动态添加控件配置
/** * 向前端动态增加控件 * * @param e */ @Override public void loadCustomControlMetas(LoadCustomControlMetasArgs e) { super.loadCustomControlMetas(e); FormShowParameter formShowParameter = (FormShowParameter) e.getSource(); Object pk = formShowParameter.getCustomParam("projectId"); FlexPanelAp dynamicFlex = this.createDynamicFlex(pk); if (dynamicFlex != null) { Map<String, Object> mapFlex = new HashMap<>(); mapFlex.put(ClientProperties.Id, "dmp_dynamicap");//动态控件区域 mapFlex.put(ClientProperties.Items, dynamicFlex.createControl().get(ClientProperties.Items)); e.getItems().add(mapFlex); } }
(1)、在loadCustomControlMetas中创建flex面板,通过业务需求判断预置进度条控件
/** * 创建flex面板 * * @param pk * @return */ private FlexPanelAp createDynamicFlex(Object pk) { QFilter qFilter = new QFilter("dmp_project", QCP.equals, pk); DynamicObject[] stages = BusinessDataServiceHelper.load(Constant.KEY_PROGJRCTSTAGE_FORMID, Constant.PROGJRCTSTAGE_SELECTFIELD, new QFilter[] { qFilter }); int size = stages.length; if (size == 0) { return null; } FlexPanelAp dynamicFlex = new FlexPanelAp(); dynamicFlex.setKey("dynamicflex"); for (int i = size - 1; i >= 0; i--) { DynamicObject stage = stages[i]; String stagePk = stage.getPkValue().toString(); if (i == size - 1) { lastStage=stagePk; } DynamicObject project = stage.getDynamicObject("dmp_project"); if (project == null) { break; } log.info("查了第一次数据!!!"); int length = this.getLength(stagePk, pk); // project float finished = this.getFinished(stagePk, pk); String stageName = stage.getString("name");// Constant.ITERATION_NAME //创建需求面板 FlexPanelAp firstFlex = this.createFirstFlex(stageName, length, finished, i, stagePk); //创建进度条 FlexPanelAp secondFlex = this.createSecondFlex(length, finished, i); FlexPanelAp flex = new FlexPanelAp(); flex.setKey(stagePk); flex.setWidth(new LocaleString("100%")); flex.setClickable(true); Style style = new Style(); Border border = new Border(); border.setBottom("1px solid #e2e7ef"); border.setRight("1px solid #e2e7ef"); style.setBorder(border); flex.setStyle(style); flex.getItems().add(firstFlex); flex.getItems().add(secondFlex); dynamicFlex.getItems().add(flex); } return dynamicFlex; }
(2)、在flex面板中预置进度条控件
private FlexPanelAp createSecondFlex(int length, float finished, int i) { DecimalFormat df = new DecimalFormat("0.00%"); String progress = length != 0 ? df.format(finished / length) : "0.00%"; FlexPanelAp flex2 = new FlexPanelAp(); flex2.setKey("flex2" + i); flex2.setAlignItems("center"); flex2.setJustifyContent("space-between"); flex2.setWidth(new LocaleString("100%")); Style flexStyle = new Style(); Padding flexPadding = new Padding(); flexPadding.setLeft("14px"); flexPadding.setBottom("10px"); flexPadding.setRight("10px"); flexStyle.setPadding(flexPadding); flex2.setStyle(flexStyle); // 创建进度条 ProgressBarAp progressBar = new ProgressBarAp(); progressBar.setId("progressbar" + i); progressBar.setKey("progressbar" + i); progressBar.setHeight(new LocaleString("10px")); progressBar.setWidth(new LocaleString("160px")); flex2.getItems().add(progressBar); // 创建进度lab LabelAp progressLab = new LabelAp(); progressLab.setId("progress" + i); progressLab.setKey("progress" + i); progressLab.setName(new LocaleString(progress)); flex2.getItems().add(progressLab); return flex2; }
3、重写beforeBindData:将前端动态增加的控件注册到后端
/** * 将前端动态增加的控件注册到后端 * * @param e */ @Override public void beforeBindData(EventObject e) { super.beforeBindData(e); Object pk = this.getProjectId(); this.getModel().setValue("dmp_projectid", pk); FlexPanelAp dynamicFlex = this.createDynamicFlex(pk); if (dynamicFlex != null) { Container dynamicAp = this.getControl("dmp_dynamicap"); dynamicAp.getItems().addAll(dynamicFlex.buildRuntimeControl().getItems()); this.getView().createControlIndex(dynamicAp.getItems()); } }
4、重写onGetControl:向表单添加控件添加编程模型实例,并侦听控件的插件事件
/** * 向表单添加控件编程模型实例,并侦听控件的插件事件 * * @param e */ @Override public void onGetControl(OnGetControlArgs e) { String pk = String.valueOf(this.getProjectId()); QFilter qFilter = new QFilter("dmp_project", QCP.equals, pk); Map<Object, DynamicObject> stages = BusinessDataServiceHelper.loadFromCache(Constant.KEY_PROGJRCTSTAGE_FORMID, Constant.PROGJRCTSTAGE_SELECTFIELD, new QFilter[] { qFilter }); if (stages != null) { for (DynamicObject stage : stages.values()) { String stagePk = stage.getPkValue().toString(); if (StringUtils.equals(stagePk, e.getKey())) { Container container = new Container(); container.setKey(stagePk); container.setView(this.getView()); container.addClickListener(this); e.setControl(container); break; } } } }
5、重写afterBindData:根据实际的业务数据为动态创建的进度条赋值
/** * 为动态创建的进度条赋值 * * @param e */ @Override public void afterBindData(EventObject e) { super.afterBindData(e); Object pk = this.getModel().getValue("dmp_projectid"); QFilter qFilter = new QFilter("dmp_project", QCP.equals, pk); // 根据项目id去获取项目迭代 Map<Object, DynamicObject> stages = BusinessDataServiceHelper.loadFromCache(Constant.KEY_PROGJRCTSTAGE_FORMID, Constant.PROGJRCTSTAGE_SELECTFIELD, new QFilter[] { qFilter }); if (stages != null && stages.size() > 0) { String cachestage = this.getPageCache().get("cachestage"); String stageid = null; if (cachestage != null && cachestage != "") { stageid = cachestage; } else { stageid = lastStage; } // 展示未完成数量 String projectId = String.valueOf(pk); this.handleCardData(stageid, projectId); int size = stages.size(); setDmpIindex(size); int i = 0; this.getModel().batchCreateNewEntryRow("dmp_entryentityflex", size); for (DynamicObject stage : stages.values()) { String stagePk = stage.getPkValue().toString(); String stageName = stage.getString("name"); // 给页面初始化单据体dmp_entryentityflex this.getModel().setValue("dmp_stageidtext", stagePk, i); this.getModel().setValue("dmp_firstflex", i, i);// dmp_stagename this.getModel().setValue("dmp_stagename", stageName, i); int length = this.getLength(stagePk, String.valueOf(pk)); float finished = this.getFinished(stagePk, projectId); float progress = length != 0 ? (finished / length) * 100 : 0; ProgressBar progressBar = this.getControl("progressbar" + i); progressBar.setPercent((int) progress); i++; } this.getView().updateView("dmp_entryentityflex"); // 初始化单据体数据 this.handleTableData(); PointLineChart pointLineChart = this.getMainChart(); this.drawChart(pointLineChart); } }
四、实现效果
原单:
动态添加后:
五、开发环境版本
4.0.012.0