3.3.2 模型的类型

本文会介绍不同类型模型以及其简单的应用场景,方便大家理解不同类型模型的用途

模型分为元模型和业务模型。元数据是指描述应用程序运行所必需的数据、规则和逻辑的数据集;元模型是指用于描述内核元数据的一套模式集合;业务模型是指用于描述业务应用元数据的一套模式集合。

元模型分为模块域、模型域和函数域三个域。域的划分规则是根据元模型定义数据关联关系的离散性来判断,离散程度越小越聚集到一个域。在4.1.4【模块元数据详解】一文中介绍的ModuleDefinition就是元模型。而我们在开发中涉及的就是业务模型

一、模型类型

  • 抽象模型:往往是提供公共能力和字段的模型,它本身不会直接用于构建协议和基础设施(如表结构等)。

  • 传输模型:用于表现层和应用层之间的数据交互,本身不会存储,没有默认的数据管理器,只有数据构造器。

  • 存储模型:存储模型用于定义数据表结构和数据的增删改查(数据管理器)功能,是直接与连接器进行交互的数据容器。

  • 代理模型:用于代理存储模型的数据管理器能力的同时,扩展出非存储数据信息的交互功能的模型。

二、模型定义种类

模型定义就是模型描述,不同定义类型,代表计算描述模型的元数据的规则不同

  • 静态模型定义:模型元数据不持久化、不进行模型定义的计算(默认值、主键、继承、关联关系)

  • 静态计算模型定义:模型元数据不持久化但初始化时进行模型定义计算获得最终的模型定义

  • 动态模型定义:模型元数据持久化且初始化时进行模型定义计算获得最终的模型定义

静态模型定义需要使用@Model.Static进行注解;静态计算模型定义使用@Model.Static(compute=true)进行注解;动态模型定义不注解@Model.Static注解。

三、安装与更新

使用@Model.model来配置模型的不可变更编码。模型一旦安装,无法在对该模型编码值进行修改,之后的模型配置更新会依据该编码进行查找并更新;如果仍然修改该注解的配置值,则系统会将该模型识别为新模型,存储模型会创建新的数据库表,而原表将会rename为废弃表。

如果模型配置了@Base注解,表明在【oinone的设计器】中该模型配置不可变更;如果字段配置了@Base注解,表明在【oinone的设计器】中该字段配置不可变更。

四、基础配置

模型基类

所有的模型都需要继承以下模型中的一种,来表明模型的类型,同时继承以下模型的默认数据管理器(详见3.3.3模型的数据管理器一节)。

  • 继承BaseModel,构建存储模型,默认无id属性。

  • 继承BaseRelation,构建多对多关系模型,默认无id属性。

  • 继承TransientModel,构建临时模型(传输模型),临时模型没有数据管理器,也没有id属性。

  • 继承EnhanceModel,构建数据源为ElasticSearch的增强模型。

快捷继承

  • 继承IdModel,构建主键为id的模型。继承IdModel的模型会数据管理器会增加queryById方法(根据id查询单条记录)

  • 继承CodeModel,构建带有唯一编码code的主键为id的模型。可以使用@Model.Code注解配置编码生成规则。也可以直接覆盖CodeModel的generateCode方法或者自定义新增的前置扩展点自定义编码生成逻辑。继承CodeModel的模型会数据管理器会增加queryByCode方法(根据唯一编码查询单条记录)

  • 继承VersionModel,构建带有乐观锁,唯一编码code且主键为id的模型。

  • 继承IdRelation,构建主键为id的多对多关系模型。

模型继承关系图

3.3.2 模型的类型

图3-3-2-1 模型继承关系图

  • AbstractModel抽象基类是包含createDate创建时间、writeDate更新时间、createUid创建用户ID、writeUid更新用户ID、aggs聚合结果和activePks批量主键列表等基础字段的抽象模型。

  • TransientModel传输模型抽象基类是所有传输模型的基类,传输模型不存储,没有数据管理器。

  • TransientRelation传输关系模型是所有传输关系模型的基类,传输关系模型不存储,用于承载多对多关系,没有数据管理器。

  • BaseModel存储模型基类提供数据管理器功能,数据模型主键可以不是ID。

  • IdModel带id模型抽象基类,在BaseModel数据管理器基础之上提供根据ID查询、更新、删除数据的功能。

  • BaseRelation关系模型抽象基类用于承载多对多关系,是多对多关系的中间模型,数据模型主键可以不是ID。

  • IdRelation带id关系模型抽象基类,在BaseRelation数据管理器基础之上提供根据ID查询、更新、删除数据的功能。

  • CodeModel带code模型抽象基类,提供按配置生成业务唯一编码功能,根据code查询、更新、删除数据的功能。

  • EnhanceModel增强模型,提供全文检索能力。此模型会在4.1.25【框架之搜索引擎】一文中展开介绍。

