Admin Core

新建模块接口(仓储模式)

路径: Domain/Module/ModuleEntity.cs

目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
MyCompanyName.MyProjectName.Api
├── Domain
│ └── Module
│ └── ModuleEntity.cs
├── Repositories
│ └── Module
│ └── ModuleRepository.cs
├── Contracts
│ └── Services
│ └── Module
│ ├── Input
│ │ ├── ModuleAddInput.cs
│ │ ├── ModuleUpdateInput.cs
│ │ └── ModuleGetPageInput.cs
│ └── Output
│ ├── ModuleGetOutput.cs
│ └── ModuleGetPageOutput.cs
└── Services
└── Module
└── ModuleService.cs

1. 新建模块实体类

路径: Domain/Module/ModuleEntity.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using ZhonTai.Admin.Core.Entities;
using FreeSql.DataAnnotations;

namespace MyCompanyName.MyProjectName.Api.Domain.Module;

/// <summary>
/// 模块实体
/// </summary>
[Table(Name = ApiConsts.AreaName + "_module")]
[Index("idx_{tablename}_01", nameof(TenantId) + "," + nameof(Name), true)]
public partial class ModuleEntity : EntityTenant
{
/// <summary>
/// 名称
/// </summary>
[Column(StringLength = 50)]
public string Name { get; set; }
}

约定说明

约定项 说明
实体类命名 Entity 结尾,如 ModuleEntity
表名命名 下划线命名法,前缀为项目前缀
索引命名 idx 开头
多租户支持 继承EntityTenant 后自动按 TenantId 筛选数据

2. 新建模块仓储接口

路径: Domain/Module/IModuleRepository.cs

1
2
3
4
5
6
7
8
9
10
using ZhonTai.Admin.Core.Repositories;

namespace MyCompanyName.MyProjectName.Api.Domain.Module;

/// <summary>
/// 模块仓储接口
/// </summary>
public interface IModuleRepository : IRepositoryBase<ModuleEntity>
{
}

3. 新建模块仓储实现

路径: Repositories/Module/ModuleRepository.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using MyCompanyName.MyProjectName.Api.Core.Repositories;
using MyCompanyName.MyProjectName.Api.Domain.Module;
using ZhonTai.Admin.Core.Db.Transaction;

namespace MyCompanyName.MyProjectName.Api.Repositories.Module;

/// <summary>
/// 模块仓储
/// </summary>
public class ModuleRepository : AppRepositoryBase<ModuleEntity>, IModuleRepository
{
public ModuleRepository(UnitOfWorkManagerCloud uowm) : base(uowm)
{
}
}

说明

模块仓储需继承 App 项目基础仓储 AppRepositoryBase,使用当前项目主库操作模块表。


4. 新建输入输出 Dto

4.1 添加输入 Dto

路径: Contracts/Services/Module/Input/ModuleAddInput.cs

1
2
3
4
5
6
7
8
9
10
11
12
namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;

/// <summary>
/// 添加模块
/// </summary>
public class ModuleAddInput
{
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
}

4.2 修改输入 Dto

路径: Contracts/Services/Module/Input/ModuleUpdateInput.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System.ComponentModel.DataAnnotations;
using ZhonTai.Admin.Core.Validators;

namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;

/// <summary>
/// 修改模块
/// </summary>
public partial class ModuleUpdateInput : ModuleAddInput
{
/// <summary>
/// 编号
/// </summary>
[Required]
[ValidateRequired("请选择模块")]
public long Id { get; set; }
}

4.3 分页查询输入 Dto

路径: Contracts/Services/Module/Input/ModuleGetPageInput.cs

1
2
3
4
5
6
7
8
9
10
11
12
namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;

/// <summary>
/// 模块分页查询
/// </summary>
public partial class ModuleGetPageInput
{
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
}

4.4 单条查询输出 Dto

路径: Contracts/Services/Module/Output/ModuleGetOutput.cs

1
2
3
4
5
6
7
8
9
10
using MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Input;

namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Output;

/// <summary>
/// 模块详情
/// </summary>
public class ModuleGetOutput : ModuleUpdateInput
{
}

4.5 分页查询输出 Dto

路径: Contracts/Services/Module/Output/ModuleGetPageOutput.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace MyCompanyName.MyProjectName.Api.Contracts.Services.Module.Output;

/// <summary>
/// 模块分页列表
/// </summary>
public class ModuleGetPageOutput
{
/// <summary>
/// 主键
/// </summary>
public long Id { get; set; }

/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
}

