X-Admin&ABP框架开发-版本管理

  多租户系统中,针对于不同租户开放不同功能,或是按照不同功能进行收费管理,需要从宿主本身去管理租户的版本信息,如同酒店人员对不同房间收取不同费用,依据房间内部设施,房间大小等设置不同收费标准。Abp系统中默认是多租户的,并且在Zero模块中实现了版本管理功能。

  演示地址:http://119.3.138.127/,更改Account/HostLogin进入宿主管理

一、设计前提

  基于Abp进行了相关限制,我将多租户变成了单租户,不允许添加新的租户,由于日常接触中,发现除了云平台这种SaaS需要多租户,对于企业客户来讲,自备物理服务器或自购云服务器是常有的事情,因此对于该部分客户而言,多租户也就没有太多意义,但是从软件公司本身考虑,一套软件能够销售多家客户,能够通过简单配置,开放关闭某些功能,以此来适应客户功能需求,是最佳选项了。因此对于这两种情况考虑后,对于本系统而言,采用的是单租户+宿主形式的,企业客户使用单租户,宿主形式留给软件公司方便配置单租户实际需要的功能。

  在Zero中,已经默认实现了版本管理,但是对于非收费版本的页面管理,应用服务等没有具体代码实现。

二、版本管理

1、应用层增加版本应用服务,对于版本需要进行的用户操作归纳为三个。

  • 可查看现有版本列表;
  • 可对现有版本信息及版本拥有的功能项进行编辑更改;
  • 可增加或是删除版本;
/// <summary>
/// 版本管理应用服务接口
/// </summary>
public interface IEditionAppService : IApplicationService
{
    /// <summary>
    /// 获取全部版本列表
    /// </summary>
    /// <returns></returns>
    Task<ListResultDto<EditionListDto>> GetEditionsList();

    /// <summary>
    /// 获取版本用于编辑
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task<GetEditionForEditOutput> GetEditionForEdit(NullableIdDto input);

    /// <summary>
    /// 创建或更新版本
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task CreateOrUpdateEdition(CreateOrUpdateEditionInput input);

    /// <summary>
    /// 删除版本
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task DeleteEdition(EntityDto input);

    /// <summary>
    /// 租户更换版本
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task MoveTenantsToAnotherEdition(MoveTenantsToAnotherEditionDto input);
}

2、实现应用服务

实现版本应用服务接口,以创建版本为例,顶部权限验证,增加版本信息,并且设置该版本所拥有的功能项,对于版本领域服务,Zero模块提供了完整实现AbpEditionManager,只需调用即可。

[AbpAuthorize(PermissionNames.Pages_Frame_Editions_Create)]
private async Task CreateEdition(CreateOrUpdateEditionInput input)
{
    var edition = ObjectMapper.Map<Edition>(input.Edition);

    await _editionManager.CreateAsync(edition);
    await CurrentUnitOfWork.SaveChangesAsync();

    await SetFeatureValues(edition, input.FeatureValues);
}

private Task SetFeatureValues(Edition edition, List<NameValueDto> featureValues)
{
    return _editionManager.SetFeatureValuesAsync(edition.Id, featureValues.Select(fv => new NameValue(fv.Name, fv.Value)).ToArray());
}

3、控制器中增加版本管理控制器并设计相应的方法(逐渐认识到,能够使用Dto的尽量使用Dto),控制器部分主要承担路由功能,将前端请求转发到应用服务、领域服务中。

4、页面层实现,列表展示+弹框添加/编辑,弹框内展示出功能项树结构,供版本配置需要的功能项。

5、页面功能展示,列表展示现有版本,因考虑到版本数量不会很多,无需分页也无需条件查询。该部分菜单仅对宿主提供

三、版本功能管理

  对于功能项,ABP框架中采用声明式,现在领域层中声明具体的功能项,在代码中,依照当前租户是否存在声明的某个功能项去决定是否执行某个功能,

1、功能项声明,在Core层->Features文件夹中声明该系统拥有的功能,需要对租户进行控制划分的。如客户服务模块,对于小部分企业客户而言,可能不需要该模块,则可通过对客户服务模块进行功能控制,页面上,代码中该部分功能都会绕过去。

/// <summary>
/// 功能管理
/// </summary>
public static class AppFeatures
{
    public const string HostSettings = "App.HostSettings";

    public const string CustomerService = "App.CustomerService";
}

2、功能绑定到系统中,在Features文件夹中,AppFeatureProvider负责将声明的功能绑定到系统中,可以对功能项进行默认设置,如对于客户服务要默认为都具有,可以更改defaultValue设置为true,具体更丰富的设计查看Abp提供的重载方法。可对功能项进行树结构设计。

