代码示例:快速找到示例代码

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
    @Transactional
    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获取value
Integer 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注册中心相同
b)ModuleB 对应的方法需要暴露dubbo接口,自定义service需要增加@Function注解

8、流程拒绝和回退调用自定义函数

1)、工作流撤销的自定义函数

@Function
public XXX recall(String data) {    
    return new XXX();
} 

2)、撤销回退调用的自定义函数
调用入口:
pro/shushi/pamirs/workflow/app/core/service/operator/ApprovalFallbackOperatorService.java:181

@Function
public XXX fallBack(String data) {
    return new XXX();
}

3)、工作流拒绝之后回调钩子

@Function
public XXX reject((String data) {    
    return new XXX();
} 

9、启动后访问页面报枚举项不存在

现象:枚举项不存在, model:base.ViewAction, name:target,value:ROUTER

pro.shushi.pamirs.meta.common.exception.PamirsException: 枚举项不存在, model:base.ViewAction, name:target,value:ROUTER
    at pro.shushi.pamirs.meta.common.exception.PamirsException$Builder.errThrow(PamirsException.java:173) ~[pamirs-meta-common-4.6.6.jar:na]
    at pro.shushi.pamirs.framework.orm.converter.entity.handler.EnumNamedHandler.lambda$dealEnum$4(EnumNamedHandler.java:149) ~[pamirs-framework-orm-4.6.8.jar:na]
    at pro.shushi.pamirs.framework.orm.converter.multi.MultiValueStrategy.submit(MultiValueStrategy.java:59) ~[pamirs-framework-orm-4.6.8.jar:na]
    at pro.shushi.pamirs.framework.orm.converter.multi.MultiValueStrategy.submit(MultiValueStrategy.java:23) ~[pamirs-framework-orm-4.6.8.jar:na]
    at pro.shushi.pamirs.framework.orm.converter.entity.handler.EnumNamedHandler.dealEnum(EnumNamedHandler.java:86) ~[pamirs-framework-orm-4.6.8.jar:na]
    at pro.shushi.pamirs.framework.orm.converter.entity.handler.EnumNamedHandler.stringify(EnumNamedHandler.java:66) ~[pamirs-framework-orm-4.6.8.jar:na]
    at pro.shushi.pamirs.framework.orm.converter.entity.handler.EnumHandler.stringify(EnumHandler.java:57) ~[pamirs-framework-orm-4.6.8.jar:na]
    at pro.shushi.pamirs.framework.orm.client.converter.entity.ClientEnumConverter.out(ClientEnumConverter.java:30) ~[pamirs-framework-orm-client-4.6.8.jar:na]
    at pro.shushi.pamirs.framework.orm.client.converter.processor.ClientTypeProcessor.lambda$out$6(ClientTypeProcessor.java:71) ~[pamirs-framework-orm-client-4.6.8.jar:na]
    at pro.shushi.pamirs.meta.common.enmu.BaseEnum.switchConsume(BaseEnum.java:717) ~[pamirs-meta-common-4.6.6.jar:na]
    at pro.shushi.pamirs.meta.common.enmu.BaseEnum.switch0(BaseEnum.java:697) ~[pamirs-meta-common-4.6.6.jar:na]
    at pro.shushi.pamirs.meta.common.enmu.BaseEnum.switches(BaseEnum.java:638) ~[pamirs-meta-common-4.6.6.jar:na]

问题原因:
Oinone重写了GraphQL的枚举转换类,报错是没有加载到这个自定义类

解决方法
在boot工程的pom的最前面引用如下的jar,重新发布即可

<dependency>
  <groupId>pro.shushi.pamirs</groupId>
  <artifactId>a</artifactId>
</dependency>

10、配置日志文件

现在启动输出到out.log应该是启动脚本中定向输出了(>>)

不定向输出,采用自己配置的方式,与标准的SpringBoot工程配置日志一样
两种方式(都是Spring提供的方式):
1、bootstrap.yml 里面可以按profiles指定logback的配置文件,例如:
logging:
config: classpath:logback-pre.xml
具体文件名和文件输入在logback里面进行配置,跟通用的logback配置一致

2、resources的根目录,直接配置 logback-spring.xml, 启动会自动加载

11、自定义controller如何获取用户信息

    private PamirsUser fetchUserByRequest() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String sessionId = CookieUtil.getValue(request, pro.shushi.pamirs.framework.common.utils.CookieUtil.USER_SESSION_ID);
        PamirsUserDTO pamirsUserDTO = UserCache.get(sessionId);
        if (pamirsUserDTO!=null) {
            // 根据用户ID获取完整的用户信息
           return UserInfoCache.queryUserById(pamirsUserDTO.getUserId()); 
        } else {
            throw PamirsException.construct(BaseExpEnumerate.BASE_USER_NOT_LOGIN_ERROR).errThrow();
        }
    }

