4.2 前端高级特性

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

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

(0)
史, 昂的头像史, 昂数式管理员
上一篇 2024年5月23日
下一篇 2024年5月23日

相关推荐

  • 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.2K00
  • 3.3.4 模型的继承

    在我们的很多项目中,客户都是有个性化需求的,就像我们不能找到两件一模一样的东西,何况是企业的经营与管理思路,多少都会有差异。常规的方式只能去修改标准产品的逻辑来适配客户的需求。导致后续标品维护非常困难。而在介绍完这节以后是不是让你更加清晰认知到我们2.4.2【oinone独特性之每一个需求都可以是一个模块】一文中所表达的特性带来的好处呢? 一、继承方式 继承方式可以分为五种: 抽象基类ABSTRACT,只保存不希望为每个子模型重复键入的信息的模型,抽象基类模型不生成数据表存储数据,只供其他模型继承模型可继承域使用,抽象基类可以继承抽象基类。 扩展继承EXTENDS,子模型与父模型的数据表相同,子模型继承父模型的字段与函数。存储模型之间的继承默认为扩展继承。 多表继承MULTI_TABLE,父模型不变,子模型获得父模型的可继承域生成新的模型;父子模型不同表,子模型会建立与父模型的一对一关联关系字段(而不是交叉表),使用主键关联,同时子模型会通过一对一关联关系引用父模型的所有字段。多表继承父模型需要使用@Model.MultiTable来标识,子模型需要使用@Model.MultiTableInherited来标识。 代理继承PROXY,为原始模型创建代理,可以增删改查代理模型的实体数据,就像使用原始(非代理)模型一样。不同之处在于代理继承并不关注更改字段,可以更改代理中的元信息、函数和动作,而无需更改原始内容。一个代理模型必须仅能继承一个非抽象模型类。一个代理模型可以继承任意数量的没有定义任何模型字段的抽象模型类。一个代理模型也可以继承任意数量继承相同父类的代理模型。 临时继承TRANSIENT,将父模型作为传输模型使用,并可以添加传输字段。 二、继承约束 通用约束 对于扩展继承,查询的时候,父模型只能查询到父模型字段的数据,子模型可以查询出父模型及子模型的字段数据(因为派生关系所以子模型复刻了一份父模型的字段到子模型中)。 系统不会为抽象基类创建实际的数据库表,它们也没有默认的数据管理器,不能被实例化也无法直接保存,它们就是用来被继承的。抽象基类完全就是用来保存子模型们共有的内容部分,达到重用的目的。当它们被继承时,它们的字段会全部复制到子模型中。 系统不支持非jar包依赖模型的继承。 多表继承具有阻断效应,子模型无法继承多表继承父模型的存储父模型的字段,需要使用@Model.Advanced注解的inherited属性显示声明继承父模型的父模型。但是可以继承多表继承父模型的抽象父模型的字段。 可以使用@Model.Advanced的unInheritedFields和unInheritedFunctions属性设置不从父类继承的字段和函数。 跨模块继承约束 如果模型间的继承是跨模块继承,应该与模型所属模块建立依赖关系;如果模块间有互斥关系,则不允许建立模块依赖关系,同理模型间也不允许存在继承关系。 跨模块代理继承,对代理模型的非inJvm函数调用将使用远程调用方式;跨模块扩展(同表)继承将使用本地调用方式,如果是数据管理器函数,将直连数据源。 模型类型与继承约束 抽象模型可继承:抽象模型(Abstract) 临时模型可继承:抽象模型(Abstract)、传输模型(Transient) 存储模型可继承:抽象模型(Abstract)、存储模型(Store)、存储模型(多表,Multi-table Store),不可继承多个Store或Multi-table Store 多表存储模型(父)可继承:同扩展继承 多表存储模型(子)在继承单个Multi-table Store后可继承:抽象模型(Abstract)、存储模型(Store),不可继承多个Store 代理模型可继承: 抽象模型(Abstract),须搭配继承Store、Multi-table Store或Proxy 存储模型(Store),不可继承多个Store或Multi-table Store 存储模型(多表,Multi-table Store),不可继承多个Store或Multi-table Store 代理模型(Proxy),可继承多个Proxy,但多个父Proxy须继承自同一个Store或Multi-table Store,且不能再继承其他Store或Multi-table Store 同名字段以模型自身字段为有效配置,若模型自身不存在该字段,继承字段以第一个加载的字段为有效配置,所以在多重继承的情况下,未避免继承同名父模型字段的不确定性,在自身模型配置同名字段来确定生效配置。 三、继承的使用场景 模型的继承可以继承父模型的元信息、字段、数据管理器和函数 抽象基类 解决公用字段问题 扩展继承 解决开放封闭原则、跨模块扩展等问题 多表继承 解决多型派生类字段差异问题和前端多存储模型组合外观问题 代理继承 解决同一模型在不同场景下的多态问题(一表多态) 临时继承 解决使用现有模型进行数据传输问题 举例,前端多存储模型组合外观问题可通过多表继承的子模型,并一对一关联到关联模型,同时使用排除继承字段去掉不需要继承的字段。子模型通过默认模型管理器提供查询功能给前端,默认查询会查询子模型数据列表并在列表行内根据一对一关系查出关联模型数据合并,关联模型数据展现形态在行内是平铺还是折叠,在详情是分组还是选项卡可以自定义view进行配置 扩展继承 父子同表,模型在所有场景都有一致化的表现,意味着原模型被扩展成了新模型,父子模型的表名一致,模型编码不同,可覆盖父模型的模型管理器、数据排序规则、函数 多表继承 父子多表,父子间有隐式一对一关系,即父子模型都增加了一对一关联关系字段,同时父模型的字段被引用到子模型,且引用字段为只读字段,意味着子模型不可以直接更改父模型的字段值,子模型不继承父模型的模型管理器、数据排序规则、函数,子模型拥有自己的默认模型管理器、数据排序规则、函数。多表继承具有阻断效应,子模型无法自动多表继承父模型的存储父模型,需要显式声明多表继承父模型的存储父模型。 代理继承 代理模型继承并可覆盖父模型的模型管理器、数据排序规则、函数,同时可以使用排除继承字段和函数来达到不同场景不同视觉交互的效果。 图3-3-4-1 继承的使用场景 四、抽象基类(举例) 参考前文中3.3.2【模型的类型】一文中关于抽象模型的介绍 五、多表继承(举例) 场景设计如下 图3-3-4-2 多表继承设计场景 Step1 新建宠物品种、宠狗品种和萌猫品种模型 新建宠物品种模型,用@Model.MultiTable(typeField = "kind"),申明为可多表继承父类,typeField指定为kind字段 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.IdModel; @Model.MultiTable(typeField = "kind") @Model.model(PetType.MODEL_MODEL) @Model(displayName="品种",labelFields = {"name"}) public class PetType extends IdModel { public static final String MODEL_MODEL="demo.PetType"; @Field(displayName = "品种名") private String name; @Field(displayName = "宠物分类") private String kind; } 图3-3-4-3 多表继承示例代码 新建宠狗品种模型,用@Model.MultiTableInherited(type = PetDogType.KIND_DOG),申明以多表继承模式继承PetType,覆盖kind字段(用defaultValue设置默认值,用invisible = true设置为前端不展示),更多模块元数据以及模型字段元数据配置详见4.1.6【模型之元数据详解】一文 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.MultiTableInherited(type = PetDogType.KIND_DOG) @Model.model(PetDogType.MODEL_MODEL) @Model(displayName="宠狗品种",labelFields = {"name"}) public class PetDogType extends PetType { public static final String MODEL_MODEL="demo.PetDogType"; public static final String KIND_DOG="DOG"; @Field(displayName = "宠物分类",defaultValue = PetDogType.KIND_DOG,invisible = true) private String kind; } 图3-3-4-4 多表继承示例代码 新建萌猫品种模型,用@Model.MultiTableInherited(type = PetCatType.KIND_CAT),申明以多表继承模式继承PetType,覆盖kind字段(用defaultValue设置默认值,用invisible = true设置为前端不展示),并新增一个CatShapeEnum枚举类型的字段shape package pro.shushi.pamirs.demo.api.enumeration; import pro.shushi.pamirs.meta.annotation.Dict; import pro.shushi.pamirs.meta.common.enmu.BaseEnum; @Dict(dictionary = CatShapeEnum.DICTIONARY,displayName = "萌猫体型") public class CatShapeEnum extends BaseEnum<CatShapeEnum,Integer>…

    2024年5月23日
    1.4K00
  • 3.3.10 字段类型之关系描述的特殊场景

    在3.3.9【字段类型之关系与引用】一文中已经描述了各种关系字段的常规写法,还有一些特殊场景如:关系映射中存在常量,或者M2M中间表是大于两个字段构成。 举例说明关系字段-高级用法 场景描述 PetTalent模型增加talentType字段,PetItem与PetTalent的多对多关系增加talentType(达人类型),PetItemRelPetTalent 中间表维护petItemId、petTalentId以及talentType,PetDogItem和PetCatItem分别重写petTalents 字段,关系中增加常量描述。示意图如下 实际操作步骤: Step1 新增 TalentTypeEnum package pro.shushi.pamirs.demo.api.enumeration; import pro.shushi.pamirs.meta.annotation.Dict; import pro.shushi.pamirs.meta.common.enmu.BaseEnum; @Dict(dictionary = TalentTypeEnum.DICTIONARY,displayName = "达人类型") public class TalentTypeEnum extends BaseEnum<TalentTypeEnum,Integer> { public static final String DICTIONARY ="demo.TalentTypeEnum"; public final static TalentTypeEnum DOG =create("DOG",1,"狗达人","狗达人"); public final static TalentTypeEnum CAT =create("CAT",2,"猫达人","猫达人"); } Step2 PetTalent模型增加talentType字段 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.demo.api.enumeration.TalentTypeEnum; 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; @Field(displayName = "达人类型") private TalentTypeEnum talentType; } Step3 修改PetItem的petTalents字段,在关系描述中增加talentType(达人类型) @Field.many2many(relationFields = {"petItemId"},referenceFields = {"petTalentId","talentType"},through = "PetItemRelPetTalent") @Field.Relation(relationFields = {"id"}, referenceFields = {"id","talentType"}) @Field(displayName = "推荐达人",summary = "推荐该商品的达人们") private List<PetTalent> petTalents; Step4 PetDogItem增加petTalents字段,重写父类PetItem的关系描述 talentType配置为常量,填入枚举的值 增加domain描述用户页面选择的时候自动过滤出特定类型的达人,RSQL用枚举的name @Field.many2many(relationFields = {"petItemId"},referenceFields = {"petTalentId","talentType"},through = "PetItemRelPetTalent") @Field.Relation(relationFields = {"id"}, referenceFields = {"id","talentType"}) @Field(displayName = "推荐达人",summary = "推荐该商品的达人们") private List<PetTalent> petTalents; Step5 PetCatItem增加petTalents字段,重写父类PetItem的关系描述 talentType配置为常量,填入枚举的值 增加domain描述用户页面选择的时候自动过滤出特定类型的达人,RSQL用枚举的name @Field(displayName = "推荐达人") @Field.many2many( through = "PetItemRelPetTalent", relationFields = {"petItemId"}, referenceFields = {"petTalentId","talentType"} ) @Field.Relation(relationFields = {"id"}, referenceFields = {"id", "#2#"}, domain = " talentType == CAT") private List<PetTalent> petTalents; Step6 清除中间表demo_core_pet_item_rel_pet_talent的数据记录 清除PetItem与PetTalent的多对多中间表demo_core_pet_item_rel_pet_talent的数据记录 Step7 重启看效果 修改达人记录,选择不同达人类型 PetItem、PetCatItem、PetDogItem不同的交互页面

    2024年5月23日
    1.5K00
  • 3.5.6.4 动作的配置

    在3.5.3【Action的类型】一文中,我们介绍Action的几种类型,以及组合动作。 通用配置 配置项 可选值 默认值 作用 name 动作名称 label 显示名称 icon 图标 type primary defaultlink primary 按钮类型样式,支持主要样式、次要样式以及链接样式。 bizStyle defaultsuccesswarningdangerinfo default 按钮业务样式,支持成功(green)、警告(yellow)、危险(red)、信息(grey)四种样式。 invisible truefalse condition false 展示规则,有简单的true/false显隐,也支持复杂的表达式 disabled truefalse condition 根据动作上下文类型进行自动推断 是否禁用自动推断规则:当上下文类型为【单行】时,相当于使用表达式LIST_COUNT(context.activeRecords) != 1当上下文类型为【多行】时,相当于使用表达式LIST_COUNT(context.activeRecords) <= 1当上下文类型为【单行或多行】时,相当于使用表达式LIST_COUNT(context.activeRecords) == 0 disabledTitle string 根据动作上下文类型进行自动推断 禁用悬浮提示 表3-5-6-12 动作通用配置 二次确认配置 二次确认框默认支持两种模式,对话框和气泡框; 对话框 图3-5-6-51 对话框提示 气泡框 图3-5-6-52 气泡框警告 配置项 配置项 可选值 默认值 作用 备注 confirm string 二次确认提示文字 配置后开启二次确认 confirmType POPPER(气泡提示框) MODAL(对话框) POPPER 确认框类型 confirmPosition TM(按钮上方) BM(按钮下方) LM(按钮左侧) RM(按钮右侧) BM 确认框位置 气泡框该配置生效 enterText 确定 确定按钮文字 cancelText 取消 取消按钮文字 表3-5-6-13 配置项 弹出层动作配置(窗口动作ViewAction) 目前平台对于弹出层支持了两种展示形式。弹窗(modal/dialog)和抽屉(drawer) 支持两种配置方式【内嵌视图配置】和【引用已有页面】,内嵌视图配置优先于引用已有页面。 内嵌视图配置 该配置对于弹窗和抽屉均适用。 <action name="窗口动作名称" label="创建"> <view model="模型编码" type="form"> <template slot="form" widget="form"> <field data="id" invisible="true" /> <field data="code" label="编码" widget="Input" /> <field data="name" label="名称" widget="Input" /> </template> <template slot="footer"> <action name="$$internal_DialogCancel" label="关闭" type="default" /> <action name="create" label="确定" /> </template> </view> </action> 图3-5-6-53 内嵌视图配置 引用已有页面配置 该配置对于弹窗和抽屉均适用。 <view model="模型编码" type="form"> <template slot="form" widget="form"> <field data="id" invisible="true" /> <field data="code" label="编码" widget="Input" /> <field data="name" label="名称" widget="Input" /> </template> <template slot="footer"> <action name="$$internal_DialogCancel" label="关闭" type="default" /> <action name="create" label="确定" /> </template> </view> 图3-5-6-54 引用已有页面示例 <action name="窗口动作名称" label="创建" resViewName="$viewName$" /> 图3-5-6-55 引用已有页面 弹窗 当窗口动作的路由方式(target)为dialog时,内嵌视图/引用页面将以弹窗形式展示在页面上。 配置项 配置项 可选值 默认值 作用 title…

    2024年5月23日
    98500
  • 3.3 Oinone以模型为驱动

    模型(model):Oinone一切从模型出发,是数据及对行为的载体: 是对所需要描述的实体进行必要的简化,并用适当的变现形式或规则把它的主要特征描述出来所得到的系统模仿品。模型由元信息、字段、数据管理器和自定义函数构成; 符合面向对象设计原则包括:封装、继承、多态。 本章会带大家快速而全方位地认识Oinone的模型。会从以下几个维度去对模型展开详细介绍。 构建第一个Model 模型的类型 模型的数据管理器 模型的继承 模型编码生成器 枚举与数据字典 字段序列化方式 字段类型之基础与复合 字段类型之关系与引用

    Oinone 7天入门到精通 2024年5月23日
    1.3K00

Leave a Reply

登录后才能评论