3.5.1 构建第一个Menu

在前面章节中我们也涉及到菜单,因为菜单我们模块就是地图、导航,没有地图、导航就无法畅游模块并进行相关业务操作。在3.3.4【模块的继承】一文关于多表继承的内容就有涉及到菜单的初始化,本文将展开介绍初始化Menu的两种方式分别是:注解式、数据初始化式。

注解式(举例)

Step1 分析现有菜单注解

用@UxMenus声明DemoMenus为菜单初始化入口,同时该类在DemoModule配置扫描路径中,那么通过DemoMenus初始化的菜单都挂在demo_core这个模块上。

如果采用这种模式,建议同一个模块的菜单都只配置在一处

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

import pro.shushi.pamirs.boot.base.constants.ViewActionConstants;
import pro.shushi.pamirs.boot.base.ux.annotation.action.UxRoute;
import pro.shushi.pamirs.boot.base.ux.annotation.navigator.UxMenu;
import pro.shushi.pamirs.boot.base.ux.annotation.navigator.UxMenus;
import pro.shushi.pamirs.demo.api.model.*;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxy;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxyA;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxyB;

@UxMenus
public class DemoMenus implements ViewActionConstants {
    @UxMenu("商店管理")@UxRoute(PetShopProxy.MODEL_MODEL) class PetShopProxyMenu{}
    @UxMenu("商店管理A")@UxRoute(PetShopProxyA.MODEL_MODEL) class PetShopProxyAMenu{}
    @UxMenu("商店管理B")@UxRoute(PetShopProxyB.MODEL_MODEL) class PetShopProxyBMenu{}
    @UxMenu("商品管理")@UxRoute(PetItem.MODEL_MODEL) class ItemMenu{}
    @UxMenu("宠狗商品")@UxRoute(PetDogItem.MODEL_MODEL) class DogItemMenu{}
    @UxMenu("萌猫商品")@UxRoute(PetCatItem.MODEL_MODEL) class CatItemMenu{}
    @UxMenu("宠物品种")@UxRoute(PetType.MODEL_MODEL) class PetTypeMenu{}
    @UxMenu("萌猫品种")@UxRoute(PetCatType.MODEL_MODEL) class CatTypeMenu{}
    @UxMenu("宠狗品种")@UxRoute(PetDogType.MODEL_MODEL) class DogTypeMenu{}
    @UxMenu("宠物达人")@UxRoute(PetTalent.MODEL_MODEL) class PetTalentMenu{}
}

图3-5-1-1 菜单注解

Step2 改造现有菜单注解

  1. 菜单的层级关系通过@UxMenu的嵌套进行描述

  2. 菜单点击效果有三种分别对应不同的Action的类型,关于Action的类型详见3.5.3【Action的类型】一文。

    1. 通过@UxRoute定义一个与菜单绑定的viewAction,@UxMenu("创建商店")@UxRoute(value = PetShop.MODEL_MODEL,viewName = "redirectCreatePage",viewType = ViewTypeEnum.FORM),其中viewName代表视图的name(其默认值为redirectListPage,也就是跳转到列表也),value代码视图所属模型的编码,viewType代表view类型(其默认值为ViewTypeEnum.TABLE)

    2. @UxServer定义一个与菜单绑定的serverAction,@UxMenu("UxServer")@UxServer(model = PetCatItem.MODEL_MODEL,name = "uxServer") ,其中name代表serverAction的name,model或value代码serverAction所属模型的编码

    3. @UxLink定义一个与菜单绑定的UrlAction,@UxMenu("Oinone官网")@UxLink(value = "http://www.oinone.top",openType= ActionTargetEnum.OPEN_WINDOW) ,其中value为跳转url,openType为打开方式默认为ActionTargetEnum.ROUTER,打开方式有以下几种

      1. ROUTER("router", "页面路由", "页面路由")
      2. DIALOG("dialog", "页面弹窗", "页面弹窗")
      3. DRAWER("drawer", "打开抽屉", "打开抽屉")
      4. OPEN_WINDOW("openWindow", "打开新窗口", "打开新窗口")
  3. 配合菜单演示,PetCatItemAction增加一个uxServer的ServerAction

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

