需求:abp框架原有的abpusers表字段无法满足业务需求,需要新增字段来解决。
实现步骤如下
一.向abpusres表添加字段
1、在domain程序集下新建AppUser表
该类用来定义新增的字段,不需要继承任何父类,如下所示:
public class AppUser
{
/// <summary>
/// 会员Code
/// </summary>
[MaxLength(50)]
public string MemberCode { get; set; }
}
2.在EntityFrameworkCore程序集添加MyAppEfCoreEntityExtensionMappings类,
类名可以随意,但是按照惯例,一般以“项目名”+EfCoreEntityExtensionMappings命名。该类主要用来配置为IdentityUser新增字段,代码如下:
public class DemoEfCoreEntityExtensionMappings
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance.MapEfCoreProperty<IdentityUser, string>(nameof(AppUser.MemberCode), b => { b.HasMaxLength(50); });
});
}
}
3.在DemoEntityFrameworkCore程序集下的DemoEntityFrameworkCoreModule模块中配置PreConfigureServices
public override void PreConfigureServices(ServiceConfigurationContext context)
{
DemoEfCoreEntityExtensionMappings.Configure();
base.PreConfigureServices(context);
}
4.在Admin.HttpApi.Host程序集配置AdminHttpApiHostMigrationsDbContextFactory类中的CreateDbContext
同上一步,在DbContextFactory中进行同样配置,一些情况下我们需要通过DbContextFactory来获取DbContext,如不配置此项,将会导致获取的DbContext中内容不一致。
public DemoDbContext CreateDbContext(string[] args)
{
var configuration = BuildConfiguration();
var builder = new DbContextOptionsBuilder<DemoDbContext>()
.UseMySql(configuration.GetConnectionString("Default"), MySqlServerVersion.LatestSupportedServerVersion,
option => { option.MigrationsAssembly("Demo.Admin.HttpApi.Host"); });
//添加扩展配置
DemoEfCoreEntityExtensionMappings.Configure();
return new DemoDbContext(builder.Options);
}
5.在Application.Contracts层配置用户表相关Dto的扩展字段
public static class DemoDtoExtensions
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance
.AddOrUpdateProperty<string>(
new[]
{
typeof(IdentityUserDto),
typeof(IdentityUserCreateDto),
typeof(IdentityUserUpdateDto),
typeof(ProfileDto),
typeof(UpdateProfileDto)
},
"MemberCode"
);
});
}
}
6、在模块类ApplicationContractsModule中进行配置
为了是上一步配置生效,还需要在MyAppApplicationContractsModule中进行如下配置:
public override void PreConfigureServices(ServiceConfigurationContext context)
{
DemoDtoExtensions.Configure();
base.PreConfigureServices(context);
}
7、通过EF Core将MemberCode字段添加到abpUsers表中
1)生成迁移脚本
add-migration add_abpUusers_MemberCode
2) 将迁移脚本sql更新到数据库
update-database
二.向CurrentUser会话中Claim赋值
1.在Admin.HttpApi程序集下LoginController类中给toekn中Claim添加自定义字段
/// <summary>
/// 在CurrentUser对象的Claims中添加扩展字段
/// </summary>
private List<Claim> SetUserClaims(IdentityUser userInfo)
{
List<Claim> claims = new List<Claim>();
if (userInfo.ExtraProperties.ContainsKey("MemberCode"))
{
//添加会员Code
claims.Add(new Claim(MemberCode,userInfo.ExtraProperties["MemberCode"].ToString()));
}
return claims;
}
//在abp框架生成的方法中添加
private async Task<string> GetToken(IdentityUser user, string[] roles)
{
var claims = await CreateJwtClaims(user, roles);
//添加自定义claim
List<Claim> customClaims = SetUserClaims(userInfo);
if (!customClaims.IsNullOrEmpty())
{
claims.AddRange(customClaims);
}
//...
}
2.在程序集中使用
//获取abpuser表中扩展字段MemberCode值
var storeCode = CurrentUser.FindClaimValue("MemberCode");
三、前端账号管理添加扩展字段
1.账号管理列表
//修改vben-admin\src\views\identity\user\datas\TableData.ts列表参数配置
{
title: '会员Code',
dataIndex: 'extraProperties.MemberCode',
align: 'left',
width: 270,
sorter: true,
slots: { customRender: 'MemberCode' }, //通过自定义插槽在列表中显示
},
//(修改vben-admin\src\views\identity\user\components\UserTable.vue列表参数配置)
<BasicTable @register="registerTable">
<template #MemberCode="{ record }">
{{ record.extraProperties.MemberCode}}
</template>
</BasicTable>
2.修改列表添加扩展字段
//修改vben-admin\src\views\identity\user\datas\ModalData.ts配置
{
tab: t('AbpIdentity.UserInformations'),
field: 'memberCode',
component: 'Input',
label: '会员Code',
colProps: { span: 24 },
},
//在弹框打开事件里,通过useForm回调函数setFieldsValue设置会员code值
const [registerModal, { closeModal }] = useModalInner(async (val) => {
const formEl = unref(formElRef);
formEl?.setFieldsValue({
memberCode: val.extraProperties.MemberCode,
});
});
//保存时需要将会员Code值按后台api接口存在
handleSubmit() {
const formEl = unref(this.formElRef);
const param = formEl?.getFieldsValue();
if (param) {
param.extraProperties = { MemberCode: param.MemberCode};
}
formEl?.validate().then(() => {
this.handleSaveUser(param).then(() => {
this.$emit('change');
this.closeModal();
});
});
},
注:表单组件对JSON数据格式读取只能读取一层,像val.extraProperties.MemberCode是读取不到的,需要转换一下。
保存的时候格式又要转回去,必须和接口数据保持一致才行