3.3.9 字段类型之关系与引用

有关系与引用类型才让oinone具备完整的描述模型与模型间关系的能力

在PetShop以及其代理模型中已经上用到了O2M、M2O字段,分别如petItems(PetItem)和create(PamrisUser)字段,但是没有过多的讲解。本文重点举例RELATED、M2M、O2M,至于M2O留给大家自行尝试。

一、引用类型(举例)

业务类型 Java类型 数据库类型 规则说明
RELATED 基本类型或关系类型 不存储或varchar、text 引用字段【数据库规则】:点表达式最后一级对应的字段类型;数据库字段值默认为Java字段的序列化值,默认使用JSON序列化【前端交互规则】:点表达式最后一级对应的字段控件类型

表3-3-9-1 字段引用类型

Step1 修改PetShopProxy类

  1. 为PetShopProxy类新增一个引用字段relatedShopName,并加上@Field.Related("shopName")注解

  2. 为PetShopProxy类新增一个引用字段createrId,并加上@Field.Related({"creater","id"})注解

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;

    @Field.Related("shopName")
    @Field(displayName = "引用字段shopName")
    private String relatedShopName;

    @Field.Related({"creater","id"})
    @Field(displayName = "引用创建者Id")
    private String createrId;

}

图3-3-9-1 修改PetShopProxy类

Step2 重启系统查看效果

我们发现商店管理-列表页面多出了两个有值字段:引用字段shopName和引用创建者Id

1711608487971-8e48aebc-e6c3-4143-a95d-ca649dfdee8f图3-3-9-2 商店管理-列表页面新增两个有值字段

二、关系类型

业务类型 Java类型 数据库类型 规则说明
O2O 模型/DataMap 不存储或varchar、text 一对一关系
M2O 模型/DataMap 不存储或varchar、text 多对一关系
O2M List<模型/DataMap> 不存储或varchar、text 一对多关系
M2M List<模型/DataMap> 不存储或varchar、text 多对多关系

表3-3-9-2 字段关系类型

多值字段或者关系字段需要存储,默认使用JSON格式序列化。多值字段数据库字段类型默认为varchar(1024);关系字段数据库字段类型默认为text。

关系字段

关联关系用于描述模型间的关联方式:

  • 多对一关系,主要用于明确从属关系
  • 一对多关系,主要用于明确从属关系
  • 多对多关系,主要用于弱依赖关系的处理,提供中间模型进行关联关系的操作
  • 一对一关系,主要用于多表继承和行内合并数据

3.3.9 字段类型之关系与引用

图3-3-9-3 字段关联关系

名词解释

关联关系比较重要的名词解释如下:

  • 关联关系:使用relation表示,模型间的关联方式的一种描述,包括关联关系类型、关联关系双边的模型和关联关系的读写
  • 关联关系字段:业务类型ttype为O2O、O2M、M2O或M2M的字段
  • 关联模型:使用references表示,自身模型关联的模型
  • 关联字段:使用referenceFields表示,关联模型的字段,表示关联模型的哪些字段与自身模型的哪些字段建立关系
  • 关系模型:自身模型
  • 关系字段:使用relationFields表示,自身模型的字段,表示自身模型的哪些字段与关联模型的哪些字段建立关系
  • 中间模型,使用through表示,只有多对多存在中间模型,模型的relationship=true

举例M2M关系类型

多对多关系,主要用于弱依赖关系的处理,提供中间模型进行关联关系的操作。这也是在业务开发中很常见用于描述单据间关系,该例子会举例两种方式描述多对多关系中间表,一是中间表没有在系统显示定义模型,二种是中间表显示定义模型。第一种往往仅是维护多对多关系,第二种往往用于多对多关系中间表自身也需要管理有业务含义,中间表模型还经常额外增加其他字段。

一是中间表没有在系统显示定义模型:如果出现跨模块的场景,在分布式环境下两个模块独立启动,有可能会导致系统关系表被删除的情况发生,因为没有显示定义中间表模型,中间表的模型所属模块会根据两边模型的名称计算,如果刚好被计算到非关系字段所属模型的模块。那么单独启动非关系字段所属模型的模块,则会导致删除关系表。