5. 新建模块服务

路径: Services/Module/ModuleService.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System.Threading.Tasks;
using ZhonTai.Admin.Core.Dto;
using ZhonTai.Admin.Services;
using MyCompanyName.MyProjectName.Api.Domain.Module;
using MyCompanyName.MyProjectName.Api.Services.Module.Input;
using MyCompanyName.MyProjectName.Api.Services.Module.Output;
using MyCompanyName.MyProjectName.Api.Core.Consts;
using ZhonTai;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using Microsoft.AspNetCore.Mvc;
using Mapster;

namespace MyCompanyName.MyProjectName.Api.Services.Module;

/// <summary>
/// 模块服务
/// </summary>
[DynamicApi(Area = ApiConsts.AreaName)]
public class ModuleService : BaseService, IDynamicApi
{
private readonly IModuleRepository _moduleRepository;

public ModuleService(IModuleRepository moduleRepository)
{
_moduleRepository = moduleRepository;
}

/// <summary>
/// 查询模块
/// </summary>
/// <param name="id">模块编号</param>
/// <returns></returns>
public async Task<ModuleGetOutput> GetAsync(long id)
{
var result = await _moduleRepository.GetAsync<ModuleGetOutput>(id);
return result;
}

/// <summary>
/// 查询分页
/// </summary>
/// <param name="input">分页参数</param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<ModuleGetPageOutput>> GetPageAsync(PageInput<ModuleGetPageInput> input)
{
var key = input.Filter?.Name;

var list = await _moduleRepository.Select
.WhereIf(key.NotNull(), a => a.Name.Contains(key))
.Count(out var total)
.OrderByDescending(true, c => c.Id)
.Page(input.CurrentPage, input.PageSize)
.ToListAsync<ModuleGetPageOutput>();

return new PageOutput<ModuleGetPageOutput>
{
List = list,
Total = total
};
}

/// <summary>
/// 新增模块
/// </summary>
/// <param name="input">新增参数</param>
/// <returns>新模块编号</returns>
public async Task<long> AddAsync(ModuleAddInput input)
{
var entity = input.Adapt<ModuleEntity>();
await _moduleRepository.InsertAsync(entity);

return entity.Id;
}

/// <summary>
/// 修改模块
/// </summary>
/// <param name="input">修改参数</param>
public async Task UpdateAsync(ModuleUpdateInput input)
{
var entity = await _moduleRepository.GetAsync(input.Id);
if (entity?.Id == null)
{
throw ResultOutput.Exception("模块不存在");
}

input.Adapt(entity);
await _moduleRepository.UpdateAsync(entity);
}

/// <summary>
/// 彻底删除
/// </summary>
/// <param name="id">模块编号</param>
public async Task DeleteAsync(long id)
{
await _moduleRepository.DeleteAsync(m => m.Id == id);
}

/// <summary>
/// 软删除
/// </summary>
/// <param name="id">模块编号</param>
public async Task SoftDeleteAsync(long id)
{
await _moduleRepository.SoftDeleteAsync(id);
}

/// <summary>
/// 批量软删除
/// </summary>
/// <param name="ids">模块编号集合</param>
public async Task BatchSoftDeleteAsync(long[] ids)
{
await _moduleRepository.SoftDeleteAsync(ids);
}
}

动态接口生成

ModuleService 上增加 [DynamicApi(Area = ApiConsts.AreaName)] 特性,并继承 IDynamicApi 接口。


6. 接口权限说明

6.1 需要登录

1
2
3
4
5
6
[Login]
public async Task<ModuleGetOutput> GetAsync(long id)
{
var result = await _moduleRepository.GetAsync<ModuleGetOutput>(id);
return result;
}

6.2 允许匿名访问

1
2
3
4
5
6
[AllowAnonymous]
public async Task<ModuleGetOutput> GetAsync(long id)
{
var result = await _moduleRepository.GetAsync<ModuleGetOutput>(id);
return result;
}

6.3 授权接口

注意: 授权接口需删除 [Login][AllowAnonymous] 标记。


命名替换参考

占位符 替换为 示例
MyCompanyName 公司名 ZhonTai
MyProjectName 项目名 Admin
Module 业务模块名 User, Role, Product

#中台 |

#中台/新建接口项目 #中台/.NET模板 #中台/分布式微服务 #仓储模式 #API接口