五、抽象模型(举例)

抽象模型本身不会直接用于构建协议和基础设施(如表结构等),而是通过继承的机制供子模型复用其字段和函数。子模型可以是所有类型的模型。

比如demo模块要管理的一些公共模型字段,我们可以建一个AbstractDemoIdModel和AbstractDemoCodeModel,demo模块中的实体模型就可以继承它们。我们来为demo模块的模型统一增加一个数据状态这么一个字段,用做数据的生效与失效管理。

Step1 引入DataStatusEnum类

pamirs-demo-api的pom.xml包增加依赖,便于引入DataStatusEnum类,当然也可以自己建,这里只是oinone提供了统一的数据记录状态的枚举,以及相应的通用方法,这边就直接引入

<dependency>
    <groupId>pro.shushi.pamirs.core</groupId>
    <artifactId>pamirs-core-common</artifactId>
</dependency>

图3-3-2-2 引入通用类库

Step2 修改DemoModule

DataStatusEnum枚举类本身也会做为数据字典,以元数据的方式被管理起来,当一个模块依赖另一个模块的元数据相关对象,则需要改模块的模块依赖定义。为DemoModule增加CommonModule的依赖注解

package pro.shushi.pamirs.demo.api;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.boot.base.ux.annotation.action.UxRoute;
import pro.shushi.pamirs.boot.base.ux.annotation.navigator.UxHomepage;
import pro.shushi.pamirs.core.common.CommonModule;
import pro.shushi.pamirs.demo.api.model.PetShop;
import pro.shushi.pamirs.meta.annotation.Module;
import pro.shushi.pamirs.meta.base.PamirsModule;
import pro.shushi.pamirs.meta.common.constants.ModuleConstants;

@Component
@Module(
        name = DemoModule.MODULE_NAME,
        displayName = "oinoneDemo工程",
        version = "1.0.0",
        dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE}
)
@Module.module(DemoModule.MODULE_MODULE)
@Module.Advanced(selfBuilt = true, application = true)
@UxHomepage(@UxRoute(PetShop.MODEL_MODEL))
public class DemoModule implements PamirsModule {
    public static final String MODULE_MODULE = "demo_core";
    public static final String MODULE_NAME = "DemoCore";

    @Override
    public String[] packagePrefix() {
        return new String[]{ "pro.shushi.pamirs.demo"};
    }
}

图3-3-2-3 定义模块依赖

Step3 新建AbstractDemoCodeModel和AbstractDemoIdModel

并新增AbstractDemoIdModel和AbstractDemoCodeModel分别继承IdModel和CodeModel,实现IDataStatus接口不是必须的,刚好DataStatus有配套的通用逻辑,暂时也先加进去,具体使用会在本文的【代理模型】这段介绍

package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.core.common.behavior.IDataStatus;
import pro.shushi.pamirs.core.common.enmu.DataStatusEnum;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.annotation.sys.Base;
import pro.shushi.pamirs.meta.base.common.CodeModel;
import pro.shushi.pamirs.meta.enmu.ModelTypeEnum;

@Base
@Model.model(AbstractDemoCodeModel.MODEL_MODEL)
@Model.Advanced(type = ModelTypeEnum.ABSTRACT)
@Model(displayName = "AbstractDemoCodeModel")
public abstract class AbstractDemoCodeModel extends CodeModel implements IDataStatus {

    public static final String MODEL_MODEL="demo.AbstractDemoCodeModel";

    @Base
    @Field.Enum
    @Field(displayName = "数据状态",defaultValue = "DISABLED",required = true,summary = "作为基类给每一个继承模型增加一个数据状态字段")
    private DataStatusEnum dataStatus;
}

图3-3-2-4 新建AbstractDemoCodeModel