为什么不直接把中间表的模型所属模块设置为关系字段所属模型的模块?因为如果这样做,当模型两边都定义了多对多关系字段则会导致M2M关系表的所属模块出现混乱。

所以这里建议大家都选用:第二种中间表显示定义模型,不论扩展性还是适应性都会好很多。请用:through=XXXRelationModel.MODEL_MODEL 或者 throughClass=XXXRelationModel.class

Step1 新建宠物达人模型,并分别为宠物商品和宠物商店增加

到宠物达人模型的字段

  1. 新建宠物达人模型PetTalent
package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;

@Model.model(PetTalent.MODEL_MODEL)
@Model(displayName = "宠物达人",summary="宠物达人",labelFields ={"name"})
public class PetTalent extends AbstractDemoIdModel{
    public static final String MODEL_MODEL="demo.PetTalent";

    @Field(displayName = "达人")
    private String name;

}

图3-3-9-4 新建宠物达人模型PetTalent

  1. 修改宠物商品模型,新增many2many字段petTalents,类型为List ,并加上注解@Field.many2many(relationFields = {"petItemId"},referenceFields = {"petTalentId"},through = PetItemRelPetTalent.MODEL_MODEL),through为指定关联中间表。
package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.demo.api.tmodel.PetItemDetail;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.enmu.NullableBoolEnum;

import java.math.BigDecimal;
import java.util.List;

@Model.model(PetItem.MODEL_MODEL)
@Model(displayName = "宠物商品",summary="宠物商品",labelFields = {"itemName"})
public class PetItem  extends AbstractDemoCodeModel{

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

    @Field(displayName = "商品名称",required = true)
    private String itemName;

    @Field(displayName = "商品价格",required = true)
    private BigDecimal price;

    @Field(displayName = "店铺",required = true)
    @Field.Relation(relationFields = {"shopId"},referenceFields = {"id"})
    private PetShop shop;

    @Field(displayName = "店铺Id",invisible = true)
    private Long shopId;

    @Field(displayName = "品种")
    @Field.many2one
    @Field.Relation(relationFields = {"typeId"},referenceFields = {"id"})
    private PetType type;

    @Field(displayName = "品种类型",invisible = true)
    private Long typeId;

    @Field(displayName = "详情", serialize = Field.serialize.JSON, store = NullableBoolEnum.TRUE)
    @Field.Advanced(columnDefinition = "varchar(1024)")
    private List<PetItemDetail> petItemDetails;

    @Field(displayName = "商品标签",serialize = Field.serialize.COMMA,store = NullableBoolEnum.TRUE,multi = true)
    @Field.Advanced(columnDefinition = "varchar(1024)")
    private List<String> tags;

    @Field.many2many(relationFields = {"petItemId"},referenceFields = {"petTalentId"},through = PetItemRelPetTalent.MODEL_MODEL)
    @Field(displayName = "推荐达人",summary = "推荐该商品的达人们")
    private List<PetTalent> petTalents;

}

图3-3-9-5 修改宠物商品模型

  1. 修改宠物商店模型

    a. 新增many2many关联模型PetShopRelPetTalent并继承BaseRelation,BaseRelation为关系模型抽象基类用于承载多对多关系,是多对多关系的中间模型,数据模型主键可以不是ID。更多类似抽象基类详见3.3.2【模型的类型】一文中关于模型快捷继承相关内容。

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

import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.base.BaseRelation;

@Model.model(PetShopRelPetTalent.MODEL_MODEL)
@Model(displayName = "宠物店铺与达人关联表",summary="宠物店铺与达人关联表")
public class PetShopRelPetTalent extends BaseRelation {

    public static final String MODEL_MODEL="demo.PetShopRelPetTalent";
    @Field(displayName = "店铺Id")
    private Long petShopId;

