自定义用户中心菜单

使用扩展点实现用户中心菜单替换

1. 工程中引起pamirs-user-api

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

2. 实现TopBarUserBlockAction的后置扩展

  • 实现HookAfter后置扩展接口
  • @Hook(model = {TopBarUserBlock.MODEL_MODEL}, fun = {"construct"})添加Hook注解注明是TopBarUserBlock模型的construct函数的后置扩展。

增加用户中心菜单

@Component
@Order(1)
@SPI.Service
public class MyTopBarActionExt implements TopBarActionExtendApi {

    public void edit(List<TopBarAction> list) {
        list.add(new TopBarAction("top_demo", "top.Teacher", "uiView9a0caf1d574a42c9847a057a0c4a4ad1", ActionTypeEnum.VIEW, 1)
                .setDisplayName("商品管理")
                .setIcon("oinone-gongzuotai")
        );
    }

}

实现效果

自定义用户中心菜单

替换原有的用户中心菜单

  1. 替换原有的菜单跳转

    @Component
    public class DemoTopBarUserBlockDataHookAfter implements HookAfter {
    
    @Override
    @Hook(model = {TopBarUserBlock.MODEL_MODEL}, fun = {"construct"})
    public Object run(Function function, Object ret) {
        if (ret == null) {
            return null;
        }
        TopBarUserBlock result = null;
        if (ret instanceof Object[]) {
            Object[] rets = (Object[]) ((Object[]) ret);
            if (rets.length == 1) {
                result = (TopBarUserBlock) rets[0];
              //例:替换用户中心:修改密码菜单
              //使用name和model查询出模型的ViewAction替换修改密码ViewAction
                ViewAction demoViewAction = PamirsSession.getContext().getExtendCache(ActionCacheApi.class).get(Dog.MODEL_MODEL, "changePassword");
                //设置菜单的icon
                Map<String, Object> attributes = Optional.ofNullable(demoViewAction.getAttributes()).orElse(new HashMap<>());
                attributes.put("icon", "oinone-xiugaimima");
                demoViewAction.setAttributes(attributes);
                //UserViewAction第0个是修改密码ViewAction,使用自定义的ViewAction就可以实现替换
                result.getUserViewAction().set(0, demoViewAction);
            }
        } else {
            result = (TopBarUserBlock) ret;
        }
        return result;
    }
    }
  2. 使用@UxRouteButton方式新增ViewAction,更多新增Action方式详见:Action的类型

    @Model.model(Dog.MODEL_MODEL)
    @Component
    @UxRouteButton(
        action = @UxAction(name = "changePassword", displayName = "修改密码"),
        value = @UxRoute(model = Dog.MODEL_MODEL, openType = ActionTargetEnum.DIALOG))
    public class DogAction {
    }

替换原有的个人设置头像跳转

  1. 修改点击头像绑定的跳转逻辑

    @Order(10)
    @Component
    @SPI.Service
    public class DemoTopBarUserBlockDataApi implements TopBarUserBlockDataApi {
    
    @Override
    public TopBarUserBlock extendData(TopBarUserBlock data) {
        //例如增加一个菜单, PamirsDemo.MODEL_MODEL: 模型。 MenuuiMenu31f22466735a4abe8e0544b428ed88ac:viewAction的name。
        Action demoViewAction = PamirsSession.getContext().getExtendCache(ActionCacheApi.class).get(PamirsDemo.MODEL_MODEL, "MenuuiMenu31f22466735a4abe8e0544b428ed88ac");
        if (demoViewAction != null){
            AccessResourceInfo info = PageLoadHelper.generatorAccessResourceInfo(TopModule.MODULE_MODULE, demoViewAction);
            AccessResourceInfoSession.setInfo(info);
            String path = ResourcePath.generatorPath(demoViewAction.getModel(), demoViewAction.getName());
            demoViewAction.setSessionPath(path);
            data.setUserAvatarAction(demoViewAction);
        }
        return data;
    }
    }
  2. 添加权限节点,用于控制权限。

    @Component
    @Order(88)
    @SPI.Service
    public class MyTestNodeLoadExtend implements PermissionNodeLoadExtendApi {
    
    @Override
    public List<PermissionNode> buildRootPermissions(PermissionLoadContext loadContext, List<PermissionNode> nodes) {
        PermissionNode root = AuthNodeHelper.createNodeWithTranslate("CustomNode", "自定义节点");
        List<PermissionNode> newNodes = new ArrayList<>();
        newNodes.add(root);
        Action demoViewAction = PamirsSession.getContext().getExtendCache(ActionCacheApi.class).get(PamirsDemo.MODEL_MODEL, "MenuuiMenu31f22466735a4abe8e0544b428ed88ac");
    
        if (demoViewAction != null) {
            //将该Action放入权限树
            //权限鉴权的path路径是根据【cacheAction.getModel() + cacheAction.getName()】拼接的。和MODULE没有关系,这里MODULE可以自定义。
            AuthNodeHelper.addNode(newNodes, root, AuthNodeHelper.createActionNode(TopModule.MODULE_MODULE, demoViewAction, root));
        }
        nodes.add(0, root);
        return newNodes;
    }
    }
  3. 管理中心控制个人设置头像权限
    自定义用户中心菜单