12、查询设置不排序

查询的page和Wrapper可设置setSortable(Boolean.FALSE),来实现查询不需要排序的场景

示例1:page中设置不排序

page.setSortable(Boolean.FALSE);
page = new PetShop().queryPage(page, queryWrapper);

示例2:Wrapper中设置不排序

IWrapper wrapper = Pops.lambdaQuery()
    .from(PetShop.MODEL_MODEL).setBatchSize(-1).setSortable(Boolean.FALSE);
List petShops4 = new PetShop().queryList(wrapper);

持续补充中。。。。。

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

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

(1)
shao的头像shao数式管理员
上一篇 2024年2月20日 pm6:52
下一篇 2024年2月20日 pm7:15

相关推荐

  • 【前端】项目开发前端知识要点地图

    概述 下面整理了目前现有的所有文章,并提供了基本的学习路径。所有使用*标记的文章属于推荐必读文章。 目录 基础篇 【路由】浏览器地址栏url参数介绍 母版-布局-DSL 渲染基础(v4)* 组件SPI机制(v4)* 组件数据交互基础(v4)* 组件生命周期(v4) 入门篇 自定义视图组件(v4)* 如何通过浏览器开发者工具提高调试效率* 如何提高自定义组件的开发效率* 自定义组件之自动渲染(组件插槽的使用)(v4)* GraphQL请求详解(v4)* 上下文在字段和动作中的应用 如何实现页面间的跳转 如何自定义指定页面的样式 进阶篇 自定义组件之手动渲染基础(v4) 自定义组件之手动渲染弹出层(v4) 自定义组件之手动渲染任意视图(v4) 【前端】IOC容器(v4) 最佳实践篇 【前端】工程结构最佳实践(v4)* 【前端】移动端工程结构最佳实践(v4)* 界面设计器实战篇 基础篇 【界面设计器】模型增删改查基础 【界面设计器】他表字段 【界面设计器】左树右表 【界面设计器】树形表格 【界面设计器】树下拉/级联选择 【界面设计器】自定义字段组件基础 展示篇 【界面设计器】自定义字段组件实战——轮播图 【界面设计器】自定义字段组件实战——表格字段组合展示 【界面设计器】自定义字段组件实战——表格字段内嵌表格 交互篇 【界面设计器】自定义字段组件实战——千分位输入框 其他 前端低无一体使用教程 如何自定义表格字段? 【界面设计器】组件开发常见问题 【前端】低无一体部署常见问题 【前端】生产环境性能调优 API文档 OioProvider详解(v4.3.0)* 前端环境配置(v4)* 默认布局模板(v4) 表格主题配置(v4) 运行时上下文API文档(v4) Class Component(ts)(v4)

    2024年5月25日
    3.8K00
  • 非存储字段搜索,适应灵活的搜索场景

    1、非存储字段搜索 1.1 描述 通常根据本模型之外的信息作为搜索条件时,通常会把 这些字段放在代理模型上。这类场景我们称之为 非存储字段搜索 1.2 场景一 非存储字段为基本的String。1.代码定义:非存储字段为基本的包装数据类型 @Field(displayName = "确认密码", store = NullableBoolEnum.FALSE) private String confirmPassword; 2.设计器拖拽:列表中需要有退拽这个字段,字段是否隐藏的逻辑自身业务是否需要决定。3.页面通过非存储字段为基本的包装数据类型进行搜索时。会拼在 queryWrapper 的属性queryData中,queryData为Map,key为字段名,value为搜索值。4.后台逻辑处理代码示例: Map<String, Object> queryData = queryWrapper.getQueryData(); if (null != queryData) { Object productIdObj = queryData.get(PRODUCT_ID); if (Objects.nonNull(productIdObj)) { String productId = productIdObj.toString(); queryWrapper.lambda().eq(MesProduceOrderProxy::getProductId, productId); } } 1.3 场景二 非存储字段为非存储对象。 定义 为非存储的 @Field(displayName = "款", store = NullableBoolEnum.FALSE) @Field.many2one @Field.Relation(store = false) private MesProduct product; 2.页面在搜索栏拖拽非存储字段作为搜索条件 3.后台逻辑处理代码示例: try { if (null != queryData && !queryData.isEmpty()) { List<Long> detailId = null; BasicSupplier supplier = JsonUtils.parseMap2Object((Map<String, Object>) queryData.get(supplierField), BasicSupplier.class); MesProduct product = JsonUtils.parseMap2Object((Map<String, Object>) queryData.get(productField), MesProduct.class); MesMaterial material = JsonUtils.parseMap2Object((Map<String, Object>) queryData.get(materialField), MesMaterial.class); if (supplier != null) { detailId = bomService.queryBomDetailIdBySupplierId(supplier.getId()); if (CollectionUtils.isEmpty(detailId)) { detailId.add(-1L); } } if (product != null) { List<Long> produceOrderId = produceOrderService.queryProductOrderIdByProductIds(product.getId()); if (CollectionUtils.isNotEmpty(produceOrderId)) { queryWrapper.lambda().in(MesProduceBomSizes::getProduceOrderId, produceOrderId); } } if (material != null) { //找出两个bom列表的并集 List<Long> materBomDetailId = bomService.queryBomDetailIdByMaterialId(material.getId()); if (CollectionUtils.isNotEmpty(detailId)) { detailId = detailId.stream().filter(materBomDetailId::contains).collect(Collectors.toList()); } else { detailId = new ArrayList<>(); if (CollectionUtils.isEmpty(materBomDetailId)) { detailId.add(-1L); } else { detailId.addAll(materBomDetailId); } } } if (CollectionUtils.isNotEmpty(detailId)) { queryWrapper.lambda().in(MesProduceBomSizes::getProductBomId, detailId); } } } catch (Exception e) { log.error("queryData处理异常", e); } 注意:…

    2024年2月20日
    1.1K00
  • IWrapper、QueryWrapper和LambdaQueryWrapper使用

    条件更新updateByWrapper 通常我们在更新的时候new一个对象出来在去更新,减少更新的字段 Integer update = new DemoUser().updateByWrapper(new DemoUser().setFirstLogin(Boolean.FALSE), Pops.<DemoUser>lambdaUpdate().from(DemoUser.MODEL_MODEL).eq(IdModel::getId, userId) 使用基础模型的updateById方法更新指定字段的方法: new 一下update对象出来,更新这个对象。 WorkflowUserTask userTaskUp = new WorkflowUserTask(); userTaskUp.setId(userTask.getId()); userTaskUp.setNodeContext(json); userTaskUp.updateById(); 条件删除updateByWrapper public List<T> delete(List<T> data) { List<Long> petTypeIdList = new ArrayList(); for(T item:data){ petTypeIdList.add(item.getId()); } Models.data().deleteByWrapper(Pops.<PetType>lambdaQuery().from(PetType.MODEL_MODEL).in(PetType::getId,petTypeIdList)); return data; } 构造条件查询数据 示例1: LambdaQueryWrapper拼接查询条件 private void queryPetShops() { LambdaQueryWrapper<PetShop> query = Pops.<PetShop>lambdaQuery(); query.from(PetShop.MODEL_MODEL); query.setSortable(Boolean.FALSE); query.orderBy(true, true, PetShop::getId); List<PetShop> petShops2 = new PetShop().queryList(query); System.out.printf(petShops2.size() + ""); } 示例2: IWrapper拼接查询条件 private void queryPetShops() { IWrapper<PetShop> wrapper = Pops.<PetShop>lambdaQuery() .from(PetShop.MODEL_MODEL).eq(PetShop::getId,1L); List<PetShop> petShops4 = new PetShop().queryList(wrapper); System.out.printf(petShops4.size() + ""); } 示例3: QueryWrapper拼接查询条件 private void queryPetShops() { //使用Lambda获取字段名,防止后面改字段名漏改 String nameField = LambdaUtil.fetchFieldName(PetTalent::getName); //使用Lambda获取Clumon名,防止后面改字段名漏改 String nameColumn = PStringUtils.fieldName2Column(nameField); QueryWrapper<PetShop> wrapper2 = new QueryWrapper<PetShop>().from(PetShop.MODEL_MODEL) .eq(nameColumn, "test"); List<PetShop> petShops5 = new PetShop().queryList(wrapper2); System.out.printf(petShops5.size() + ""); } IWrapper转为LambdaQueryWrapper @Function.Advanced(type= FunctionTypeEnum.QUERY) @Function.fun(FunctionConstants.queryPage) @Function(openLevel = {FunctionOpenEnum.API}) public Pagination<PetShopProxy> queryPage(Pagination<PetShopProxy> page, IWrapper<PetShopProxy> queryWrapper) { LambdaQueryWrapper<PetShopProxy> wrapper = ((QueryWrapper<PetShopProxy>) queryWrapper).lambda(); // 非存储字段从QueryData中获取 Map<String, Object> queryData = queryWrapper.getQueryData(); if (null != queryData && !queryData.isEmpty()) { String codes = (String) queryData.get("codes"); if (org.apache.commons.lang3.StringUtils.isNotBlank(codes)) { wrapper.in(PetShopProxy::getCode, codes.split(",")); } } return new PetShopProxy().queryPage(page, wrapper); }

    2024年5月25日
    1.6K00
  • 对字段进行加密存储

    需求: 模型字段上使用 pro.shushi.pamirs.user.api.crypto.annotation.EncryptField 注解模型动作上使用 pro.shushi.pamirs.user.api.crypto.annotation.NeedDecrypt 注解 示例: 对需要加密的字段添加@EncryptField注解 @Model.model(Student.MODEL_MODEL) @Model(displayName = "学生", summary = "学生") public class Student extends IdModel { public static final String MODEL_MODEL = "top.Student"; @Field(displayName = "学生名字") @Field.String private String studentName; @Field(displayName = "学生ID") @Field.Integer private Long studentId; @Field(displayName = "学生卡号") @Field.String @EncryptField private String studentCard; } 对函数添加@NeedDecrypt注解 @Action.Advanced(name = FunctionConstants.create, managed = true)//默认取的是方法名 @Action(displayName = "确定", summary = "添加", bindingType = ViewTypeEnum.FORM) @Function(name = FunctionConstants.create)//默认取的是方法名 @Function.fun(FunctionConstants.create)//默认取的是方法名 @NeedDecrypt public Student create(Student data) { String studentCard = data.getStudentCard(); if (studentCard != null) { //自定义加密方法 data.setStudentCard(StudentEncoder.encode(studentCard)); } return data.create(); }

    2024年10月10日
    93700
  • 自定义表格支持合并或列、表头分组

    本文将讲解如何通过自定义实现表格支持单元格合并和表头分组。 点击下载对应的代码 在学习该文章之前,你需要先了解: 1: 自定义视图2: 自定义视图、字段只修改 UI,不修改数据和逻辑3: 自定义视图动态渲染界面设计器配置的视图、动作 1. 自定义 widget 创建自定义的 MergeTableWidget,用于支持合并单元格和表头分组。 // MergeTableWidget.ts import { BaseElementWidget, SPI, ViewType, TableWidget, Widget, DslRender } from '@kunlun/dependencies'; import MergeTable from './MergeTable.vue'; @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Table, widget: 'MergeTableWidget' }) ) export class MergeTableWidget extends TableWidget { public initialize(props) { super.initialize(props); this.setComponent(MergeTable); return this; } /** * 表格展示字段 */ @Widget.Reactive() public get currentModelFields() { return this.metadataRuntimeContext.model.modelFields.filter((f) => !f.invisible); } /** * 渲染行内动作VNode */ @Widget.Method() protected renderRowActionVNodes() { const table = this.metadataRuntimeContext.viewDsl!; const rowAction = table?.widgets.find((w) => w.slot === 'rowActions'); if (rowAction) { return rowAction.widgets.map((w) => DslRender.render(w)); } return null; } } 2. 创建对应的 Vue 组件 定义一个支持合并单元格与表头分组的 Vue 组件。 <!– MergeTable.vue –> <template> <vxe-table border height="500" :column-config="{ resizable: true }" :merge-cells="mergeCells" :data="showDataSource" @checkbox-change="checkboxChange" @checkbox-all="checkedAllChange" > <vxe-column type="checkbox" width="50"></vxe-column> <!– 渲染界面设计器配置的字段 –> <vxe-column v-for="field in currentModelFields" :key="field.name" :field="field.name" :title="field.label" ></vxe-column> <!– 表头分组 https://vxetable.cn/v4.6/#/table/base/group –> <vxe-colgroup title="更多信息"> <vxe-column field="role" title="Role"></vxe-column> <vxe-colgroup title="详细信息"> <vxe-column field="sex" title="Sex"></vxe-column> <vxe-column field="age" title="Age"></vxe-column> </vxe-colgroup> </vxe-colgroup> <vxe-column title="操作" width="120"> <template #default="{ row, $rowIndex }"> <!– 渲染界面设计器配置的行内动作 –> <row-action-render :renderRowActionVNodes="renderRowActionVNodes" :row="row" :rowIndex="$rowIndex" :parentHandle="currentHandle" ></row-action-render> </template> </vxe-column> </vxe-table> <!– 分页 –> <oio-pagination :pageSizeOptions="pageSizeOptions" :currentPage="pagination.current"…

    2025年1月9日
    1.1K00

Leave a Reply

登录后才能评论