package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.core.common.behavior.IDataStatus;
import pro.shushi.pamirs.core.common.enmu.DataStatusEnum;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.annotation.sys.Base;
import pro.shushi.pamirs.meta.base.IdModel;
import pro.shushi.pamirs.meta.enmu.ModelTypeEnum;

@Base
@Model.model(AbstractDemoIdModel.MODEL_MODEL)
@Model.Advanced(type = ModelTypeEnum.ABSTRACT)
@Model(displayName = "AbstractDemoIdModel")
public abstract class AbstractDemoIdModel extends IdModel implements IDataStatus {

    public static final String MODEL_MODEL="demo.AbstractDemoIdModel";

    @Base
    @Field.Enum
    @Field(displayName = "数据状态",defaultValue = "DISABLED",required = true,summary = "作为基类给每一个继承模型增加一个数据状态字段")
    private DataStatusEnum dataStatus;
}

图3-3-2-5 新建AbstractDemoIdModel

Step4 修改PetShop的父类

修改PetShop父类从IdMode变更为AbstractDemoIdModel

package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import java.sql.Time;

@Model.model(PetShop.MODEL_MODEL)
@Model(displayName = "宠物店铺",summary="宠物店铺")
public class PetShop extends AbstractDemoIdModel {
    public static final String MODEL_MODEL="demo.PetShop";

    @Field(displayName = "店铺名称",required = true)
    private String shopName;

    @Field(displayName = "开店时间",required = true)
    private Time openTime;

    @Field(displayName = "闭店时间",required = true)
    private Time closeTime;
}

图3-3-2-6 修改PetShop的父类

重启看效果

宠物商店的列表页面和修改页面都增加数据状态字段,如下图3-3-2-7及3-3-2-8所示:

3.3.2 模型的类型

图3-3-2-7 宠物商店列表页增加数据状态字段

3.3.2 模型的类型

图3-3-2-8 宠物商店修改页增加数据状态字段

六、存储模型

存储模型用于定义数据表结构和数据的增删改查(数据管理器)功能,是直接与连接器进行交互的数据容器。

PetShop就是一个存储模型,这里就不过多举例子介绍了

七、代理模型(举例)

代理模型是用于代理存储模型的数据管理器能力,同时又可以扩展出非存储数据信息的交互功能的模型。

如果我们PetShop模型要展示创建人昵称?那么就可以建一个PetShopProxy类来完成,代理模型增加的字段都是非存储字段,只用于交互包括展示或提交

Step1 引入PamirsUser类

pamirs-demo-api的pom.xml包增加依赖,便于引入PamirsUser类。

<dependency>
    <groupId>pro.shushi.pamirs.core</groupId>
    <artifactId>pamirs-user-api</artifactId>
</dependency>

图3-3-2-9 引入基础类库user

Step2 新建PetShopProxy模型

新建一个PetShopProxy类继承PetShop,并声明类型为PROXY。同时增加一个creater字段

package pro.shushi.pamirs.demo.api.proxy;

import pro.shushi.pamirs.demo.api.model.PetShop;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.enmu.ModelTypeEnum;
import pro.shushi.pamirs.user.api.model.PamirsUser;

@Model.model(PetShopProxy.MODEL_MODEL)
@Model.Advanced(type = ModelTypeEnum.PROXY)
@Model(displayName = "宠物店铺代理模型",summary="宠物店铺代理模型")
public class PetShopProxy extends PetShop {

    public static final String MODEL_MODEL="demo.PetShopProxy";

    @Field.many2one
    @Field(displayName = "创建者",required = true)
    @Field.Relation(relationFields = {"createUid"},referenceFields = {"id"})
    private PamirsUser creater;
}

图3-3-2-10 新建PetShopProxy模型

Step3 修改DemoModule

PamirsUser模型隶属于UserModule。为DemoModule增加UserModule的依赖注解,同时修改DemoModule的homepage注解,默认进入PetShopProxy的管理页面

package pro.shushi.pamirs.demo.api;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.boot.base.ux.annotation.action.UxRoute;
import pro.shushi.pamirs.boot.base.ux.annotation.navigator.UxHomepage;
import pro.shushi.pamirs.core.common.CommonModule;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxy;
import pro.shushi.pamirs.meta.annotation.Module;
import pro.shushi.pamirs.meta.base.PamirsModule;
import pro.shushi.pamirs.meta.common.constants.ModuleConstants;
import pro.shushi.pamirs.user.api.UserModule;

