集成设计器数据流程、流程设计器可以暴露接口触发

集成设计器数据流程暴露接口触发

需求:在集成设计器配置的连接器、数据流程链接到外部接口,需要可以有一个管理页面,统一管理这些集成配置。比如对接多个医院的挂号系统,希望可以配置好数据流程之后,能够在已经实现的开放接口上,动态的调用集成平台配置的数据流程。

连接器暴露接口触发

  1. 设计连接器资源配置模型。使用业务ID+接口唯一标识+连接器实现连接器资源和业务唯一。

    @Model.model(EipConnectorResourceSetting.MODEL_MODEL)
    @Model(displayName = "连接器资源配置", summary = "连接器资源配置")
    @Model.Advanced(unique = {"hospitalId, interfaceUnique"})
    public class EipConnectorResourceSetting extends IdModel {
    
    public static final String MODEL_MODEL = "hr.simple.EipConnectorResourceSetting";
    
    @UxTableSearch.FieldWidget(@UxWidget())
    @Field(displayName = "医院", required = true)
    @Field.Relation(relationFields = {"hospitalId"}, referenceFields = {"id"})
    private Hospital hospital;
    
    @Field.Integer
    @Field(displayName = "医院ID", invisible = true)
    private Long hospitalId;
    
    @UxTableSearch.FieldWidget(@UxWidget())
    @Field.String
    @Field(displayName = "接口唯一标识", required = true)
    private String interfaceUnique;
    
    @UxTableSearch.FieldWidget(@UxWidget())
    @Field.many2one
    @Field(displayName = "连接器", required = true)
    @Field.Relation(relationFields = {"connectorId"}, referenceFields = {"id"})
    private EipConnector connector;
    
    @Field.Integer
    @Field(displayName = "连接器ID", invisible = true)
    private Long connectorId;
    
    @UxTableSearch.FieldWidget(@UxWidget())
    @Field.many2one
    @Field(displayName = "连接器接口", required = true)
    @Field.Relation(relationFields = {"integrationInterfaceId"}, referenceFields = {"id"}, domain = "connectorId==${activeRecord.connector.id}")
    private EipConnectorResource connectorResource;
    
    @Field.Integer
    @Field(displayName = "连接器接口ID", invisible = true)
    private Long connectorResourceId;
    }
  2. 开放接口定义,文档参考:https://doc.oinone.top/oio4/9326.html
    外部平台调用开放接口,实现动态调用连接器资源

    @Model.model(HospitalSection.MODEL_MODEL)
    @Model(displayName = "医院科室", summary = "医院科室")
    public class HospitalSection extends IdModel {
    
    public static final String MODEL_MODEL = "net.example.HospitalSection";
    
    @Field(displayName = "科室Code", required = true)
    private String deptCode;
    
    @Field(displayName = "科室名称", required = true)
    private String deptName;
    
    @Field(displayName = "科室描述")
    private String deptDesc;
    }
    @Slf4j
    @Fun
    @Component
    public class TestOpenService {
    
    @Resource
    private TestCommonService testCommonService;
    
    @Function
    @Open(name = "获取科室", path = "test/gainSections")
    @Open.Advanced(httpMethod = "POST")
    public OpenEipResult<List<HospitalSection>> gainSections(IEipContext<SuperMap> context, ExtendedExchange exchange) {
        return new OpenEipResult<>(testCommonService.gainSections(context));
    }
    }
    @Slf4j
    @Component
    public class TestCommonService {
    
    @Resource
    private CustomWorkflowService customWorkflowService;
    
    /**
     * 获取科室
     *
     * @param context 请求上下文
     * @return 科室集合
     */
    public List<HospitalSection> gainSections(IEipContext<SuperMap> context) {
        EipResult<SuperMap> gainSections = executeEipConnector(context, "gainSections");
        if (gainSections.getSuccess()) {
            if (gainSections.getContext().getInterfaceContext().get("DepartmentList")!=null) {
                return JSON.parseArray(JSON.toJSONString(gainSections.getContext().getInterfaceContext().get("DepartmentList")),
                        HospitalSection.class);
    
            }
        }
        String errorCode = gainSections.getErrorCode();
        String errorMessage = gainSections.getErrorMessage();
        // Object result = gainSections.getResult();
        return new ArrayList<>();
    }
        /**
     * 根据请求参数中医院id和参数key-value、接口标识获取连接器
     *
     * @param context         请求上下文
     * @param interfaceUnique 接口标识
     * @return 连接器
     */
    private EipResult<SuperMap> executeEipConnector(IEipContext<SuperMap> context, String interfaceUnique) {
        String hospitalId = Optional.ofNullable(String.valueOf(context.getInterfaceContext().getIteration("hospitalId"))).orElse("");
        String parameterValue = Optional.ofNullable(String.valueOf(context.getInterfaceContext().getIteration("parameterValue"))).orElse("");
        //step1. 获取连接器模型
        EipConnectorResourceSetting interfaceSetting = new EipConnectorResourceSetting()
                .setHospitalId(Long.valueOf(hospitalId)).setInterfaceUnique(interfaceUnique).queryOne();
        if (interfaceSetting == null) {
            throw PamirsException.construct(ExpEnumerate.SYSTEM_ERROR).appendMsg("连接器模型未找到").errThrow();
        }
        //step2. 获取连接器接口
        interfaceSetting.fieldQuery(EipConnectorResourceSetting::getConnectorResource);
        EipConnectorResource connectorResource = interfaceSetting.getConnectorResource();
        if (connectorResource == null) {
            throw PamirsException.construct(ExpEnumerate.SYSTEM_ERROR).appendMsg("连接器接口未找到").errThrow();
        }
        //3. 执行连接器获取结果
        Map<String, Object> params = new HashMap<>();
        params.put("wxValue1", parameterValue);
        return EipExecutor.newInstance().call(connectorResource.getInterfaceName(), params);
    }

数据流程暴露接口触发

  1. 设计数据流程配置模型。使用业务ID+接口唯一标识+连接器实现数据流程配置和业务唯一。

    @Model.model(EipOpenDataflowSetting.MODEL_MODEL)
    @Model(displayName = "数据流程配置", summary = "数据流程配置")
    @Model.Advanced(unique = {"hospitalId,interfaceUnique"})
    public class EipOpenDataflowSetting extends IdModel {
    
    public static final String MODEL_MODEL = "hr.simple.EipOpenDataflowSetting";
    
    @UxTableSearch.FieldWidget(@UxWidget())
    @Field(displayName = "医院", required = true)
    @Field.Relation(relationFields = {"hospitalId"}, referenceFields = {"id"})
    private Hospital hospital;
    
    @Field.Integer
    @Field(displayName = "医院ID", invisible = true)
    private Long hospitalId;
    
    @UxTableSearch.FieldWidget(@UxWidget())
    @Field.String
    @Field(displayName = "接口唯一标识", required = true)
    private String interfaceUnique;
    
    @UxTableSearch.FieldWidget(@UxWidget())
    @Field.many2one
    @Field(displayName = "数据流程", required = true)
    @Field.Relation(relationFields = {"dataflowId"}, referenceFields = {"id"})
    private DataflowDesigner dataflow;
    
    @Field.Integer
    @Field(displayName = "数据流程编码", invisible = true)
    private Long dataflowId;
    
    @Field.String
    @Field.Related(related = {"dataflow", "code"})
    @UxForm.FieldWidget(@UxWidget(readonly = "true"))
    @Field(displayName = "数据流程编码", store = NullableBoolEnum.TRUE)
    private String dataflowCode;
    }
  2. 开放接口定义。

    @Fun(RegisterOpenService.FUN_NAMESPACE)
    public interface RegisterOpenService {
    
    String FUN_NAMESPACE = "net.example.RegisterService";
    
    @Function
    RegisterOrder queryById(Long hospitalId, Long memberId);
    }
    @Slf4j
    @Fun(RegisterOpenService.FUN_NAMESPACE)
    @Component
    public class RegisterOpenServiceImpl implements RegisterOpenService {
    
    @Autowired
    private CustomWorkflowService customWorkflowService;
    
    /**
     * 开放接口:把自己的开放出去供外部调用(如:小程序调用)
     *
     * 文档参考:https://doc.oinone.top/oio4/9326.html
     *
     * 1、接口访问URL地址:http://127.0.0.1:8195/openapi/pamirs/register/queryById 端口根据yml配置进行修改
     * 2、参数默认是map格式,构造为IEipContext对象
     */
    @Function
    @Open(name = "根据ID查询挂号流水", path = "register/queryById")
    @Open.Advanced(
            httpMethod = "GET"
    )
    public OpenEipResult<RegisterOrder> queryById4Open(IEipContext<SuperMap> context, ExtendedExchange exchange) {
        String memberId = Optional.ofNullable(String.valueOf(context.getInterfaceContext().getIteration("id"))).orElse("0");
        String hospitalId = Optional.ofNullable(String.valueOf(context.getInterfaceContext().getIteration("hospitalId"))).orElse("0");
        // 开发接口的内部具体实现
        RegisterOrder register = queryById(Long.valueOf(hospitalId), Long.valueOf(memberId));
        if (register!=null) {
            return new OpenEipResult<>(register);
        } else {
            throw PamirsException.construct(EipExpEnumerate.SYSTEM_ERROR).appendMsg("根据ID "+ memberId +"查询挂号流水").errThrow();
        }
    }
    
    @Override
    @Function
    public RegisterOrder queryById(Long hospitalId, Long memberId) {
        // step1、业务前置逻辑、参数校验等
        // step2、构造请求数据、或者通过BD获取数据(这里先进行Mock)
        RegisterOrder register = new RegisterOrder();
        register.setHospitalId("719331903102009889");
        register.setSectionId("1");
        register.setDoctorId("1");
        register.setSourceId("1");
        register.setPatienterName("zhangsan");
        register.setPatienterIdCard("123444");
        // 配置表,医院 + 接口功能 == >> 流程编码。   ****** 实际项目这些基础数据需要缓存,如果Caffeine/Redis*********
        EipOpenDataflowSetting dataflowSetting = new EipOpenDataflowSetting().setHospitalId(hospitalId).setInterfaceUnique("theWeather").queryOne();
        if (dataflowSetting !=  null) {
            // step3、调用数据流程
            WorkflowDefinition workflowDefinition = customWorkflowService.queryWorkflowDefinition(dataflowSetting.getDataflowCode());
            if (workflowDefinition != null) {
                // 分支1:调用数据流程
                Map<String, Object> result = customWorkflowService.startWorkflow(workflowDefinition, register);
                log.info("调用数据流程返回:" + result);
    
                // 根据返回处理业务逻辑
            }
        } else {
            // 分支2:异常处理,或者没有数据流程实现执行默认逻辑
        }
    
        // Step4 业务后置逻辑,数据操作、其他service的调用之类
        return register;
    }
    }
    @Slf4j
    @Component
    public class CustomWorkflowService {
    
    public WorkflowDefinition queryWorkflowDefinition(String workflowCode) {
        return new WorkflowDefinition().queryOneByWrapper(
                Pops.<WorkflowDefinition>lambdaQuery()
                        .from(WorkflowDefinition.MODEL_MODEL)
                        .eq(WorkflowDefinition::getWorkflowCode, workflowCode)
                        .eq(WorkflowDefinition::getActive, 1)
        );
    }
    
    /**
     * 触发⼯作流实例
     */
    public Map<String, Object> startWorkflow(WorkflowDefinition workflowDefinition, IdModel modelData) {
        Map<String, Object> result = new HashMap<>();
        if (null == workflowDefinition) {
            // 流程没有运⾏实例
            return result;
        }
        String model = Models.api().getModel(modelData);
        //⼯作流上下⽂
        WorkflowDataContext wdc = new WorkflowDataContext();
        wdc.setDataType(WorkflowVariationTypeEnum.ADD);
        wdc.setModel(model);
        wdc.setWorkflowDefinitionDefinition(workflowDefinition.parseContent());
        wdc.setWorkflowDefinition(workflowDefinition);
        wdc.setWorkflowDefinitionId(workflowDefinition.getId());
        IdModel copyData = KryoUtils.get().copy(modelData);
        // ⼿动触发创建的动作流,将操作⼈设置为当前用户,作为流程的发起⼈
        copyData.setCreateUid(PamirsSession.getUserId());
        copyData.setWriteUid(PamirsSession.getUserId());
        String jsonData = JsonUtils.toJSONString(copyData.get_d());
        //触发工作流 新增时触发-onCreateManual 更新时触发-onUpdateManual
        Fun.run(WorkflowModelTriggerFunction.FUN_NAMESPACE, "onCreateManualSync", wdc, "1", jsonData);
    
        // 处理返回结果
        Long workflowInstanceId = (Long) wdc.getDataMap().get(WorkflowConstant.WORKFLOW_INSTANCE_ID);
        if (workflowInstanceId !=null) {
            WorkflowInstance workflowInstance = new WorkflowInstance().setId(workflowInstanceId).queryById();
            WorkflowContext workflowContext = workflowInstance.fetchWorkflowContext();
            result = (HashMap)workflowContext.get(ParamNode.PARAM_PREFIX);
        }
    
        return result;
    }
    
    public Map<String,Object> startCreatOrderWorkflow(WorkflowDefinition workflowDefinition, IdModel modelData){
        Map<String, Object> result = new HashMap<>();
        if (null == workflowDefinition) {
            // 流程没有运⾏实例
            return result;
        }
        String model = Models.api().getModel(modelData);
        //⼯作流上下⽂
        WorkflowDataContext wdc = new WorkflowDataContext();
        wdc.setDataType(WorkflowVariationTypeEnum.ADD);
        wdc.setModel(model);
        wdc.setWorkflowDefinitionDefinition(workflowDefinition.parseContent());
        wdc.setWorkflowDefinition(workflowDefinition);
        wdc.setWorkflowDefinitionId(workflowDefinition.getId());
        IdModel copyData = KryoUtils.get().copy(modelData);
        // ⼿动触发创建的动作流,将操作⼈设置为当前用户,作为流程的发起⼈
        copyData.setCreateUid(PamirsSession.getUserId());
        copyData.setWriteUid(PamirsSession.getUserId());
        String jsonData = JsonUtils.toJSONString(copyData.get_d());
        //触发⼯作流 新增时触发-onCreateManual 更新时触发-onUpdateManual
        Fun.run(WorkflowModelTriggerFunction.FUN_NAMESPACE, "onCreateManualSync", wdc, "1", jsonData);
    
        // 处理返回结果
        Long workflowInstanceId = (Long) wdc.getDataMap().get(WorkflowConstant.WORKFLOW_INSTANCE_ID);
        if (workflowInstanceId !=null) {
            WorkflowInstance workflowInstance = new WorkflowInstance().setId(workflowInstanceId).queryById();
            WorkflowContext workflowContext = workflowInstance.fetchWorkflowContext();
            result = (HashMap)workflowContext.get(ParamNode.PARAM_PREFIX);
        }
    
        return result;
    }
    }

Oinone社区 作者:yexiu原创文章,如若转载,请注明出处:https://doc.oinone.top/dai-ma-shi-jian/20972.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
yexiu's avataryexiu数式员工
Previous 2025年4月17日 pm8:52
Next 2025年4月21日 pm3:53

相关推荐

  • 如何跳过固定path路径下面所有的按钮权限

    场景: 业务上需要跳过弹窗打开里面的所有按钮权限。 实践: 实现AuthFilterService权限接口。 package pro.shushi.pamirs.top.api.spi; import org.apache.commons.lang3.StringUtils; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import pro.shushi.pamirs.auth.api.spi.AuthFilterService; import pro.shushi.pamirs.boot.web.session.AccessResourceInfoSession; import pro.shushi.pamirs.meta.common.spi.SPI; /** * @author Yexiu at 09:04 on 2024/9/27 */ @Order(88) @Component @SPI.Service public class CustomAuthFilterService implements AuthFilterService { public static final String skipPath = "/top_demo/uiMenuc6238c29bca44250a041691565056a63/ACTION#top.Teacher#uiView2b60cc6daa334c7280cb78207d41addc"; @Override public Boolean isAccessAction(String model, String name) { String path = AccessResourceInfoSession.getInfo().getOriginPath(); if (StringUtils.isNotEmpty(path) && path.startsWith(skipPath)) { //返回true就代表通过验证 return true; } return null; } @Override public Boolean isAccessAction(String path) { if (StringUtils.isNotEmpty(path) && path.startsWith(skipPath)) { //返回true就代表通过验证 return true; } return null; } } 可以看到弹窗下面的按钮都不需要权限控制了。

    2025年3月11日
    1.1K00
  • 工作流:通过业务数据操作工作流程(催办、撤销等)

    一、抽象模型,需要操作流程的模型继承此模型 定义流程相关的一些信息在模型中;如果直接定义在存储模型中,下面这些字段都是显示的指定为非存储字段。更好的建议:1、如果有多个业务模型有这类需要,则可以把这些字段抽取到抽象模型中2、如果仅有一个业务模型需要,则可以放到代理模型中 /** * 定义流程相关的一些信息在模型中 */ @Model.model(DemoBaseAbstractModel.MODEL_MODEL) @Model(displayName = "抽象模型") @Model.Advanced(type= ModelTypeEnum.ABSTRACT) public abstract class DemoBaseAbstractModel extends IdModel { public static final String MODEL_MODEL = "hr.simple.DemoBaseAbstractModel"; // 流程相关 @Field.Integer @Field(displayName = "工作流用户任务ID", summary = "业务数据列表中审核流程使用", invisible = true, store = NullableBoolEnum.FALSE) private Long workflowUserTaskId; @Field.Integer @Field(displayName = "流程实例ID", summary = "业务数据列表中催办使用", invisible = true, store = NullableBoolEnum.FALSE) private Long instanceId; @Field.String @UxForm.FieldWidget(@UxWidget(invisible = "true")) @UxDetail.FieldWidget(@UxWidget(invisible = "true")) @Field(displayName = "当前流程节点", store = NullableBoolEnum.FALSE) private String currentFlowNode; @Field.Boolean @Field(displayName = "能否催办", invisible = true, defaultValue = "false", store = NullableBoolEnum.FALSE) private Boolean canUrge; // 审批状态控制申请单是否可以被发起流程、能否编辑等控制 @Field.Enum @Field(displayName = "审批状态", defaultValue = "NC") @UxForm.FieldWidget(@UxWidget(invisible = "true")) private ApprovalStatusEnum approvalStatus; } @Dict(dictionary = ApprovalStatusEnum.dictionary, displayName = "审批状态") public enum ApprovalStatusEnum implements IEnum<String> { NC("NC", "待提交", "待提交"), PENDING("PENDING", "已提交", "已提交,待审批"), APPROVED("APPROVED", "已批准", "已批准"), REJECTED("REJECTED", "已拒绝", "已拒绝"); public static final String dictionary = "land.enums.LandApprovalStatusEnum"; private final String value; private final String displayName; private final String help; ApprovalStatusEnum(String value, String displayName, String help) { this.value = value; this.displayName = displayName; this.help = help; } public String getValue() { return value; } public String getDisplayName() { return…

    2025年6月26日
    94700
  • 如何使用位运算的数据字典

    场景举例 日常有很多项目,数据库中都有表示“多选状态标识”的字段。在这里用我们项目中的一个例子进行说明一下: 示例一: 表示某个商家是否支持多种会员卡打折(如有金卡、银卡、其他卡等),项目中的以往的做法是:在每条商家记录中为每种会员卡建立一个标志位字段。如图: 用多字段来表示“多选标识”存在一定的缺点:首先这种设置方式很明显不符合数据库设计第一范式,增加了数据冗余和存储空间。再者,当业务发生变化时,不利于灵活调整。比如,增加了一种新的会员卡类型时,需要在数据表中增加一个新的字段,以适应需求的变化。  – 改进设计:标签位flag设计二进制的“位”本来就有表示状态的作用。可以用各个位来分别表示不同种类的会员卡打折支持:这样,“MEMBERCARD”字段仍采用整型。当某个商家支持金卡打折时,则保存“1(0001)”,支持银卡时,则保存“2(0010)”,两种都支持,则保存“3(0011)”。其他类似。表结构如图: 我们在编写SQL语句时,只需要通过“位”的与运算,就能简单的查询出想要数据。通过这样的处理方式既节省存储空间,查询时又简单方便。 //查询支持金卡打折的商家信息:   select * from factory where MEMBERCARD & b'0001'; // 或者:   select * from factory where MEMBERCARD & 1;    // 查询支持银卡打折的商家信息:   select * from factory where MEMBERCARD & b'0010'; // 或者:   select * from factory where MEMBERCARD & 2; 二进制( 位运算)枚举 可以通过@Dict注解设置数据字典的bit属性或者实现BitEnum接口来标识该枚举值为2的次幂。二进制枚举最大的区别在于值的序列化和反序列化方式是不一样的。 位运算的枚举定义示例 import pro.shushi.pamirs.meta.annotation.Dict; import pro.shushi.pamirs.meta.common.enmu.BitEnum; @Dict(dictionary = ClientTypeEnum.DICTIONARY, displayName = "客户端类型枚举", summary = "客户端类型枚举") public enum ClientTypeEnum implements BitEnum { PC(1L, "PC端", "PC端"), MOBILE(1L << 1, "移动端", "移动端"), ; public static final String DICTIONARY = "base.ClientTypeEnum"; private final Long value; private final String displayName; private final String help; ClientTypeEnum(Long value, String displayName, String help) { this.value = value; this.displayName = displayName; this.help = help; } @Override public Long value() { return value; } @Override public String displayName() { return displayName; } @Override public String help() { return help; } } 使用方法示例 API: addTo 和 removeFrom List<ClientTypeEnum> clientTypes = module.getClientTypes(); // addTo ClientTypeEnum.PC.addTo(clientTypes); // removeFrom ClientTypeEnum.PC.removeFrom(clientTypes); 在查询条件中的使用 List<Menu> moduleMenus = new Menu().queryListByWrapper(menuPage, LoaderUtils.authQuery(wrapper).eq(Menu::getClientTypes, ClientTypeEnum.PC));

    2023年11月24日
    2.3K00
  • 复杂Excel模版定义

    模版示例: Demo Excel样例 代码示例: @Model.model(TestApply.MODEL_MODEL) @Model(displayName = "测试申请") public class TestApply extends IdModel { public static final String MODEL_MODEL = "top.TestApply"; @Field.String @Field(displayName = "发件人") private String addresser; @Field.String @Field(displayName = "委托单位") private String entrustedUnit; @Field.String @Field(displayName = "付款单位") private String payer; @Field.String @Field(displayName = "付款单位地址") private String paymentUnitAdd; } 模版: package pro.shushi.pamirs.top.core.temp; import org.springframework.stereotype.Component; import pro.shushi.pamirs.file.api.builder.SheetDefinitionBuilder; import pro.shushi.pamirs.file.api.builder.WorkbookDefinitionBuilder; import pro.shushi.pamirs.file.api.enmu.ExcelAnalysisTypeEnum; import pro.shushi.pamirs.file.api.enmu.ExcelDirectionEnum; import pro.shushi.pamirs.file.api.enmu.ExcelHorizontalAlignmentEnum; import pro.shushi.pamirs.file.api.model.ExcelWorkbookDefinition; import pro.shushi.pamirs.file.api.util.ExcelHelper; import pro.shushi.pamirs.file.api.util.ExcelTemplateInit; import pro.shushi.pamirs.top.api.model.TestApply; import java.util.Collections; import java.util.List; @Component public class DemoTemplate implements ExcelTemplateInit { public static final String TEMPLATE_NAME = "DemoTemplate"; @Override public List<ExcelWorkbookDefinition> generator() { WorkbookDefinitionBuilder builder = WorkbookDefinitionBuilder.newInstance(TestApply.MODEL_MODEL, TEMPLATE_NAME) .setDisplayName("测试Demo"); DemoTemplate.createSheet(builder); return Collections.singletonList(builder.build()); } private static void createSheet(WorkbookDefinitionBuilder builder) { SheetDefinitionBuilder sheetBuilder = builder.createSheet().setName("测试Demo"); buildBasicInfo(sheetBuilder); } private static void buildBasicInfo(SheetDefinitionBuilder builder) { //A1:D8:表示表头占的单元格数,范围必须大于实际表头行 BlockDefinitionBuilder mergeRange = builder.createBlock(TestApply.MODEL_MODEL, ExcelAnalysisTypeEnum.FIXED_HEADER, ExcelDirectionEnum.HORIZONTAL, "A1:D8") //预设行 .setPresetNumber(10) //合并哪几个单元格 .createMergeRange("A1:D1") .createMergeRange("A2:D2") .createMergeRange("A3:D3") .createMergeRange("A4:A6") .createMergeRange("B4:B6") .createMergeRange("C4:C6") .createMergeRange("D4:D5"); //createHeader创建行,createCell创建单元格,setField指定解析字段,setIsConfig指定为true标记该行是需要解析的值 mergeRange.createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle()).setIsConfig(Boolean.TRUE) .createCell().setField("addresser").setStyleBuilder(ExcelHelper.createDefaultStyle().setWidth(6000)).and() .createCell().setField("entrustedUnit").and() .createCell().setField("payer").and() .createCell().setField("paymentUnitAdd").and() .and() .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER)) .createCell().setValue("Demo").and() .createCell().and() .createCell().and() .createCell().and() .and() //由于该行合并为一个单元格,所以其他可以不设置value .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER)) .createCell().setValue("生效金额").and() .createCell().and() .createCell().and() .createCell().and() .and() .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.RIGHT)) .createCell().setValue("金额单位:元").and() .createCell().and() .createCell().and() .createCell().and() .and() //easyExcel解析不了空行,所以这里写上值。由于上面使用createMergeRange把单元格合并了,并且D列有分割,这里填上每个单元格的值,把合并的单元格填为一样的。 .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER)) .createCell().setValue("发件人").and() .createCell().setValue("委托单位").and()…

    2024年11月18日
    2.6K00
  • 代码示例:快速找到示例代码

    1、图表设计器 数据可视化能加载到的接口,方法上需要加 category = FunctionCategoryEnum.QUERY_PAGE @Model.model(ExpensesIncome.MODEL_MODEL) @Component @Slf4j public class ExpensesIncomeAction { @Function.Advanced(type = FunctionTypeEnum.QUERY,category = FunctionCategoryEnum.QUERY_PAGE) @Function.fun(FunctionConstants.queryPage) @Function(openLevel = {FunctionOpenEnum.API}) public Pagination<ExpensesIncome> queryPage(Pagination<ExpensesIncome> page, IWrapper<ExpensesIncome> queryWrapper) { page = new ExpensesIncome().queryPage(page, queryWrapper); if (page!=null && CollectionUtils.isNotEmpty(page.getContent())) { page.getContent().forEach(a->{ if (a.getBudgetInCome()!=null && a.getBudgetInCome().compareTo(new BigDecimal("0.0"))!=0) { if (a.getRetailAmount()!=null) { a.setInComeRate(a.getRetailAmount().divide(a.getBudgetInCome(),2)); } } }); } return page; } } 2、事务支持 1)对于单个系统(InJvm)/模型内部采用强事务的方式。比如:在库存转移时,库存日志和库存数量的变化在一个事务中,保证两个表的数据同时成功或者失败。2)强事务管理采用编码式,Oinone事务管理兼容Spring的事务管理方式;有注解的方式和代码块的方式。a) 使用注解的方式: @Override @PamirsTransactional public void awardOut(AwardBookOutEmpRecordDetail detail) { List<OutEmpRecordSubjectDetail> subjectDetails = detail.getSubjectDetails(); …… } 重要说明基于注解的事务,Bean和加注解的方法必须能被Spring切面到。 b) 使用编码方式: //组装数据/获取数据/校验 Tx.build(new TxConfig()).executeWithoutResult(status -> { // 1、保存部门数据 deliDepartmentService.createOrUpdateBatch(departments); //2、如果父进行了下级关联设置,处理下级关联设置的逻辑 for (DeliDepartment department : departments) { doDepartSubLink(department); } }); ………… 3)对于分布式事务采用最终数据一致性,借助【可靠消息】或者【Job】的方式来实现。 3、平台工具类使用 3.1 FetchUtil pro.shushi.pamirs.core.common.FetchUtil,重点关注 # 根据Id查询列表 pro.shushi.pamirs.core.common.FetchUtil#fetchMapByIds # 根据Id查询,返回Map pro.shushi.pamirs.core.common.FetchUtil#fetchListByIds # 根据Codes查询列表 pro.shushi.pamirs.core.common.FetchUtil#fetchMapByCodes # 根据Code查询,返回Map pro.shushi.pamirs.core.common.FetchUtil#fetchListByCodes # 根据Entity查询 pro.shushi.pamirs.core.common.FetchUtil#fetchOne 其他更多方法参考这个类的源代码 3.2 ListUtils pro.shushi.pamirs.meta.common.util.ListUtils # 把输入的List,按给定的长度进行分组 pro.shushi.pamirs.meta.common.util.ListUtils#fixedGrouping # 从给定的List中返回特定字段的数组,忽略Null并去重 pro.shushi.pamirs.meta.common.util.ListUtils#transform 4、枚举获取 根据枚举的name获取valueInteger value = ArchivesConfigTypeEnum.getValueByName(ArchivesConfigTypeEnum.class,“status1”);根据枚举的name获取枚举项ArchivesConfigTypeEnum typeEnum = TtypeEnum.getEnum(ArchivesConfigTypeEnum.class, “status1”); 5、Map类型的数据怎么定义,即ttype 为map的字段写法 @Field(displayName = "上下文", store = NullableBoolEnum.TRUE, serialize = JSON) @Field.Advanced(columnDefinition = "TEXT") private Map<String, Object> context; 6、后端获取前端请求中的variables PamirsRequestVariables requestVariables = PamirsSession.getRequestVariables(); 7、为什么有时候调用服务走远程了 1、假设: A模型(modelA)所在的模块(ModuleA) B模型(modelB)所在的模块(ModuleB) 部署方式决定调用方式: 1)部署方式1: ModuleA 和 ModuleB 部署在一个jvm中,此时: modelA的服务/页面去调用 modelB,因为部署在一起,直接走inJvm 2、部署方式2: ModuleA 和 ModuleB 部署在不同的jvm中; modelA的服务/页面去调用 modelB,则会走远程(RPC);此时需要: a)ModuleB 需要开启dubbo服务,且ModuleA 和 ModuleB注册中心相同…

    2024年2月20日
    1.8K00

Leave a Reply

Please Login to Comment