/// <summary>
/// 功能设置提供器
/// </summary>
public class AppFeatureProvider : FeatureProvider
{
    public override void SetFeatures(IFeatureDefinitionContext context)
    {
        var hostSettings = context.Create(
            AppFeatures.HostSettings,
            defaultValue: "false",
            displayName: L("HostSettings"),
            inputType: new CheckboxInputType()
        );

        var customerService = context.Create(
            AppFeatures.CustomerService,
            defaultValue: "false",
            displayName: L("CustomerService"),
            inputType: new CheckboxInputType()
        );

        var customerServiceMaps = customerService.CreateChildFeature(
            AppFeatures.CustomerService_Maps,
            defaultValue: "false",
            displayName: L("CustomerServiceMaps"),
            inputType: new CheckboxInputType()
        );
    }

    private ILocalizableString L(string name)
    {
        return new LocalizableString(name, SurroundConsts.LocalizationSourceName);
    }
}

3、版本管理中关联功能项,在版本管理页面,编辑版本信息弹框内右侧tab页功能项树结构,可查看系统已有功能,并通过勾选形式确定该版本需要的功能。

四、租户版本管理

  软件公司可以在发售给客户的软件中预先配置好几个版本,方便部署实施时,更改租户使用的版本即可完成功能划分。默认使用的是单个租户,因此,对于租户的增删操作直接pass掉了。对于Abp提供的多租户的管理部分代码进行相关更改,适应单租户的一些操作。

  • 可查看当前租户信息;
  • 可切换租户使用版本;

1、在已有租户应用服务中更改已有代码,取消原有继承的CRUD服务,实现获取租户列表,更改版本等几个操作。

/// <summary>
/// 租户应用服务
/// </summary>
public interface ITenantAppService : IApplicationService
{
    /// <summary>
    /// 获取单个租户
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task<TenantListDto> GetTenant(EntityDto<int> input);

    /// <summary>
    /// 获取全部租户列表
    /// </summary>
    /// <returns></returns>
    Task<ListResultDto<TenantListDto>> GetTenantsList();

    /// <summary>
    /// 移动当前租户版本到其它版本
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task MoveTenantToAnotherEdition(MoveTenantToAnotherEditionInput input);
}

2、实现替换的几个租户应用服务接口方法,此处仅展示切换租户版本。完成顶部权限验证,版本参数验证,租户版本修改。

[AbpAuthorize(PermissionNames.Pages_Frame_Tenants_MoveTenantToAnotherEdition)]
public async Task MoveTenantToAnotherEdition(MoveTenantToAnotherEditionInput input)
{
    if (input.SourceEditionId == input.TargetEditionId)
    {
        throw new UserFriendlyException("原版本与目标版本一致,无需切换");
    }

    var tenant = await _tenantManager.GetByIdAsync(input.TenantId);
    tenant.EditionId = input.TargetEditionId;
    await _tenantManager.UpdateAsync(tenant);
}

3、租户控制器层面已经存在了相关代码,改造部分代码并完成页面实现,页面实现中主要是弹框内列举出当前系统已有的版本列表信息,方便切换版本。

4、页面效果实现,版本切换操作实现。

五、菜单权限控制

  对于诸如版本管理、租户管理这部分菜单仅能够对宿主进行开放,因此在权限列表中对该部分权限进行控制,在导航菜单中会依据是否有权限进行过滤菜单。权限中使用命名参数multiTenancySides设置为仅宿主使用。

#region 版本管理
var editions = frame.CreateChildPermission(PermissionNames.Pages_Frame_Editions, L("Editions"), multiTenancySides: MultiTenancySides.Host);
editions.CreateChildPermission(PermissionNames.Pages_Frame_Editions_Create, L("CreateEdition"), multiTenancySides: MultiTenancySides.Host);
editions.CreateChildPermission(PermissionNames.Pages_Frame_Editions_Update, L("UpdateEdition"), multiTenancySides: MultiTenancySides.Host);
editions.CreateChildPermission(PermissionNames.Pages_Frame_Editions_Delete, L("DeleteEdition"), multiTenancySides: MultiTenancySides.Host);
editions.CreateChildPermission(PermissionNames.Pages_Frame_Editions_MoveTenantsToAnotherEdition, L("MoveTenantsToAnotherEdition"), multiTenancySides: MultiTenancySides.Host);
#endregion

#region 租户管理
var tenants = frame.CreateChildPermission(PermissionNames.Pages_Frame_Tenants, L("Tenants"), multiTenancySides: MultiTenancySides.Host);
tenants.CreateChildPermission(PermissionNames.Pages_Frame_Tenants_MoveTenantToAnotherEdition, L("MoveTenantsToAnotherEdition"), multiTenancySides: MultiTenancySides.Host);
#endregion

  对于宿主登录,在主页面设置了两个入口,如登录时使用Account/HostLogin则为宿主登录,否则为租户登录。

 仓库地址:https://gitee.com/530521314/Partner.Surround.git

2020-04-12,望技术有成后能回来看见自己的脚步

原文地址:https://www.cnblogs.com/CKExp/p/12682687.html

时间: 2024-10-12 12:41:43

X-Admin&ABP框架开发-版本管理的相关文章

X-Admin&amp;ABP框架开发-代码生成器