@Component
@Module(
        name = DemoModule.MODULE_NAME,
        displayName = "oinoneDemo工程",
        version = "1.0.0",
        dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE, UserModule.MODULE_MODULE})
@Module.module(DemoModule.MODULE_MODULE)
@Module.Advanced(selfBuilt = true, application = true)
@UxHomepage(@UxRoute(PetShopProxy.MODEL_MODEL))
public class DemoModule implements PamirsModule {

    public static final String MODULE_MODULE = "demo_core";
    public static final String MODULE_NAME = "DemoCore";

    @Override
    public String[] packagePrefix() {
        return new String[]{ "pro.shushi.pamirs.demo"};
    }
} 

图3-3-2-11 定义模块依赖及修改首页入口

Step4 新增PetShopProxyAction类

为了展示效果覆盖PetShopProxy默认从PetShop继承的数据管理器方法,但对于Action和Function这些这里不展开介绍,具体会3.4【oinone以函数为内在】和3.5【oinone以交互为外在】两章中介绍。

  1. 新建一个PetShopProxyAction类,Model.model设置为PetShopProxy,也就是把所有aciton和function都挂在PetShopProxy这个模型载体上

  2. PetShopProxyAction继承DataStatusBehavior类配套dataStatus使用,定义一个【启用】serverAction,而启用逻辑则复用父类DataStatusBehavior的dataStatusEnable方法。

  3. 覆盖【queryPage】Function,该方法名为前后约定协议中列表查询的默认方法

package pro.shushi.pamirs.demo.core.action;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.core.common.behavior.impl.DataStatusBehavior;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxy;
import pro.shushi.pamirs.meta.annotation.Action;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.api.dto.condition.Pagination;
import pro.shushi.pamirs.meta.api.dto.wrapper.IWrapper;
import pro.shushi.pamirs.meta.constant.FunctionConstants;
import pro.shushi.pamirs.meta.enmu.FunctionOpenEnum;
import pro.shushi.pamirs.meta.enmu.FunctionTypeEnum;

@Model.model(PetShopProxy.MODEL_MODEL)
@Component
public class PetShopProxyAction extends DataStatusBehavior<PetShopProxy> {

    @Override
    protected PetShopProxy fetchData(PetShopProxy data) {
        return data.queryById();
    }
    @Action(displayName = "启用")
    public PetShopProxy dataStatusEnable(PetShopProxy data){
        data = super.dataStatusEnable(data);
        data.updateById();
        return data;
    }

    @Function.Advanced(type= FunctionTypeEnum.QUERY)
    @Function.fun(FunctionConstants.queryPage)
    @Function(openLevel = {FunctionOpenEnum.API})
    public Pagination<PetShopProxy> queryPage(Pagination<PetShopProxy> page, IWrapper<PetShopProxy> queryWrapper){
        Pagination<PetShopProxy> result = new PetShopProxy().queryPage(page,queryWrapper);
        new PetShopProxy().listFieldQuery(result.getContent(),PetShopProxy::getCreater);
        return result;
    }

}

图3-3-2-12 新增PetShopProxyAction类

Step5 重启看效果

宠物商店的列表页面和修改页面都增加数据状态字段,如下图3-3-24所示:

3.3.2 模型的类型

图3-3-2-13 宠物商店页面效果

多次点击启用会报对应的错误。当然如果场景不需要,则没有必要复用DataStatusBehavior逻辑,也就不需要实现IDataStatus接口了,启动按钮只在禁用状态展示在后续的教程中会学到

3.3.2 模型的类型

图3-3-2-14 启用操作效果

八、传输模型(举例)

由于传输模型没有默认的数据管理器,只有数据构造器,所以在不自定义动作的情况下,传输模型可以打开详情页、新增表单和修改表单和列表页,但是所有的动作全部为窗口动作。传输模型本身不会存储,如果是关联关系字段关联传输模型,可以将传输模型序列化存储在模型的关联关系字段上。因为没有数据管理器,所以传输模型的列表页没有分页能力。