    @Field(displayName = "达人Id")
    private Long petTalentId;

}

图3-3-9-6 新增many2many关联模型PetShopRelPetTalent

b. 修改宠物商店模型,新增many2many字段petTalents,类型为List ,并加上注解@Field.many2many(relationFields = {"petShopId"},referenceFields = {"petTalentId"},throughClass =PetShopRelPetTalent.class) ,throughClass为指定关联模型类

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

import pro.shushi.pamirs.core.common.enmu.DataStatusEnum;
import pro.shushi.pamirs.demo.api.enumeration.PetShopOptionEnum;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.enmu.DateFormatEnum;
import pro.shushi.pamirs.meta.enmu.DateTypeEnum;

import java.math.BigDecimal;
import java.sql.Time;
import java.util.Date;
import java.util.List;

@Model.model(PetShop.MODEL_MODEL)
@Model(displayName = "宠物店铺",summary="宠物店铺",labelFields ={"shopName"} )
@Model.Code(sequence = "DATE_ORDERLY_SEQ",prefix = "P",size=6,step=1,initial = 10000,format = "yyyyMMdd")
public class PetShop extends AbstractDemoIdModel {
    public static final String MODEL_MODEL="demo.PetShop";

    @Field(displayName = "店铺编码")
    private String code;

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

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

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

    @Field.Enum
    @Field(displayName = "数据状态",defaultValue = "DISABLED",required = true,summary = "枚举可选项举例")
    private DataStatusEnum dataStatus;

    @Field(displayName = "店铺标志")
    private List<PetShopOptionEnum> options;

    @Field(displayName = "一年内新店")
    private Boolean oneYear;

    @Field.Float
    @Field(displayName = "店内员工平均年龄")
    private BigDecimal averageAge;

    @Field.Text
    @Field(displayName = "描述")
    private String description;

    @Field.Html
    @Field(displayName = "html描述")
    private String descHtml;

    @Field.Date(type = DateTypeEnum.DATE,format = DateFormatEnum.DATE)
    @Field(displayName = "店庆")
    private Date anniversary;

//    前端未提供默认支持,演示不了。这个留在我们自定义前端页面时演示
//    @Field.Date(type = DateTypeEnum.YEAR,format = DateFormatEnum.YEAR)
//    @Field(displayName = "开店年份")
//    private Date shopYear;

    @Field.Money
    @Field(displayName = "收入",priority = 1)
    private BigDecimal income;

    @Field.many2many(relationFields = {"petShopId"},referenceFields = {"petTalentId"},throughClass =PetShopRelPetTalent.class)
    @Field(displayName = "推荐达人",summary = "推荐该商品的达人们")
    private List<PetTalent> petTalents;

}

图3-3-9-7 新增many2many字段petTalents

Step2 重启看效果

  1. 进入宠物商品-编辑页面,可以看到多了推荐达人字段,点击添加选择达人记录。至于达人数据管理这里就不赘述了,只要为达人模型配一个菜单入口进去新增就好了

3.3.9 字段类型之关系与引用

图3-3-9-8 新增many2many字段petTalents

  1. 进入宠物商品-列表页面,就可以看到达人字段所选的记录

3.3.9 字段类型之关系与引用

图3-3-9-9 进入宠物商品-列表页面

  1. 宠物商店的效果参考宠狗商品的编辑路径

  2. 查看数据库表,对应的表和字段都已经生成了

3.3.9 字段类型之关系与引用

图3-3-9-10 数据库表对应的表和字段都已生成

举例O2M

O2M跟M2O和M2M不一样,O2M的交互方式新建关联模型记录并一把提交,而M2O和M2M而是通过添加方式选择已有关联模型记录。

Step1 把PetShopProxyA的items字段提取到父类PetShop中去

为什么要把PetShopProxyA的items提取到PetShop中去呢?因为代理模型新增的字段都是非存储字段,如果需要保存需要自己覆盖模型的create和update方法手工保存关联对象。这个在3.3.2【模型的类型】一文中关于代理模型的内容中有详细介绍,大家忘了可以去温习下。

  1. 去除PetShopProxyA的items字段