Oinone社区 作者:yexiu原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/14399.html

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

(0)
yexiu的头像yexiu数式员工
上一篇 2024年7月2日 pm7:42
下一篇 2024年7月4日 pm10:10

相关推荐

  • Schedule相关

    1、Schedule初始化 TODO 2、Schedule执行器的入口 通常本地创建了Schedule,没有被正常执行,可以通过这个入口去排查问题 pro.shushi.pamirs.middleware.schedule.core.tasks.AbstractScheduleTaskDealSingle#selectTasks 3、Schedule执行环境隔离 项目中开发如果本地进行任务调试,通过通过指定ownSign进行环境隔离,如果不配置可能会导致这个任务被别的机器执行,本机的代码无法调试,如果开发的时候出现任务未执行可能是这个原因导致的 event: enabled: true schedule: enabled: true ownSign: dev_wx rocket-mq: namesrv-addr: 127.0.0.1:9876

    后端 2023年11月16日
    1.3K00
  • Maven Setting 配置详解

    常用标签概览 servers/server:配置私有仓库用户名和密码进行认证,以 id 进行关联。 mirrors/mirror:配置镜像仓库拉取时的地址源和额外配置。 profiles/profile:配置多个可能使用的镜像仓库。 activeProfiles/activeProfile:配置默认激活的 profile,以 id 进行关联。 Oinone 私有仓库配置 以下配置可以在使用 Oinone 私有仓库的同时,也可以正常使用 aliyun 镜像源。 <servers> <server> <id>shushi</id> <username>${username}</username> <password>${password}</password> </server> </servers> <mirrors> <mirror> <id>shushi</id> <mirrorOf>shushi</mirrorOf> <url>http://ss.nexus.ixtx.fun/repository/public</url> <!– 忽略 https 认证,maven 版本过高时需要配置 –> <blocked>false</blocked> </mirror> </mirrors> <profiles> <profile> <id>shushi</id> <repositories> <repository> <!– 对应 server.id –> <id>shushi</id> <url>http://ss.nexus.ixtx.fun/repository/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <!– 对应 server.id –> <id>shushi</id> <url>http://ss.nexus.ixtx.fun/repository/snapshots</url> <releases> <enabled>false</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories> </profile> <profile> <id>aliyun</id> <repositories> <repository> <id>aliyun</id> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>aliyun</id> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </profile> </profiles> <activeProfiles> <!– 使用 shushi 私有仓库 –> <activeProfile>shushi</activeProfile> <!– 使用 aliyun 镜像仓库 –> <activeProfile>aliyun</activeProfile> </activeProfiles> 常见问题 使用 mvn 时无法拉取 Oinone 最新版镜像,提示找不到对应的包 原因:在 Oinone 开源后,oinone-pamirs 内核相关包都被部署到 maven 中央仓库,但由于其他镜像仓库的同步存在延时,在未正确同步的其他镜像源拉取时会出现找不到对应的包相关异常。 解决方案:检查 mirrors 中是否配置了 aliyun 镜像源,如果配置了,使用上述 Oinone 私有仓库配置重新配置后,再进行拉取。这一问题是由于 mirrors 配置不当,拦截了所有从 maven 中央仓库拉取的地址替换为了 aliyun 镜像源导致的。

    2025年11月10日
    49300
  • Oinone引入搜索引擎(增强模型)

    场景描述 在碰到大数据量并且需要全文检索的场景,我们在分布式架构中基本会架设ElasticSearch来作为一个常规解决方案。在oinone体系中增强模型就是应对这类场景,其背后也是整合了ElasticSearch; 使用前你应该 了解ElasticSearch,包括不限于:Index(索引)、分词、Node(节点)、Document(文档)、Shards(分片) & Replicas(副本)。参考官方网站:https://www.elastic.co/cn/ 有一个可用的ElasticSearch环境(本地项目能引用到) 前置约束 增强模型增量依赖数据变更实时消息,因此确保项目的event是开启的,mq配置正确。 项目引入搜索步骤 1、boot工程加入相关依赖包 boot工程需要指定ES客户端包版本,不指定版本会隐性依赖顶层spring-boot依赖管理指定的低版本 boot工程加入pamris-channel的工程依赖 <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>8.4.1</version> </dependency> <dependency> <groupId>jakarta.json</groupId> <artifactId>jakarta.json-api</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-sql-record-core</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-channel-core</artifactId> </dependency> 2、api工程加入相关依赖包 在XXX-api中增加入pamirs-channel-api的依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-channel-api</artifactId> </dependency> 3、yml文件配置 在pamirs-demo-boot的application-dev.yml文件中增加配置pamirs.boot.modules增加channel,即在启动模块中增加channel模块。同时注意es的配置,是否跟es的服务一致 pamirs: record: sql: #改成自己本地路径(或服务器路径) store: /Users/oinone/record boot: modules: – channel ## 确保也安装了sql_record – sql_record channel: packages: # 增强模型扫描包配置 – com.xxx.xxx elastic: url: 127.0.0.1:9200 4、项目的模块增加模块依赖 XXXModule增加对ChannelModule的依赖 @Module(dependencies = {ChannelModule.MODULE_MODULE}) 5、增加增强模型(举例) package pro.shushi.pamirs.demo.api.enhance; import pro.shushi.pamirs.channel.enmu.IncrementEnum; import pro.shushi.pamirs.channel.meta.Enhance; import pro.shushi.pamirs.channel.meta.EnhanceModel; import pro.shushi.pamirs.demo.api.model.ShardingModel; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.enmu.ModelTypeEnum; @Model(displayName = "测试EnhanceModel") @Model.model(ShardingModelEnhance.MODEL_MODEL) @Model.Advanced(type = ModelTypeEnum.PROXY, inherited = {EnhanceModel.MODEL_MODEL}) @Enhance(shards = "3", replicas = "1", reAlias = true,increment= IncrementEnum.OPEN) public class ShardingModelEnhance extends ShardingModel { public static final String MODEL_MODEL="demo.ShardingModelEnhance"; } 6、重启系统看效果 1、进入【传输增强模型】应用,访问增强模型列表我们会发现一条记录,并点击【全量同步】初始化ES,并全量dump数据 2、再次回到Demo应用,进入增强模型页面,可以正常访问并进增删改查操作 个性化dump逻辑 通常dump逻辑是有个性化需求,那么我们可以重写模型的synchronize方法,函数重写特性在“面向对象-继承与多态”部分中已经有详细介绍。 重写ShardingModelEnhance模型的synchronize方法 重写后,如果针对老数据记录需要把新增的字段都自动填充,可以进入【传输增强模型】应用,访问增强模型列表,找到对应的记录并点击【全量同步】 package pro.shushi.pamirs.demo.api.enhance; import pro.shushi.pamirs.channel.enmu.IncrementEnum; import pro.shushi.pamirs.channel.meta.Enhance; import pro.shushi.pamirs.channel.meta.EnhanceModel; import pro.shushi.pamirs.demo.api.model.ShardingModel; 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.enmu.FunctionTypeEnum; import pro.shushi.pamirs.meta.enmu.ModelTypeEnum; import java.util.List; @Model(displayName = "测试EnhanceModel") @Model.model(ShardingModelEnhance.MODEL_MODEL) @Model.Advanced(type = ModelTypeEnum.PROXY, inherited = {EnhanceModel.MODEL_MODEL}) @Enhance(shards = "3", replicas = "1", reAlias = true,increment= IncrementEnum.OPEN) public class ShardingModelEnhance extends ShardingModel { public static final String MODEL_MODEL="demo.ShardingModelEnhance"; @Field(displayName = "nick") private String nick;…

    2024年5月14日
    2.0K00
  • 【DM】后端部署使用Dameng数据库(达梦)

    达梦数据库配置 驱动配置 达梦数据库的服务端版本和驱动版本需要匹配,建议使用服务端安装时提供的jdbc驱动,不要使用官方maven仓库中的驱动。 报错 表 xx 中不能同时包含聚集 KEY 和大字段,建表的时候就指定非聚集主键。SELECT * FROM V$DM_INI WHERE PARA_NAME = ‘PK_WITH_CLUSTER’;SP_SET_PARA_VALUE(1,’PK_WITH_CLUSTER’,0) Maven配置 DM8(目前maven仓库最新版本) <dm.version>8.1.2.192</dm.version> <dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver18</artifactId> <version>${dm.version}</version> </dependency> PS: 8.1.3.12版本驱动需要手动上传到nexus仓库使用,本文包含该版本相关内容。 Maven配置 DM7 <dm7.version>7.6.1.120</dm7.version> <dependency> <groupId>com.dameng</groupId> <artifactId>Dm7JdbcDriver18</artifactId> <version>${dm7.version}</version> </dependency> PS: 7.6.1.120版本驱动需要手动上传到nexus仓库使用,本文包含该版本相关内容。 离线驱动下载 Dm7JdbcDriver18-7.6.1.120.jarDmJdbcDriver18-8.1.3.12.jar JDBC连接配置 pamirs: datasource: base: type: com.alibaba.druid.pool.DruidDataSource driverClassName: dm.jdbc.driver.DmDriver # url: jdbc:dm://127.0.0.1:5236/BASE?clobAsString=true&useUnicode=true&characterEncoding=utf8&compatibleMode=mysql url: jdbc:dm://127.0.0.1:5236?schema=BASE&clobAsString=true&columnNameUpperCase=false&useUnicode=true&characterEncoding=utf8&compatibleMode=mysql username: xxxxxx password: xxxxxx initialSize: 5 maxActive: 200 minIdle: 5 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true asyncInit: true validConnectionCheckerClassName: com.alibaba.druid.pool.vendor.OracleValidConnectionChecker validationQuery: SELECT 1 FROM DUAL 连接url配置 点击查看官方文档:DM JDBC 编程指南 连接串1 jdbc:dm://127.0.0.1:5236?schema=BASE&clobAsString=true&columnNameUpperCase=false&useUnicode=true&characterEncoding=utf8&compatibleMode=mysql PS:schema参数在低版本驱动区分大小写,高版本驱动不再区分大小写,为了避免错误,统一使用全大写。columnNameUpperCase参数与官方介绍不一致,为了避免错误,需要显式指定。 连接串2 jdbc:dm://127.0.0.1:5236/BASE?clobAsString=true&useUnicode=true&characterEncoding=utf8&compatibleMode=mysql PS:可能是未来更高版本中使用的连接串形式。 达梦数据库在不同驱动版本下需要使用不同的连接串进行处理,具体可参考下表:(使用错误的连接串将无法正常启动) Dm7JdbcDriver18版本 Build-Time 使用的连接串类型 是否支持指定schema schema是否区分大小写 是否可用 不可用原因 7.6.0.165 2019.06.04 1 否 是 否 不支持LocalDateTime类型 7.6.1.120(建议) 2022.09.14 1 是 是 是 – DmJdbcDriver18版本 Build-Time 使用的连接串类型 是否支持指定schema schema是否区分大小写 是否可用 不可用原因 8.1.2.192 2023.01.12 1 是 否 是 – 8.1.3.12(建议) 2023.04.17 2 是 否 是 – 方言配置 pamirs方言配置 pamirs: dialect: ds: base: type: DM version: 8 majorVersion: 8 pamirs: type: DM version: 8 majorVersion: 8 数据库版本 type version majorVersion 7-20220916 DM 7 20220916 8-20230418 DM 8 8 schedule方言配置 pamirs: event: schedule: dialect: type: DM version: 8 majorVersion: 8 type version majorVersion…

    2023年11月1日
    13.6K00
  • 自定义数据权限拦截处理

    业务场景 公司给员工对哪些模块有访问权限,这个时候就需要在员工访问模块表的时候做数据过滤, 解决方案 我们可以通过平台提供的数据过滤占位符解决这个问题,新建一条数据行权限,过滤语句条件是占位符,再编写占位符的解析逻辑 1.初始化权限基础数据 package pro.shushi.pamirs.demo.core.init; import com.google.common.collect.Lists; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import pro.shushi.pamirs.auth.api.constants.AuthConstants; import pro.shushi.pamirs.auth.api.enmu.AuthGroupTypeEnum; import pro.shushi.pamirs.auth.api.enmu.PermissionDataSourceEnum; import pro.shushi.pamirs.auth.api.enmu.PermissionTypeEnum; import pro.shushi.pamirs.auth.api.model.AuthGroup; import pro.shushi.pamirs.auth.api.model.AuthRole; import pro.shushi.pamirs.auth.api.model.ResourcePermission; import pro.shushi.pamirs.boot.base.model.UeModule; import pro.shushi.pamirs.boot.common.api.command.AppLifecycleCommand; import pro.shushi.pamirs.boot.common.api.init.InstallDataInit; import pro.shushi.pamirs.boot.common.api.init.UpgradeDataInit; import pro.shushi.pamirs.demo.api.DemoModule; import pro.shushi.pamirs.demo.core.placeholder.EmployeeModulePlaceholder; import pro.shushi.pamirs.framework.common.utils.ObjectUtils; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.meta.domain.module.ModuleDefinition; import java.util.Collections; import java.util.List; @Slf4j @Component @Order(0) public class DemoModuleBizInit implements InstallDataInit, UpgradeDataInit { @Override public List<String> modules() { return Collections.singletonList(DemoModule.MODULE_MODULE); } @Override public int priority() { return 0; } @Override public boolean init(AppLifecycleCommand command, String version) { this.initAuth(); return true; } @Override public boolean upgrade(AppLifecycleCommand command, String version, String existVersion) { this.initAuth(); return true; } private void initAuth() { AuthGroup authGroup = new AuthGroup(); authGroup.setName("测试权限组") .setDisplayName("测试权限组") .setType(AuthGroupTypeEnum.RUNTIME) .setActive(true); authGroup.createOrUpdate(); AuthRole authRole = new AuthRole(); authRole.setCode("TEST_ROLE_1") .setName("测试角色") .setRoleTypeCode(AuthConstants.ROLE_SYSTEM_TYPE_CODE) .setPermissionDataSource(PermissionDataSourceEnum.CUSTOM) .setActive(true); authRole.createOrUpdate(); authRole.setGroups(Lists.newArrayList(authGroup)); authRole.fieldSave(AuthRole::getGroups); ResourcePermission authPermission = new ResourcePermission(); authPermission.setName("测试模块权限过滤") .setDomainExp(EmployeeModulePlaceholder.PLACEHOLDER) .setModel(ModuleDefinition.MODEL_MODEL) .setPermRead(true) .setPermRun(true) .setPermissionType(PermissionTypeEnum.ROW) .setPermissionDataSource(PermissionDataSourceEnum.CUSTOM) .setCanShow(true) .setActive(true); ResourcePermission authPermission2 = ObjectUtils.clone(authPermission); authPermission2.setName("测试ue模块权限过滤").setModel(UeModule.MODEL_MODEL); authGroup.setPermissions(Lists.newArrayList(authPermission, authPermission2)); authGroup.fieldSave(AuthGroup::getPermissions); } } 这里演示的module表比较特殊,需要同时设置ModuleDefinition和UeModule这2个模型做数据过滤 2.编写占位符拦截替换逻辑 package pro.shushi.pamirs.demo.core.placeholder; import org.springframework.stereotype.Component; import pro.shushi.pamirs.user.api.AbstractPlaceHolderParser; @Component public class EmployeeModulePlaceholder extends AbstractPlaceHolderParser { public static final String PLACEHOLDER = "${employeeModulePlaceholder}"; protected String value() { // TODO…

    2023年11月24日
    1.1K00

Leave a Reply

登录后才能评论