场景举例:如果我们想批量修改PetShop的数据状态,那么我们需要在列表页选中数据记录点击【批量修改】跳转到一个批量修改页面,选择要修改的数据状态,并点确认提交。那么传输模型就可以承载批量修改页面、数据以及操作的载体模型。

Step1 新建PetShopBatchUpdate模型

新建一个PetShopBatchUpdate类继承TransientModel,同时增加petShopList和dataStatus字段用于接收页面传值

package pro.shushi.pamirs.demo.api.tmodel;

import pro.shushi.pamirs.core.common.enmu.DataStatusEnum;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxy;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.base.TransientModel;

import java.util.List;

@Model.model(PetShopBatchUpdate.MODEL_MODEL)
@Model(displayName = "批量修改宠物商店数据状态",summary = "批量修改宠物商店数据状态")
public class PetShopBatchUpdate extends TransientModel {
    public static final String MODEL_MODEL="demo.PetShopBatchUpdate";

    @Field(displayName = "数据状态",required = true)
    private DataStatusEnum dataStatus;

    @Field(displayName = "宠物商店列表",required = true)
    @Field.many2many
    private List<PetShopProxy> petShopList;
}

图3-3-2-15 新建PetShopBatchUpdate模型

Step2 新增PetShopBatchUpdateAction类

传输模型没有默认的数据管理器,只有数据构造器(construct)。

  1. 新建一个PetShopBatchUpdateAction类,Model.model设置为PetShopBatchUpdate,也就是把所有Aciton和Function都挂在PetShopBatchUpdateAction这个模型载体上

  2. 覆盖数据构造器(construct),接收从宠物商店列表多选带过来的数据参数,非PetShopBatchUpdate本模型参数不能放第一个,用List petShopList来接收,进行数据组装逻辑处理,对应数据也是由PetShopBatchUpdate来承载返回给PetShopBatchUpdate的Form编辑页。

  3. 定义一个【确定】serverAction,绑定PetShopBatchUpdate的Form编辑页。点击确定则批量修改Form页面中的宠物商店列表为指定的数据状态

package pro.shushi.pamirs.demo.core.action;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxy;
import pro.shushi.pamirs.demo.api.tmodel.PetShopBatchUpdate;
import pro.shushi.pamirs.meta.annotation.Action;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.enmu.ActionContextTypeEnum;
import pro.shushi.pamirs.meta.enmu.FunctionOpenEnum;
import pro.shushi.pamirs.meta.enmu.FunctionTypeEnum;
import pro.shushi.pamirs.meta.enmu.ViewTypeEnum;

import java.util.List;

@Model.model(PetShopBatchUpdate.MODEL_MODEL)
@Component
public class PetShopBatchUpdateAction {

    @Function(openLevel = FunctionOpenEnum.API)
    @Function.Advanced(type= FunctionTypeEnum.QUERY)
    public PetShopBatchUpdate construct(PetShopBatchUpdate petShopBatchUpdate, List<PetShopProxy> petShopList){
        PetShopBatchUpdate result = new PetShopBatchUpdate();
        //前端传递只有id,补全下数据
        petShopList = FetchUtil.fetchList(petShopList);
        //补全创建者字段
        new PetShopProxy().listFieldQuery(petShopList,PetShopProxy::getCreater);
        result.setPetShopList(petShopList);
        return result;
    }

    @Action(displayName = "确定",bindingType = ViewTypeEnum.FORM,contextType = ActionContextTypeEnum.SINGLE)
    public PetShopBatchUpdate conform(PetShopBatchUpdate data){
        List<PetShopProxy> proxyList = data.getPetShopList();
        for(PetShopProxy petShopProxy:proxyList){
            petShopProxy.setDataStatus(data.getDataStatus());
        }
        new PetShopProxy().updateBatch(proxyList);
        return data;
    }
}

图3-3-2-16 新建PetShopBatchUpdateAction类

Step3 注解式初始化ViewAction窗口动作

在PetShopProxyAction增加类注解,并注释掉DemoModuleMetaDataEditor的viewActionInit方法体代码。用UxRouteButton注解来申明一个ViewAction。更多Ux系列注解详见3.5.4【Ux注解详解】一文

  1. @Model.model(PetShopProxy.MODEL_MODEL),代表UxRouteButton申明viewAction所在模型

  2. @UxRoute.model代表viewAction的resModel,路由的目标模型