package pro.shushi.pamirs.demo.api.proxy;

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

@Model.model(PetShopProxyA.MODEL_MODEL)
@Model.Advanced(type = ModelTypeEnum.PROXY)
@Model(displayName = "宠物店铺代理模型A",summary="宠物店铺代理模型A")
public class PetShopProxyA extends PetShop {
    public static final String MODEL_MODEL="demo.PetShopProxyA";

}

图3-3-9-11 去除PetShopProxyA的items字段

  1. 在PetShop中增加items字段
package pro.shushi.pamirs.demo.api.model;

import pro.shushi.pamirs.core.common.enmu.DataStatusEnum;
import pro.shushi.pamirs.demo.api.enumeration.PetShopOptionEnum;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.enmu.DateFormatEnum;
import pro.shushi.pamirs.meta.enmu.DateTypeEnum;

import java.math.BigDecimal;
import java.sql.Time;
import java.util.Date;
import java.util.List;

@Model.model(PetShop.MODEL_MODEL)
    @Model(displayName = "宠物店铺",summary="宠物店铺",labelFields ={"shopName"} )
    @Model.Code(sequence = "DATE_ORDERLY_SEQ",prefix = "P",size=6,step=1,initial = 10000,format = "yyyyMMdd")
    public class PetShop extends AbstractDemoIdModel {
        public static final String MODEL_MODEL="demo.PetShop";

        @Field(displayName = "店铺编码")
        private String code;

        @Field(displayName = "店铺编码2")
        @Field.Sequence(sequence = "DATE_ORDERLY_SEQ",prefix = "C",size=6,step=1,initial = 10000,format = "yyyyMMdd")
        private String codeTwo;

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

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

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

        @Field.Enum
        @Field(displayName = "数据状态",defaultValue = "DRAFT",required = true,summary = "枚举可选项举例")
        private DataStatusEnum dataStatus;

        @Field(displayName = "店铺标志")
        private List<PetShopOptionEnum> options;

        @Field(displayName = "一年内新店")
        private Boolean oneYear;

        @Field.Float
        @Field(displayName = "店内员工平均年龄")
        private BigDecimal averageAge;

        @Field.Text
        @Field(displayName = "描述")
        private String description;

        @Field.Html
        @Field(displayName = "html描述")
        private String descHtml;

        @Field.Date(type = DateTypeEnum.DATE,format = DateFormatEnum.DATE)
        @Field(displayName = "店庆")
        private Date anniversary;

        @Field.Date(type = DateTypeEnum.YEAR,format = DateFormatEnum.YEAR)
        @Field(displayName = "开店年份")
        private Date publishYear;

        @Field.Money
        @Field(displayName = "收入",priority = 1)
        private BigDecimal income;

        @Field.many2many(relationFields = {"petShopId"},referenceFields = {"petTalentId"},throughClass =PetShopRelPetTalent.class)
        @Field(displayName = "推荐达人",summary = "推荐该商品的达人们")
        private List<PetTalent> petTalents;

        @Field.one2many
        @Field(displayName = "商品列表")
        @Field.Relation(relationFields = {"id"},referenceFields = {"shopId"})
        private List<PetItem> items;

    }

图3-3-9-12 在PetShop中增加items字段

Step2 重启应用查看效果

前文中PetShopProxyB代理模型扩展了catItems萌猫商品列表字段,因为该字段是代理模型的非存储字段。但上一步操作中原本PetShopProxyB从PetShopProxyA继承的非存储字段items,转而变成了从PetShop继承的存储字段。那么我们试下catItems和items都添加记录的效果吧。

  1. 点击菜单商店管理B进入PetShopProxyB代理模型的管理页,选择商店记录点编辑进入商店管理B-编辑页,商品列表字段处新增两个商品分别是萌猫商品1005,宠狗商品1006;

3.3.9 字段类型之关系与引用