……包引用

@Model.model(PetCatItem.MODEL_MODEL)
@Component
public class PetCatItemAction extends DataStatusBehavior<PetCatItem> {
    ……省略其他代码

    @Action(displayName = "uxServer")
    public PetCatItem uxServer(PetCatItem data){
        PamirsSession.getMessageHub().info("uxServer");
        return data;
    }

}

图3-5-1-2 示例代码

  1. 新的菜单初始化代码如下
package pro.shushi.pamirs.demo.core.init;

import pro.shushi.pamirs.boot.base.constants.ViewActionConstants;
import pro.shushi.pamirs.boot.base.enmu.ActionTargetEnum;
import pro.shushi.pamirs.boot.base.ux.annotation.action.UxLink;
import pro.shushi.pamirs.boot.base.ux.annotation.action.UxRoute;
import pro.shushi.pamirs.boot.base.ux.annotation.action.UxServer;
import pro.shushi.pamirs.boot.base.ux.annotation.navigator.UxMenu;
import pro.shushi.pamirs.boot.base.ux.annotation.navigator.UxMenus;
import pro.shushi.pamirs.demo.api.model.*;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxy;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxyA;
import pro.shushi.pamirs.demo.api.proxy.PetShopProxyB;
import pro.shushi.pamirs.meta.enmu.ViewTypeEnum;

@UxMenus public class DemoMenus implements ViewActionConstants {

    @UxMenu("商店") class ShopMenu{
        @UxMenu("UxServer")@UxServer(model = PetCatItem.MODEL_MODEL,name = "uxServer") class ShopSayHelloMenu{
        }
        @UxMenu("创建商店")@UxRoute(value = PetShop.MODEL_MODEL,viewName = "redirectCreatePage",viewType = ViewTypeEnum.FORM) class ShopCreateMenu{
        }
        @UxMenu("商店管理")@UxRoute(PetShopProxy.MODEL_MODEL) class ShopProxyMenu{
        }
        @UxMenu("商店管理A")@UxRoute(PetShopProxyA.MODEL_MODEL) class ShopProxyAMenu{
        }
        @UxMenu("商店管理B")@UxRoute(PetShopProxyB.MODEL_MODEL) class ShopProxyBMenu{
        }

    }
    @UxMenu("商品") class ItemPMenu{
        @UxMenu("商品管理")@UxRoute(PetItem.MODEL_MODEL) class ItemMenu{
        }
        @UxMenu("宠狗商品")@UxRoute(PetDogItem.MODEL_MODEL) class DogItemMenu{}
        @UxMenu("萌猫商品")@UxRoute(PetCatItem.MODEL_MODEL) class CatItemMenu{}
    }
    @UxMenu("品种")@UxRoute(PetType.MODEL_MODEL) class PetTypePMenu{
        @UxMenu("宠物品种")@UxRoute(PetType.MODEL_MODEL) class PetTypeMenu{}
        @UxMenu("萌猫品种")@UxRoute(PetCatType.MODEL_MODEL) class CatTypeMenu{}
        @UxMenu("宠狗品种")@UxRoute(PetDogType.MODEL_MODEL) class DogTypeMenu{}
    }
    @UxMenu("宠狗达人")@UxRoute(PetTalent.MODEL_MODEL) class PetTalentMenu{}
    @UxMenu("友情链接")class FlinkManagement{
        @UxMenu("Oinone官网")@UxLink(value = "http://www.oinone.top",openType= ActionTargetEnum.OPEN_WINDOW) class SsLink{}
        @UxMenu("百度") @UxLink(value = "http://www.baidu.com",openType= ActionTargetEnum.OPEN_WINDOW) class BaiduLink{}
    }
}