@Model.model(PetShopProxy.MODEL_MODEL)
@UxRouteButton(action = @UxAction(name = "demo_petShop_batch_update", label = "批量更新数据状态",contextType = ActionContextTypeEnum.SINGLE_AND_BATCH), value = @UxRoute(model = PetShopBatchUpdate.MODEL_MODEL, viewType = ViewTypeEnum.FORM,openType = ActionTargetEnum.DIALOG,viewName= ViewConstants.Name.formView))
@Component
public class PetShopProxyAction extends DataStatusBehavior<PetShopProxy> {}

图3-3-2-17 在PetShopProxyAction增加类注解

Step4 重启看效果

3.3.2 模型的类型

图3-3-2-18 批量操作效果示意

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9233.html

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

Like (2)
史, 昂's avatar史, 昂数式管理员
Previous 2024年5月23日 am9:49
Next 2024年5月23日 am9:51

相关推荐

  • 4.2.8 自定义组件与设计器结合(新)

    界面设计器组件管理页面添加组件 进入组件的元件管理页面 点击“添加元件” 设计元件的属性 这里以是否“显示清除按钮”作为自定义属性从左侧拖入到中间设计区域,然后发布 点击“返回组件” 鼠标悬浮到卡片的更多按钮的图标,弹出下拉弹出“低无一体”的按钮 在弹窗内点击“生成SDK”的按钮 生成完成后,点击“下载模板工程” 解压模板工程kunlun-sdk.zip 解压后先查看README.MD,了解一下工程运行要点,可以先运行 npm i 安装依赖 再看kunlun-plugin目录下已经有生成好的组件对应的ts和vue文件 下面在vue文件内增加自定义代码,可以运行 npm run dev 在开发模式下调试看效果 <template> <div class="my-form-string-input"> <oio-input :value="realValue" @update:value="change" > <template #prepend>MyPrepend</template> </oio-input> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue'; import { OioInput } from '@kunlun/vue-ui-antd'; export default defineComponent({ name: 'customField1', components: { OioInput }, props: { value: { type: String }, change: { type: Function }, }, setup(props) { const realValue = ref<string | null | undefined>(props.value); return { realValue }; } }); </script> <style lang="scss"> .my-form-string-input { border: 1px solid red; } </style> 确定改好代码后运行 npm run build,生成上传所需的js和css文件 可以看到 kunlun-plugin目录下多出了dist目录,我们需要的是 kunlun-plugin.umd.js 和 kunlun-plugin.css 这2个文件 再次回到组件的“低无一体”管理弹窗页面,上传上面生成的js和css文件,并点击“确定”保存,到这里我们的组件就新增完成了。 下面我们再到页面设计器的页面中使用上面设计的组件(这里的表单页面是提前准备好的,这里就不介绍如何新建表单页面了) 将左侧组件库拉直最底部,可以看到刚刚新建的组件,将其拖至中间设计区域,我们可以看到自定义组件的展示结果跟刚刚的代码是对应上的(ps: 如果样式未生效,请刷新页面查看,因为刚刚上传的js和css文件在页面初始加载的时候才会导入进来,刚刚上传的动作未导入新上传的代码文件),再次点击设计区域中的自定义组件,可以看到右侧属性设置面板也出现了元件设计时拖入的属性。 最后再去运行时的页面查看效果,与代码逻辑一致!

    2024年5月23日
    1.5K00
  • 自定义组件

    1. 定义组件介绍 平台提供了大多数的通用组件,面对企业个性话需求、复杂的业务场景,我们也提供了自定义组件的能力,帮助企业更快实施业务需求。 自定义组件包含“组件画廊”“组件排序”“元件画廊”“元件属性设计”四个页面。 1.1 组件与元件 在介绍如何自定义组件前,需要先了解以下概念: 组件:页面设计的组件库中看到的是组件。每个组件都有自己的属性面板,通过属性、字段决定组件逻辑,而自定义组件就是需要构建出组件自身的属性信息,再结合业务配置组件的属性、使用组件。 一个组件在不同的业务类型、视图类型、单值/多值,其属性面板是不同的,不同业务类型、视图类型、单值/多值的组合我们成为元件,多种组合即为多个元件,所以一个组件包括多个元件。 元件:一个组件可以对应多个元件。在创建时明确元件所适用的字段业务类型、单/多值、视图类型,在画布中切换元件时,会结合当前组件的字段业务类型、单/多值、所在视图类型确定可以使用哪一个元件。 此处切换的也是元件。 示例:创建一个“下拉选”的组件,其中可以包含“下拉单选”“下拉多选”两个元件。“下拉选”组件从组件库中拖入时,设置单值时使用“下拉单选”元件,设置多值时使用“下拉多选”元件。 2. 组件管理 2.1 组件创建 在组件画廊页面,点击添加组件,在弹窗中完善信息创建组件。 2.2 组件操作 自定义组件支持“搜索、删除、作废、查看引用关系、管理元件、编辑、低无一体、排序”的操作。 搜索:默认搜索可见组件,可切换“全部、可用、废弃”搜索组件,也可使用组件名称搜索。 删除:若组件未被引用,则可以直接删除。 作废:组件作废后,不可在画布中展示,不可在组件切换时使用,但已使用的数据不影响。 查看引用关系:可以查看存在引用关系的页面,支持点击跳转到对应页面的设计页面。仅当组件无引用关系时才支持删除。 管理元件:点击进入元件的管理页面。 编辑:可修改组件名称、组件图表、组件描述。 低无一体:比较复杂,在第5章中单独讲解。 排序:进入排序页,可拖动排序自定义组件。自定义组件会插在系统组件之后。可以点击“查看排序结果”选项页查看最终排序结果。排序同样会更新画布中的组件库顺序。 3. 元件管理 3.1 元件创建 在元件画廊页面,点击添加元件,在弹窗中完善信息创建一个元件。 3.2 元件操作 元件支持“删除、作废、查看引用关系、编辑、设计元件属性”的操作。 删除:若元件未被引用,则可以直接删除。 作废:元件作废后,不影响原来已使用的元件,无法新添加、使用该元件。 查看引用关系:可以查看存在引用关系的页面,支持点击跳转到对应页面的设计页面。仅当元件无引用关系时才支持删除。此处的引用关系数量会小于等于组件引用关系的数量。 编辑:可修改元件名称、支持视图类型、元件描述。 设计元件属性:比较复杂,将在第4章中单独讲解。 4. 设计元件属性 元件属性设计页面主要操作集中在这三部分,分别是①视图切换②属性面板设计区③复制功能 视图切换:元件创建时选择的支持视图类型,在①区域平铺可切换对应视图的属性面板进行设计。 属性面板设计区:可将组件拖入属性面板设计区进行设计,设计的是自定义组件的属性面板,左侧组件库和页面设计的组件库相同,仍然支持创建字段或使用模型字段,右侧进行元数据面板、属性面板设置。 复制功能:可将已设置好的属性面板复制到其他视图,提高设计效率。 5. 低无一体 低无一体简单讲就是组件代码上传,通过载入代码使组件在设计页面和实现页面可见和交互。 系统内置的属性不满足需求时,要用低无一体写代码,定制属性,比如从模型中拖拽设计就是内置的属性,从组件库中设置,就要配合低无一体,否则无效。 首次进入组件设计或组件中的元件变更时需要生成SDK。 生成结束后展示SDK生成时间,并且“下载模版工程”按钮可用。 点击下载模版工程,会自动下载模板工程。 在模版工程中编写前端代码。 根据实际需求上传JS、CSS文件后提交即可。

    2024年6月20日
    2.2K00
  • 6.5 权限体系(改)

    做好企业级软件,首先得过权限这一关 在企业的IT部门沟通中,权限是避免不了。自嘲下在我们刚出来创业时,为了收获客户对我们技术能力的信任,每每与跟客户沟通时都会说我们是阿里出来的,但在权限设计这个环节不那么灵验,反而被打上了不懂B端权限设计的标签,会问很多问题。我就很奇怪难道大厂就没有内部管理系统了?大厂只有C端交易,没有B端交易?但从侧面说明权限不简单还特别重要。做好企业级软件,首先得过权限这一关。 整体介绍 对于平台运行来说,权限是必须,但我们的auth模块不是必须的,auth模块只是我们提供的一种默认实现,客户可以根据平台的spi机制进行替换。auth模块利用了平台的Hook特性做到与业务无关,在我们开发上层应用的时,是不用感知它的存在的。 auth模块涉及:功能权限、数据权限 数据权限:行权限和列权限。备注:数据权限的控制只能用于【存储模型】 表级权限:表达的语义是:是否该表可读/写(修改和新增) 列权限:表达的语义是:是否该列可读/写(修改和新增) 行权限:表达的语义是:是否对该行可读/写(修改)/删除 功能权限:表达的语义是ServerAction/Function是否可执行/展示,viewAction是否可展示,菜单是否可以显示 范围说明: 配置多个权限项的时候,取并集 配置多个角色的时候,取并集 模型设计 产品体验 Step1 创建角色 通过App Finder 切换至【权限】应用,点击新增按钮创建一个名为oinone的角色 Step2 创建数据权限项 在【权限项列表】菜单,点击【创建】按钮新增一个名为【宠物达人数据权限项】,同时宠物达人的数据权限设置为只能查看性别为男的记录 配置说明: 名称: 代表该项配置的权限的名字(必填)(必须是全系统唯一) 权限模型: 选择需要拦截的数据所在的表,即为模型,可以搜索使用 描述:对该权限项的描述 权限条件的配置: 满足全部:对条件一和条件二要同时满足的数据才能被看见 满足任一:对条件一和条件二要任意满足的数据都能被看见 读权限:对该数据是否有读取的权限 写权限:对该数据是否有修改的权限 删除权限:对该条件内的数据是否有删除的权限 Step3 为角色配置权限 编辑oinone角色,只开通oinoneDemo工程应用 选中【数据权限】选项卡点击【添加】按钮,勾选宠物达人数据权限项点击【确定】按钮 整体点击保存,回到列表页记得点击【权限生效】按钮 Step4 新建用户绑定角色 切换到用户中心模块,点击【创建】按钮填写必要信息,并在角色选中oinone权限组。 退出admin用户,用oinone登陆,权限效果: 只能看见demo模块 oinone登陆只能看到性别为男的宠物达人记录 admin用户登陆 oinone用户登陆 因为宠物达人的页面没有把性别字段放出来,我们看下数据库数据 auth模块扩展 在日常项目开发中,难免会碰到一些针对权限管理的特殊需求,或是为提升性能做的特殊逻辑。接下来我给大家介绍auth模块扩展性。 权限全局配置 对所有权限角色都做限制,而且不想让用户感知,可以实现PermissionFunApi接口,API接口实现的配置方式【只能用于支持全局的数据权限配置】 实现接口PermissionFunApi 将实现托管给SpringAOP 接口的具体实现看下图的代码 package pro.shushi.pamirs.demo.core.service; import org.springframework.stereotype.Component; import pro.shushi.pamirs.auth.api.service.PermissionFunApi; import pro.shushi.pamirs.demo.api.model.PetTalent; @Component public class PetTalentPermissionFunApi implements PermissionFunApi { @Override public String permissionDomain(Object… args) { //获取当前组织中 return "name == '张学友'"; } @Override public String nameSpace() { return PetTalent.MODEL_MODEL; } } 不参与权限控制 如果某一接口不想做权限控制,则可以在启动工程的application-dev.yml文件中配置不需要权限过滤的接口 pamirs: auth: fun-filter: – namespace: demo.PetTalent fun: queryPage 换一个没有配置宠物达人权限的用户(除管理员以外)进入系统,则也可以看到数据。注意【权限全局控制】还是生效的 API 1. 获取当前用户对该模型的行权限 Result<String> result = CommonApiFactory.getApi(AuthApi.class).canReadAccessData("Model"); 返回值为 { 'data':"name=in=('hahaha')" 'success':true … } 用法 : 场景:前端发起的请求都会经过权限拦截,后端代码逻辑发起的数据请求都是不经过任何权限的过滤,但是某些特殊情况需要在后端代码逻辑发起的数据请求也带上权限过滤 入参:请求的模型 出参:Result 数据结构中data会存储一段字符串,该字符串为Rsql 将该Rsql追加到wrapper中 Result<String> result = CommonApiFactory.getApi(AuthApi.class).canReadAccessData("base.UeModule"); String data=result.getData(); QueryWrapper<UeModule> wrapper = Pops.query(); wrapper.setEntity(ueModule); if (!StringUtils.isBlank(data)) { wrapper.apply(data); }

    2024年5月23日
    1.9K00

Leave a Reply

Please Login to Comment