图3-3-9-13 示例效果图

3.3.9 字段类型之关系与引用

图3-3-9-14 示例效果图

  1. 萌猫商品列表处字段新增商品“代理模型萌猫商品1007”

3.3.9 字段类型之关系与引用

图3-3-9-15 示例效果图

3.3.9 字段类型之关系与引用

图3-3-9-16 示例效果图

  1. 保存查看商品管理页面发现商品只是创建了萌猫商品1005和宠狗商品1006,而没有代理模型萌猫商品

3.3.9 字段类型之关系与引用

图3-3-9-17 示例效果图

O2O

O2O与M2O相比,在从前端交互体验上跟M2O一样都是下拉单选,但有一个区别在于目标对象只能被一个操作对象绑定。

限制:同时模型的O2O字段关联的模型与本模型必须要在同一模块中,否则会报错。因为O2O字段需要两边对等建立关系字段

O2M,O2O字段的提交策略(该版本还未支持)

注解的onUpdate和onDelete属性指定在删除模型或更新模型关系字段值时,对关联模型进行的相应操作。操作包括RESTRICT、NO ACTION、SET NULL和CASCADE,默认值为SET NULL。

  • RESTRICT是指模型与关联模型有关联记录的情况下,引擎会阻止模型关系字段的更新或删除模型记录;

  • NO ACTION是指不作约束(这里与数据库约束的定义不相同);

  • CASCADE表示在更新模型关系字段或者删除模型时,级联更新关联模型对应记录的关联字段值或者级联删除关联模型对应记录;

  • SET NULL则是表示在更新模型关系字段或者删除模型的时候,关联模型的对应关联字段将被SET NULL(该字段值允许为null的情况下,若不允许为null,则引擎阻止对模型的操作)。

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

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

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