图3-5-1-3 示例代码

Step3 重启看效果

我们会发现菜单按照我们预先设定的效果进行组织和展示

image.png

图3-5-1-4 示例效果

数据初始化式(不推荐)

在模块启动生命周期中,调用InitializationUtil工具中的createViewActionMenu。在前面的学习中我们用在DemoModuleMetaDataEditor这个类中用InitializationUtil工具初始化过viewAction和View。大家可以自行回忆,温故知新。

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

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

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

相关推荐

  • 3.4.3.1 面向对象-继承与多态

    本节为小伙伴们介绍,Function的面向对象的特性:继承与多态; 一、继承 我们在3.4.1【构建第一个Function】一文中伴随模型新增函数和独立类新增函数绑定到模型部分都是在父模型PetShop新增了sayHello的Function,同样其子模型都具备sayHello的Function。因为我们是通过Function的namespace来做依据的,子模型在继承父模型的sayHello函数后会以子模型的编码为namespace,名称则同样为sayHello。 二、多态(举例) oinone的多态,我们只提供覆盖功能,不提供重载,因为oinone相同name和fun的情况下不会去识别参数个数和类型。 Step1 为PetShop新增hello函数 package pro.shushi.pamirs.demo.api.model; …… //import @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"; …… //省略其他代码 @Function(openLevel = FunctionOpenEnum.API) @Function.Advanced(type= FunctionTypeEnum.QUERY) public PetShop sayHello(PetShop shop){ PamirsSession.getMessageHub().info("Hello:"+shop.getShopName()); return shop; } @Function(name = "sayHello2",openLevel = FunctionOpenEnum.API) @Function.Advanced(type= FunctionTypeEnum.QUERY) @Function.fun("sayHello2") public PetShop sayHello(PetShop shop, String s) { PamirsSession.getMessageHub().info("Hello:"+shop.getShopName()+",s:"+s); return shop; } @Function(openLevel = FunctionOpenEnum.API) @Function.Advanced(type= FunctionTypeEnum.QUERY) public PetShop hello(PetShop shop){ PamirsSession.getMessageHub().info("Hello:"+shop.getShopName()); return shop; } } 图3-4-3-1 为PetShop新增hello函数 Step2 为PetShopProxyB新增对应的三个函数 其中PetShopProxyB新增的hello函数,在java中是重载了hello,在代码中new PetShopProxyB()是可以调用父类的sayHello单参方法,也可以调用本类的双参方法。但在oinone的体系中对于PetShopProxyB只有一个可识别的Function就是双参的sayHello package pro.shushi.pamirs.demo.api.proxy; import pro.shushi.pamirs.demo.api.model.PetCatItem; import pro.shushi.pamirs.demo.api.model.PetShop; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.api.session.PamirsSession; import pro.shushi.pamirs.meta.enmu.FunctionOpenEnum; import pro.shushi.pamirs.meta.enmu.FunctionTypeEnum; import pro.shushi.pamirs.meta.enmu.ModelTypeEnum; import java.util.List; @Model.model(PetShopProxyB.MODEL_MODEL) @Model.Advanced(type = ModelTypeEnum.PROXY,inherited ={PetShopProxy.MODEL_MODEL,PetShopProxyA.MODEL_MODEL} ) @Model(displayName = "宠物店铺代理模型B",summary="宠物店铺代理模型B") public class PetShopProxyB extends PetShop { public static final String MODEL_MODEL="demo.PetShopProxyB"; @Field.one2many @Field(displayName = "萌猫商品列表") @Field.Relation(relationFields = {"id"},referenceFields = {"shopId"}) private List<PetCatItem> catItems; @Function(openLevel = FunctionOpenEnum.API) @Function.Advanced(type= FunctionTypeEnum.QUERY) public PetShop sayHello(PetShop shop){ PamirsSession.getMessageHub().info("PetShopProxyB Hello:"+shop.getShopName()); return shop; } @Function(name = "sayHello2",openLevel = FunctionOpenEnum.API) @Function.Advanced(type= FunctionTypeEnum.QUERY) @Function.fun("sayHello2") public PetShop sayHello(PetShop shop,String hello){ PamirsSession.getMessageHub().info("PetShopProxyB say:"+hello+","+shop.getShopName()); return shop; } @Function(openLevel = FunctionOpenEnum.API)…

    2024年5月23日
    1.5K00
  • 4.2.1 组件之生命周期

    组件生命周期的意义所在:比如动态创建了「视图、字段」,等它们初始化完成或者发生了修改后要执行业务逻辑,这个时候只能去自定义当前字段或者视图,体验极差,平台应该提供一些列的生命周期,允许其他人调用生命周期的api去执行对应的逻辑。 一、实现原理 图4-2-1-1 实现原理 当用户通过内部API去监听某个生命周期的时候,内部会动态的去创建该生命周期,每个生命周期都有「唯一标识」,内部会根据「唯一标识」去创建对应的「Effect」,Effect会根据生命周期的「唯一标识」实例化一个「lifeCycle」,「lifeCycle」创建完成后,会被存放到「Heart」中,「Heart」是整个生命周期的心脏,当心脏每次跳动的时候(生命周期被监听触发)都会触发对应的生命周期 二、生命周期API API 描述 返回值 View LifeCycle onViewBeforeCreated 视图创建前 ViewWidget onViewCreated 视图创建后 ViewWidget onViewBeforeMount 视图挂载前 ViewWidget onViewMounted 视图挂载后 ViewWidget onViewBeforeUpdate 视图数据发生修改前 ViewWidget onViewUpdated 视图数据修改后 ViewWidget onViewBeforeUnmount 视图销毁前 ViewWidget onViewUnmounted 视图销毁 ViewWidget onViewSubmit 提交数据 ViewWidget onViewSubmitStart 数据开始提交 ViewWidget onViewSubmitSuccess 数据提交成功 ViewWidget onViewSubmitFailed 数据提交失败 ViewWidget onViewSubmitEnd 数据提交结束 ViewWidget onViewValidateStart 视图字段校验 ViewWidget onViewValidateSuccess 校验成功 ViewWidget onViewValidateFailed 校验失败 ViewWidget onViewValidateEnd 校验结束 ViewWidget Field LifeCycle onFieldBeforeCreated 字段创建前 FieldWidget onFieldCreated 字段创建后 FieldWidget onFieldBeforeMount 字段挂载前 FieldWidget onFieldMounted 字段挂载后 FieldWidget onFieldBeforeUpdate 字段数据发生修改前 FieldWidget onFieldUpdated 字段数据修改后 FieldWidget onFieldBeforeUnmount 字段销毁前 FieldWidget onFieldUnmounted 字段销毁 FieldWidget onFieldFocus 字段聚焦 FieldWidget onFieldChange 字段的值发生了变化 FieldWidget onFieldBlur 字段失焦 FieldWidget onFieldValidateStart 字段开始校验 FieldWidget onFieldValidateSuccess 校验成功 FieldWidget onFieldValidateFailed 校验失败 FieldWidget onFieldValidateEnd 校验结束 FieldWidget 表4-2-1-1 生命周期API 上面列出的分别是「视图、字段」的生命周期,目前Action的生命周期还没有,后续再补充。 三、第一个View组件生命周期的监听(举例) Step1 新建registryLifeCycle.ts 新建registryLifeCycle.ts,监听宠物达人的列表页。’宠物达人table_demo_core’为视图名,您需要找后端配合 import { onViewCreated } from '@kunlun/dependencies' function registryLifeCycle(){ onViewCreated('宠物达人table_demo_core', (viewWidget) => { console.log('宠物达人table_demo_core'); console.log(viewWidget); }); } export {registryLifeCycle} 图4-2-1-2 新建registryLifeCycle.ts Step2 修改main.ts 全局注册lifeCycle import { registryLifeCycle } from './registryLifeCycle'; registryLifeCycle(); 图4-2-1-3 修改main.ts Step3 看效果 图4-2-1-4 示例效果 四、第一个Filed组件生命周期的监听(举例) Step1 修改registryLifeCycle.ts 通过onFieldValueChange增加宠物达人搜索视图的name(达人)字段的值变化进行监听。 宠物达人search:name 代表 视图名:字段名 import { onViewCreated , onFieldValueChange} from '@kunlun/dependencies' function registryLifeCycle(){ onViewCreated('宠物达人table_demo_core', (viewWidget) => { console.log('宠物达人table_demo_core'); console.log(viewWidget); }); onFieldValueChange('宠物达人search:name', (filedWidget) => { console.log('宠物达人search:name');…

    Oinone 7天入门到精通 2024年5月23日
    1.3K00
  • 合作伙伴中心

    合作伙伴中心包含“公司、个人、部门、岗位、员工”五个菜单。其中公司、个人为合作伙伴,是创建组织架构的前置条件;部门、岗位、员工为组织架构,是选择的公司下的内部架构。 合作伙伴 公司页面中包含常规的增删改查和查看详情。 公司的创建页面如下: 个人暂不支持创建。 组织架构 同样菜单中包含常规的增删改查和查看详情。 组织架构可以依次创建部门、岗位、员工。对应关系为,一个部门下有多个岗位,一个员工可以归属于多个部门和多个岗位。 部门创建页面如下: 岗位创建页面如下: 员工创建页面如下: 合作伙伴中心创建的员工会自动生成可登录的用户并进行绑定。 在用户中心创建的用户仅为可登录用户无法操作管理员工、关联部门。 流程设计器中可选到的操作人分类为“员工、部门、角色”。

    2024年6月20日
    1.4K00
  • 流程触发

    1. 流程触发 新增的流程设计页面默认包含两个节点,一个是流程的触发节点:确定流程开始的条件;另一个是流程结束的节点。 流程触发方式有模型触发、定时触发、日期触发三种方式,未设置流程触发方式时无法继续添加后续流程节点,同时无法进行流程发布,如左下图。触发方式设置完成后,可从左侧菜单栏拖入或流程箭头中的加号点击添加节点动作,如右下图。 1.1 模型触发 模型触发适用于模型中的数据字段变化开始流程的场景,比如员工请假审批流程。 模型触发的场景有数据的增删改,也可以对模型中的单个或多个字段进行条件筛选,若包含更新数据的场景可以设置选择更新字段,只有设置的字段更新才会触发流程,若不设置选择更新字段或者筛选条件,则模型中任一字段发生设置场景的变化时都会触发流程。 1.2 定时触发 定时触发适用于周期性调用流程的场景,比如仓库周期性盘点的流程。 需要设置一个流程第一次执行的时间,配置好循环的周期间隔。特殊的是选择周为周期时,当前周选中的日期也会执行流程。例:开始时间:2022-01-14(周四) 循环周期间隔:1周 自定义设置为周一到周五,则2022-01-15(本周五)也会执行流程操作。 1.3 日期触发 日期触发适用于模型中的日期时间字段引发流程的场景,比如给员工发生日祝福短信的流程。 设置日期触发时,若指定字段只包含日期,则必须要指定时刻,如左下图。例如给员工发生日祝福短信时根据模型中的员工生日数据获取到了执行流程的日期,需要制定开始该流程执行的具体时刻。若指定字段包含日期和时间,则不填写指定时刻时默认按照字段中的时刻开始执行流程,如右下图。例如办理业务后短信回访收集评价时根据模型中的业务完成时间,立即或延时发送短息。

    2024年6月20日
    2.3K00

Leave a Reply

Please Login to Comment