在日常开发中,有时会遇到一些相似的代码,甚至是只要CV一次,改几个名称,就可以实现功能了,而且总归起来,都可以由一些公用的页面更改而来,因此,结合我日常开发中使用到的页面,封装一个适合自己的代码生成器,仅处于入门阶段,包括生成的代码结构都仅是把框架展示出来,内部详细暂时没得,针对于应用服务中的接口和实现,相关Dto,MVC中的控制器.视图及视图模型进行了模板制作及生成相关的文件. 一.设计思路 方案一:开始想到的是,搞个控制台,然后给一个.cs文件,然后控制台去解析其中的命名空间,类名,属性,再

X-Admin&amp;ABP框架开发-设置管理

在网站开发中,设置是不可缺少的一环,如用户设置.系统设置.甚至是租户设置等.ABP对于设置的管理已经做了很好的处理,我们可以借助巨人的力量来完成我们的冒险. ABP官网地址:https://aspnetboilerplate.com/ 一.设置的层级划分 ABP中提供了三种类型的设置,用户级别.应用级别.租户级别,针对于不同级别有着不同的侧重点,比如用户级别,针对于用户的一些设置,如主题设置,接收通知设置等:针对应用级别,该级别也能在用户层级上进行影响,好比如设置统一的主题皮肤,而它主要体现在整

Module Zero模块 [X-Admin&amp;ABP框架开发-RBAC]

在业务系统需求规划过程中,通常对于诸如组织机构.用户和角色等这种基础功能,通常是将这部分功能规划到通用子域中,这也说明了,对于这部分功能来讲,是系统的基石,整个业务体系是建立于这部分基石之上的,当然,还有诸如多语言.设置管理.认证和授权等.对于这部分功能,ABP中存在这些概念,并且通过Module Zero模块完成了这些概念. 一.角色访问控制之RBAC RBAC:Role Based Access Control,基于角色的访问控制,这在目前大多数软件中来讲已经算得上是普遍应用了,最常见的结构

ABP框架个人开发实战(1)_环境搭建

前言 之前关注ABP框架有一阵子了,一直没有潜下心来实际研究一下.最近想自己建站,以后有自己的功能开发项目,可以在自己的站点上开发,并一步步的完善,所以找个比较好用的框架迫在眉睫,选来选去,决定用ABP框架.用群里的大大门的话来说,掌握了ABP,基本就可以飞天了~ 先简单介绍下吧(以下部分资料来自群里资料,如有侵权,请告知): ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开

ABP开发框架前后端开发系列---(15)ABP框架的服务端和客户端缓存的使用

缓存在一个大型一点的系统里面是必然会涉及到的,合理的使用缓存能够给我们的系统带来更高的响应速度.由于数据提供服务涉及到数据库的相关操作,如果客户端的并发数量超过一定的数量,那么数据库的请求处理则以爆发式增长,如果数据库服务器无法快速处理这些并发请求,那么将会增加客户端的请求时间,严重者可能导致数据库服务或者应用服务直接瘫痪.缓存方案就是为这个而诞生,随着缓存的引入,可以把数据库的IO耗时操作,转换为内存数据的快速响应操作,或者把整个页面缓存到缓存系统里面.本篇随笔主要介绍利用ABP框架的支持实现

Eclipse+CXF框架开发Web服务实战

一. 说明 采用CXF框架开发webservice. 所用软件及版本如下. ? 操作系统:Window XP SP3. ? JDK:JDK1.6.0_07,http://www.oracle.com/technetwork/java/javase/downloads/index.html. ? Tomcat:apache-tomcat-6.0.14.exe,http://tomcat.apache.org/. ? IDE:eclipse-jee-juno-SR1-win32.zip,http:/

详解ABP框架的多租户

(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ABP框架对多租户场景提供了很好的支持,内建了多租户的处理机制,今天我们来深入解析一下这一特性. 最近在基于ABP框架(ASP.NET Boilerplate)开发了一个SaaS.所以接下来可能会时不时分享一下ABP方面的文章.今天来介绍一下ABP对多租户提供的支持特性. ABP简介 ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个

ABP框架详解(五)Navigation

ABP框架中的Navigation功能用于管理业务系统中所有可用的菜单导航控件,通常在业务系统的首页会有一个全局性的导航菜单,JD商城,天猫,猪八戒网莫不如是.所以为方便起见,Navigation功能默认定义了一个"MainMenu"菜单添加到缓存字典中.该Navigation功能与普通ERP项目中可定制动态生成的导航菜单最大的区别应该是每一个菜单定义(MenuItemDefinition)可以设置一个权限只有用户拥有权限才会显示给该用户,控制更加的细更加的松耦合不是直接绑定到某个用户

ABP框架用Dapper实现通过SQL访问数据库

为了防止不提供原网址的转载,特在这里加上原文链接:http://www.cnblogs.com/skabyy/p/7517397.html 本篇我们实现数据库的访问.我们将实现两种数据库访问方法来访问一个SQLite数据库--使用NHibernate实现的ORM映射访问和使用Dapper实现的SQL语句访问.然后完成前一篇未完成的CreateTweet和GetTweets接口. 在开始之前,先做一些准备工作,新建Domain层的Module: public class MyTweetDomain