相关推荐

  • 5.7 商业支撑之库存域

    库存的差异会反馈到企业的整个价值链上,所以对库存的设计是至关重要的 一、基础介绍 我们先抛开仓库中对库存的实操管理和整个流通领域的库存,只围绕企业自身一级的采销链路上我们可以从管理和销售两个角度去看。 从管理角度上我们会关心:实物库存、在途库存、在产库存、库存批次等等,也就是企业有多少库存分布在哪里在什么环节。 从销售角度上我们会关心:可售库存、安全库存等等,也就是企业在特定渠道销售中库存分配规则。 在商业场景中库存管理一头对接仓库、生成、采购,另一头对接多个销售渠道。它的挑战在于不同行业不同特征商品都有比较大的差异。比如家具行业卖的是生产能力,家电区域化销售,生鲜拼车销售,服饰一仓销全国。热销的要分配提升体验防止超卖,滞销的要活动拉流量,普通的要渠道共享最大化可售。库存管理的差异会反馈到企业的整个价值链上,所以对库存的设计是至关重要的。 库存设计挑战在于: 技术上:库存类似账户账本的设计,需要能追溯库存变化的过程,且库存操作都能可追溯业务单据。热点数据的并发控制 业务上:在管理角度上游能跟仓库、采购、生产等进行对接、对账、并为其设置可售规则,下游能为各个销售渠道设置库存分配与同步规则 二、模型介绍 图5-7-1 模型介绍 核心设计逻辑: 单据链路:业务单据(外部业务单据+库存业务单据)产生库存指令(库存调整入\出库单),再由库存指令操作库存并记录库存流水。 管理链路:基础数据维护仓库、供应商、服务范围与费用。这些数据是订单履约路由和可售库存同步的基础 库存数据:对外跟商品域,通过库存指令进行操作。不同库存各自维护自身库存与流水记录,确保可追溯。 如果跟销售渠道对接,还需要扩展可售库存逻辑规则以及同步规则。比如oms类似的应用

    2024年5月23日
    1.6K00
  • 4.1 后端高级特性

    了解oinone的基础入门基本上可以胜任业务代码的开发,但对于构建一个完善的应用,作为技术专家或者架构需要考虑的方面还有很多,这章期望能给到您解答构建应用的所有所需知识,让您能成为那个可以带领小伙伴飞的人

    Oinone 7天入门到精通 2024年5月23日
    1.1K00
  • 4.2.6 框架之网络请求-拦截器

    在整个http的链路中,异常错误对前端来说尤为重要,他作用在很多不同的场景,通用的比如500, 502等; 一个好的软件通常需要在不同的错误场景中做不同的事情。当用户cookie失效时,希望能自动跳转到登录页;当用户权限发生变更时,希望能跳转到一个友好的提示页;那么如何满足这些个性化的诉求呢?接下来让我们一起了解oinone前端网络请求-拦截器。 一、入口 在src目录下main.ts中可以看到VueOioProvider,这是系统功能提供者的注册入口 图4-2-6-1 VueOioProvider import interceptor from './middleware/network-interceptor'; VueOioProvider( { http: { callback: interceptor } }, [] ); 图4-2-6-2 拦截器的申明入口 二、middleware 在项目初始化时使用CLI构建初始化前端工程,在src/middleware有拦截器的默认实现: 图4-2-6-3 在src/middleware有拦截器的默认实现 三、interceptor interceptor在请求返回后触发,interceptor有两个回调函数,error和next error参数 graphQLErrors 处理业务异常 networkError 处理网络异常 next extensions 后端返回扩展参数 const interceptor: RequestHandler = (operation, forward) => { return forward(operation).subscribe({ error: ({ graphQLErrors, networkError }) => { console.log(graphQLErrors, networkError); // 默认实现 => interceptor error }, next: ({ extensions }) => { console.log(extensions); // 默认实现 => interceptor next }, }); }; 图4-2-6-4 后端返回扩展参数 四、interceptor error // 定义错误提示等级 const DEFAULT_MESSAGE_LEVEL = ILevel.ERROR; // 错误提示等级 对应提示的报错 const MESSAGE_LEVEL_MAP = { [ILevel.ERROR]: [ILevel.ERROR], [ILevel.WARN]: [ILevel.ERROR, ILevel.WARN], [ILevel.INFO]: [ILevel.ERROR, ILevel.WARN, ILevel.INFO], [ILevel.SUCCESS]: [ILevel.ERROR, ILevel.WARN, ILevel.INFO, ILevel.SUCCESS], [ILevel.DEBUG]: [ILevel.ERROR, ILevel.WARN, ILevel.INFO, ILevel.SUCCESS, ILevel.DEBUG] }; // 错误提示通用函数 const notificationMsg = (type: string = 'error', tip: string = '错误', desc: string = '') => { notification[type]({ message: tip, description: desc }); }; // 根据错误等级 返回错误提示和类型 const getMsgInfoByLevel = (level: ILevel) => { let notificationType = 'info'; let notificationText = translate('kunlun.common.info'); switch (level) { case ILevel.DEBUG: notificationType = 'info'; notificationText = translate('kunlun.common.debug'); break; case ILevel.INFO: notificationType = 'info'; notificationText = translate('kunlun.common.info'); break;…

    2024年5月23日
    1.5K00
  • 文件

    文件应用下包含“导入/导出模版、导入任务、导出任务”三个菜单。其中导入/导出任务菜单比较常用。 导入/导出模版 当前版本会为租户的表格视图自动创建导出模版,此处可进行编辑、查看详情的操作。 导入任务 导入任务可以下载导入文档,点击详情可以查看该条记录的导入结果,任务信息分组中可以查看错误信息。 导出任务 和导入任务一致,导出任务菜单中可以下载导出文档,点击详情可以查看该条记录的导出结果,任务信息分组中可以查看错误信息。

    2024年6月20日
    1.2K00
  • 3.5.7.2 自定义母版

    母版是什么 在业务系统中,母版是一种全局通用的组件,用于包裹每个页面的元素。这个概念类似于 PPT 中的母版,它定义了页面的整体结构、样式和布局,使得系统具有一致的外观和风格。 特点: 全局通用:母版是全局性的,适用于系统中的每个页面,确保一致性的用户体验。 包裹元素:母版包裹每个页面的元素,定义了整体的结构和布局。 外观一致性:通过统一的母版设计,系统达到外观和风格的一致性。 与 PPT 母版的类比: 在母版的概念上,与 PPT 中的母版类似,都是用于定义整体结构和样式,确保每个页面都具有一致的外观。 默认母版范围: 图3-5-7-20 默认母版范围 作用场景 在系统中,我们提供了多个纬度的母版,包括全局、应用和页面纬度。这样的设计允许根据不同的业务场景选择合适的母版纬度,以满足不同层次的定制需求。 母版纬度: 全局母版: 覆盖系统中所有页面,确保全局的一致性和统一的用户体验。 定义全局性的结构、样式和布局。 应用母版: 适用于特定应用或模块,定制化程度介于全局和页面之间。 允许在不同应用间实现一定的差异化。 页面母版: 面向具体页面,提供最大的定制化空间。 允许在不同页面中定义不同的结构和样式。 选择纬度: 业务场景决定:根据具体的业务场景和需求选择合适的母版纬度。 定制化需求:如果需要全局一致性,选择全局母版;如果在应用层面有特定需求,选择应用母版;如果需要最大的灵活性和定制化,选择页面母版。 参数说明: 在系统中,使用 registerMask 注册母版时,需要提供两个参数。第一个参数是母版的 XML,第二个参数用于控制母版的注册行为,包括 module、moduleName、model 和 actionName。 母版 XML(第一个参数): 提供母版的 XML 描述,定义了母版的结构和样式。 控制参数(第二个参数): module:指定模块的名称。 moduleName:指定模块的显示名称。 model:指定母版所属的模型。 actionName:指定母版的操作名称,可以是字符串或字符串数组。 全局母版 可以使用 registerMask 注册母版。当第二个参数为 {} 时,即代表注册全局母版。 示例工程目录 以下是需关注的工程目录示例,并确保导入导出依赖正确: 图3-5-7-21 全局纬度注册母版工程目录示例 示例代码 以下是一个示例代码: import { registerMask } from '@kunlun/dependencies'; /** * mask: 在做系统时,我们通常会把外层的布局(菜单、顶部导航)等抽出公共组件,公共组件会抽离全局通用。类似ppt母版的概念即为Mask * registerMask 第二个入参为{}即注册了全局得母版 * * 和默认母版相比移除右上角消息、语言切换、用户 * `<block> * <widget widget="notification" /> * <widget widget="divider" /> * <widget widget="language" /> * <widget widget="divider" /> * <widget widget="user" /> * </block>` */ const registerGlobalMask = () => { registerMask(` <mask> <multi-tabs /> <header> <widget widget="app-switcher" /> </header> <container> <sidebar> <widget widget="nav-menu" height="100%" /> </sidebar> <content> <breadcrumb /> <block width="100%"> <widget width="100%" widget="main-view" /> </block> </content> </container> </mask>`, {}); } registerGlobalMask(); 图3-5-7-22 全局纬度注册母版代码示例 复制这段代码执行下registerGlobalMask()试试看吧 效果 右上角消息、语言切换、用户被移除。 图3-5-7-23 全局纬度注册母版效果示例 应用母版 在系统中,可以使用 registerMask 注册母版。当第二个参数为 {moduleName: ‘resource’} 时,即注册了 resource(资源)应用的母版。 示例工程目录 以下是需关注的工程目录示例,更新导出./moduleMask: 图3-5-7-24 应用纬度注册母版工程目录示例 示例代码 以下是一个示例代码: /** * registerMask 第二个入参为{moduleName: 'resource'}即注册了resource(资源)应用的母版 * * resource来源: 通常是浏览器url上的module * * 和默认模版相比拿掉了菜单 * `<sidebar> * <widget widget="nav-menu" height="100%"…

    2024年5月23日
    1.6K00

Leave a Reply

Please Login to Comment