├── test ├── Mbill.Core.Test │ ├── GlobalUsings.cs │ ├── SnowFlakeTest.cs │ └── Mbill.Core.Test.csproj ├── Mbill.Service.Test │ ├── GlobalUsings.cs │ ├── UnitTest1.cs │ └── Mbill.Service.Test.csproj └── Mbill.Infrastructure.Test │ ├── GlobalUsings.cs │ └── Mbill.Infrastructure.Test.csproj ├── doc ├── 技术栈.xmind └── images │ ├── 技术栈.png │ └── memoyu.png ├── .gitattributes ├── src ├── Mbill │ ├── Program.cs │ ├── Startup.cs │ ├── wwwroot │ │ └── logo │ │ │ └── favicon-32x32.png │ ├── Controllers │ │ ├── ApiControllerBase.cs │ │ ├── Core │ │ │ ├── DataSeedController.cs │ │ │ ├── LogController.cs │ │ │ ├── WxController.cs │ │ │ ├── NoticeController.cs │ │ │ ├── PermissionController.cs │ │ │ └── FileController.cs │ │ └── User │ │ │ └── UserController.cs │ ├── Modules │ │ ├── RepositoryModule.cs │ │ ├── AutofacModule.cs │ │ ├── ServiceModule.cs │ │ ├── Configs │ │ │ ├── MigrationStartupTask.cs │ │ │ ├── ValidJtiHandler.cs │ │ │ └── PermissionAuthorizationHandler.cs │ │ ├── DependencyModule.cs │ │ └── FreeSqlModule.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Dockerfile │ ├── appsettings.Production.json │ ├── appsettings.json │ ├── appsettings.Development.json │ └── Mbill.csproj ├── Mbill.Service │ ├── Core │ │ ├── Logger │ │ │ ├── ILogSvc.cs │ │ │ ├── LogSvc.cs │ │ │ ├── Input │ │ │ │ └── LogPagingDto.cs │ │ │ └── Output │ │ │ │ └── LogDto.cs │ │ ├── Auth │ │ │ ├── Input │ │ │ │ ├── BaseLoginInput.cs │ │ │ │ ├── AccountLoginDto.cs │ │ │ │ └── WxLoginInput.cs │ │ │ ├── Output │ │ │ │ ├── TokenWithUserDto.cs │ │ │ │ ├── PreLoginUserDto.cs │ │ │ │ ├── TokenDto.cs │ │ │ │ └── LoginUserDto.cs │ │ │ ├── IJwtTokenSvc.cs │ │ │ └── IAccountSvc.cs │ │ ├── Files │ │ │ ├── Input │ │ │ │ └── MediaImagePagingInput.cs │ │ │ ├── Output │ │ │ │ ├── MediaImageDto.cs │ │ │ │ ├── FileDto.cs │ │ │ │ └── QiniuUploadTokenDto.cs │ │ │ ├── IMediaImageSvc.cs │ │ │ ├── IQiniuFileSvc.cs │ │ │ └── MediaImageSvc.cs │ │ ├── User │ │ │ ├── Output │ │ │ │ ├── UserWithRolesDto.cs │ │ │ │ └── UserDto.cs │ │ │ ├── Input │ │ │ │ ├── UserPagingDto.cs │ │ │ │ ├── ModifyUserBaseInfoDto.cs │ │ │ │ └── ModifyUserDto.cs │ │ │ ├── IUserIdentitySvc.cs │ │ │ ├── IUserSvc.cs │ │ │ └── UserIdentitySvc.cs │ │ ├── Notice │ │ │ ├── Output │ │ │ │ └── NoticeDto.cs │ │ │ ├── Input │ │ │ │ └── ModifyNoticeDto.cs │ │ │ ├── INoticeSvc.cs │ │ │ └── NoticeSvc.cs │ │ ├── Permission │ │ │ ├── Input │ │ │ │ ├── ModifyPermissionDto.cs │ │ │ │ ├── ModifyRoleDto.cs │ │ │ │ ├── DispatchPermissionsDto.cs │ │ │ │ └── PermissionDto.cs │ │ │ ├── Output │ │ │ │ ├── RoleDto.cs │ │ │ │ ├── RoleWithPermissionDto.cs │ │ │ │ ├── TreePermissionDto.cs │ │ │ │ └── RolePermissionDto.cs │ │ │ ├── IPermissionSvc.cs │ │ │ └── IRoleSvc.cs │ │ ├── Wx │ │ │ ├── IWxSvc.cs │ │ │ ├── Output │ │ │ │ └── WxCode2SessionDto.cs │ │ │ └── WxSvc.cs │ │ └── DataSeed │ │ │ ├── IDataSeedSvc.cs │ │ │ └── Output │ │ │ ├── BillAssetDataSeedDto.cs │ │ │ └── BillCategoryDataSeedDto.cs │ ├── Base │ │ ├── IApplicationSvc.cs │ │ ├── ICrudApplicationSvc.cs │ │ └── ApplicationSvc.cs │ ├── PreOrder │ │ ├── Output │ │ │ ├── PreOrderItemDto.cs │ │ │ ├── IndexPreOrderStatDto.cs │ │ │ ├── PreOrderGroupWithPreAmountDto.cs │ │ │ ├── PreOrderGroupDto.cs │ │ │ ├── PreOrderGroupWithStatDto.cs │ │ │ ├── GroupPreOrderStatDto.cs │ │ │ ├── PreOrderDto.cs │ │ │ └── PreOrderSimpleDto.cs │ │ ├── Input │ │ │ ├── GroupPreOrderStatInput.cs │ │ │ ├── IndexPreOrderStatInput.cs │ │ │ ├── UpdatePreOrderGroupInput.cs │ │ │ ├── GroupToBillInput.cs │ │ │ ├── GroupPreOrderPagingInput.cs │ │ │ ├── MonthPreOrderGroupPagingInput.cs │ │ │ ├── UpdatePreOrderStatusInput.cs │ │ │ ├── CreatePreOrderGroupInput.cs │ │ │ ├── UpdatePreOrderInput.cs │ │ │ └── CreatePreOrderInput.cs │ │ ├── IPreOrderSvc.cs │ │ └── IPreOrderGroupSvc.cs │ ├── Bill │ │ ├── Asset │ │ │ ├── Input │ │ │ │ ├── SortAssetInput.cs │ │ │ │ ├── AssetPagingDto.cs │ │ │ │ ├── EditAssetInput.cs │ │ │ │ └── CreateAssetInput.cs │ │ │ ├── Output │ │ │ │ ├── AssetPageDto.cs │ │ │ │ ├── AssetGroupDto.cs │ │ │ │ └── AssetDto.cs │ │ │ └── IAssetSvc.cs │ │ ├── Category │ │ │ ├── Input │ │ │ │ ├── SortCategoryInput.cs │ │ │ │ ├── CategoryPagingInput.cs │ │ │ │ ├── EditCategoryInput.cs │ │ │ │ └── CreateCategoryInput.cs │ │ │ ├── Output │ │ │ │ ├── CategoryPageDto.cs │ │ │ │ ├── CategoryGroupDto.cs │ │ │ │ └── CategoryDto.cs │ │ │ └── ICategorySvc.cs │ │ └── Bill │ │ │ ├── Output │ │ │ ├── RankingDto.cs │ │ │ ├── CategoryPercentSummaryDto.cs │ │ │ ├── BillsByDayWithStatDto.cs │ │ │ ├── StatisticsDto.cs │ │ │ ├── BillsByDayDto.cs │ │ │ ├── CategoryPercentStatDto.cs │ │ │ ├── YearSurplusStatDto.cs │ │ │ ├── YearTotalStatDto.cs │ │ │ ├── YearTotalTrendStatDto.cs │ │ │ ├── MapDto.cs │ │ │ ├── MonthTotalTrendStatDto.cs │ │ │ ├── BillDetailDto.cs │ │ │ ├── MonthTotalStatDto.cs │ │ │ ├── BiIllDto.cs │ │ │ ├── BillTotalDto.cs │ │ │ ├── BillDateWithTotalDto.cs │ │ │ ├── BillSimpleDto.cs │ │ │ ├── CategoryPercentGroupDto.cs │ │ │ └── BillSearchRecordOutput.cs │ │ │ └── Input │ │ │ ├── YearTotalTrendStatInput.cs │ │ │ ├── MonthTotalTrendStatInput.cs │ │ │ ├── BillDateInput.cs │ │ │ ├── RangeHasBillDaysInput.cs │ │ │ ├── YearTotalStatInput.cs │ │ │ ├── MonthTotalStatInput.cs │ │ │ ├── CategoryPercentGroupInput.cs │ │ │ ├── RankingPagingInput.cs │ │ │ ├── DayBillInput.cs │ │ │ ├── MonthBillPagingInput.cs │ │ │ ├── CategoryPercentStatInput.cs │ │ │ ├── BillPagingInput.cs │ │ │ ├── ModifyBillInput.cs │ │ │ └── BillSearchPagingInput.cs │ ├── Common │ │ └── Registers │ │ │ ├── Core │ │ │ ├── FileRegister.cs │ │ │ ├── NoticeRegister.cs │ │ │ └── UserRegister.cs │ │ │ ├── Bill │ │ │ ├── AssetRegister.cs │ │ │ ├── CategoryRegister.cs │ │ │ └── BillRegister.cs │ │ │ ├── BaseRegister.cs │ │ │ └── PreOrder │ │ │ └── PreOrderRegister.cs │ └── Mbill.Service.csproj ├── Mbill.Core │ ├── Data │ │ └── Authorization │ │ │ ├── ValidJtiRequirement.cs │ │ │ └── PermissionAuthorizationRequirement.cs │ ├── Interface │ │ ├── IRepositories │ │ │ ├── Bill │ │ │ │ ├── IBillMongoRepo.cs │ │ │ │ ├── IBillSearchRecordRepo.cs │ │ │ │ ├── IBillRepo.cs │ │ │ │ ├── IAssetRepo.cs │ │ │ │ └── ICategoryRepo.cs │ │ │ ├── Core │ │ │ │ ├── INoticeRepo.cs │ │ │ │ ├── IBaseItemRepo.cs │ │ │ │ ├── IDataSeedRepo.cs │ │ │ │ ├── IUserRoleRepo.cs │ │ │ │ ├── IMediaImageRepo.cs │ │ │ │ ├── IRoleRepo.cs │ │ │ │ ├── IIPLogRepo.cs │ │ │ │ ├── IBaseTypeRepo.cs │ │ │ │ ├── IPermissionRepo.cs │ │ │ │ ├── IUserIdentityRepo.cs │ │ │ │ ├── IRolePermissionRepo.cs │ │ │ │ ├── IFileRepo.cs │ │ │ │ └── IUserRepo.cs │ │ │ ├── PreOrder │ │ │ │ ├── IPreOrderGroupRepo.cs │ │ │ │ └── IPreOrderRepo.cs │ │ │ └── Base │ │ │ │ └── IAuditBaseRepo.cs │ │ └── IDependency │ │ │ ├── ISingletonDependency.cs │ │ │ ├── IScopedDependency.cs │ │ │ └── ITransientDependency.cs │ ├── Domains │ │ ├── Common │ │ │ ├── SortInput.cs │ │ │ ├── Consts │ │ │ │ ├── CacheKeyConst.cs │ │ │ │ ├── CoreClaimTypes.cs │ │ │ │ └── SystemConst.cs │ │ │ ├── Base │ │ │ │ ├── BaseChart.cs │ │ │ │ └── BaseSerie.cs │ │ │ ├── RequestInfo.cs │ │ │ ├── Enums │ │ │ │ ├── Enums.cs │ │ │ │ └── Base │ │ │ │ │ ├── CapConfigEnums.cs │ │ │ │ │ └── ServiceResultCode.cs │ │ │ └── ServicePage.cs │ │ └── Entities │ │ │ ├── Core │ │ │ ├── RolePermissionEntity.cs │ │ │ ├── NoticeEntity.cs │ │ │ ├── IPLogEntity.cs │ │ │ ├── DataSeedEntity.cs │ │ │ ├── MediaImageEntity.cs │ │ │ ├── UserRoleEntity.cs │ │ │ ├── BaseTypeEntity.cs │ │ │ ├── PermissionEntity.cs │ │ │ ├── FileEntity.cs │ │ │ ├── RoleEntity.cs │ │ │ ├── BaseItemEntity.cs │ │ │ └── UserIdentityEntity.cs │ │ │ ├── PreOrder │ │ │ ├── PreOrderGroupEntity.cs │ │ │ └── PreOrderEntity.cs │ │ │ └── Bill │ │ │ ├── CategoryEntity.cs │ │ │ ├── AssetEntity.cs │ │ │ └── BillSearchRecordEntity.cs │ ├── Security │ │ ├── Dto │ │ │ └── UserRoleCacheDto.cs │ │ ├── ICurrentUser.cs │ │ └── PermissionDefinition.cs │ ├── AOP │ │ ├── Attributes │ │ │ ├── DisableAuditingAttribute.cs │ │ │ ├── MongoCollectionAttribute.cs │ │ │ ├── CacheableAttribute.cs │ │ │ ├── TransactionalAttribute.cs │ │ │ └── LocalAuthorizeAttribute.cs │ │ ├── Intercepts │ │ │ └── UnitOfWorkInterceptor.cs │ │ ├── Middleware │ │ │ ├── IpLimitMilddleware.cs │ │ │ ├── SwaggerMiddleware.cs │ │ │ └── ExceptionHandlerMiddleware.cs │ │ └── Filters │ │ │ ├── InputFieldActionFilter.cs │ │ │ └── SwaggerDocumentFilter.cs │ ├── Extensions │ │ ├── AttributeExtensions.cs │ │ ├── Converters │ │ │ └── JsonLongToStringConverter.cs │ │ ├── ClaimsIdentityExtensions.cs │ │ └── ServiceCollection │ │ │ └── ControllerSetup.cs │ ├── Common │ │ ├── Configs │ │ │ └── FileStorageOptions.cs │ │ └── SnowFlake.cs │ └── Exceptions │ │ └── KnownException.cs ├── Mbill.ToolKits │ ├── _Imports.cs │ ├── Utils │ │ ├── StringUtil.cs │ │ ├── MultipartRequestUtil.cs │ │ ├── HashUtil.cs │ │ ├── EncryptUtil.cs │ │ └── ColorUtil.cs │ └── Mbill.ToolKits.csproj └── Mbill.Infrastructure │ ├── Mbill.Infrastructure.csproj │ ├── Repository │ ├── Bill │ │ ├── BillMongoRepo.cs │ │ ├── BillSearchRecordRepo.cs │ │ ├── AssetRepo.cs │ │ ├── CategoryRepo.cs │ │ └── BillRepo.cs │ ├── Core │ │ ├── IPLogRepo.cs │ │ ├── NoticeRepo.cs │ │ ├── BaseItemRepo.cs │ │ ├── DataSeedRepo.cs │ │ ├── PermissionRepo.cs │ │ ├── MediaImageRepo.cs │ │ ├── UserRoleRepo.cs │ │ ├── RoleRepo.cs │ │ ├── BaseTypeRepo.cs │ │ ├── UserIdentityRepo.cs │ │ ├── RolePermissionRepo.cs │ │ ├── UserRepo.cs │ │ └── FileRepo.cs │ └── PreOrder │ │ ├── PreOrderGroupRepo.cs │ │ └── PreOrderRepo.cs │ └── _Imports.cs ├── init └── mbill-images-init.7z ├── .dockerignore ├── scripts ├── Delete bin&obj Folder.bat └── CreateNewProject.bat ├── LICENSE └── README.md /test/Mbill.Core.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /test/Mbill.Service.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /test/Mbill.Infrastructure.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /doc/技术栈.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Memoyu/mbill_service/HEAD/doc/技术栈.xmind -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /doc/images/技术栈.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Memoyu/mbill_service/HEAD/doc/images/技术栈.png -------------------------------------------------------------------------------- /doc/images/memoyu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Memoyu/mbill_service/HEAD/doc/images/memoyu.png -------------------------------------------------------------------------------- /src/Mbill/Program.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Memoyu/mbill_service/HEAD/src/Mbill/Program.cs -------------------------------------------------------------------------------- /src/Mbill/Startup.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Memoyu/mbill_service/HEAD/src/Mbill/Startup.cs -------------------------------------------------------------------------------- /init/mbill-images-init.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Memoyu/mbill_service/HEAD/init/mbill-images-init.7z -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Logger/ILogSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Logger; 2 | 3 | public interface ILogSvc 4 | { 5 | } -------------------------------------------------------------------------------- /src/Mbill.Service/Base/IApplicationSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Base; 2 | 3 | public interface IApplicationSvc 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /test/Mbill.Core.Test/SnowFlakeTest.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Memoyu/mbill_service/HEAD/test/Mbill.Core.Test/SnowFlakeTest.cs -------------------------------------------------------------------------------- /src/Mbill/wwwroot/logo/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Memoyu/mbill_service/HEAD/src/Mbill/wwwroot/logo/favicon-32x32.png -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/Input/BaseLoginInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth.Input; 2 | 3 | public class BaseLoginInput 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Output/PreOrderItemDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Output; 2 | 3 | public class PreOrderItemDto : IEntityDto 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill/Controllers/ApiControllerBase.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Controllers.Core; 2 | 3 | [ApiController] 4 | public class ApiControllerBase : ControllerBase 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/Mbill.Core/Data/Authorization/ValidJtiRequirement.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Data.Authorization; 2 | 3 | public class ValidJtiRequirement : IAuthorizationRequirement 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Bill/IBillMongoRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Bill; 2 | 3 | public interface IBillMongoRepo : IMongoBaseRepo 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/INoticeRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Core; 2 | 3 | public interface INoticeRepo : IAuditBaseRepo 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Asset/Input/SortAssetInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Asset.Input; 2 | 3 | public class SortAssetInput 4 | { 5 | public List Sorts { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IBaseItemRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Core; 2 | 3 | public interface IBaseItemRepo : IAuditBaseRepo 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IDataSeedRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Core; 2 | 3 | public interface IDataSeedRepo : IAuditBaseRepo 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IUserRoleRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Core; 2 | 3 | public interface IUserRoleRepo : IAuditBaseRepo 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/SortInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common; 2 | 3 | public class SortInput 4 | { 5 | public long BId { get; set; } 6 | 7 | public int Sort { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Category/Input/SortCategoryInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Category.Input; 2 | 3 | public class SortCategoryInput 4 | { 5 | public List Sorts { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /test/Mbill.Service.Test/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Test 2 | { 3 | public class UnitTest1 4 | { 5 | [Fact] 6 | public void Test1() 7 | { 8 | 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Bill/IBillSearchRecordRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Bill; 2 | 3 | public interface IBillSearchRecordRepo : IMongoBaseRepo 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IMediaImageRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Core 2 | { 3 | public interface IMediaImageRepo : IAuditBaseRepo 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Mbill.Core/Security/Dto/UserRoleCacheDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Security.Dto; 2 | 3 | public class UserRoleCacheDto 4 | { 5 | public long RoleBId { get; set; } 6 | 7 | public int RoleType { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/Consts/CacheKeyConst.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common.Consts; 2 | 3 | public class CacheKeyConst 4 | { 5 | public static string UserRole(long userBId) => $"user:role:{userBId}"; 6 | } 7 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/RankingDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class RankingDto 4 | { 5 | public int Ranking { get; set; } 6 | 7 | public BillSimpleDto Item { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Files/Input/MediaImagePagingInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Files.Input 2 | { 3 | public class MediaImagePagingInput : PagingDto 4 | { 5 | public int Type { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/User/Output/UserWithRolesDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.User.Output 2 | { 3 | public class UserWithRolesDto : UserDto 4 | { 5 | public List Roles { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Mbill.ToolKits/_Imports.cs: -------------------------------------------------------------------------------- 1 | global using System; 2 | global using System.Collections.Generic; 3 | global using System.Text; 4 | global using System.IO; 5 | global using System.Reflection; 6 | global using System.Security.Cryptography; -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Files/Output/MediaImageDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Files.Output; 2 | 3 | public class MediaImageDto : EntityDto 4 | { 5 | public string Path { get; set; } 6 | 7 | public string Url { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IDependency/ISingletonDependency.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IDependency; 2 | 3 | /// 4 | /// 实现该接口将自动注册到Ioc容器,生命周期为单例例 5 | /// 6 | public interface ISingletonDependency 7 | { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Asset/Output/AssetPageDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Asset.Output; 2 | 3 | public class AssetPageDto : AssetDto 4 | { 5 | public string ParentName { get; set; } 6 | 7 | public string TypeName { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Notice/Output/NoticeDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Notice.Output; 2 | 3 | public class NoticeDto : EntityDto 4 | { 5 | public string Content { get; set; } 6 | 7 | public DateTime CreateTime { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IDependency/IScopedDependency.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IDependency; 2 | 3 | /// 4 | /// 实现该接口将自动注册到Ioc容器,生命周期为每次请求创建一个实例 5 | /// 6 | public interface IScopedDependency 7 | { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/CategoryPercentSummaryDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class CategoryPercentSummaryDto 4 | { 5 | public long BId { get; set; } 6 | 7 | public decimal Sum { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/Base/BaseChart.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common.Base; 2 | 3 | public class BaseChart 4 | { 5 | public List Categories { get; set; } = new(); 6 | 7 | public List Series { get; set; } = new(); 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IDependency/ITransientDependency.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IDependency; 2 | 3 | /// 4 | /// 实现该接口将自动注册到Ioc容器,生命周期为每次调用,都会重新实例化对象;每次请求都创建一个新的对象 5 | /// 6 | public interface ITransientDependency 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/BillsByDayWithStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class BillsByDayWithStatDto : BillsByDayDto 4 | { 5 | public string Expend { get; set; } 6 | 7 | public string Income { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Category/Output/CategoryPageDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Category.Output; 2 | 3 | public class CategoryPageDto : CategoryDto 4 | { 5 | public string ParentName { get; set; } 6 | 7 | public string TypeName { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Files/Output/FileDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Files.Output; 2 | 3 | public class FileDto : EntityDto 4 | { 5 | public string Key { get; set; } 6 | public string Path { get; set; } 7 | public string Url { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Attributes/DisableAuditingAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Attributes; 2 | 3 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)] 4 | public class DisableAuditingAttribute : Attribute 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/YearTotalTrendStatInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class YearTotalTrendStatInput 4 | { 5 | /// 6 | /// 指定的年 7 | /// 8 | public int Year { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/GroupPreOrderStatInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class GroupPreOrderStatInput 4 | { 5 | /// 6 | /// 指定的分组 7 | /// 8 | public long BId { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/IndexPreOrderStatInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class IndexPreOrderStatInput 4 | { 5 | /// 6 | /// 指定的年月 7 | /// 8 | public DateTime Month { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/UpdatePreOrderGroupInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Input; 2 | 3 | public class UpdatePreOrderGroupInput : BaseUpdateInput 4 | { 5 | public string Name { get; set; } 6 | 7 | public string Description { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.ToolKits/Utils/StringUtil.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.ToolKits.Utils; 2 | 3 | public static class StringUtil 4 | { 5 | public static string AmountFormat(this decimal amount) 6 | { 7 | return string.Format("{0:#,0.##}", amount); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Attributes/MongoCollectionAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Attributes 2 | { 3 | [AttributeUsage(AttributeTargets.Class)] 4 | public class MongoCollectionAttribute : Attribute 5 | { 6 | public string Name { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/MonthTotalTrendStatInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class MonthTotalTrendStatInput 4 | { 5 | /// 6 | /// 指定的年月 7 | /// 8 | public DateTime Month { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Files/Output/QiniuUploadTokenDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Files.Output 2 | { 3 | public class QiniuUploadTokenDto 4 | { 5 | public string Token { get; set; } 6 | 7 | public string Host { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/StatisticsDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class StatisticsDto 4 | { 5 | public long BId { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public decimal Data { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Asset/Output/AssetGroupDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Asset.Output; 2 | 3 | public class AssetGroupDto 4 | { 5 | public long BId { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public List Childs { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/Input/ModifyPermissionDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission.Input; 2 | 3 | public class ModifyPermissionDto 4 | { 5 | public string Name { get; set; } 6 | public string Module { get; set; } 7 | public string Router { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/Consts/CoreClaimTypes.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common.Consts; 2 | public static class CoreClaimTypes 3 | { 4 | public static string Roles { get; set; } = "CoreClaimTypes.Roles"; 5 | public static string IsAdmin { get; set; } = "CoreClaimTypes.IsAdmin"; 6 | } 7 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Logger/LogSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Logger; 2 | 3 | public class LogSvc : ApplicationSvc, ILogSvc 4 | { 5 | private readonly IIpLogRepo _ipLogRepo; 6 | public LogSvc(IIpLogRepo ipLogRepo) 7 | { 8 | _ipLogRepo = ipLogRepo; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/GroupToBillInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Input; 2 | 3 | public class GroupToBillInput 4 | { 5 | public long BId { get; set; } 6 | 7 | /// 8 | /// 账单Id 9 | /// 10 | public long BillBId { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Category/Output/CategoryGroupDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Category.Output; 2 | 3 | public class CategoryGroupDto 4 | { 5 | public long BId { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public List Childs { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/Base/BaseSerie.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common.Base; 2 | 3 | public class BaseSerie : BaseSerie 4 | { 5 | } 6 | 7 | public class BaseSerie 8 | { 9 | public string Name { get; set; } 10 | 11 | public List Data { get; set; } = new(); 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IRoleRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Base; 3 | 4 | namespace Mbill.Core.Interface.IRepositories.Core 5 | { 6 | public interface IRoleRepo : IAuditBaseRepo 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/Output/RoleDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission.Output; 2 | 3 | public class RoleDto : EntityDto 4 | { 5 | public string Name { get; set; } 6 | public string Info { get; set; } 7 | public bool IsStatic { get; set; } 8 | public int Sort { get; set; } 9 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IIPLogRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Base; 3 | 4 | namespace Mbill.Core.Interface.IRepositories.Core 5 | { 6 | public interface IIpLogRepo : IAuditBaseRepo 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IBaseTypeRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Base; 3 | 4 | namespace Mbill.Core.Interface.IRepositories.Core 5 | { 6 | public interface IBaseTypeRepo : IAuditBaseRepo 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/BillsByDayDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class BillsByDayDto 4 | { 5 | public int Day { get; set; } 6 | 7 | public string Week { get; set; } 8 | 9 | public List Items { get; set; } = new List(); 10 | } 11 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IPermissionRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Base; 3 | 4 | namespace Mbill.Core.Interface.IRepositories.Core 5 | { 6 | public interface IPermissionRepo: IAuditBaseRepo 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Mbill.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/CategoryPercentStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class CategoryPercentStatDto: BaseChart 4 | { 5 | 6 | } 7 | 8 | public class RingSerie 9 | { 10 | public string Name { get; set; } 11 | 12 | public decimal Value { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Mbill.ToolKits/Mbill.ToolKits.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IUserIdentityRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Base; 3 | 4 | namespace Mbill.Core.Interface.IRepositories.Core 5 | { 6 | public interface IUserIdentityRepo : IAuditBaseRepo 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/RequestInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common; 2 | 3 | public class RequestInfo 4 | { 5 | public string Ip { get; set; } 6 | public string Url { get; set; } 7 | public string Datetime { get; set; } 8 | public string Date { get; set; } 9 | public string Week { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IRolePermissionRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Base; 3 | 4 | namespace Mbill.Core.Interface.IRepositories.Core 5 | { 6 | public interface IRolePermissionRepo : IAuditBaseRepo 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/YearSurplusStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class YearSurplusStatDto 4 | { 5 | public int Month { get; set; } 6 | 7 | public string Surplus { get; set; } 8 | 9 | public string Expend { get; set; } 10 | 11 | public string Income { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/BillDateInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class BillDateInput 4 | { 5 | public int? Year { get; set; } 6 | public int? Month { get; set; } 7 | public int? Day { get; set; } 8 | public string Type { get; set; } 9 | public long? UserId { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/YearTotalStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class YearTotalStatDto 4 | { 5 | 6 | public string Expend { get; set; } 7 | 8 | public string Income { get; set; } 9 | 10 | public string Surplus { get; set; } 11 | 12 | public string ExpendAvg { get; set; } 13 | } -------------------------------------------------------------------------------- /src/Mbill/Controllers/Core/DataSeedController.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Controllers.Core; 2 | 3 | [Route("api/dataseed")] 4 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v2)] 5 | [Authorize] 6 | public class DataSeedController : ApiControllerBase 7 | { 8 | public DataSeedController() 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Wx/IWxSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Wx; 2 | 3 | public interface IWxSvc 4 | { 5 | /// 6 | /// GetCode2Session 7 | /// 8 | /// wx.login获取到的code 9 | /// 10 | Task> GetCode2Session(string code); 11 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IFileRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Core; 2 | 3 | public interface IFileRepo : IAuditBaseRepo 4 | { 5 | /// 6 | /// 获取文件完整路径 7 | /// 8 | /// 9 | /// 10 | string GetFileUrl(string path); 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/Input/ModifyRoleDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission.Input; 2 | 3 | public class ModifyRoleDto 4 | { 5 | public List PermissionBIds { get; set; } 6 | public string Name { get; set; } 7 | public string Info { get; set; } 8 | public bool IsStatic { get; set; } 9 | public int Sort { get; set; } 10 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Bill/IBillRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Bill; 2 | 3 | public interface IBillRepo : IAuditBaseRepo 4 | { 5 | /// 6 | /// 获取账单信息 7 | /// 8 | /// 账单BId 9 | /// 10 | Task GetBillAsync(long bId); 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.ToolKits/Utils/MultipartRequestUtil.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.ToolKits.Utils; 2 | 3 | 4 | public class MultipartRequestUtil 5 | { 6 | public static bool IsMultipartContentType(string contentType) 7 | { 8 | return !string.IsNullOrEmpty(contentType) 9 | && contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0; 10 | } 11 | } -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/RangeHasBillDaysInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class RangeHasBillDaysInput 4 | { 5 | /// 6 | /// 起始时间 7 | /// 8 | public DateTime BeginDate { get; set; } 9 | 10 | /// 11 | /// 结束时间 12 | /// 13 | public DateTime EndDate { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/YearTotalTrendStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class YearTotalTrendStatDto : BaseChart 4 | { 5 | public decimal ExpendHighest { get; set; } 6 | 7 | public decimal ExpendLowst { get; set; } 8 | 9 | public decimal IncomeHighest { get; set; } 10 | 11 | public decimal IncomeLowst { get; set; } 12 | } -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Files/IMediaImageSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Files; 2 | 3 | public interface IMediaImageSvc 4 | { 5 | /// 6 | /// 校验MD5文件是否存在 7 | /// 8 | /// 媒体图片分页参数 9 | /// 10 | Task>> GetPageAsync(MediaImagePagingInput pagingDto); 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/GroupPreOrderPagingInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class GroupPreOrderPagingInput : PagingDto 4 | { 5 | /// 6 | /// 指定的分组 7 | /// 8 | public long BId { get; set; } 9 | 10 | /// 11 | /// 预购状态 12 | /// 13 | public int? Status { get; set; } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Bill/IAssetRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Bill; 2 | 3 | public interface IAssetRepo : IAuditBaseRepo 4 | { 5 | /// 6 | /// 获取资产信息 By bId 7 | /// 8 | /// 资产Id 9 | /// 10 | Task GetAssetAsync(long bId); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Bill/ICategoryRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Bill; 2 | 3 | public interface ICategoryRepo : IAuditBaseRepo 4 | { 5 | /// 6 | /// 获取分类信息 By bId 7 | /// 8 | /// 9 | /// 10 | Task GetCategoryAsync(long bId); 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/MapDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class MapDto 4 | { 5 | public string CategoryName { get; set; } 6 | 7 | public string CategoryIconPath { get; set; } 8 | 9 | public string AssetName { get; set; } 10 | 11 | public string TargetAssetName { get; set; } 12 | 13 | public string TypeName { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/MonthTotalTrendStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class MonthTotalTrendStatDto : BaseChart 4 | { 5 | public string ExpendHighest { get; set; } 6 | 7 | public string ExpendLowst { get; set; } 8 | 9 | public string IncomeHighest { get; set; } 10 | 11 | public string IncomeLowst { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Output/IndexPreOrderStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Output; 2 | 3 | public class IndexPreOrderStatDto 4 | { 5 | public long Total { get; set; } 6 | 7 | /// 8 | /// 转账单分组数 9 | /// 10 | public int ToBill { get; set; } 11 | 12 | public long Done { get; set; } 13 | 14 | public long UnDone { get; set; } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Bill/BillMongoRepo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using MongoDB.Driver; 3 | 4 | namespace Mbill.Infrastructure.Repository.Bill; 5 | 6 | public class BillMongoRepo : MongoBaseRepo, IBillMongoRepo 7 | { 8 | public BillMongoRepo(ILoggerFactory loggerFactory, MongoClient client) : base(loggerFactory, client) 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/Input/DispatchPermissionsDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission.Input; 2 | 3 | public class DispatchPermissionsDto 4 | { 5 | /// 6 | /// 角色Id 7 | /// 8 | public long RoleBId { get; set; } 9 | 10 | /// 11 | /// 权限Id集合 12 | /// 13 | public List PermissionBIds { get; set; } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/Output/RoleWithPermissionDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission.Output; 2 | 3 | public class RoleWithPermissionDto : EntityDto 4 | { 5 | public List RolePermissions { get; set; } 6 | public string Name { get; set; } 7 | public string Info { get; set; } 8 | public bool IsStatic { get; set; } 9 | public int Sort { get; set; } 10 | } -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/MonthPreOrderGroupPagingInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class MonthPreOrderGroupPagingInput : PagingDto 4 | { 5 | /// 6 | /// 指定的年月 7 | /// 8 | public DateTime Month { get; set; } 9 | 10 | /// 11 | /// 分组名称 12 | /// 13 | public string Name { get; set; } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Output/PreOrderGroupWithPreAmountDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Output; 2 | 3 | public class PreOrderGroupWithPreAmountDto : PreOrderGroupDto 4 | { 5 | public decimal PreAmount { get; set; } 6 | 7 | public decimal RealAmount { get; set; } 8 | 9 | public string PreAmountFormate { get; set; } 10 | 11 | public string RealAmountFormate { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Notice/Input/ModifyNoticeDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Notice.Input; 2 | 3 | public class ModifyNoticeDto 4 | { 5 | [Required(ErrorMessage ="公告内容必填")] 6 | [MaxLength(500, ErrorMessage ="公告内容长度不能超过500个字符")] 7 | public string Content { get; set; } 8 | 9 | /// 10 | /// 可见范围,用户BId 使用,分割 11 | /// 12 | public string Range { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/PreOrder/IPreOrderGroupRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.PreOrder; 2 | 3 | public interface IPreOrderGroupRepo : IAuditBaseRepo 4 | { 5 | /// 6 | /// 获取预购分组 7 | /// 8 | /// 9 | /// 10 | Task GetPreOrderGroupAsync(long bId); 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Asset/Input/AssetPagingDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Asset.Input; 2 | 3 | public class AssetPagingDto : PagingDto 4 | { 5 | public string AssetName { get; set; } 6 | 7 | public string ParentBIds { get; set; } 8 | 9 | public string Type { get; set; } 10 | 11 | public DateTime? CreateStartTime { get; set; } 12 | 13 | public DateTime? CreateEndTime { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/YearTotalStatInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class YearTotalStatInput 4 | { 5 | /// 6 | /// 指定的年 7 | /// 8 | public int Year { get; set; } 9 | 10 | /// 11 | /// 操作: 12 | /// 0 查询基本数据(支出、收入、预购金额) 13 | /// 1 0的前提下加平均支出 14 | /// 15 | public int Opearte { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Wx/Output/WxCode2SessionDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Wx.Output; 2 | 3 | public class WxCode2SessionDto 4 | { 5 | public string OpenId { get; set; } 6 | 7 | [JsonProperty("session_key")] 8 | public string SessionKey { get; set; } 9 | 10 | public string UnionId { get; set; } 11 | 12 | public int ErrCode { get; set; } 13 | 14 | public string ErrMsg { get; set; } 15 | } -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/UpdatePreOrderStatusInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Input; 2 | 3 | public class UpdatePreOrderStatusInput 4 | { 5 | public long BId { get; set; } 6 | 7 | /// 8 | /// 账单Id 9 | /// 10 | public long RealAmount { get; set; } 11 | 12 | /// 13 | /// 状态 14 | /// 15 | public int Status { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Attributes/CacheableAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Attributes; 2 | 3 | [AttributeUsage(AttributeTargets.Method)] 4 | public class CacheableAttribute : Attribute 5 | { 6 | public CacheableAttribute() 7 | { 8 | } 9 | 10 | public CacheableAttribute(string cacheKey) 11 | { 12 | CacheKey = cacheKey; 13 | } 14 | 15 | public string CacheKey { get; set; } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/MonthTotalStatInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class MonthTotalStatInput 4 | { 5 | /// 6 | /// 指定的年月 7 | /// 8 | public DateTime Month { get; set; } 9 | 10 | /// 11 | /// 操作: 12 | /// 0 查询基本数据(支出、收入) 13 | /// 1 0的前提下加平均支出 14 | /// 15 | public int Opearte { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/Output/TreePermissionDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission.Output; 2 | 3 | public class TreePermissionDto 4 | { 5 | public long BId { get; set; } 6 | public string Rowkey { get; set; } 7 | public string Name { get; set; } 8 | public string Router { get; set; } 9 | public DateTime? CreateTime { get; set; } 10 | public List Children { get; set; } 11 | } -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/IPLogRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | 4 | namespace Mbill.Infrastructure.Repository.Core; 5 | 6 | public class IpLogRepo : AuditBaseRepo, IIpLogRepo 7 | { 8 | public IpLogRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/NoticeRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | 4 | namespace Mbill.Infrastructure.Repository.Core; 5 | 6 | public class NoticeRepo : AuditBaseRepo, INoticeRepo 7 | { 8 | public NoticeRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Category/Input/CategoryPagingInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Category.Input; 2 | 3 | public class CategoryPagingInput : PagingDto 4 | { 5 | public string CategoryName { get; set; } 6 | 7 | public string ParentBIds { get; set; } 8 | 9 | public string Type { get; set; } 10 | 11 | public DateTime? CreateStartTime { get; set; } 12 | 13 | public DateTime? CreateEndTime { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Bill/BillSearchRecordRepo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using MongoDB.Driver; 3 | 4 | namespace Mbill.Infrastructure.Repository.Bill; 5 | 6 | public class BillSearchRecordRepo : MongoBaseRepo, IBillSearchRecordRepo 7 | { 8 | public BillSearchRecordRepo(ILoggerFactory loggerFactory, MongoClient client) : base(loggerFactory, client) 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/BaseItemRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | 4 | namespace Mbill.Infrastructure.Repository.Core; 5 | 6 | public class BaseItemRepo : AuditBaseRepo, IBaseItemRepo 7 | { 8 | public BaseItemRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/DataSeedRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | 4 | namespace Mbill.Infrastructure.Repository.Core; 5 | 6 | public class DataSeedRepo : AuditBaseRepo, IDataSeedRepo 7 | { 8 | public DataSeedRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/Output/RolePermissionDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission.Output 2 | { 3 | public class RolePermissionDto : EntityDto 4 | { 5 | /// 6 | /// 角色BId 7 | /// 8 | public long RoleBId { get; set; } 9 | 10 | /// 11 | /// 权限BId 12 | /// 13 | public long PermissionBId { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/Input/PermissionDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission.Input; 2 | public class PermissionDto 3 | { 4 | public PermissionDto(string name, string module, string router) 5 | { 6 | Name = name; 7 | Module = module; 8 | Router = router; 9 | } 10 | 11 | public string Name { get; set; } 12 | public string Module { get; set; } 13 | public string Router { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/User/Input/UserPagingDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.User.Input; 2 | 3 | public class UserPagingDto : PagingDto 4 | { 5 | public string Username { get; set; } 6 | 7 | public string Nickname { get; set; } 8 | 9 | public int IsEnable { get; set; } 10 | 11 | public long RoleBId { get; set; } 12 | 13 | public DateTime? CreateStartTime { get; set; } 14 | 15 | public DateTime? CreateEndTime { get; set; } 16 | } -------------------------------------------------------------------------------- /src/Mbill/Controllers/Core/LogController.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Controllers.Core; 2 | 3 | /// 4 | /// 日志管理 5 | /// 6 | [Route("api/admin/log")] 7 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v2)] 8 | public class LogController : ApiControllerBase 9 | { 10 | private readonly ILogSvc _logService; 11 | public LogController(ILogSvc logService) 12 | { 13 | _logService = logService; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/PermissionRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | 4 | namespace Mbill.Infrastructure.Repository.Core; 5 | 6 | public class PermissionRepo : AuditBaseRepo, IPermissionRepo 7 | { 8 | public PermissionRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/BillDetailDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class BillDetailDto : BillDto 4 | { 5 | public string Asset { get; set; } 6 | 7 | public string Category { get; set; } 8 | 9 | public string CategoryIcon { get; set; } 10 | 11 | public string AssetIcon { get; set; } 12 | 13 | public string AmountFormat { get; set; } 14 | 15 | public string TimeFormat { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Output/PreOrderGroupDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Output; 2 | 3 | public class PreOrderGroupDto : EntityDto 4 | { 5 | public long BillBId { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public string Description { get; set; } 10 | 11 | public string Time { get; set; } 12 | 13 | /// 14 | /// 创建时间 15 | /// 16 | public DateTime CreateTime { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /scripts/Delete bin&obj Folder.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | cls 3 | 4 | ECHO Deleting all 'bin' and 'obj' folders... 5 | ECHO. 6 | 7 | FOR /d /r . %%d in (bin,obj) DO ( 8 | IF EXIST "%%d" ( 9 | ECHO %%d | FIND /I "\node_modules\" > Nul && ( 10 | ECHO.Skipping: %%d 11 | ) || ( 12 | ECHO.Deleting: %%d 13 | rd /s/q "%%d" 14 | ) 15 | ) 16 | ) 17 | 18 | ECHO. 19 | ECHO.'bin' and 'obj' folders have been successfully deleted. Press any key to exit... 20 | pause > nul -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Logger/Input/LogPagingDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Logger.Input; 2 | 3 | public class LogPagingDto : PagingDto 4 | { 5 | public string Method { get; set; } 6 | 7 | public string Username { get; set; } 8 | 9 | public string UserId { get; set; } 10 | 11 | public string StatusCode { get; set; } 12 | 13 | public DateTime? CreateStartTime { get; set; } 14 | 15 | public DateTime? CreateEndTime { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/MediaImageRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | 4 | namespace Mbill.Infrastructure.Repository.Core 5 | { 6 | public class MediaImageRepo : AuditBaseRepo, IMediaImageRepo 7 | { 8 | public MediaImageRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/Output/TokenWithUserDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth.Output; 2 | 3 | public class TokenWithUserDto 4 | { 5 | public TokenWithUserDto(TokenDto token, LoginUserDto user) 6 | { 7 | Token = token ?? throw new ArgumentNullException(nameof(token)); 8 | User = user ?? throw new ArgumentNullException(nameof(user)); 9 | } 10 | 11 | public TokenDto Token { get; set; } 12 | 13 | public LoginUserDto User { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/CategoryPercentGroupInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class CategoryPercentGroupInput 4 | { 5 | public DateTime Date { get; set; } 6 | 7 | /// 8 | /// 查询类型: 9 | /// 0 月统计 10 | /// 1 年统计 11 | /// 12 | public int Type { get; set; } 13 | 14 | /// 15 | /// 账单类型 16 | /// 0 支出 17 | /// 1 收入 18 | /// 19 | public int BillType { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/MonthTotalStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class MonthTotalStatDto 4 | { 5 | /// 6 | /// 收入(格式化后) 7 | /// 8 | public string Income { get; set; } 9 | 10 | /// 11 | /// 支出(格式化后) 12 | /// 13 | public string Expend { get; set; } 14 | 15 | /// 16 | /// 平均支出(格式化后) 17 | /// 18 | public string ExpendAvg { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Asset/Output/AssetDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Asset.Output; 2 | 3 | public class AssetDto 4 | { 5 | public long BId { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public long ParentBId { get; set; } 10 | 11 | public string Type { get; set; } 12 | 13 | public decimal Amount { get; set; } 14 | 15 | public int Sort { get; set; } 16 | 17 | public string IconUrl { get; set; } 18 | 19 | public string Icon { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Category/Output/CategoryDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Category.Output; 2 | 3 | public class CategoryDto 4 | { 5 | public long BId { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public long ParentBId { get; set; } 10 | 11 | public int Type { get; set; } 12 | 13 | public decimal Budget { get; set; } 14 | 15 | public int Sort { get; set; } 16 | 17 | public string IconUrl { get; set; } 18 | 19 | public string Icon { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mbill.Service/Common/Registers/Core/FileRegister.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | 3 | namespace Mbill.Service.Common.Registers.Core; 4 | 5 | public class FileRegister : BaseRegister 6 | { 7 | protected override void TypeRegister(TypeAdapterConfig config) 8 | { 9 | config.ForType() 10 | .Map(d => d.Path, s => s.File == null ? "" : s.File.Path) 11 | .Map(d => d.Url, s => UrlConverter(s.File == null ? string.Empty : s.File.Path)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Mbill/Modules/RepositoryModule.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Modules; 2 | 3 | public class RepositoryModule : Autofac.Module 4 | { 5 | protected override void Load(ContainerBuilder builder) 6 | { 7 | Assembly assemblysRepository = Assembly.Load("Mbill.Infrastructure"); 8 | builder.RegisterAssemblyTypes(assemblysRepository) 9 | .Where(a => a.Name.EndsWith("Repo")) 10 | .AsImplementedInterfaces() 11 | .InstancePerLifetimeScope(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/BiIllDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class BillDto 4 | { 5 | public long BId { get; set; } 6 | 7 | public long CategoryBId { get; set; } 8 | 9 | public long AssetBId { get; set; } 10 | 11 | public decimal Amount { get; set; } 12 | 13 | public int Type { get; set; } 14 | 15 | public string Description { get; set; } 16 | 17 | public string Address { get; set; } 18 | 19 | public DateTime Time { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/CreatePreOrderGroupInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Input; 2 | public class CreatePreOrderGroupInput 3 | { 4 | /// 5 | /// 分组名 6 | /// 7 | [Required(ErrorMessage = "必须传入分组名")] 8 | [MaxLength(10, ErrorMessage ="分组名长度不超过10")] 9 | public string Name { get; set; } 10 | 11 | /// 12 | /// 分组描述 13 | /// 14 | [MaxLength(40, ErrorMessage = "分组描述度不超过40")] 15 | public string Description { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Output/PreOrderGroupWithStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Output; 2 | 3 | public class PreOrderGroupWithStatDto : PreOrderGroupDto 4 | { 5 | /// 6 | /// 分组预购单总金额 7 | /// 8 | public decimal Amount { get; set; } 9 | 10 | /// 11 | /// 分组中已完成预购总数 12 | /// 13 | public long Done { get; set; } 14 | 15 | /// 16 | /// 分组中未完成预购总数 17 | /// 18 | public long UnDone { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Intercepts/UnitOfWorkInterceptor.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Intercepts; 2 | 3 | public class UnitOfWorkInterceptor : IInterceptor 4 | { 5 | private readonly UnitOfWorkAsyncInterceptor asyncInterceptor; 6 | 7 | public UnitOfWorkInterceptor(UnitOfWorkAsyncInterceptor interceptor) 8 | { 9 | asyncInterceptor = interceptor; 10 | } 11 | 12 | public void Intercept(IInvocation invocation) 13 | { 14 | asyncInterceptor.ToInterceptor().Intercept(invocation); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mbill.Core/Data/Authorization/PermissionAuthorizationRequirement.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Data.Authorization; 2 | 3 | public class ModuleAuthorizationRequirement : OperationAuthorizationRequirement 4 | { 5 | public ModuleAuthorizationRequirement(string module, string permission) 6 | { 7 | Module = module ?? throw new ArgumentNullException(nameof(module)); 8 | Name = permission ?? throw new ArgumentNullException(nameof(permission)); 9 | } 10 | 11 | public string Module { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/UserRoleRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Interface.IRepositories.Core; 2 | using Mbill.Core.Domains.Entities.Core; 3 | 4 | namespace Mbill.Infrastructure.Repository.Core; 5 | 6 | public class UserRoleRepo : AuditBaseRepo, IUserRoleRepo 7 | { 8 | private readonly ICurrentUser _currentUser; 9 | public UserRoleRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 10 | { 11 | _currentUser = currentUser; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Attributes/TransactionalAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Attributes; 2 | 3 | /// 4 | /// 事务 5 | /// 6 | [AttributeUsage(AttributeTargets.Method, Inherited = true)] 7 | public class TransactionalAttribute : Attribute 8 | { 9 | /// 10 | /// 事务传播方式 11 | /// 12 | public Propagation Propagation { get; set; } = Propagation.Required; 13 | 14 | /// 15 | /// 事务隔离级别 16 | /// 17 | public IsolationLevel? IsolationLevel { get; set; } 18 | } 19 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/RankingPagingInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class RankingPagingInput : PagingDto 4 | { 5 | public DateTime Date { get; set; } 6 | 7 | /// 8 | /// 查询类型: 9 | /// 0 月统计 10 | /// 1 年统计 11 | /// 12 | public int DateType { get; set; } 13 | 14 | /// 15 | /// 账单类型 16 | /// 0 支出 17 | /// 1 收入 18 | /// 19 | public int BillType { get; set; } 20 | 21 | public long? CategoryBId { get; set; } 22 | } 23 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/IJwtTokenSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth; 2 | 3 | public interface IJwtTokenSvc 4 | { 5 | /// 6 | /// 创建Token和RefreshToken 7 | /// 8 | /// 9 | /// 10 | Task CreateTokenAsync(UserEntity user); 11 | 12 | /// 13 | /// 刷新token 14 | /// 15 | /// 16 | /// 17 | Task RefreshTokenAsync(string refreshToken); 18 | } 19 | -------------------------------------------------------------------------------- /scripts/CreateNewProject.bat: -------------------------------------------------------------------------------- 1 | color 3 2 | @echo off 3 | 4 | dotnet new -i .template\Memoyu.Core.WebApi.Template.1.0.0.nupkg 5 | 6 | set /p OP=Please set your project name(for example:Memoyu.Core): 7 | 8 | md .NewProject 9 | 10 | cd .NewProject 11 | 12 | dotnet new memoyucoretpl -n %OP% 13 | 14 | cd ../ 15 | 16 | echo "----------------Create Successfully!! ^ please see the folder .NewProject----------------" 17 | 18 | dotnet new -u Memoyu.Core.WebApi.Template 19 | 20 | echo "----------------Delete Template Successfully!----------------" 21 | 22 | pause -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/RoleRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | using Mbill.Core.Security; 4 | using Mbill.Infrastructure.Repository.Base; 5 | using FreeSql; 6 | 7 | namespace Mbill.Infrastructure.Repository.Core 8 | { 9 | public class RoleRepo : AuditBaseRepo, IRoleRepo 10 | { 11 | public RoleRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Output/GroupPreOrderStatDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Output; 2 | 3 | public class GroupPreOrderStatDto 4 | { 5 | public long BillBId { get; set; } 6 | 7 | public string GroupName { get; set; } 8 | 9 | /// 10 | /// 分组创建时间 11 | /// 12 | public string Time { get; set; } 13 | 14 | public decimal PreAmount { get; set; } 15 | 16 | public decimal RealAmount { get; set; } 17 | 18 | public long Done { get; set; } 19 | 20 | public long UnDone { get; set; } 21 | } 22 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/PreOrder/PreOrderGroupRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Infrastructure.Repository.PreOrder; 2 | 3 | public class PreOrderGroupRepo : AuditBaseRepo, IPreOrderGroupRepo 4 | { 5 | public PreOrderGroupRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 6 | { 7 | } 8 | 9 | public async Task GetPreOrderGroupAsync(long bId) 10 | { 11 | return await Select.Where(a => a.BId == bId).ToOneAsync(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/BillTotalDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class BillTotalDto 4 | { 5 | //月统计 6 | public decimal MonthExpend { get; set; } 7 | public decimal MonthIncome { get; set; } 8 | public decimal MonthRepayment { get; set; } 9 | public decimal MonthTransfer { get; set; } 10 | 11 | //日统计 12 | public decimal DayExpend { get; set; } 13 | public decimal DayIncome { get; set; } 14 | public decimal DayRepayment { get; set; } 15 | public decimal DayTransfer { get; set; } 16 | } -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/BillDateWithTotalDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class BillDateWithTotalDto 4 | { 5 | /// 6 | /// 年 7 | /// 8 | public int Year { get; set; } 9 | 10 | /// 11 | /// 月 12 | /// 13 | public int Month { get; set; } 14 | 15 | /// 16 | /// 日 17 | /// 18 | public int Day { get; set; } 19 | 20 | /// 21 | /// 账单总数 22 | /// 23 | public int Total { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/RolePermissionEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 角色权限表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_role_permission")] 7 | public class RolePermissionEntity : Entity 8 | { 9 | /// 10 | /// 角色BId 11 | /// 12 | [Description("角色BId")] 13 | public long RoleBId { get; set; } 14 | 15 | /// 16 | /// 权限BId 17 | /// 18 | [Description("权限BId")] 19 | public long PermissionBId { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/BaseTypeRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | using Mbill.Core.Security; 4 | using Mbill.Infrastructure.Repository.Base; 5 | using FreeSql; 6 | 7 | namespace Mbill.Infrastructure.Repository.Core 8 | { 9 | public class BaseTypeRepo : AuditBaseRepo, IBaseTypeRepo 10 | { 11 | public BaseTypeRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Asset/Input/EditAssetInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Asset.Input; 2 | 3 | public class EditAssetInput 4 | { 5 | public long BId { get; set; } 6 | 7 | /// 8 | /// 资产分类名 9 | /// 10 | [Required(ErrorMessage = "必须传入资产分类名称")] 11 | public string Name { get; set; } 12 | 13 | /// 14 | /// 资产金额 15 | /// 16 | 17 | public decimal Amount { get; set; } 18 | 19 | /// 20 | /// 图标地址 21 | /// 22 | 23 | public string Icon { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mbill.Service/Common/Registers/Core/NoticeRegister.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | using Mbill.Service.Core.Notice.Input; 3 | 4 | namespace Mbill.Service.Common.Registers.Core; 5 | 6 | internal class NoticeRegister : BaseRegister 7 | { 8 | protected override void TypeRegister(TypeAdapterConfig config) 9 | { 10 | config.ForType() 11 | .Map(d => d.Range, s => JsonConvert.SerializeObject((string.IsNullOrWhiteSpace(s.Range) ? "" : s.Range).Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/BillSimpleDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class BillSimpleDto 4 | { 5 | public long BId { get; set; } 6 | 7 | public string Category { get; set; } 8 | 9 | public string CategoryIcon { get; set; } 10 | 11 | public decimal Amount { get; set; } 12 | 13 | public string AmountFormat { get; set; } 14 | 15 | public int Type { get; set; } 16 | 17 | public string Description { get; set; } 18 | 19 | public string Date { get; set; } 20 | 21 | public string Time { get; set; } 22 | } 23 | -------------------------------------------------------------------------------- /src/Mbill.Core/Extensions/AttributeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Extensions; 2 | 3 | public static class AttributeExtensions 4 | { 5 | public static TValue GetAttributeValue(this Type type, Func valueSelector) where TAttribute : Attribute 6 | { 7 | var att = type.GetCustomAttributes( 8 | typeof(TAttribute), true 9 | ).FirstOrDefault() as TAttribute; 10 | if (att != null) 11 | { 12 | return valueSelector(att); 13 | } 14 | return default(TValue); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Bill/AssetRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Infrastructure.Repository.Bill; 2 | 3 | public class AssetRepo : AuditBaseRepo, IAssetRepo 4 | { 5 | private readonly ICurrentUser _currentUser; 6 | public AssetRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 7 | { 8 | _currentUser = currentUser; 9 | } 10 | 11 | public async Task GetAssetAsync(long bId) 12 | { 13 | return await Select.Where(a => a.BId == bId).ToOneAsync(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/Base/ICrudApplicationSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Base; 2 | 3 | public interface ICrudApplicationSvc 4 | where TGetOutputDto : IEntityDto 5 | where TUpdateInput : BaseUpdateInput 6 | { 7 | Task> GetAsync(long bId); 8 | 9 | Task> CreateAsync(TCreateInput createInput); 10 | 11 | Task> UpdateAsync(TUpdateInput updateInput); 12 | 13 | Task DeleteAsync(long bId); 14 | } 15 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/DayBillInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class DayBillInput 4 | { 5 | /// 6 | /// 指定的日期 7 | /// 8 | public DateTime Date { get; set; } 9 | 10 | /// 11 | /// 账单类型 12 | /// 13 | public int? Type { get; set; } 14 | 15 | /// 16 | /// 账单分类 17 | /// 18 | public long? CategoryId { get; set; } 19 | 20 | /// 21 | /// 账单账户 22 | /// 23 | public long? AssetId { get; set; } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/Mbill.Core/Security/ICurrentUser.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Security.Dto; 2 | 3 | namespace Mbill.Core.Security; 4 | 5 | public interface ICurrentUser 6 | { 7 | // long? Id { get; } 8 | 9 | long? BId { get; } 10 | 11 | string UserName { get; } 12 | List Roles { get; } 13 | 14 | 15 | Claim FindClaim(string claimType); 16 | 17 | Claim[] FindClaims(string claimType); 18 | 19 | Claim[] GetAllClaims(); 20 | 21 | /// 22 | /// 是否超级管理员 23 | /// 24 | /// 25 | bool IsAdministrator(); 26 | } 27 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/UserIdentityRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | using Mbill.Core.Security; 4 | using Mbill.Infrastructure.Repository.Base; 5 | using FreeSql; 6 | 7 | namespace Mbill.Infrastructure.Repository.Core 8 | { 9 | class UserIdentityRepo : AuditBaseRepo, IUserIdentityRepo 10 | { 11 | public UserIdentityRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/Input/AccountLoginDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth.Input; 2 | 3 | public class AccountLoginDto : BaseLoginInput 4 | { 5 | /// 6 | /// 登录名 7 | /// 8 | /// 9 | /// admin 10 | /// 11 | [Required(ErrorMessage = "登录名为必填项")] 12 | public string Username { get; set; } 13 | /// 14 | /// 密码 15 | /// 16 | /// 17 | /// 123456 18 | /// 19 | [Required(ErrorMessage = "密码为必填项")] 20 | public string Password { get; set; } 21 | } 22 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Bill/CategoryRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Infrastructure.Repository.Bill; 2 | 3 | public class CategoryRepo : AuditBaseRepo, ICategoryRepo 4 | { 5 | private readonly ICurrentUser _currentUser; 6 | public CategoryRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 7 | { 8 | _currentUser = currentUser; 9 | } 10 | 11 | public async Task GetCategoryAsync(long bId) 12 | { 13 | return await Select.Where(c => c.BId == bId).ToOneAsync(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/RolePermissionRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Entities.Core; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | using Mbill.Core.Security; 4 | using Mbill.Infrastructure.Repository.Base; 5 | using FreeSql; 6 | 7 | namespace Mbill.Infrastructure.Repository.Core 8 | { 9 | public class RolePermissionRepo : AuditBaseRepo, IRolePermissionRepo 10 | { 11 | public RolePermissionRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Notice/INoticeSvc.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Service.Core.Notice.Input; 2 | using Mbill.Service.Core.Notice.Output; 3 | 4 | namespace Mbill.Service.Core.Notice; 5 | 6 | public interface INoticeSvc : IApplicationSvc 7 | { 8 | /// 9 | /// 新增公告 10 | /// 11 | /// 12 | /// 13 | Task> InsertAsync(ModifyNoticeDto input); 14 | 15 | /// 16 | /// 获取最新的公告 17 | /// 18 | /// 19 | Task> GetLatestAsync(); 20 | } 21 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/_Imports.cs: -------------------------------------------------------------------------------- 1 | global using System; 2 | global using System.Collections.Generic; 3 | global using System.Linq; 4 | global using System.Text; 5 | global using System.Threading.Tasks; 6 | global using FreeSql; 7 | global using Mbill.Core.Domains.Entities.Bill; 8 | global using Mbill.Core.Domains.Entities.PreOrder; 9 | global using Mbill.Core.Interface.IRepositories.Bill; 10 | global using Mbill.Core.Interface.IRepositories.PreOrder; 11 | global using Mbill.Infrastructure.Repository.Base; 12 | global using Mbill.Core.Security; 13 | global using Mbill.Core.Interface.IRepositories.Base; 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/MonthBillPagingInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class MonthBillPagingInput : PagingDto 4 | { 5 | /// 6 | /// 指定的年月 7 | /// 8 | public DateTime Month { get; set; } 9 | 10 | /// 11 | /// 账单类型 12 | /// 13 | public int? Type { get; set; } 14 | 15 | /// 16 | /// 账单分类 17 | /// 18 | public long? CategoryBId { get; set; } 19 | 20 | /// 21 | /// 账单账户 22 | /// 23 | public long? AssetBId { get; set; } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/NoticeEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 公告表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_notice")] 7 | public class NoticeEntity : FullAduitEntity 8 | { 9 | /// 10 | /// 内容 11 | /// 12 | [Description("内容")] 13 | [Column(StringLength = 500)] 14 | public string Content { get; set; } 15 | 16 | /// 17 | /// 可见范围 18 | /// 19 | [Description("可见范围")] 20 | [Column(DbType = "json")] 21 | public string Range { get; set; } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/CategoryPercentGroupDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class CategoryPercentGroupDto 4 | { 5 | public string Group { get; set; } 6 | 7 | public string Amount { get; set; } 8 | 9 | public List Items { get; set; } = new(); 10 | } 11 | 12 | public class CategoryPercentItemDto 13 | { 14 | public long BId { get; set; } 15 | 16 | public string Category { get; set; } 17 | 18 | public string CategoryIcon { get; set; } 19 | 20 | public double Percent { get; set; } 21 | 22 | public string Amount { get; set; } 23 | } -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/Input/WxLoginInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth.Input; 2 | 3 | public class WxLoginInput 4 | { 5 | public string OpenId { get; set; } 6 | 7 | public string Nickname { get; set; } 8 | 9 | public string AvatarUrl { get; set; } 10 | 11 | public (bool flag, string Msg) Valid() 12 | { 13 | if (OpenId.IsNullOrWhiteSpace()) return (false, "微信OpenId不能为空"); 14 | if (Nickname.IsNullOrWhiteSpace()) return (false, "用户昵称不能为空"); 15 | if (AvatarUrl.IsNullOrWhiteSpace()) return (false, "用户头像不能为空"); 16 | return (true, string.Empty); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Category/Input/EditCategoryInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Category.Input; 2 | 3 | public class EditCategoryInput 4 | { 5 | /// 6 | /// 分组/分类BId 7 | /// 8 | public long BId { get; set; } 9 | 10 | /// 11 | /// 账单分类名 12 | /// 13 | [Required(ErrorMessage = "必须传入分类名称")] 14 | public string Name { get; set; } 15 | 16 | /// 17 | /// 预算金额 18 | /// 19 | public decimal Budget { get; set; } 20 | 21 | /// 22 | /// 图标地址 23 | /// 24 | public string Icon { get; set; } 25 | } 26 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/Enums/Enums.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common.Enums; 2 | 3 | public enum PreOrderStatusEnum 4 | { 5 | UnDone,//未购买 6 | Done,//已购买 7 | } 8 | 9 | public enum BillTypeEnum 10 | { 11 | expend,//支出 12 | income,//收入 13 | transfer,//转账 14 | repayment,//还款 15 | } 16 | 17 | public enum RoleType 18 | { 19 | User, // 普通用户 20 | Administrator, // 超级管理员 21 | Admin, // 管理员 22 | Custom, // 用户自定义 23 | } 24 | 25 | public enum DataSeedType 26 | { 27 | [Description("账单分类种子数据")] 28 | BillCategory, // 账单分类 29 | [Description("资产分类种子数据")] 30 | AssetCategory, // 资产分类 31 | } 32 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/Output/PreLoginUserDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth.Output; 2 | 3 | public class PreLoginUserDto 4 | { 5 | public string OpenId { get; set; } 6 | 7 | /// 8 | /// 用户名 9 | /// 10 | public string Username { get; set; } 11 | 12 | /// 13 | /// 昵称 14 | /// 15 | public string Nickname { get; set; } 16 | 17 | /// 18 | /// 头像地址 19 | /// 20 | public string AvatarUrl { get; set; } 21 | 22 | /// 23 | /// 用户是否已存在 24 | /// 25 | public int IsCompletedInfo { get; set; } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mbill.Service/Mbill.Service.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 1701;1702;1705;1591 9 | Mbill.Service.xml 10 | bin\Debug\ 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/CategoryPercentStatInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class CategoryPercentStatInput 4 | { 5 | public DateTime Date { get; set; } 6 | 7 | /// 8 | /// 查询类型: 9 | /// 0 月统计 10 | /// 1 年统计 11 | /// 12 | public int Type { get; set; } 13 | 14 | /// 15 | /// 汇总类型: 16 | /// 0 根据父分类统计 17 | /// 1 根据子分类统计 18 | /// 19 | public int SummaryType { get; set; } 20 | 21 | /// 22 | /// 账单类型 23 | /// 0 支出 24 | /// 1 收入 25 | /// 26 | public int BillType { get; set; } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/Output/TokenDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth.Input; 2 | 3 | public class TokenDto 4 | { 5 | public TokenDto(string accessToken, string refreshToken) 6 | { 7 | AccessToken = accessToken ?? throw new ArgumentNullException(nameof(accessToken)); 8 | RefreshToken = refreshToken ?? throw new ArgumentNullException(nameof(refreshToken)); 9 | } 10 | 11 | public string AccessToken { get; set; } 12 | 13 | public string RefreshToken { get; set; } 14 | 15 | public override string ToString() 16 | { 17 | return $"TokenDto - 授权Token:{AccessToken},刷新Token:{RefreshToken}"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Mbill.Core/Common/Configs/FileStorageOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Common.Configs; 2 | 3 | public class FileStorageOptions 4 | { 5 | public int Default { get; set; } 6 | 7 | public LocalOption Local { get; set; } 8 | 9 | public QiniuClientOption Qiniu { get; set; } 10 | 11 | } 12 | 13 | public class LocalOption 14 | { 15 | public string Host { get; set; } 16 | } 17 | 18 | public class QiniuClientOption 19 | { 20 | public string AK { get; set; } 21 | 22 | public string SK { get; set; } 23 | 24 | public string Bucket { get; set; } 25 | 26 | public string Host { get; set; } 27 | 28 | public bool UseHttps { get; set; } 29 | } -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/UpdatePreOrderInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Input; 2 | 3 | public class UpdatePreOrderInput : BaseUpdateInput 4 | { 5 | /// 6 | /// 预购金额 7 | /// 8 | public decimal PreAmount { get; set; } 9 | 10 | /// 11 | /// 实购金额 12 | /// 13 | public decimal RealAmount { get; set; } 14 | 15 | /// 16 | /// 描述 17 | /// 18 | [MaxLength(40, ErrorMessage = "预购描述度不超过40")] 19 | public string Description { get; set; } 20 | 21 | /// 22 | /// 记录日期:时间 23 | /// 24 | public DateTime Time { get; set; } 25 | } 26 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Base/IAuditBaseRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Base; 2 | 3 | public interface IAuditBaseRepo : IBaseRepository where TEntity : class 4 | { 5 | Task UpdateWithIgnoreAsync(TEntity entity, Expression> ignoreExp, CancellationToken cancellationToken = default(CancellationToken)); 6 | } 7 | 8 | public interface IAuditBaseRepo : IBaseRepository where TEntity : class 9 | { 10 | Task UpdateWithIgnoreAsync(TEntity entity, Expression> ignoreExp, CancellationToken cancellationToken = default(CancellationToken)); 11 | } 12 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Bill/BillRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Infrastructure.Repository.Bill; 2 | 3 | public class BillRepo : AuditBaseRepo, IBillRepo 4 | { 5 | private readonly ICurrentUser _currentUser; 6 | 7 | public BillRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 8 | { 9 | _currentUser = currentUser; 10 | } 11 | 12 | public async Task GetBillAsync(long bId) 13 | { 14 | return await Select 15 | .Include(b => b.Category) 16 | .Include(b => b.Asset) 17 | .Where(a => a.BId == bId).ToOneAsync(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/IPLogEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// IP访问日志表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_ip_log")] 7 | public class IpLogEntity : FullAduitEntity 8 | { 9 | /// 10 | /// 客户端IP 11 | /// 12 | [Description("客户端IP")] 13 | public string Ip { get; set; } 14 | 15 | /// 16 | /// 访问路径 17 | /// 18 | [Description("访问路径")] 19 | public string Path { get; set; } 20 | 21 | /// 22 | /// 访问时间 23 | /// 24 | [Description("访问时间")] 25 | public DateTime VisitTime { get; set; } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mbill.Service/Common/Registers/Bill/AssetRegister.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | 3 | namespace Mbill.Service.Common.Registers.Bill; 4 | 5 | public class AssetRegister : BaseRegister 6 | { 7 | protected override void TypeRegister(TypeAdapterConfig config) 8 | { 9 | config.ForType() 10 | .Map(d => d.IconUrl, s => UrlConverter(s.Icon)); 11 | 12 | config.ForType() 13 | .Map(d => d.ParentName, s => s.Parent == null ? string.Empty : s.Parent.Name) 14 | .Map(d => d.TypeName, s => CategoryTypeConverter(s.Type)) 15 | .Map(d => d.IconUrl, s => UrlConverter(s.Icon)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Mbill.Core/Common/SnowFlake.cs: -------------------------------------------------------------------------------- 1 | using Yitter.IdGenerator; 2 | 3 | namespace Mbill.Core.Common 4 | { 5 | public static class SnowFlake 6 | { 7 | /// 8 | /// 初始化雪花ID生成器 9 | /// 10 | public static void SnowFlakeConfig() 11 | { 12 | var options = new IdGeneratorOptions(); 13 | options.SeqBitLength = 10; 14 | YitIdHelper.SetIdGenerator(options); 15 | } 16 | 17 | /// 18 | /// 获取雪花ID 19 | /// 20 | /// 21 | public static long NextId() 22 | { 23 | return YitIdHelper.NextId(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/Enums/Base/CapConfigEnums.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common.Enums.Base; 2 | 3 | public enum CapStorageTypeEnums 4 | { 5 | /// 6 | /// 引用包 DotNetCore.CAP.InMemoryStorage 7 | /// 8 | InMemoryStorage = 0, 9 | /// 10 | /// 引用包 DotNetCore.CAP.MySql 11 | /// 12 | Mysql = 1, 13 | /// 14 | /// 引用包 DotNetCore.CAP.SqlServer 15 | /// 16 | SqlServer = 2 17 | } 18 | 19 | public enum CapMessageQueueTypeEnums 20 | { 21 | /// 22 | /// 内存队列 23 | /// 24 | InMemoryQueue = 0, 25 | /// 26 | /// RabbitMQ 27 | /// 28 | RabbitMQ = 1, 29 | } 30 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/BillPagingInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class BillPagingInput : PagingDto 4 | { 5 | /// 6 | /// 指定的日期 7 | /// 8 | public DateTime Date { get; set; } 9 | 10 | /// 11 | /// 查询时间类型:0 查询月份,1 查询年份 12 | /// 13 | public int DateType { get; set; } 14 | 15 | /// 16 | /// 账单类型 17 | /// 18 | public int? Type { get; set; } 19 | 20 | /// 21 | /// 账单分类 22 | /// 23 | public long? CategoryBId { get; set; } 24 | 25 | /// 26 | /// 账单账户 27 | /// 28 | public long? AssetBId { get; set; } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/Mbill/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "Mbill": { 5 | "commandName": "Project", 6 | "launchUrl": "swagger", 7 | "environmentVariables": { 8 | "ASPNETCORE_ENVIRONMENT": "Development" 9 | }, 10 | "dotnetRunMessages": "true", 11 | "applicationUrl": "http://localhost:5000" 12 | }, 13 | "Docker": { 14 | "commandName": "Docker", 15 | "launchBrowser": true, 16 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Production" 19 | }, 20 | "publishAllPorts": true 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/DataSeedEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 种子数据表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_data_seed")] 7 | public class DataSeedEntity : FullAduitEntity 8 | { 9 | /// 10 | /// 数据类型 11 | /// 12 | [Description("数据类型")] 13 | public int Type { get; set; } 14 | 15 | /// 16 | /// 描述 17 | /// 18 | [Description("描述")] 19 | [Column(StringLength = 100)] 20 | public string Desc { get; set; } 21 | 22 | /// 23 | /// 种子数据 24 | /// 25 | [Description("种子数据")] 26 | [Column(DbType = "json")] 27 | public string Data { get; set; } 28 | } 29 | -------------------------------------------------------------------------------- /src/Mbill.Service/Common/Registers/Bill/CategoryRegister.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | 3 | namespace Mbill.Service.Common.Registers.Bill 4 | { 5 | public class CategoryRegister : BaseRegister 6 | { 7 | protected override void TypeRegister(TypeAdapterConfig config) 8 | { 9 | config.ForType() 10 | .Map(d => d.IconUrl, s => UrlConverter(s.Icon)); 11 | 12 | config.ForType() 13 | .Map(d => d.ParentName, s => s.Parent == null ? string.Empty : s.Parent.Name) 14 | .Map(d => d.TypeName, s => CategoryTypeConverter(s.Type)) 15 | .Map(d => d.IconUrl, s => UrlConverter(s.Icon)); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Mbill.Core/Security/PermissionDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Security; 2 | 3 | public class PermissionDefinition 4 | { 5 | public PermissionDefinition(string permission, string module, string router) 6 | { 7 | Permission = permission ?? throw new ArgumentNullException(nameof(permission)); 8 | Module = module ?? throw new ArgumentNullException(nameof(module)); 9 | Router = router ?? throw new ArgumentNullException(nameof(router)); 10 | } 11 | 12 | public string Permission { get; } 13 | public string Module { get; } 14 | public string Router { get; } 15 | public override string ToString() 16 | { 17 | return base.ToString() + $" Permission:{Permission}、Module:{Module}、Router:{Router}"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Mbill/Dockerfile: -------------------------------------------------------------------------------- 1 | #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. 2 | 3 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base 4 | WORKDIR /app 5 | EXPOSE 80 6 | 7 | RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 8 | RUN echo 'Asia/Shanghai' >/etc/timezone 9 | 10 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 11 | WORKDIR /src 12 | COPY . . 13 | RUN dotnet restore "Mbill.sln" 14 | WORKDIR "/src/src/Mbill" 15 | RUN dotnet build "Mbill.csproj" -c Release -o /app/build 16 | 17 | FROM build AS publish 18 | RUN dotnet publish "Mbill.csproj" -c Release -o /app/publish 19 | 20 | FROM base AS final 21 | WORKDIR /app 22 | COPY --from=publish /app/publish . 23 | ENTRYPOINT ["dotnet", "Mbill.dll"] -------------------------------------------------------------------------------- /src/Mbill/Controllers/Core/WxController.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Controllers.Core; 2 | 3 | /// 4 | /// 账户相关 5 | /// 6 | [Route("api/wx")] 7 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v3)] 8 | public class WxController : ApiControllerBase 9 | { 10 | private readonly IWxSvc _wxSvc; 11 | 12 | public WxController(IWxSvc wxSvc) 13 | { 14 | _wxSvc = wxSvc; 15 | } 16 | 17 | /// 18 | /// 小程序 GetCode2Session 19 | /// 20 | /// wx.login获取到的code 21 | /// 22 | [HttpGet("getcode2session")] 23 | public async Task> GetCode2Session(string code) 24 | { 25 | return await _wxSvc.GetCode2Session(code); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Middleware/IpLimitMilddleware.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Middleware; 2 | 3 | public class IpLimitMiddleware : IpRateLimitMiddleware 4 | { 5 | public IpLimitMiddleware(RequestDelegate next, IProcessingStrategy processingStrategy, IOptions options, IIpPolicyStore policyStore, IRateLimitConfiguration config, ILogger logger) 6 | : base(next, processingStrategy, options, policyStore, config, logger) 7 | { 8 | } 9 | 10 | public override Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule, string retryAfter) 11 | { 12 | httpContext.Response.Headers.Append("Access-Control-Allow-Origin", "*"); 13 | return base.ReturnQuotaExceededResponse(httpContext, rule, retryAfter); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mbill.Service/Common/Registers/BaseRegister.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | 3 | namespace Mbill.Service.Common.Registers; 4 | 5 | public abstract class BaseRegister : IRegister 6 | { 7 | public void Register(TypeAdapterConfig config) 8 | { 9 | TypeRegister(config); 10 | } 11 | 12 | protected abstract void TypeRegister(TypeAdapterConfig config); 13 | 14 | public string UrlConverter(string url) 15 | { 16 | if (url.IsNullOrWhiteSpace()) return ""; 17 | var fileRepo = MapContext.Current.GetService(); 18 | return fileRepo.GetFileUrl(url); 19 | } 20 | 21 | public string GenderConverter(int gender) => gender == 0 ? "未知" : gender == 1 ? "男" : "女"; 22 | 23 | public string CategoryTypeConverter(int type) => Switcher.CategoryType(type); 24 | } 25 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Input/CreatePreOrderInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Input; 2 | public class CreatePreOrderInput 3 | { 4 | /// 5 | /// 分组Id 6 | /// 7 | [Required(ErrorMessage = "预购分组BId不能为空")] 8 | public long? GroupBId { get; set; } 9 | 10 | /// 11 | /// 金额 12 | /// 13 | public decimal PreAmount { get; set; } 14 | 15 | /// 16 | /// 描述 17 | /// 18 | [MaxLength(40, ErrorMessage = "预购描述度不超过40")] 19 | public string Description { get; set; } 20 | 21 | /// 22 | /// 记录日期:时间 23 | /// 24 | public DateTime Time { get; set; } 25 | 26 | /// 27 | /// 图标颜色 28 | /// 29 | public string Color { get; set; } 30 | } 31 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/Core/IUserRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.Core; 2 | 3 | public interface IUserRepo : IAuditBaseRepo 4 | { 5 | /// 6 | /// 获取用户信息 By bId 7 | /// 8 | /// 用户bId 9 | /// 10 | Task GetUserAsync(long bId); 11 | 12 | /// 13 | /// 根据条件得到用户信息 14 | /// 15 | /// 16 | /// 17 | Task GetUserAsync(Expression> expression); 18 | 19 | /// 20 | /// 根据用户Id更新用户的最后登录时间 21 | /// 22 | /// 23 | /// 24 | Task UpdateLastLoginTimeAsync(long userId); 25 | } 26 | -------------------------------------------------------------------------------- /src/Mbill.Service/Common/Registers/PreOrder/PreOrderRegister.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | 3 | namespace Mbill.Service.Common.Registers.PreOrder; 4 | 5 | public class PreOrderRegister : BaseRegister 6 | { 7 | protected override void TypeRegister(TypeAdapterConfig config) 8 | { 9 | config.ForType() 10 | .Map(d => d.Time, s => $"{s.Time.GetWeek()} {s.Time:MM月-dd日}"); 11 | 12 | config.ForType() 13 | .Map(d => d.Time, s => $"{s.CreateTime.GetWeek()} {s.CreateTime.Day}日 {s.CreateTime:HH:mm}"); 14 | 15 | config.ForType() 16 | .Map(d => d.Time, s => $"{s.CreateTime.GetWeek()} {s.CreateTime.Month}/{s.CreateTime.Day} {s.CreateTime:HH:mm}"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Output/BillSearchRecordOutput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Output; 2 | 3 | public class BillSearchRecordOutput 4 | { 5 | /// 6 | /// 账单类型 7 | /// 8 | public int? Type { get; set; } 9 | 10 | /// 11 | /// 账单分类 12 | /// 13 | public long? CategoryId { get; set; } 14 | 15 | /// 16 | /// 账单账户 17 | /// 18 | public long? AssetId { get; set; } 19 | 20 | /// 21 | /// 账单时间起始 22 | /// 23 | public DateTime? TimeBegin { get; set; } 24 | 25 | /// 26 | /// 账单时间截止 27 | /// 28 | public DateTime? TimeEnd { get; set; } 29 | 30 | /// 31 | /// 搜索关键字 32 | /// 33 | public string KeyWord { get; set; } 34 | } 35 | -------------------------------------------------------------------------------- /src/Mbill/Modules/AutofacModule.cs: -------------------------------------------------------------------------------- 1 | using Module = Autofac.Module; 2 | 3 | namespace Mbill.Modules; 4 | 5 | public class AutofacModule : Module 6 | { 7 | protected override void Load(ContainerBuilder builder) 8 | { 9 | builder.RegisterType().As().SingleInstance(); 10 | builder.RegisterType().As().InstancePerLifetimeScope(); 11 | builder.RegisterType().As().InstancePerLifetimeScope(); 12 | builder.RegisterType().As().InstancePerDependency(); 13 | 14 | builder.RegisterType().SingleInstance(); 15 | builder.RegisterBuildCallback(async (c) => await c.Resolve().StartAsync()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/MediaImageEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 图片媒体文件信息表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_media_image")] 7 | [Index("index_media_image_on_file_bid", nameof(FileBId), false)] 8 | [Index("index_media_image_on_type", nameof(Type), false)] 9 | public class MediaImageEntity : FullAduitEntity 10 | { 11 | /// 12 | /// 文件BId 13 | /// 14 | [Description("文件BId")] 15 | public long FileBId { get; set; } 16 | 17 | /// 18 | /// 图片类型:0 Icon, 1 background 19 | /// 20 | [Description("图片类型:0 Icon, 1 background")] 21 | public int Type { get; set; } 22 | 23 | 24 | [Navigate(nameof(FileBId), TempPrimary = nameof(BId))] 25 | public virtual FileEntity File { get; set; } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/PreOrder/PreOrderGroupEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.PreOrder; 2 | 3 | /// 4 | /// 预购清单分组实体 5 | /// 6 | [Table(Name = DbTablePrefix + "_pre_order_group")] 7 | [Index("index_preorder_group_on_bill_bid", nameof(BillBId), false)] 8 | public class PreOrderGroupEntity : FullAduitEntity 9 | { 10 | /// 11 | /// 账单BId 12 | /// 13 | [Description("账单BId")] 14 | public long BillBId { get; set; } 15 | 16 | /// 17 | /// 分组名 18 | /// 19 | [Description("分组名")] 20 | [Column(StringLength = 10)] 21 | public string Name { get; set; } 22 | 23 | /// 24 | /// 说明 25 | /// 26 | [Description("说明")] 27 | [Column(StringLength = 40)] 28 | public string Description { get; set; } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/DataSeed/IDataSeedSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.DataSeed; 2 | 3 | public interface IDataSeedSvc : IApplicationSvc 4 | { 5 | /// 6 | /// 初始化已知类型的种子数据 7 | /// 8 | /// 9 | Task InitDataSeedAsync(); 10 | 11 | /// 12 | /// 初始化权限,根据PermissionAttribute生成权限,改变的则更新,否则新增 13 | /// 14 | /// 15 | /// 16 | Task InitPermissionAsync(List defPermissions); 17 | 18 | /// 19 | /// 初始化超级管理员角色权限 20 | /// 21 | /// 22 | Task InitAdministratorPermissionAsync(); 23 | 24 | /// 25 | /// 初始化普通用户角色权限 26 | /// 27 | /// 28 | Task InitUserPermissionAsync(); 29 | } 30 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/User/IUserIdentitySvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.User; 2 | 3 | public interface IUserIdentitySvc 4 | { 5 | /// 6 | /// 验证用户密码是否正确 7 | /// 8 | /// 用户Id 9 | /// 密码 10 | /// 11 | Task VerifyUserPasswordAsync(long userBId, string password); 12 | 13 | /// 14 | /// 验证微信用户OpenId是否存在 15 | /// 16 | /// Wx OpenId 17 | /// 18 | Task VerifyWxOpenIdAsync(string openId); 19 | 20 | /// 21 | /// 根据用户ID,修改用户的密码 22 | /// 23 | /// 24 | /// 25 | Task ChangePasswordAsync(long userId, string newpassword); 26 | } -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Files/IQiniuFileSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Files; 2 | 3 | public interface IQiniuFileSvc 4 | { 5 | /// 6 | /// 校验MD5文件是否存在 7 | /// 8 | /// 9 | /// 10 | Task> CheckMD5(string md5); 11 | 12 | /// 13 | /// 获取上传Token 14 | /// 15 | /// 文件路径 16 | /// 17 | ServiceResult GetUploadToken(string key = null); 18 | 19 | /// 20 | /// 单文件上传,键为file 21 | /// 22 | /// 文件流 23 | /// 类型 24 | /// 25 | /// 26 | Task> UploadAsync(IFormFile file, string type, int key = 0); 27 | } 28 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Asset/Input/CreateAssetInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Asset.Input; 2 | 3 | public class CreateAssetInput 4 | { 5 | /// 6 | /// 资产分类名 7 | /// 8 | [Required(ErrorMessage = "必须传入资产分类名称")] 9 | public string Name { get; set; } 10 | 11 | /// 12 | /// 父级BId 13 | /// 14 | public long ParentBId { get; set; } 15 | 16 | /// 17 | /// 资产分类类型:存款、负债 18 | /// 19 | [Required(ErrorMessage = "必须传入资产分类类型")] 20 | public int Type { get; set; } 21 | 22 | /// 23 | /// 资产金额 24 | /// 25 | 26 | public decimal Amount { get; set; } 27 | 28 | /// 29 | /// 图标地址 30 | /// 31 | 32 | public string Icon { get; set; } 33 | 34 | /// 35 | /// 排序 36 | /// 37 | public int Sort { get; set; } 38 | } 39 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/DataSeed/Output/BillAssetDataSeedDto.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Common; 2 | 3 | namespace Mbill.Service.Core.DataSeed.Output; 4 | 5 | public class BillAssetDataSeedDto 6 | { 7 | public string Name { get; set; } 8 | 9 | public int Type { get; set; } 10 | 11 | public int Sort { get; set; } 12 | 13 | public string Icon { get; set; } 14 | 15 | public List Childs { get; set; } 16 | 17 | public AssetEntity ToEntity(long? bId, long? parent, long userBId) 18 | { 19 | return new AssetEntity 20 | { 21 | BId = bId.HasValue ? bId.Value : SnowFlake.NextId(), 22 | ParentBId = parent.HasValue ? parent.Value : 0, 23 | Name = Name, 24 | Type = Type, 25 | Sort = Sort, 26 | Icon = parent.HasValue ? Icon : string.Empty, 27 | CreateUserBId = userBId, 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/Output/LoginUserDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth.Output; 2 | 3 | public class LoginUserDto 4 | { 5 | /// 6 | /// 用户名 7 | /// 8 | public string Username { get; set; } 9 | 10 | /// 11 | /// 昵称 12 | /// 13 | public string Nickname { get; set; } 14 | 15 | /// 16 | /// 性别,0:未知,1:男,2:女 17 | /// 18 | public string Gender { get; set; } 19 | 20 | /// 21 | /// 邮箱 22 | /// 23 | public string Email { get; set; } 24 | 25 | /// 26 | /// 电话 27 | /// 28 | public string Phone { get; set; } 29 | 30 | /// 31 | /// 头像地址 32 | /// 33 | public string AvatarUrl { get; set; } 34 | 35 | /// 36 | /// 用户创建日期 37 | /// 38 | public DateTime CreateTime { get; set; } 39 | } 40 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Logger/Output/LogDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Logger.Output; 2 | 3 | public class LogDto : FullEntityDto 4 | { 5 | /// 6 | /// 访问哪个权限 7 | /// 8 | public string Authority { get; set; } 9 | 10 | /// 11 | /// 日志信息 12 | /// 13 | public string Message { get; set; } 14 | 15 | /// 16 | /// 请求方法 17 | /// 18 | public string Method { get; set; } 19 | 20 | /// 21 | /// 请求路径 22 | /// 23 | public string Path { get; set; } 24 | 25 | /// 26 | /// 请求的http返回码 27 | /// 28 | public int? StatusCode { get; set; } 29 | 30 | /// 31 | /// 用户id 32 | /// 33 | public long UserId { get; set; } 34 | 35 | /// 36 | /// 用户当时的昵称 37 | /// 38 | public string Username { get; set; } 39 | } 40 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/User/Input/ModifyUserBaseInfoDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.User.Input 2 | { 3 | public class ModifyUserBaseDto 4 | { 5 | public long BId { get; set; } 6 | 7 | /// 8 | /// 头像地址 9 | /// 10 | public string AvatarUrl { get; set; } 11 | 12 | /// 13 | /// 昵称 14 | /// 15 | [Required(ErrorMessage = "必须传入昵称")] 16 | public string Nickname { get; set; } 17 | 18 | /// 19 | /// 性别,0:未知,1:男,2:女 20 | /// 21 | [Required(ErrorMessage = "必须传入昵称")] 22 | public int Gender { get; set; } 23 | 24 | /// 25 | /// 邮箱 26 | /// 27 | public string Email { get; set; } 28 | 29 | /// 30 | /// 电话 31 | /// 32 | public string Phone { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Output/PreOrderDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Output; 2 | 3 | public class PreOrderDto : EntityDto 4 | { 5 | /// 6 | /// 分组Id 7 | /// 8 | public long GroupBId { get; set; } 9 | 10 | /// 11 | /// 金额 12 | /// 13 | public decimal Amount { get; set; } 14 | 15 | /// 16 | /// 说明 17 | /// 18 | public string Description { get; set; } 19 | 20 | /// 21 | /// 记录日期:时间 22 | /// 23 | public DateTime Time { get; set; } 24 | 25 | /// 26 | /// 记录日期:时间 27 | /// 28 | public string TimeFormat { get; set; } 29 | 30 | 31 | /// 32 | /// 状态 0:未购买;1:已购买 33 | /// 34 | public int Status { get; set; } 35 | 36 | /// 37 | /// 图标颜色 38 | /// 39 | public string Color { get; set; } 40 | } 41 | -------------------------------------------------------------------------------- /src/Mbill.ToolKits/Utils/HashUtil.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.ToolKits.Utils; 2 | 3 | public class HashUtil 4 | { 5 | /// 6 | /// 继承HashAlgorithm 7 | /// 8 | /// 9 | /// 10 | /// 11 | public static string GetHash(Stream stream) where T : HashAlgorithm 12 | { 13 | StringBuilder sb = new StringBuilder(); 14 | 15 | MethodInfo create = typeof(T).GetMethod("Create", new Type[] { }); 16 | using (T crypt = (T)create.Invoke(null, null)) 17 | { 18 | if (crypt != null) 19 | { 20 | byte[] hashBytes = crypt.ComputeHash(stream); 21 | foreach (byte bt in hashBytes) 22 | { 23 | sb.Append(bt.ToString("x2")); 24 | } 25 | } 26 | } 27 | return sb.ToString(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/IPreOrderSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder; 2 | 3 | public interface IPreOrderSvc : ICrudApplicationSvc 4 | { 5 | /// 6 | /// 更新预购状态 7 | /// 8 | /// 9 | /// 10 | Task UpdateStatusAsync(UpdatePreOrderStatusInput input); 11 | 12 | /// 13 | /// 获取指定月份分页预购分组 14 | /// 15 | /// 分页查询 16 | /// 17 | Task>> GetByGroupPagesAsync(GroupPreOrderPagingInput input); 18 | 19 | 20 | /// 21 | /// 获取指定分组预购清单统计 22 | /// 23 | /// 24 | /// 25 | Task> GetIndexStatAsync(IndexPreOrderStatInput input); 26 | } 27 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/DataSeed/Output/BillCategoryDataSeedDto.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Common; 2 | 3 | namespace Mbill.Service.Core.DataSeed.Output; 4 | 5 | public class BillCategoryDataSeedDto 6 | { 7 | public string Name { get; set; } 8 | 9 | public int Type { get; set; } 10 | 11 | public int Sort { get; set; } 12 | 13 | public string Icon { get; set; } = string.Empty; 14 | 15 | public List Childs { get; set; } 16 | 17 | public CategoryEntity ToEntity(long? bId, long? parent, long userBId) 18 | { 19 | return new CategoryEntity 20 | { 21 | BId = bId.HasValue ? bId.Value : SnowFlake.NextId(), 22 | ParentBId = parent.HasValue ? parent.Value : 0, 23 | Name = Name, 24 | Type = Type, 25 | Sort = Sort, 26 | Icon = parent.HasValue ? Icon : string.Empty, 27 | CreateUserBId = userBId, 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Category/Input/CreateCategoryInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Category.Input; 2 | 3 | public class CreateCategoryInput 4 | { 5 | /// 6 | /// 账单分类名 7 | /// 8 | [Required(ErrorMessage = "必须传入分类名称")] 9 | public string Name { get; set; } 10 | 11 | /// 12 | /// 父级BId,默认0 13 | /// 14 | [Required(ErrorMessage = "分类父BId不能为空")] 15 | public long? ParentBId { get; set; } 16 | 17 | /// 18 | /// 分类类型:支出、收入 19 | /// 20 | [Required(ErrorMessage = "必须传入分类类型")] 21 | public string Type { get; set; } 22 | 23 | /// 24 | /// 预算金额 25 | /// 26 | public decimal Budget { get; set; } 27 | 28 | /// 29 | /// 图标地址 30 | /// 31 | public string Icon { get; set; } 32 | 33 | /// 34 | /// 排序 35 | /// 36 | public int Sort { get; set; } 37 | } 38 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/IPermissionSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission; 2 | 3 | public interface IPermissionSvc 4 | { 5 | /// 6 | /// 获取所有权限(树形结构) 7 | /// 8 | /// 9 | Task> GetAllTreeAsync(); 10 | 11 | /// 12 | /// 获取所有权限(Module分组结构化) 13 | /// 14 | /// 15 | Task>> GetAllStructualAsync(); 16 | 17 | /// 18 | /// 检查当前登陆用户的分组权限 19 | /// 20 | /// 21 | /// 22 | /// 23 | Task CheckAsync(string module, string permission); 24 | 25 | /// 26 | /// 配置角色权限 27 | /// 28 | /// 29 | /// 30 | Task DispatchPermissionsAsync(DispatchPermissionsDto dto); 31 | } -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/Output/PreOrderSimpleDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder.Output; 2 | 3 | public class PreOrderSimpleDto 4 | { 5 | public long BId { get; set; } 6 | 7 | /// 8 | /// 分组Id 9 | /// 10 | public long GroupBId { get; set; } 11 | 12 | /// 13 | /// 预购金额 14 | /// 15 | public decimal PreAmount { get; set; } 16 | 17 | 18 | /// 19 | /// 实际金额 20 | /// 21 | public decimal RealAmount { get; set; } 22 | 23 | /// 24 | /// 说明 25 | /// 26 | public string Description { get; set; } 27 | 28 | /// 29 | /// 记录日期:时间 30 | /// 31 | public string Time { get; set; } 32 | 33 | /// 34 | /// 状态 0:未购买;1:已购买 35 | /// 36 | public int Status { get; set; } 37 | 38 | /// 39 | /// 图标颜色 40 | /// 41 | public string Color { get; set; } 42 | } 43 | -------------------------------------------------------------------------------- /src/Mbill.Core/Extensions/Converters/JsonLongToStringConverter.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Extensions.Converters; 2 | 3 | public class JsonLongToStringConverter : JsonConverter 4 | { 5 | public override bool CanConvert(Type typeToConvert) 6 | { 7 | return typeof(long) == typeToConvert || typeof(long?) == typeToConvert; 8 | } 9 | 10 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 11 | { 12 | if ((reader.ValueType == null || reader.ValueType == typeof(long?)) && reader.Value == null) 13 | { 14 | return null; 15 | } 16 | else 17 | { 18 | long.TryParse(reader.Value != null ? reader.Value.ToString() : "", out long value); 19 | return value; 20 | } 21 | } 22 | 23 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 24 | { 25 | writer.WriteValue(value?.ToString()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Files/MediaImageSvc.cs: -------------------------------------------------------------------------------- 1 | using MapsterMapper; 2 | 3 | namespace Mbill.Service.Core.Files; 4 | 5 | public class MediaImageSvc : IMediaImageSvc 6 | { 7 | private readonly IMapper _mapper; 8 | 9 | private readonly IMediaImageRepo _mediaImageRepo; 10 | 11 | public MediaImageSvc(IMediaImageRepo mediaImageRepo, IMapper mapper) 12 | { 13 | _mapper = mapper; 14 | _mediaImageRepo = mediaImageRepo; 15 | } 16 | 17 | public async Task>> GetPageAsync(MediaImagePagingInput pagingDto) 18 | { 19 | var list = await _mediaImageRepo 20 | .Select 21 | .Include(r => r.File) 22 | .Where(r => r.Type == pagingDto.Type) 23 | .ToPageListAsync(pagingDto, out long totalCount); 24 | 25 | var dtos = list.Select(l => _mapper.Map(l)).ToList(); 26 | return ServiceResult>.Successed(new PagedDto (dtos, totalCount )); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Auth/IAccountSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Auth; 2 | 3 | public interface IAccountSvc : IApplicationSvc 4 | { 5 | /// 6 | /// 账户登录 7 | /// 8 | /// 9 | /// 10 | Task> AccountLoginAsync(AccountLoginDto input); 11 | 12 | /// 13 | /// 微信预登录 14 | /// 15 | /// 微信login code 16 | /// 17 | Task> WxPreLoginAsync(string code); 18 | 19 | /// 20 | /// 微信登录 21 | /// 22 | /// 23 | /// 24 | Task> WxLoginAsync(WxLoginInput input); 25 | 26 | /// 27 | /// 刷新Token 28 | /// 29 | /// 30 | /// 31 | Task> GetTokenByRefreshAsync(string refreshToken); 32 | } 33 | -------------------------------------------------------------------------------- /test/Mbill.Service.Test/Mbill.Service.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | all 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Permission/IRoleSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Permission; 2 | 3 | public interface IRoleSvc 4 | { 5 | /// 6 | /// 新增角色 7 | /// 8 | /// 角色信息 9 | /// 10 | Task InsertAsync(ModifyRoleDto role); 11 | 12 | /// 13 | /// 删除角色 14 | /// 15 | /// 角色Id 16 | /// 17 | Task DeleteAsync(long bId); 18 | 19 | /// 20 | /// 更新角色 21 | /// 22 | /// 账单分类信息 23 | /// 24 | Task UpdateAsync(ModifyRoleDto role); 25 | 26 | /// 27 | /// 获取所有角色信息 28 | /// 29 | /// 30 | Task>> GetAllAsync(); 31 | 32 | /// 33 | /// 获取角色信息 34 | /// 35 | /// 36 | Task> GetAsync(long bId); 37 | } -------------------------------------------------------------------------------- /src/Mbill.Service/Common/Registers/Core/UserRegister.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | 3 | namespace Mbill.Service.Common.Registers.Core; 4 | 5 | public class UserRegister : BaseRegister 6 | { 7 | protected override void TypeRegister(TypeAdapterConfig config) 8 | { 9 | config.ForType() 10 | .Map(d => d.AvatarUrl, s => UrlConverter(s.AvatarUrl)) 11 | .Map(d => d.Address, s => $"{s.Province}{s.City}{s.District}{s.Street}") 12 | .Map(d => d.GenderName, s => GenderConverter(s.Gender)); 13 | 14 | config.ForType() 15 | .Map(d => d.AvatarUrl, s => UrlConverter(s.AvatarUrl)) 16 | .Map(d => d.Roles, s => s.UserRoles.Select(u => u.Role.Adapt())) 17 | .Map(d => d.Address, s => $"{s.Province}{s.City}{s.District}{s.Street}") 18 | .Map(d => d.GenderName, s => GenderConverter(s.Gender)); 19 | 20 | config.ForType() 21 | .Map(d => d.Gender, s => GenderConverter(s.Gender)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/UserRoleEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 用户角色表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_user_role")] 7 | [Index("index_user_role_on_user_bid", nameof(UserBId), false)] 8 | public class UserRoleEntity : Entity 9 | { 10 | public UserRoleEntity() 11 | { 12 | } 13 | public UserRoleEntity(long userBId, long roleBId) 14 | { 15 | UserBId = userBId; 16 | RoleBId = roleBId; 17 | } 18 | 19 | /// 20 | /// 用户BId 21 | /// 22 | [Description("用户BId")] 23 | public long UserBId { get; set; } 24 | 25 | /// 26 | /// 角色BId 27 | /// 28 | [Description("角色BId")] 29 | public long RoleBId { get; set; } 30 | 31 | [Navigate(nameof(UserBId), TempPrimary = nameof(UserEntity.BId))] 32 | public virtual UserEntity User { get; set; } 33 | 34 | [Navigate(nameof(RoleBId), TempPrimary = nameof(RoleEntity.BId))] 35 | public virtual RoleEntity Role { get; set; } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/Mbill.Core/Interface/IRepositories/PreOrder/IPreOrderRepo.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Interface.IRepositories.PreOrder; 2 | 3 | public interface IPreOrderRepo : IAuditBaseRepo 4 | { 5 | /// 6 | /// 获取预购单 7 | /// 8 | /// 9 | /// 10 | Task GetPreOrderAsync(long bId); 11 | 12 | /// 13 | /// 获取指定用户、指定状态的预购清单总数 14 | /// 15 | /// 分组 16 | /// 17 | Task<(long done, long unDone)> GetCountByStatusAsync(List groupBIds); 18 | 19 | /// 20 | /// 获取分组下预购清单总预购金额 21 | /// 22 | /// 23 | /// 24 | Task GetPreAmountByGroupAsync(List groupBIds); 25 | 26 | /// 27 | /// 获取分组下预购清单总实购金额 28 | /// 29 | /// 30 | /// 31 | Task GetRealAmountByGroupAsync(List groupBIds); 32 | } 33 | -------------------------------------------------------------------------------- /src/Mbill.ToolKits/Utils/EncryptUtil.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.ToolKits.Utils; 2 | 3 | public class EncryptUtil 4 | { 5 | /// 6 | /// 通过创建哈希字符串适用于任何 MD5 哈希函数 (在任何平台) 上创建 32 个字符的十六进制格式哈希字符串 7 | /// 8 | /// 9 | /// 10 | public static string Encrypt(string source) 11 | { 12 | using MD5 md5Hash = MD5.Create(); 13 | byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(source)); 14 | StringBuilder sBuilder = new StringBuilder(); 15 | foreach (byte t in data) 16 | { 17 | sBuilder.Append(t.ToString("x2")); 18 | } 19 | 20 | string hash = sBuilder.ToString(); 21 | return hash.ToUpper(); 22 | } 23 | 24 | /// 25 | /// 验证source加密码后是否生成mdPwd 26 | /// 27 | /// Md5生成的代码 28 | /// 29 | /// 30 | public static bool Verify(string mdPwd, string source) 31 | { 32 | return mdPwd == Encrypt(source).ToUpper(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Middleware/SwaggerMiddleware.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Middleware; 2 | 3 | public static class SwaggerMiddleware 4 | { 5 | public static void UseSwaggerUI(this IApplicationBuilder app, Func streamHtml) 6 | { 7 | app.UseSwaggerUI(options => 8 | { 9 | 10 | ApiInfo.ApiInfos.ForEach(a => options.SwaggerEndpoint($"/swagger/{a.UrlPrefix}/swagger.json", a.Name)); 11 | 12 | // 将swagger首页,设置成我们自定义的页面,记得这个字符串的写法:{项目名.index.html} 13 | if (streamHtml.Invoke() == null) 14 | { 15 | var msg = "index.html的属性,必须设置为嵌入的资源"; 16 | throw new Exception(msg); 17 | } 18 | options.IndexStream = streamHtml; 19 | //模型默认扩展深度,-1位完全隐藏 20 | options.DefaultModelExpandDepth(-1); 21 | //API仅展开标记 22 | options.DocExpansion(DocExpansion.List); 23 | //API前缀设为空 24 | options.RoutePrefix = string.Empty; 25 | //API页面标题 26 | options.DocumentTitle = "Mbill_ApiDoc"; 27 | 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Memoyu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/User/IUserSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.User; 2 | 3 | public interface IUserSvc 4 | { 5 | /// 6 | /// 注册-新增一个用户 7 | /// 8 | /// 用户信息 9 | Task CreateAsync(ModifyUserDto input); 10 | 11 | /// 12 | /// 获取用户信息,id为空时,通过Token获取 13 | /// 14 | /// 15 | /// 16 | Task> GetAsync(long? bId); 17 | 18 | /// 19 | /// 获取用户分页信息 20 | /// 21 | /// 分页数据 22 | /// 23 | Task>> GetPagesAsync(UserPagingDto pagingDto); 24 | 25 | /// 26 | /// 更新用户信息 27 | /// 28 | /// 实体数据 29 | /// 30 | Task UpdateAsync(ModifyUserBaseDto input); 31 | 32 | /// 33 | /// 删除用户(软删除) 34 | /// 35 | /// 36 | /// 37 | Task DeleteAsync(long bId); 38 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Exceptions/KnownException.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Exceptions; 2 | 3 | [Serializable] 4 | public class KnownException : ApplicationException 5 | { 6 | /// 7 | /// 状态码 8 | /// 9 | private readonly int _statusCode; 10 | /// 11 | /// 错误码,当为1时,代表正常 12 | /// 13 | private readonly ServiceResultCode _errorCode; 14 | /// 15 | /// 16 | /// 17 | public KnownException() : base("服务器繁忙,请稍后再试!") 18 | { 19 | _errorCode = ServiceResultCode.Failed; 20 | _statusCode = 400; 21 | } 22 | 23 | public KnownException(string message = "服务器繁忙,请稍后再试!", ServiceResultCode errorCode = ServiceResultCode.Failed, int statusCode = 400) : base(message) 24 | { 25 | this._errorCode = errorCode; 26 | _statusCode = statusCode; 27 | 28 | } 29 | 30 | /// 31 | /// 32 | /// 33 | /// 34 | public int GetStatusCode() 35 | { 36 | return _statusCode; 37 | } 38 | 39 | public ServiceResultCode GetErrorCode() 40 | { 41 | return _errorCode; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/Mbill.Core.Test/Mbill.Core.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | all 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Mbill/Modules/ServiceModule.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Modules; 2 | 3 | public class ServiceModule : Autofac.Module 4 | { 5 | protected override void Load(ContainerBuilder builder) 6 | { 7 | builder.RegisterType(); 8 | builder.RegisterType(); 9 | 10 | builder.RegisterType(); 11 | 12 | List interceptorServiceTypes = new List() 13 | { 14 | typeof(UnitOfWorkInterceptor), 15 | typeof(CacheIntercept), 16 | }; 17 | 18 | string[] notIncludes = new string[] 19 | { 20 | }; 21 | 22 | Assembly servicesDllFile = Assembly.Load("Mbill.Service"); 23 | builder.RegisterAssemblyTypes(servicesDllFile) 24 | .Where(a => a.Name.EndsWith("Svc") && !notIncludes.Where(r => r == a.Name).Any() && !a.IsAbstract && !a.IsInterface && a.IsPublic) 25 | .AsImplementedInterfaces() 26 | .InstancePerLifetimeScope() 27 | .PropertiesAutowired()// 属性注入 28 | .InterceptedBy(interceptorServiceTypes.ToArray()) 29 | .EnableInterfaceInterceptors(); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/BaseTypeEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 字典类型表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_type")] 7 | public class BaseTypeEntity : FullAduitEntity 8 | { 9 | public BaseTypeEntity() 10 | { 11 | } 12 | 13 | public BaseTypeEntity(string typeCode, string fullName, int? sort) 14 | { 15 | TypeCode = typeCode ?? throw new ArgumentNullException(nameof(typeCode)); 16 | FullName = fullName ?? throw new ArgumentNullException(nameof(fullName)); 17 | Sort = sort; 18 | } 19 | 20 | /// 21 | /// 字典类型编码 22 | /// 23 | [Description("字典类型编码")] 24 | [Column(StringLength = 50)] 25 | public string TypeCode { get; set; } 26 | 27 | /// 28 | /// 字典类型名 29 | /// 30 | [Description("字典类型名")] 31 | [Column(StringLength = 50)] 32 | public string FullName { get; set; } 33 | 34 | /// 35 | /// 排序码 36 | /// 37 | [Description("排序码")] 38 | public int? Sort { get; set; } 39 | 40 | public virtual ICollection BaseItems { get; set; } 41 | } 42 | -------------------------------------------------------------------------------- /src/Mbill.Core/Extensions/ClaimsIdentityExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Extensions; 2 | 3 | public static class ClaimsIdentityExtensions 4 | { 5 | public static long? FindUserBId(this ClaimsPrincipal principal) 6 | { 7 | Claim userIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier); 8 | if (userIdOrNull == null || string.IsNullOrWhiteSpace(userIdOrNull.Value)) 9 | { 10 | return null; 11 | } 12 | 13 | return long.Parse(userIdOrNull.Value); 14 | } 15 | 16 | public static bool? IsAdmin(this ClaimsPrincipal principal) 17 | { 18 | Claim isAdminOrNull = principal.Claims?.FirstOrDefault(c => c.Type == CoreClaimTypes.IsAdmin); 19 | if (isAdminOrNull == null || string.IsNullOrWhiteSpace(isAdminOrNull.Value)) 20 | { 21 | return null; 22 | } 23 | return bool.Parse(isAdminOrNull.Value); 24 | } 25 | 26 | public static string FindUserName(this ClaimsPrincipal principal) 27 | { 28 | Claim userNameOrNull = principal.Claims?.FirstOrDefault(c => c.Type == ClaimTypes.Name); 29 | 30 | return userNameOrNull?.Value; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Filters/InputFieldActionFilter.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Filters; 2 | 3 | public class InputFieldActionFilter : IActionFilter 4 | { 5 | public void OnActionExecuted(ActionExecutedContext context) 6 | { 7 | //throw new NotImplementedException(); 8 | } 9 | 10 | public void OnActionExecuting(ActionExecutingContext context) 11 | { 12 | ServiceResult result = new(); 13 | if (!context.ModelState.IsValid) 14 | { 15 | var errorMessage = context.ModelState.Values.SelectMany(v => v.Errors).FirstOrDefault(); 16 | result.Code = ServiceResultCode.ParameterError; 17 | result.Message = errorMessage.ErrorMessage; 18 | var set = new JsonSerializerSettings 19 | { 20 | ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() 21 | }; 22 | context.Result = new ContentResult 23 | { 24 | Content = JsonConvert.SerializeObject(result, set), 25 | StatusCode = StatusCodes.Status400BadRequest, 26 | ContentType = "application/json", 27 | }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/Mbill.Infrastructure.Test/Mbill.Infrastructure.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | all 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/UserRepo.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | using Mbill.Core.Interface.IRepositories.Core; 3 | using Mbill.Core.Domains.Entities.User; 4 | 5 | namespace Mbill.Infrastructure.Repository.Core 6 | { 7 | public class UserRepo : AuditBaseRepo, IUserRepo 8 | { 9 | private readonly ICurrentUser _currentUser; 10 | public UserRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 11 | { 12 | _currentUser = currentUser; 13 | } 14 | 15 | public Task GetUserAsync(long bId) 16 | { 17 | return Select.Where(u=> u.BId == bId).ToOneAsync(); 18 | } 19 | 20 | public Task GetUserAsync(Expression> expression) 21 | { 22 | return Select.Where(expression).ToOneAsync(); 23 | } 24 | 25 | public Task UpdateLastLoginTimeAsync(long userId) 26 | { 27 | return UpdateDiy.Set(r => new UserEntity() 28 | { 29 | LastLoginTime = DateTime.Now 30 | }).Where(r => r.Id == userId).ExecuteAffrowsAsync(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Mbill.Service/PreOrder/IPreOrderGroupSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.PreOrder; 2 | 3 | public interface IPreOrderGroupSvc : ICrudApplicationSvc 4 | { 5 | /// 6 | /// 预购分组转账单 7 | /// 8 | /// 9 | /// 10 | Task> GroupToBillAsync(GroupToBillInput input); 11 | 12 | /// 13 | /// 获取预购分组带组内预购总金额 14 | /// 15 | /// 预购分组Id 16 | /// 17 | Task> GetGroupWithAmountAsync(long bId); 18 | 19 | /// 20 | /// 获取指定月份分页预购分组 21 | /// 22 | /// 分页查询 23 | /// 24 | Task>> GetByMonthPagesAsync(MonthPreOrderGroupPagingInput input); 25 | 26 | /// 27 | /// 获取指定分组预购清单统计 28 | /// 29 | /// 30 | /// 31 | Task> GetPreOrderStatAsync(GroupPreOrderStatInput input); 32 | } 33 | -------------------------------------------------------------------------------- /src/Mbill.Service/Common/Registers/Bill/BillRegister.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | 3 | namespace Mbill.Service.Common.Registers.Bill; 4 | 5 | public class BillRegister : BaseRegister 6 | { 7 | protected override void TypeRegister(TypeAdapterConfig config) 8 | { 9 | config.ForType() 10 | .Map(d => d.CategoryIcon, s => UrlConverter(s.Category.Icon)) 11 | .Map(d => d.Category, s => s.Category == null ? string.Empty : s.Category.Name) 12 | .Map(d => d.AmountFormat, s => s.Amount.AmountFormat()) 13 | .Map(d => d.Date, s => s.Time.ToString("yyyy-MM-dd")) 14 | .Map(d => d.Time, s => s.Time.ToString("HH:mm")); 15 | 16 | config.ForType() 17 | .Map(d => d.CategoryIcon, s => UrlConverter(s.Category.Icon)) 18 | .Map(d => d.Category, s => s.Category == null ? string.Empty : s.Category.Name) 19 | .Map(d => d.AssetIcon, s => UrlConverter(s.Asset.Icon)) 20 | .Map(d => d.Asset, s => s.Asset == null ? string.Empty : s.Asset.Name) 21 | .Map(d => d.AmountFormat, s => s.Amount.AmountFormat()) 22 | .Map(d => d.TimeFormat, s => $"{s.Time.GetWeek()} {s.Time:yyyy-MM-dd HH:mm}"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mbill/Controllers/Core/NoticeController.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Service.Core.Notice; 2 | using Mbill.Service.Core.Notice.Input; 3 | using Mbill.Service.Core.Notice.Output; 4 | 5 | namespace Mbill.Controllers.Core; 6 | 7 | [Route("api/notice")] 8 | [Authorize] 9 | public class NoticeController : ApiControllerBase 10 | { 11 | private readonly INoticeSvc _noticeSvc; 12 | 13 | public NoticeController(INoticeSvc noticeSvc) 14 | { 15 | _noticeSvc = noticeSvc; 16 | } 17 | 18 | /// 19 | /// 新增公告 20 | /// 21 | /// 公告 22 | [HttpPost] 23 | [LocalAuthorize("新增公告", "管理员")] 24 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v2)] 25 | public async Task> CreateAsync([FromBody] ModifyNoticeDto input) 26 | { 27 | return await _noticeSvc.InsertAsync(input); 28 | } 29 | 30 | /// 31 | /// 获取最新公告 32 | /// 33 | [HttpGet("latest")] 34 | [LocalAuthorize("获取最新公告", "公告")] 35 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v1)] 36 | public async Task> GetLatestAsync() 37 | { 38 | return await _noticeSvc.GetLatestAsync(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Mbill/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "MySql": "{MySqlConStr}", 4 | "Redis": "{RedisConStr}", 5 | "MongoDB": { 6 | "ConnStr": "mongodb://{MongoDBConStr}", 7 | "DatabaseName": "mbill" 8 | } 9 | }, 10 | "Cors": { 11 | "Name": "mbill", 12 | "Origins": "http://*.memoyu.com,http://localhost:9087" 13 | }, 14 | "FileStorage": { 15 | "Default": 1, 16 | "Local": { "Host": "" }, 17 | "Qiniu": { 18 | "AK": "{QiniuAk}", 19 | "SK": "{QiniuSk}", 20 | "Bucket": "mbill", 21 | "Host": "https://oss.memoyu.com/", 22 | "UseHttps": true 23 | } 24 | }, 25 | "Authentication": { 26 | "JwtBearer": { 27 | "SecurityKey": "{JwtSecurityKey}", 28 | "Expires": 10800, 29 | "Issuer": "Memoyu", 30 | "Audience": "Memoyu.Mbill.WebApi" 31 | } 32 | }, 33 | "MinPro": { 34 | "AppID": "{MiniProAppId}", 35 | "AppSecret": "{MiniProAppSecret}" 36 | }, 37 | "Cache": { 38 | "Enable": true, 39 | "ExpireSeconds": "300" 40 | }, 41 | "Middleware": { 42 | "IPLog": { 43 | "Enabled": true 44 | }, 45 | "SignalR": { 46 | "Enabled": false 47 | }, 48 | "IpRateLimit": { 49 | "Enabled": true 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Mbill/Modules/Configs/MigrationStartupTask.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Modules.Configs; 2 | 3 | public class MigrationStartupTask 4 | { 5 | private readonly IServiceProvider _serviceProvider; 6 | private readonly ILogger _logger; 7 | public MigrationStartupTask(IServiceProvider serviceProvider, ILogger logger) 8 | { 9 | _serviceProvider = serviceProvider; 10 | _logger = logger; 11 | } 12 | 13 | public async Task StartAsync(CancellationToken cancellationToken = default) 14 | { 15 | try 16 | { 17 | using var scope = _serviceProvider.CreateScope(); 18 | IDataSeedSvc dataSeedSvc = scope.ServiceProvider.GetRequiredService(); 19 | 20 | await dataSeedSvc.InitDataSeedAsync(); 21 | var defPermissions = DomainReflexUtil.GetAssemblyPermissionAttributes(); 22 | await dataSeedSvc.InitPermissionAsync(defPermissions); 23 | await dataSeedSvc.InitAdministratorPermissionAsync(); 24 | await dataSeedSvc.InitUserPermissionAsync(); 25 | } 26 | catch (Exception ex) 27 | { 28 | _logger.LogError($"初始化数据失败!!!{ex.Message}{ex.StackTrace}{ex.InnerException}"); 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Mbill/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ApiVersion": "1.0.0", 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning" 7 | } 8 | }, 9 | "IpRateLimiting": { 10 | //false则全局将应用限制,并且仅应用具有作为端点的规则* 。 true则限制将应用于每个端点,如{HTTP_Verb}{PATH} 11 | "EnableEndpointRateLimiting": true, 12 | //false则拒绝的API调用不会添加到调用次数计数器上 13 | "StackBlockedRequests": false, 14 | "RealIpHeader": "X-Real-IP", 15 | "ClientIdHeader": "X-ClientId", 16 | "HttpStatusCode": 200, 17 | "QuotaExceededResponse": { 18 | "Content": "{{\"code\":10140,\"message\":\"访问过于频繁,请稍后重试\",\"data\":null}}", 19 | "ContentType": "application/json", 20 | "StatusCode": 429 21 | }, 22 | "IpWhitelist": [], 23 | "EndpointWhitelist": [], 24 | "ClientWhitelist": [], 25 | "GeneralRules": [ 26 | { 27 | "Endpoint": "*", 28 | // "Endpoint": "*:/cms/test", 29 | "Period": "1s", 30 | "Limit": 10 31 | } 32 | ] 33 | }, 34 | "IpRateLimitPolicies": { 35 | "IpRules": [ 36 | { 37 | "Ip": "192.168.2.136", 38 | "Rules": [ 39 | { 40 | "Endpoint": "*", 41 | "Period": "1s", 42 | "Limit": 10 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/PermissionEntity.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Common; 2 | 3 | namespace Mbill.Core.Domains.Entities.Core; 4 | 5 | /// 6 | /// 权限表 7 | /// 8 | [Table(Name = SystemConst.DbTablePrefix + "_permission")] 9 | public class PermissionEntity : FullAduitEntity 10 | { 11 | public PermissionEntity() 12 | { 13 | 14 | } 15 | 16 | public PermissionEntity(string name, string module, string router) 17 | { 18 | BId = SnowFlake.NextId(); 19 | Name = name ?? throw new ArgumentNullException(nameof(name)); 20 | Module = module ?? throw new ArgumentNullException(nameof(module)); 21 | Router = router ?? throw new ArgumentNullException(nameof(router)); 22 | } 23 | 24 | /// 25 | /// 所属权限、权限名称,例如:访问首页 26 | /// 27 | [Description("所属权限、权限名称,例如:访问首页")] 28 | [Column(StringLength = 60)] 29 | public string Name { get; set; } 30 | 31 | /// 32 | /// 权限所属模块,例如:人员管理 33 | /// 34 | [Description("权限所属模块,例如:人员管理")] 35 | [Column(StringLength = 50)] 36 | public string Module { get; set; } 37 | 38 | /// 39 | /// 后台路由 40 | /// 41 | [Description("后台路由")] 42 | [Column(StringLength = 200)] 43 | public string Router { get; set; } 44 | } 45 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/ModifyBillInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class ModifyBillInput 4 | { 5 | public long BId { get; set; } 6 | 7 | /// 8 | /// 分类Id 9 | /// 10 | [Required(ErrorMessage = "必须传入分类BId")] 11 | public long? CategoryBId { get; set; } 12 | 13 | /// 14 | /// 资产Id 15 | /// 16 | [Required(ErrorMessage = "必须传入源资产BId")] 17 | public long? AssetBId { get; set; } 18 | 19 | /// 20 | /// 金额 21 | /// 22 | [Required(ErrorMessage = "金额不能为空")] 23 | [Range(0.01, 100000, ErrorMessage = "金额应该在0.01-100000之间")] 24 | public decimal Amount { get; set; } 25 | 26 | /// 27 | /// 记录类型:支出、收入、转账、还款 28 | /// 29 | [Required(ErrorMessage = "必须传入账单类型")] 30 | public int Type { get; set; } 31 | 32 | /// 33 | /// 说明 34 | /// 35 | [MaxLength(40, ErrorMessage = "描述长度不超过40")] 36 | public string Description { get; set; } 37 | 38 | /// 39 | /// 地点 40 | /// 41 | public string Address { get; set; } 42 | 43 | /// 44 | /// 记录日期:时间 45 | /// 46 | [Required(ErrorMessage = "必须传入记录日期:时间")] 47 | public DateTime Time { get; set; } 48 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/FileEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 上传文件表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_file")] 7 | public class FileEntity : FullAduitEntity 8 | { 9 | /// 10 | /// 后缀 11 | /// 12 | [Description("后缀")] 13 | [Column(StringLength = 50)] 14 | public string Extension { get; set; } = string.Empty; 15 | 16 | /// 17 | /// 图片md5值,防止上传重复图片 18 | /// 19 | [Description("图片md5值,防止上传重复图片")] 20 | [Column(StringLength = 40)] 21 | public string Md5 { get; set; } = string.Empty; 22 | 23 | /// 24 | /// 名称 25 | /// 26 | [Description("名称")] 27 | [Column(StringLength = 300)] 28 | public string Name { get; set; } = string.Empty; 29 | 30 | /// 31 | /// 路径 32 | /// 33 | [Description("路径")] 34 | [Column(StringLength = 500)] 35 | public string Path { get; set; } = string.Empty; 36 | 37 | /// 38 | /// 大小 39 | /// 40 | [Description("大小")] 41 | public long? Size { get; set; } 42 | 43 | /// 44 | /// 1 七牛, 99 自定义 45 | /// 46 | [Description("1 七牛, 99 自定义")] 47 | public short? Type { get; set; } 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |
6 |
7 | 8 | 个人记账系统后台 9 | 10 |

11 |
12 | 13 | > 知行合一 14 | 15 | [![.NET5](https://img.shields.io/badge/.NET5.0.0-3963bc.svg)](https://dotnet.microsoft.com/download) [![.NET5](https://img.shields.io/badge/Memoyu.Core-.NET5-red)](https://github.com/Memoyu/Memoyu.Core) [![](https://img.shields.io/badge/license-MIT-3963bc.svg)](LICENSE) 16 |
17 | 18 |   19 | 20 | ## 项目介绍 21 | 22 | 项目为个人记账管理系统的后台服务实现。 23 | 24 | 采用自己封装的项目模板进行快速开发,并在此项目中发现模板的问题以及需要向模板新增的功能。 25 | 26 | 部署文档:[mbill部署相关 ](https://www.yuque.com/memoyu/sz8ae0/pnbr6haohkhid0tf) 27 | 28 |   29 | 30 | ## 相关项目 31 | 32 | ✨ [采用uni-app实现的小程序前端 - Memoyu/mbill_wechat_app](https://github.com/Memoyu/mbill_wechat_app) 33 | 34 | ✨ [采用Blazor+Ant Blazor实现后端管理 - Memoyu/mbill_blazor_admin](https://github.com/Memoyu/mbill_blazor_admin) 35 | 36 | ✨[采用Xamarin搭建移动客户端App-Memoyu/mbill_xamarin_app](https://github.com/Memoyu/mbill_xamarin_app) 37 | 38 |   39 | 40 | ## TODO 41 | 42 | - [x] 实现基本记账接口 43 | - [x] 实现账目统计 44 | - [x] 实现账目搜索 45 | - [ ] ...... 46 | 47 |   48 | 49 | ## 开源协议 50 | 51 | [MIT](LICENSE). 52 | -------------------------------------------------------------------------------- /src/Mbill.ToolKits/Utils/ColorUtil.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.ToolKits.Utils; 2 | 3 | public static class ColorUtil 4 | { 5 | public static string GetRandomColor() 6 | { 7 | Random randomNum_1 = new Random(Guid.NewGuid().GetHashCode()); 8 | System.Threading.Thread.Sleep(randomNum_1.Next(1)); 9 | int int_Red = randomNum_1.Next(255); 10 | 11 | Random randomNum_2 = new Random((int)DateTime.Now.Ticks); 12 | int int_Green = randomNum_2.Next(255); 13 | 14 | Random randomNum_3 = new Random(Guid.NewGuid().GetHashCode()); 15 | 16 | int int_Blue = randomNum_3.Next(255); 17 | int_Blue = (int_Red + int_Green > 380) ? int_Red + int_Green - 380 : int_Blue; 18 | int_Blue = (int_Blue > 255) ? 255 : int_Blue; 19 | 20 | 21 | return GetDarkerColor(int_Red, int_Green, int_Blue); 22 | } 23 | 24 | //获取加深颜色 25 | private static string GetDarkerColor(int r, int g, int b) 26 | { 27 | const int max = 255; 28 | int increase = new Random(Guid.NewGuid().GetHashCode()).Next(30, 255); //还可以根据需要调整此处的值 29 | 30 | int rc = Math.Abs(Math.Min(r - increase, max)); 31 | int gc = Math.Abs(Math.Min(g - increase, max)); 32 | int bc = Math.Abs(Math.Min(b - increase, max)); 33 | 34 | return rc.ToString("X2") + gc.ToString("X2") + bc.ToString("X2"); ; 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/RoleEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 角色表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_role")] 7 | public class RoleEntity : FullAduitEntity 8 | { 9 | /// 10 | /// 角色唯一标识字符 11 | /// 12 | [Description("角色唯一标识字符")] 13 | [Column(StringLength = 60)] 14 | public string Name { get; set; } 15 | 16 | /// 17 | /// 角色类型 18 | /// 19 | [Description("角色类型")] 20 | public int Type { get; set; } 21 | 22 | /// 23 | /// 角色描述 24 | /// 25 | [Description("角色描述")] 26 | [Column(StringLength = 100)] 27 | public string Info { get; set; } 28 | 29 | /// 30 | /// 是否是静态分组,是静态时无法删除此分组 31 | /// 32 | [Description("是否是静态分组,是静态时无法删除此分组")] 33 | public bool IsStatic { get; set; } = false; 34 | 35 | /// 36 | /// 排序码,升序 37 | /// 38 | [Description("排序码,升序")] 39 | public int Sort { get; set; } 40 | 41 | [Navigate(ManyToMany = typeof(UserRoleEntity))] 42 | public virtual ICollection Users { get; set; } 43 | 44 | [Navigate(nameof(RolePermissionEntity.RoleBId), TempPrimary = nameof(BId))] 45 | public virtual ICollection RolePermissions { get; set; } 46 | } 47 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/Core/FileRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Common.Configs; 2 | using Mbill.Core.Domains.Entities.Core; 3 | using Mbill.Core.Interface.IRepositories.Core; 4 | using Microsoft.Extensions.Options; 5 | 6 | namespace Mbill.Infrastructure.Repository.Core 7 | { 8 | public class FileRepo : AuditBaseRepo, IFileRepo 9 | { 10 | private readonly FileStorageOptions _fileStorageOption; 11 | 12 | public FileRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser, IOptionsMonitor option) : base(unitOfWorkManager, currentUser) 13 | { 14 | _fileStorageOption = option.CurrentValue ?? throw new ArgumentNullException("FileStorage 配置为空"); 15 | } 16 | 17 | public string GetFileUrl(string path) 18 | { 19 | if (string.IsNullOrEmpty(path)) return ""; 20 | if (path.StartsWith("http") || path.StartsWith("https"))//如果是完整地址 21 | { 22 | return path; 23 | } 24 | 25 | var file = Where(r => r.Path == path).First(); 26 | if (file == null) return path; 27 | return file.Type switch 28 | { 29 | 1 => _fileStorageOption?.Qiniu?.Host + file.Path, 30 | 99 => _fileStorageOption?.Local?.Host, 31 | _ => file.Path, 32 | }; 33 | 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Mbill/Modules/DependencyModule.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Modules; 2 | 3 | public class DependencyModule : Autofac.Module 4 | { 5 | protected override void Load(ContainerBuilder builder) 6 | { 7 | Assembly[] currentAssemblies = AppDomain.CurrentDomain.GetAssemblies().Where(r => r.FullName.Contains("Mbill")).ToArray(); 8 | 9 | //每次调用,都会重新实例化对象;每次请求都创建一个新的对象; 10 | Type transientDependency = typeof(ITransientDependency); 11 | builder.RegisterAssemblyTypes(currentAssemblies) 12 | .Where(t => transientDependency.GetTypeInfo().IsAssignableFrom(t) && t.IsClass && !t.IsAbstract && !t.IsGenericType) 13 | .AsImplementedInterfaces().InstancePerDependency(); 14 | 15 | //同一个Lifetime生成的对象是同一个实例 16 | Type scopeDependency = typeof(IScopedDependency); 17 | builder.RegisterAssemblyTypes(currentAssemblies) 18 | .Where(t => scopeDependency.GetTypeInfo().IsAssignableFrom(t) && t.IsClass && !t.IsAbstract && !t.IsGenericType) 19 | .AsImplementedInterfaces().InstancePerLifetimeScope(); 20 | 21 | //单例模式,每次调用,都会使用同一个实例化的对象;每次都用同一个对象; 22 | Type singletonDependency = typeof(ISingletonDependency); 23 | builder.RegisterAssemblyTypes(currentAssemblies) 24 | .Where(t => singletonDependency.GetTypeInfo().IsAssignableFrom(t) && t.IsClass && !t.IsAbstract && !t.IsGenericType) 25 | .AsImplementedInterfaces().SingleInstance(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Mbill/Controllers/User/UserController.cs: -------------------------------------------------------------------------------- 1 | using MapsterMapper; 2 | 3 | namespace Mbill.Controllers.Core; 4 | 5 | /// 6 | /// 用户管理 7 | /// 8 | [Route("api/admin/user")] 9 | public class UserController : ApiControllerBase 10 | { 11 | private readonly IMapper _mapper; 12 | private readonly IUserSvc _userService; 13 | 14 | public UserController(IMapper mapper, IUserSvc userService) 15 | { 16 | _mapper = mapper; 17 | _userService = userService; 18 | } 19 | 20 | /// 21 | /// 超级管理员新增用户 22 | /// 23 | /// 用户更改 24 | [HttpPost] 25 | [LocalAuthorize("新增用户", "管理员")] 26 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v2)] 27 | public async Task CreateAsync([FromBody] ModifyUserDto input) 28 | { 29 | await _userService.CreateAsync(input); 30 | return ServiceResult.Successed("用户创建成功"); 31 | } 32 | 33 | /// 34 | /// 获取用户信息分页 35 | /// 36 | /// 分页 37 | [HttpGet("pages")] 38 | [Authorize] 39 | [LocalAuthorize("获取用户分页数据", "管理员")] 40 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v3)] 41 | public async Task>> GetPagesAsync([FromQuery] UserPagingDto pagingDto) 42 | { 43 | return await _userService.GetPagesAsync(pagingDto); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Mbill/Modules/Configs/ValidJtiHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Modules.Configs; 2 | 3 | public class ValidJtiHandler : AuthorizationHandler 4 | { 5 | private readonly IHttpContextAccessor _contextAccessor; 6 | 7 | public ValidJtiHandler(IHttpContextAccessor contextAccessor) 8 | { 9 | _contextAccessor = contextAccessor; 10 | } 11 | protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidJtiRequirement requirement) 12 | { 13 | //检查是否登录 14 | AuthorizationFilterContext filterContext = context.Resource as AuthorizationFilterContext; 15 | DefaultHttpContext defaultHttpContext = context.Resource as DefaultHttpContext; 16 | if (!context.User.Identity.IsAuthenticated) 17 | { 18 | HandlerAuthenticationFailed(filterContext, "认证失败,请检查请求头或者重新登陆", ServiceResultCode.AuthenticationFailed); 19 | context.Fail(); 20 | return; 21 | } 22 | 23 | await Task.CompletedTask; 24 | context.Succeed(requirement); 25 | } 26 | 27 | public void HandlerAuthenticationFailed(AuthorizationFilterContext filterContext, string meessage, ServiceResultCode code) 28 | { 29 | if (filterContext == null) return; 30 | filterContext.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden; 31 | filterContext.Result = new JsonResult(new ServiceResult(code, meessage)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/BaseItemEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Core; 2 | 3 | /// 4 | /// 字典项详情表 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_item")] 7 | public class BaseItemEntity : FullAduitEntity 8 | { 9 | public BaseItemEntity() 10 | { 11 | } 12 | 13 | public BaseItemEntity(string itemCode, string itemName, bool status, int? sort) 14 | { 15 | ItemCode = itemCode ?? throw new ArgumentNullException(nameof(itemCode)); 16 | ItemName = itemName ?? throw new ArgumentNullException(nameof(itemName)); 17 | Status = status; 18 | Sort = sort; 19 | } 20 | 21 | /// 22 | /// 字典项所属TypeBId 23 | /// 24 | [Description("字典项所属TypeBId")] 25 | public long BaseTypeBId { get; set; } 26 | 27 | /// 28 | /// 字典项编码 29 | /// 30 | [Description("字典项编码")] 31 | [Column(StringLength = 50)] 32 | public string ItemCode { get; set; } 33 | 34 | /// 35 | /// 字典项名称 36 | /// 37 | [Description("字典项名称")] 38 | [Column(StringLength = 50)] 39 | public string ItemName { get; set; } 40 | 41 | /// 42 | /// 状态:0禁用,1启用 43 | /// 44 | [Description("状态:0禁用,1启用")] 45 | public bool Status { get; set; } 46 | 47 | /// 48 | /// 排序码 49 | /// 50 | [Description("排序码")] 51 | public int? Sort { get; set; } 52 | 53 | public virtual BaseTypeEntity BaseType { get; set; } 54 | } -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Notice/NoticeSvc.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Common; 2 | using Mbill.Service.Core.Notice.Input; 3 | using Mbill.Service.Core.Notice.Output; 4 | 5 | namespace Mbill.Service.Core.Notice; 6 | 7 | public class NoticeSvc : ApplicationSvc, INoticeSvc 8 | { 9 | private readonly ILogger _logger; 10 | private readonly INoticeRepo _noticeRepo; 11 | 12 | public NoticeSvc(ILoggerFactory loggerFactory, INoticeRepo noticeRepo) 13 | { 14 | _logger = loggerFactory.CreateLogger(); 15 | _noticeRepo = noticeRepo; 16 | } 17 | 18 | public async Task> InsertAsync(ModifyNoticeDto input) 19 | { 20 | var entity = Mapper.Map(input); 21 | entity.BId = SnowFlake.NextId(); 22 | var dto = await _noticeRepo.InsertAsync(entity); 23 | return ServiceResult.Successed(Mapper.Map(dto)); 24 | } 25 | 26 | public async Task> GetLatestAsync() 27 | { 28 | var notice = await _noticeRepo.Select.OrderByDescending(n => n.CreateTime).FirstAsync(); 29 | if (notice is not null) 30 | { 31 | // 不再可见范围内,则不返回 32 | var ranges = JsonConvert.DeserializeObject>(string.IsNullOrWhiteSpace(notice.Range) ? "[]" : notice.Range); 33 | if (ranges.Count > 0 && !ranges.Any(r => r == CurrentUser.BId)) notice = null; 34 | } 35 | 36 | return ServiceResult.Successed(Mapper.Map(notice ?? new NoticeEntity())); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Bill/CategoryEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Bill; 2 | 3 | /// 4 | /// 账单分类实体 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_category")] 7 | [Index("index_category_on_parent_bid", nameof(ParentBId), false)] 8 | [Index("index_category_on_type", nameof(Type), false)] 9 | public class CategoryEntity : FullAduitEntity 10 | { 11 | /// 12 | /// 账单分类名 13 | /// 14 | [Column(StringLength = 20, IsNullable = false)] 15 | [Description("分类名称")] 16 | public string Name { get; set; } 17 | 18 | /// 19 | /// 父级BId 20 | /// 21 | [Description("父级BId")] 22 | public long ParentBId { get; set; } 23 | 24 | /// 25 | /// 分类类型:0 支出,1 收入 26 | /// 27 | [Column(IsNullable = false)] 28 | [Description("分类类型:0 支出,1 收入")] 29 | public int Type { get; set; } 30 | 31 | /// 32 | /// 预算金额 33 | /// 34 | [Column(Precision = 12, Scale = 2)] 35 | [Description("预算金额")] 36 | public decimal Budget { get; set; } 37 | 38 | /// 39 | /// 图标地址 40 | /// 41 | [Column(StringLength = 100)] 42 | [Description("图标地址")] 43 | public string Icon { get; set; } 44 | 45 | /// 46 | /// 排序 47 | /// 48 | [Description("排序")] 49 | public int Sort { get; set; } 50 | 51 | [Navigate(nameof(ParentBId), TempPrimary =nameof(CategoryEntity.BId))] 52 | public virtual CategoryEntity Parent { get; set; } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/Enums/Base/ServiceResultCode.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Mbill.Core.Domains.Common.Enums.Base; 3 | 4 | /// 5 | /// 服务层响应枚举码 6 | /// 7 | public enum ServiceResultCode 8 | { 9 | /// 10 | /// 成功 11 | /// 12 | Succeed = 0, 13 | 14 | /// 15 | /// 失败 16 | /// 17 | Failed = 1, 18 | 19 | #region Authentication 20 | /// 21 | /// 认证失败 22 | /// 23 | AuthenticationFailed = 10000, 24 | 25 | /// 26 | /// 无权限 27 | /// 28 | NoPermission = 10001, 29 | #endregion 30 | 31 | /// 32 | /// 资源不存在 33 | /// 34 | NotFound = 10020, 35 | 36 | /// 37 | /// 资源不存在 38 | /// 39 | AlreadyExists = 10021, 40 | 41 | /// 42 | /// 未知错误 43 | /// 44 | UnknownError = 1007, 45 | 46 | 47 | #region Parameter 48 | /// 49 | /// 参数错误 50 | /// 51 | [Description("参数错误")] 52 | ParameterError = 10030, 53 | 54 | /// 55 | /// 字段重复 56 | /// 57 | RepeatField = 10060, 58 | #endregion 59 | 60 | 61 | 62 | #region Token 63 | /// 64 | /// 令牌失效 65 | /// 66 | [Description("令牌失效")] 67 | TokenInvalidation = 10040, 68 | 69 | /// 70 | /// 令牌过期 71 | /// 72 | TokenExpired = 10050, 73 | 74 | /// 75 | /// refreshToken异常 76 | /// 77 | RefreshTokenError = 10100, 78 | #endregion 79 | } 80 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/PreOrder/PreOrderEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.PreOrder; 2 | 3 | /// 4 | /// 预购清单实体 5 | /// 6 | [Table(Name = DbTablePrefix + "_pre_order")] 7 | [Index("index_preorder_on_group_bid", nameof(GroupBId), false)] 8 | [Index("index_preorder_on_status", nameof(Status), false)] 9 | public class PreOrderEntity : FullAduitEntity 10 | { 11 | /// 12 | /// 分组BId 13 | /// 14 | [Description("分组BId")] 15 | public long GroupBId { get; set; } 16 | 17 | /// 18 | /// 预购金额 19 | /// 20 | [Description("预购金额")] 21 | [Column(Precision = 12, Scale = 2)] 22 | public decimal PreAmount { get; set; } 23 | 24 | /// 25 | /// 实际金额 26 | /// 27 | [Description("实际金额")] 28 | [Column(Precision = 12, Scale = 2)] 29 | public decimal RealAmount { get; set; } 30 | 31 | /// 32 | /// 说明 33 | /// 34 | [Description("说明")] 35 | [Column(StringLength = 40, IsNullable = false)] 36 | public string Description { get; set; } 37 | 38 | /// 39 | /// 记录日期 40 | /// 41 | [Description("记录日期")] 42 | [Column(StringLength = 10, IsNullable = false)] 43 | public DateTime Time { get; set; } 44 | 45 | /// 46 | /// 状态 0:未购买;1:已购买 47 | /// 48 | [Description("状态 0:未购买;1:已购买")] 49 | public int Status { get; set; } 50 | 51 | /// 52 | /// 图标颜色 53 | /// 54 | [Description("图标颜色")] 55 | public string Color { get; set; } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/Mbill/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "MySql": "Data Source=localhost;Port=3306;User ID=root;Password=mysql.pwd;Initial Catalog=mbill;Charset=utf8mb4;SslMode=none;Max pool size=1;Connection LifeTime=20;SslMode=None;", 4 | "Redis": "127.0.0.1:6379,password=redis.pwd,defaultDatabase=0", 5 | "MongoDB": { 6 | "ConnStr": "mongodb://admin:mongodb.pwd@localhost:27017", 7 | "DatabaseName": "mbill" 8 | } 9 | }, 10 | "Cors": { 11 | "Name": "mbill", 12 | "Origins": "http://*.memoyu.com,http://localhost:10087" 13 | }, 14 | "FileStorage": { 15 | "Default": 1, 16 | "Local": { "Host": "https://xxxxxxx" }, 17 | "Qiniu": { 18 | "AK": "YPwfsUNNEsTXUGwO6LlOCGutAd2t7ljTg0maJL4V", 19 | "SK": "FDLnpSPyyQeNy_rVOANLj5ND9_3pFGs-XNPANdl2", 20 | "Bucket": "mbill", 21 | "Host": "https://oss.memoyu.com/", 22 | "UseHttps": true 23 | } 24 | }, 25 | "Authentication": { 26 | "JwtBearer": { 27 | "SecurityKey": "5e1816a0b5cdbef550b59f1a77ea723326b7df760f8ab98163f09cc4aaf7f6f233c08170d885d8df978939e5509fccaaa20f8f34a85f596dc2e89c243ed37883", 28 | "Expires": 10800, 29 | "Issuer": "Memoyu", 30 | "Audience": "Memoyu.Mbill.WebApi" 31 | } 32 | }, 33 | "MinPro": { 34 | "AppID": "xxx", 35 | "AppSecret": "xxx" 36 | }, 37 | "Cache": { 38 | "Enable": true, 39 | "ExpireSeconds": "300" 40 | }, 41 | "Middleware": { 42 | "IPLog": { 43 | "Enabled": true 44 | }, 45 | "SignalR": { 46 | "Enabled": false 47 | }, 48 | "IpRateLimit": { 49 | "Enabled": true 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Middleware/ExceptionHandlerMiddleware.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Middleware; 2 | 3 | /// 4 | /// 异常处理中间件 5 | /// 6 | public class ExceptionHandlerMiddleware 7 | { 8 | private readonly RequestDelegate _next; 9 | private readonly Microsoft.Extensions.Logging.ILogger _logger; 10 | 11 | public ExceptionHandlerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) 12 | { 13 | _next = next; 14 | _logger = loggerFactory.CreateLogger(); 15 | } 16 | 17 | public async Task Invoke(HttpContext context) 18 | { 19 | try 20 | { 21 | await _next(context); 22 | } 23 | catch (Exception ex) 24 | { 25 | await ExceptionHandlerAsync(context, ex.Message); 26 | _logger.LogError(ex, ex.Message); 27 | } 28 | finally 29 | { 30 | var statusCode = context.Response.StatusCode; 31 | if (statusCode != StatusCodes.Status200OK) 32 | { 33 | //获取状态码对应的值 34 | Enum.TryParse(typeof(HttpStatusCode), statusCode.ToString(), out object message); 35 | await ExceptionHandlerAsync(context, message.ToString()); 36 | } 37 | } 38 | } 39 | 40 | private async Task ExceptionHandlerAsync(HttpContext context, string message) 41 | { 42 | context.Response.ContentType = "application/json;charset=utf-8"; 43 | 44 | var result = new ServiceResult(); 45 | result.IsFailed(message); 46 | await context.Response.WriteAsync(result.ToJson()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Bill/Input/BillSearchPagingInput.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Bill.Input; 2 | 3 | public class BillSearchPagingInput : PagingDto 4 | { 5 | /// 6 | /// 账单类型 7 | /// 8 | public List Types { get; set; } 9 | 10 | /// 11 | /// 账单分类 12 | /// 13 | public List CategoryBIds { get; set; } 14 | 15 | /// 16 | /// 账单账户 17 | /// 18 | public List AssetBIds { get; set; } 19 | 20 | /// 21 | /// 金额区间 22 | /// 23 | public SearchAmount Amount { get; set; } 24 | 25 | /// 26 | /// 日期区间 27 | /// 28 | public SearchDate Date { get; set; } 29 | 30 | /// 31 | /// 搜索关键字(地址、备注) 32 | /// 33 | public string KeyWord { get; set; } 34 | 35 | /// 36 | /// 地址 37 | /// 38 | public string Address { get; set; } 39 | 40 | /// 41 | /// 备注 42 | /// 43 | public string Remark { get; set; } 44 | 45 | 46 | } 47 | 48 | public class SearchAmount 49 | { 50 | /// 51 | /// 金额区间最小值 52 | /// 53 | public decimal? Min { get; set; } 54 | 55 | /// 56 | /// 金额区间最大值 57 | /// 58 | public decimal? Max { get; set; } 59 | 60 | } 61 | public class SearchDate 62 | { 63 | 64 | /// 65 | /// 账单时间起始 66 | /// 67 | public DateTime? Begin { get; set; } 68 | 69 | /// 70 | /// 账单时间截止 71 | /// 72 | public DateTime? End { get; set; } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/User/Output/UserDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.User.Output; 2 | 3 | public class UserDto : FullEntityDto 4 | { 5 | /// 6 | /// 用户名 7 | /// 8 | public string Username { get; set; } 9 | 10 | /// 11 | /// 昵称 12 | /// 13 | public string Nickname { get; set; } 14 | 15 | /// 16 | /// 性别,0:未知,1:男,2:女 17 | /// 18 | public int Gender { get; set; } 19 | 20 | public string GenderName { get; set; } 21 | 22 | /// 23 | /// 邮箱 24 | /// 25 | public string Email { get; set; } 26 | 27 | /// 28 | /// 电话 29 | /// 30 | public string Phone { get; set; } 31 | 32 | /// 33 | /// 省 34 | /// 35 | public string Province { get; set; } 36 | 37 | /// 38 | /// 市 39 | /// 40 | public string City { get; set; } 41 | 42 | /// 43 | /// 区 44 | /// 45 | public string District { get; set; } 46 | 47 | /// 48 | /// 街道 49 | /// 50 | public string Street { get; set; } 51 | 52 | /// 53 | /// 地址详情 54 | /// 55 | public string Address { get; set; } 56 | 57 | /// 58 | /// 头像地址 59 | /// 60 | public string AvatarUrl { get; set; } 61 | 62 | /// 63 | /// 最后一次登录的时间 64 | /// 65 | public DateTime LastLoginTime { get; set; } 66 | 67 | /// 68 | /// 是否启用 69 | /// 70 | public bool IsEnable { get; set; } 71 | } 72 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Bill/AssetEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Entities.Bill; 2 | 3 | /// 4 | /// 资产分类实体 5 | /// 6 | [Table(Name = SystemConst.DbTablePrefix + "_asset")] 7 | [Index("index_asset_on_amount", nameof(Amount), false)] 8 | [Index("index_asset_on_sort", nameof(Sort), false)] 9 | [Index("index_asset_on_parent_bid", nameof(ParentBId), false)] 10 | [Index("index_asset_on_type", nameof(Type), false)] 11 | public class AssetEntity : FullAduitEntity 12 | { 13 | /// 14 | /// 资产分类名 15 | /// 16 | [Description("资产分类名")] 17 | [Column(StringLength = 20, IsNullable = false)] 18 | public string Name { get; set; } 19 | 20 | /// 21 | /// 父级BId 22 | /// 23 | [Description("父级BId")] 24 | public long ParentBId { get; set; } 25 | 26 | /// 27 | /// 资产分类类型:存款、负债 28 | /// 29 | [Description("资产分类类型:存款、负债")] 30 | [Column(IsNullable = false)] 31 | public int Type { get; set; } 32 | 33 | /// 34 | /// 资产金额 35 | /// 36 | [Description("资产金额")] 37 | [Column(Precision = 12, Scale = 2)] 38 | public decimal Amount { get; set; } 39 | 40 | /// 41 | /// 图标地址 42 | /// 43 | [Description("图标地址")] 44 | [Column(StringLength = 100)] 45 | public string Icon { get; set; } 46 | 47 | /// 48 | /// 排序 49 | /// 50 | [Description("排序")] 51 | public int Sort { get; set; } 52 | 53 | [Navigate(nameof(ParentBId), TempPrimary = nameof(AssetEntity.BId))] 54 | public virtual AssetEntity Parent { get; set; } 55 | } 56 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/Consts/SystemConst.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common.Consts; 2 | 3 | public class SystemConst 4 | { 5 | /// 6 | /// 数据库表前缀 7 | /// 8 | public const string DbTablePrefix = "mbill"; 9 | 10 | #region API Doc 11 | 12 | public static class Grouping 13 | { 14 | /// 15 | /// 前台客户端接口组 16 | /// 17 | public const string GroupName_v1 = "v1"; 18 | 19 | /// 20 | /// 后台管理端接口组 21 | /// 22 | public const string GroupName_v2 = "v2"; 23 | 24 | /// 25 | /// 其他通用接口组 26 | /// 27 | public const string GroupName_v3 = "v3"; 28 | } 29 | 30 | #endregion API Doc 31 | 32 | /// 33 | /// 选取器 34 | /// 35 | public class Switcher 36 | { 37 | public static string BillType(int type) => type switch 38 | { 39 | 0 => "支出", 40 | 1 => "收入", 41 | 2 => "转账", 42 | 3 => "还款", 43 | _ => "", 44 | }; 45 | 46 | public static string CategoryType(int type) => type switch 47 | { 48 | 0 => "支出", 49 | 1 => "收入", 50 | _ => "", 51 | }; 52 | 53 | public static string AssetType(int type) => type switch 54 | { 55 | 0 => "储蓄", 56 | 1 => "债务", 57 | _ => "", 58 | }; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Attributes/LocalAuthorizeAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Attributes; 2 | 3 | /// 4 | /// 自定义固定权限编码给动态角色及用户,支持验证登录,指定角色、Policy 5 | /// 6 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] 7 | public class LocalAuthorizeAttribute : Attribute, IAsyncAuthorizationFilter 8 | { 9 | public string Permission { get; } 10 | public string Module { get; } 11 | 12 | public LocalAuthorizeAttribute(string permission, string module) 13 | { 14 | Permission = permission; 15 | Module = module; 16 | } 17 | public async Task OnAuthorizationAsync(AuthorizationFilterContext context) 18 | { 19 | //ICurrentUser currentUser = (ICurrentUser)context.HttpContext.RequestServices.GetService(typeof(ICurrentUser)); 20 | 21 | //if (currentUser.IsInGroup(SystemConst.Role.Administrator))//如果是超级管理员 22 | //{ 23 | // return; 24 | //} 25 | 26 | IAuthorizationService authorizationService = (IAuthorizationService)context.HttpContext.RequestServices.GetService(typeof(IAuthorizationService)); 27 | AuthorizationResult authorizationResult = await authorizationService.AuthorizeAsync(context.HttpContext.User, null, new ValidJtiRequirement()); 28 | if (!authorizationResult.Succeeded) 29 | { 30 | return; 31 | } 32 | 33 | await authorizationService.AuthorizeAsync(context.HttpContext.User, context, new ModuleAuthorizationRequirement(Module, Permission)); 34 | } 35 | 36 | public override string ToString() 37 | { 38 | return $"\"{base.ToString()}\",\"Permission:{Permission}\",\"Module:{Module}\","; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Mbill/Mbill.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | Linux 6 | ..\.. 7 | 8 | 9 | 10 | Mbill.xml 11 | bin\Debug\ 12 | 1701;1702;1705;1591 13 | AnyCPU 14 | 3 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | PreserveNewest 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/Mbill.Infrastructure/Repository/PreOrder/PreOrderRepo.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Domains.Common.Enums; 2 | 3 | namespace Mbill.Infrastructure.Repository.PreOrder; 4 | 5 | public class PreOrderRepo : AuditBaseRepo, IPreOrderRepo 6 | { 7 | private readonly ICurrentUser _currentUser; 8 | 9 | public PreOrderRepo(UnitOfWorkManager unitOfWorkManager, ICurrentUser currentUser) : base(unitOfWorkManager, currentUser) 10 | { 11 | _currentUser = currentUser; 12 | } 13 | 14 | public async Task GetPreOrderAsync(long bId) 15 | { 16 | return await Select.Where(a => a.BId == bId).ToOneAsync(); 17 | } 18 | 19 | public async Task<(long done, long unDone)> GetCountByStatusAsync(List groupBIds) 20 | { 21 | var results = await Select.Where(g => g.CreateUserBId == _currentUser.BId).Where(g => groupBIds.Contains(g.GroupBId)).ToListAsync(); 22 | var done = results.Where(g => g.Status == (int)PreOrderStatusEnum.Done).Count(); 23 | var unDone = results.Where(g => g.Status == (int)PreOrderStatusEnum.UnDone).Count(); 24 | return (done, unDone); 25 | } 26 | 27 | public async Task GetPreAmountByGroupAsync(List groupBIds) 28 | { 29 | var amount = await Select.Where(g => g.CreateUserBId == _currentUser.BId).Where(g => groupBIds.Contains(g.GroupBId)).SumAsync(g => g.PreAmount); 30 | return amount; 31 | } 32 | 33 | public async Task GetRealAmountByGroupAsync(List groupIds) 34 | { 35 | var amount = await Select.Where(g => g.CreateUserBId == _currentUser.BId).Where(g => groupIds.Contains(g.GroupBId)).SumAsync(g => g.RealAmount); 36 | return amount; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/Wx/WxSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.Wx; 2 | 3 | public class WxSvc : IWxSvc 4 | { 5 | private static string WxJscode(string appid, string secret, string code) => $"https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={code}&grant_type=authorization_code"; 6 | 7 | private readonly ILogger _logger; 8 | private readonly IHttpClientFactory _httpClient; 9 | 10 | public WxSvc(ILogger logger, IHttpClientFactory httpClient) 11 | { 12 | _logger = logger; 13 | _httpClient = httpClient; 14 | } 15 | 16 | public async Task> GetCode2Session(string code) 17 | { 18 | #if !DEBUG 19 | var url = WxJscode(Appsettings.MinPro.AppID, Appsettings.MinPro.AppSecret, code); 20 | using var client = _httpClient.CreateClient();//创建HttpClient请求 21 | var httpResponse = await client.GetAsync(url);//请求获取 22 | if (httpResponse.StatusCode != System.Net.HttpStatusCode.OK)//判断请求响应是否成功 23 | return ServiceResult.Failed($"请求微信Code2Session响应失败 错误:{httpResponse.Content.ReadAsStringAsync()}"); 24 | var content = await httpResponse.Content.ReadAsStringAsync();//获取响应内容 25 | #else 26 | var content = "{\"session_key\":\"cKAHh5rUtZqAryHAS1i7Og == \",\"openid\":\"otPIb4-QEB2eprYBLllCNf425J80\"}"; 27 | #endif 28 | await Task.CompletedTask; 29 | var code2Session = content.FromJson(); 30 | if (code2Session.ErrCode != 0) 31 | return ServiceResult.Failed($"请求微信Code2Session返回失败 错误:{content}"); 32 | return ServiceResult.Successed(code2Session); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Bill/BillSearchRecordEntity.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson.Serialization.Attributes; 2 | using MongoDB.Bson; 3 | 4 | namespace Mbill.Core.Domains.Entities.Bill 5 | { 6 | [MongoCollection(Name = "bill_search_record")] 7 | public class BillSearchRecordEntity 8 | { 9 | /// 10 | /// 主键 11 | /// 12 | [BsonId] 13 | public ObjectId Id { get; set; } 14 | 15 | /// 16 | /// 用户 17 | /// 18 | public long UserBId { get; set; } 19 | 20 | /// 21 | /// 账单类型 22 | /// 23 | public int? Type { get; set; } 24 | 25 | /// 26 | /// 分类BId 27 | /// 28 | public long CategoryBId { get; set; } 29 | 30 | /// 31 | /// 账单账户BId 32 | /// 33 | public long AssetBId { get; set; } 34 | 35 | /// 36 | /// 金额区间最小值 37 | /// 38 | public decimal? AmountMin { get; set; } 39 | 40 | /// 41 | /// 金额区间最大值 42 | /// 43 | public decimal? AmountMax { get; set; } 44 | 45 | /// 46 | /// 账单时间起始 47 | /// 48 | public DateTime? TimeBegin { get; set; } 49 | 50 | /// 51 | /// 账单时间截止 52 | /// 53 | public DateTime? TimeEnd { get; set; } 54 | 55 | /// 56 | /// 搜索关键字 57 | /// 58 | public string KeyWord { get; set; } 59 | 60 | /// 61 | /// 搜索时间 62 | /// 63 | public DateTime SearchTime { get; set; } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Mbill.Core/AOP/Filters/SwaggerDocumentFilter.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.AOP.Filters; 2 | 3 | public class SwaggerDocumentFilter : IDocumentFilter 4 | { 5 | /// 6 | /// 对应Controller的API文档描述信息 7 | /// 8 | public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) 9 | { 10 | var tags = new List 11 | { 12 | 13 | new OpenApiTag 14 | { 15 | Name = "Account", 16 | Description = "账户认证授权", 17 | ExternalDocs = new OpenApiExternalDocs { Description = "账户认证授权" } 18 | }, 19 | new OpenApiTag 20 | { 21 | Name = "User", 22 | Description = "用户相关接口", 23 | ExternalDocs = new OpenApiExternalDocs { Description = "用户管理" } 24 | }, 25 | }; 26 | 27 | #region 实现自定义API描述,并过滤不属于当前分组的API 28 | // 当前分组名称 29 | var groupName = context.ApiDescriptions.FirstOrDefault()?.GroupName; 30 | 31 | // 当前所有的API对象 32 | var apis = context.ApiDescriptions.GetType().GetField("_source", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(context.ApiDescriptions) as IEnumerable; 33 | 34 | // 不属于当前分组的所有Controller 35 | // 注意:配置的OpenApiTag,Name名称要与Controller的Name对应才会生效。 36 | var controllers = apis.Where(x => x.GroupName != groupName).Select(x => ((ControllerActionDescriptor)x.ActionDescriptor).ControllerName).Distinct(); 37 | 38 | // 筛选一下tags 39 | swaggerDoc.Tags = tags.Where(x => !controllers.Contains(x.Name)).OrderBy(x => x.Name).ToList(); 40 | #endregion 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Mbill/Modules/Configs/PermissionAuthorizationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Modules.Configs; 2 | 3 | public class PermissionAuthorizationHandler : AuthorizationHandler 4 | { 5 | private readonly IPermissionSvc _permissionSvc; 6 | 7 | public PermissionAuthorizationHandler(IPermissionSvc permissionSvc) 8 | { 9 | _permissionSvc = permissionSvc; 10 | } 11 | 12 | protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ModuleAuthorizationRequirement requirement) 13 | { 14 | AuthorizationFilterContext filterContext = context.Resource as AuthorizationFilterContext; 15 | 16 | #if DEBUG 17 | ICurrentUser currentUser = (ICurrentUser)filterContext.HttpContext.RequestServices.GetService(typeof(ICurrentUser)); 18 | 19 | if (currentUser.IsAdministrator())//如果是超级管理员 20 | return; 21 | 22 | #endif 23 | 24 | if (!context.User.Identity.IsAuthenticated) 25 | { 26 | HandlerAuthenticationFailed(filterContext, "认证失败,请检查请求头或者重新登陆", ServiceResultCode.AuthenticationFailed); 27 | context.Fail(); 28 | return; 29 | } 30 | 31 | if (await _permissionSvc.CheckAsync(requirement.Module, requirement.Name)) 32 | { 33 | context.Succeed(requirement); 34 | return; 35 | } 36 | HandlerAuthenticationFailed(filterContext, $"您没有权限:{requirement.Module}-{requirement.Name}", ServiceResultCode.NoPermission); 37 | } 38 | 39 | public void HandlerAuthenticationFailed(AuthorizationFilterContext context, string message, ServiceResultCode code) 40 | { 41 | context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; 42 | context.Result = new JsonResult(new ServiceResult(code, message)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Common/ServicePage.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Core.Domains.Common; 2 | 3 | 4 | #region 分页请求入参 5 | 6 | /// 7 | /// 分页加排序 8 | /// 9 | public class PagedAndSortedRequestDto : PagingDto, ISortedResultRequest 10 | { 11 | public string Sorting { get; set; } 12 | } 13 | 14 | /// 15 | /// 常规分页 16 | /// 17 | public class PagingDto : IPagingDto 18 | { 19 | /// 20 | /// 每页个数 21 | /// 22 | [Range(1, int.MaxValue, ErrorMessage = "每页个数最小为1")] 23 | public int Size { get; set; } = 15; 24 | /// 25 | /// 从0开始,0时取第1页,1时取第二页 26 | /// 27 | public int Page { get; set; } = 1; 28 | 29 | public string Sort { get; set; } 30 | } 31 | 32 | 33 | public interface IPagingDto : ILimitedResultRequest 34 | { 35 | int Page { get; set; } 36 | } 37 | 38 | public interface ILimitedResultRequest 39 | { 40 | int Size { get; set; } 41 | } 42 | 43 | public interface ISortedResultRequest 44 | { 45 | /// 46 | /// 分页排序 47 | /// 48 | /// 49 | /// 例子: 50 | /// "Name" 51 | /// "Name DESC" 52 | /// "Name ASC, Age DESC" 53 | /// 54 | string Sorting { get; set; } 55 | } 56 | 57 | #endregion 58 | 59 | #region 分页请求响应 60 | 61 | public class PagedDto 62 | { 63 | public long Total { get; set; } 64 | public IReadOnlyList Items { get; set; } 65 | public long Page { get; set; } 66 | public long Size { get; set; } 67 | 68 | public PagedDto() 69 | { 70 | } 71 | public PagedDto(IReadOnlyList items) 72 | { 73 | Total = items.Count; 74 | Items = items; 75 | } 76 | public PagedDto(IReadOnlyList items, long total) : this(items) 77 | { 78 | Total = total; 79 | } 80 | } 81 | 82 | #endregion 83 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/User/UserIdentitySvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.User; 2 | 3 | public class UserIdentitySvc : IUserIdentitySvc 4 | { 5 | private readonly IUserIdentityRepo _userIdentityRepo; 6 | public UserIdentitySvc(IUserIdentityRepo userIdentityRepository) 7 | { 8 | _userIdentityRepo = userIdentityRepository; 9 | } 10 | public Task ChangePasswordAsync(long userId, string newpassword) 11 | { 12 | throw new NotImplementedException(); 13 | } 14 | 15 | public async Task VerifyUserPasswordAsync(long userBId, string password) 16 | { 17 | UserIdentityEntity userIdentity = await GetFirstByUserIdAsync(userBId); 18 | return userIdentity != null && EncryptUtil.Verify(userIdentity.Credential, password); 19 | } 20 | 21 | public async Task VerifyWxOpenIdAsync(string openId) 22 | { 23 | return await GetFirstByOpenIdAsync(openId); 24 | } 25 | 26 | /// 27 | /// 通过UserId获取用户绑定信息 28 | /// 29 | /// 30 | /// 31 | public async Task GetFirstByUserIdAsync(long userBId) 32 | { 33 | return await _userIdentityRepo 34 | .Where(r => r.UserBId == userBId && r.IdentityType == UserIdentityEntity.Password) 35 | .ToOneAsync(); 36 | } 37 | 38 | /// 39 | /// 通过OpenId获取用户绑定信息 40 | /// 41 | /// Wx OpenId 42 | /// 43 | public async Task GetFirstByOpenIdAsync(string openId) 44 | { 45 | return await _userIdentityRepo 46 | .Where(r => r.Credential.Equals(openId) && r.IdentityType == UserIdentityEntity.WeiXin && r.IsDeleted == false) 47 | .ToOneAsync(); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Mbill/Controllers/Core/PermissionController.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Controllers.Core; 2 | 3 | /// 4 | /// 权限管理 5 | /// 6 | [Route("api/admin/permission")] 7 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v2)] 8 | public class PermissionController : ApiControllerBase 9 | { 10 | private readonly IPermissionSvc _permissionService; 11 | 12 | public PermissionController(IPermissionSvc permissionService) 13 | { 14 | _permissionService = permissionService; 15 | } 16 | 17 | /// 18 | /// 查询权限信息(树形结构) 19 | /// 20 | /// 21 | [HttpGet("tree")] 22 | [LocalAuthorize("查询权限信息(树形结构)", "管理员")] 23 | public async Task>> GetTreePermissions() 24 | { 25 | var result = await _permissionService.GetAllTreeAsync(); 26 | return ServiceResult>.Successed(result); 27 | } 28 | 29 | /// 30 | /// 查询所有可分配的权限 31 | /// 32 | /// 33 | [HttpGet("module")] 34 | [LocalAuthorize("查询所有可分配的权限", "管理员")] 35 | public async Task>>> GetModulePermissions() 36 | { 37 | var result = await _permissionService.GetAllStructualAsync(); 38 | return ServiceResult>>.Successed(result); 39 | } 40 | 41 | /// 42 | /// 配置角色权限 43 | /// 44 | /// 角色权限 45 | [HttpPost("dispatch")] 46 | [LocalAuthorize("配置角色权限", "管理员")] 47 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v2)] 48 | public async Task DispatchPermissions([FromBody] DispatchPermissionsDto dto) 49 | { 50 | await _permissionService.DispatchPermissionsAsync(dto); 51 | return ServiceResult.Successed("配置角色权限成功"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Mbill.Service/Base/ApplicationSvc.cs: -------------------------------------------------------------------------------- 1 | using MapsterMapper; 2 | 3 | namespace Mbill.Service.Base; 4 | 5 | public class ApplicationSvc : IApplicationSvc 6 | { 7 | //provider Lock 8 | protected readonly object ServiceProviderLock = new object(); 9 | public IServiceProvider ServiceProvider { get; set; } 10 | 11 | 12 | //懒加载 13 | protected TService LazyGetRequiredService(ref TService reference) 14 | => LazyGetRequiredService(typeof(TService), ref reference); 15 | protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference) 16 | { 17 | if (reference == null) 18 | { 19 | lock (ServiceProviderLock) 20 | { 21 | if (reference == null) 22 | { 23 | reference = (TRef)ServiceProvider.GetRequiredService(serviceType); 24 | } 25 | } 26 | } 27 | 28 | return reference; 29 | } 30 | 31 | //当前用户 32 | private ICurrentUser _currentUser; 33 | public ICurrentUser CurrentUser => LazyGetRequiredService(ref _currentUser); 34 | 35 | //实体映射 36 | private IMapper _mapper; 37 | public IMapper Mapper => LazyGetRequiredService(ref _mapper); 38 | 39 | //工作单元 40 | private UnitOfWorkManager unitOfWorkManager; 41 | public UnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref unitOfWorkManager); 42 | 43 | //日志工厂 44 | private ILoggerFactory _loggerFactory; 45 | public ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); 46 | 47 | //日志 48 | protected ILogger Logger => _lazyLogger.Value; 49 | private Lazy _lazyLogger => new Lazy(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true); 50 | 51 | //授权 52 | private IAuthorizationService _authorizationService; 53 | public IAuthorizationService AuthorizationService => LazyGetRequiredService(ref _authorizationService); 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/Mbill.Core/Extensions/ServiceCollection/ControllerSetup.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Extensions.Converters; 2 | 3 | namespace Mbill.Core.Extensions.ServiceCollection; 4 | 5 | /// 6 | /// 控制器配置注册 7 | /// 8 | public static class ControllerSetup 9 | { 10 | public static IServiceCollection AddController(this IServiceCollection services) 11 | { 12 | services.AddControllers(options => 13 | { 14 | options.Filters.Add(); 15 | options.Filters.Add(); 16 | }) 17 | .AddNewtonsoftJson(opt => 18 | { 19 | opt.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(); 20 | opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; 21 | opt.SerializerSettings.Converters.Add(new JsonLongToStringConverter()); 22 | }) 23 | .ConfigureApiBehaviorOptions(options => 24 | { 25 | options.SuppressConsumesConstraintForFormFileParameters = true; 26 | //自定义 BadRequest 响应 27 | options.InvalidModelStateResponseFactory = context => 28 | { 29 | var problemDetails = new ValidationProblemDetails(context.ModelState); 30 | 31 | var resultDto = new ServiceResult 32 | { 33 | Code = ServiceResultCode.ParameterError, 34 | Message = problemDetails.Errors 35 | }; 36 | 37 | return new BadRequestObjectResult(resultDto) 38 | { 39 | ContentTypes = { "application/json" } 40 | }; 41 | }; 42 | // 使用自定义模型验证【Api接口需要添加才能生效】 43 | options.SuppressModelStateInvalidFilter = true; 44 | }); 45 | return services; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Mbill.Service/Core/User/Input/ModifyUserDto.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Core.User.Input; 2 | 3 | public class ModifyUserDto 4 | { 5 | /// 6 | /// 用户名 7 | /// 8 | [Required(ErrorMessage = "必须传入用户名")] 9 | public string Username { get; set; } 10 | 11 | /// 12 | /// 昵称 13 | /// 14 | [Required(ErrorMessage = "必须传入昵称")] 15 | public string Nickname { get; set; } 16 | 17 | /// 18 | /// 性别,0:未知,1:男,2:女 19 | /// 20 | [Required(ErrorMessage = "必须传入昵称")] 21 | public int Gender { get; set; } 22 | 23 | /// 24 | /// 邮箱 25 | /// 26 | public string Email { get; set; } 27 | 28 | /// 29 | /// 电话 30 | /// 31 | public string Phone { get; set; } 32 | 33 | /// 34 | /// 省 35 | /// 36 | public string Province { get; set; } 37 | 38 | /// 39 | /// 市 40 | /// 41 | public string City { get; set; } 42 | 43 | /// 44 | /// 区 45 | /// 46 | public string District { get; set; } 47 | 48 | /// 49 | /// 街道 50 | /// 51 | public string Street { get; set; } 52 | 53 | /// 54 | /// 头像地址 55 | /// 56 | public string AvatarUrl { get; set; } 57 | 58 | 59 | /// 60 | /// 密码 61 | /// 62 | [Required(ErrorMessage = "新密码不可为空")] 63 | [Compare("ConfirmPassword", ErrorMessage = "两次输入的密码不一致,请输 入相同的密码")] 64 | [RegularExpression("^[A-Za-z0-9_*&$#@]{6,22}$", ErrorMessage = "密码长度必须在6~22位之间,包含字符、数字和 _")] 65 | public string Password { get; set; } 66 | 67 | /// 68 | /// 确认密码 69 | /// 70 | [Required(ErrorMessage = "请确认密码")] 71 | public string ConfirmPassword { get; set; } 72 | 73 | /// 74 | /// 权限 75 | /// 76 | public List RoleBIds { get; set; } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Asset/IAssetSvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Asset; 2 | 3 | public interface IAssetSvc 4 | { 5 | /// 6 | /// 新增资产分类 7 | /// 8 | /// 数据源 9 | /// 10 | Task> InsertAsync(CreateAssetInput input); 11 | 12 | /// 13 | /// 删除资产分类 14 | /// 15 | /// 资产分类bId 16 | /// 17 | Task DeleteAsync(long bId); 18 | 19 | /// 20 | /// 更新资产分类 21 | /// 22 | /// 资产分类信息 23 | /// 24 | Task> EditAsync(EditAssetInput input); 25 | 26 | /// 27 | /// 获取父项 by bId 28 | /// 29 | /// 资产bId 30 | /// 31 | Task> GetAsync(long bId); 32 | 33 | /// 34 | /// 获取父项 by 子项 bId 35 | /// 36 | /// 资产子项bId 37 | /// 38 | Task> GetParentAsync(long bId); 39 | 40 | /// 41 | /// 获取父项集合 42 | /// 43 | /// 44 | Task>> GetParentsAsync(); 45 | 46 | /// 47 | /// 获取分级后的组合类别数据 48 | /// 49 | /// 50 | /// 51 | Task>> GetGroupsAsync(int? type); 52 | 53 | /// 54 | /// 获取资产分类分页 55 | /// 56 | /// 分页参数 57 | /// 58 | Task>> GetPageAsync(AssetPagingDto pagingDto); 59 | 60 | /// 61 | /// 排序资产 62 | /// 63 | /// 64 | /// 65 | Task SortAsync(SortAssetInput input); 66 | } -------------------------------------------------------------------------------- /src/Mbill/Controllers/Core/FileController.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Service.Core.Files.Input; 2 | 3 | namespace Mbill.Controllers.Core; 4 | 5 | [Route("api/file")] 6 | [ApiExplorerSettings(GroupName = SystemConst.Grouping.GroupName_v3)] 7 | [Authorize] 8 | public class FileController : ApiControllerBase 9 | { 10 | private readonly IQiniuFileSvc _qiniuFileSvc; 11 | 12 | private readonly IMediaImageSvc _mediaImageSvc; 13 | 14 | public FileController(IQiniuFileSvc qiniuFileSvc, IMediaImageSvc mediaImageSvc) 15 | { 16 | _qiniuFileSvc = qiniuFileSvc; 17 | _mediaImageSvc = mediaImageSvc; 18 | } 19 | 20 | /// 21 | /// 获取上传文件token 22 | /// 23 | /// 文件路径 24 | /// 25 | [HttpGet("upload-token")] 26 | [AllowAnonymous] 27 | //[LocalAuthorize("获取上传token", "文件管理")] 28 | public ServiceResult GetUploadToken([FromQuery] string key) 29 | { 30 | return _qiniuFileSvc.GetUploadToken(key); 31 | } 32 | 33 | /// 34 | /// 单文件上传,键为file 35 | /// 36 | /// 37 | /// 38 | /// 39 | /// 40 | [HttpPost("upload")] 41 | [LocalAuthorize("上传单个文件", "文件管理")] 42 | public async Task> UploadFile(IFormFile file, string type, int key = 0) 43 | { 44 | if (!MultipartRequestUtil.IsMultipartContentType(Request.ContentType)) 45 | { 46 | throw new KnownException($"The request couldn't be processed (Error 1)."); 47 | } 48 | return await _qiniuFileSvc.UploadAsync(file, type, key); 49 | } 50 | 51 | /// 52 | /// 获取账单分类分页 53 | /// 54 | /// 分页参数 55 | [HttpGet("media-image/pages")] 56 | [LocalAuthorize("获取分页媒体图片", "文件管理")] 57 | public async Task>> GetPageAsync([FromQuery] MediaImagePagingInput pagingDto) 58 | { 59 | return await _mediaImageSvc.GetPageAsync(pagingDto); 60 | } 61 | } -------------------------------------------------------------------------------- /src/Mbill.Core/Domains/Entities/Core/UserIdentityEntity.cs: -------------------------------------------------------------------------------- 1 | using Mbill.Core.Common; 2 | 3 | namespace Mbill.Core.Domains.Entities.Core; 4 | 5 | /// 6 | /// 用户身份认证登录表 7 | /// 8 | [Table(Name = SystemConst.DbTablePrefix + "_user_identity")] 9 | [Index("index_user_identity_on_user_bid", nameof(UserBId), false)] 10 | public class UserIdentityEntity : FullAduitEntity 11 | { 12 | public const string GitHub = "GitHub"; 13 | public const string Password = "Password"; 14 | public const string QQ = "QQ"; 15 | public const string Gitee = "Gitee"; 16 | public const string WeiXin = "WeiXin"; 17 | 18 | public UserIdentityEntity() 19 | { 20 | } 21 | 22 | public UserIdentityEntity(long userBId, string identityType, string identifier, string credential, DateTime createTime) 23 | { 24 | BId = SnowFlake.NextId(); 25 | UserBId = userBId; 26 | IdentityType = identityType ?? throw new ArgumentNullException(nameof(identityType)); 27 | Identifier = identifier; 28 | Credential = credential ?? throw new ArgumentNullException(nameof(credential)); 29 | CreateTime = createTime; 30 | } 31 | 32 | /// 33 | /// 用户Id 34 | /// 35 | [Description("用户Id")] 36 | public long UserBId { get; set; } 37 | 38 | /// 39 | /// 认证类型, Password,GitHub、QQ、WeiXin等 40 | /// 41 | [Description("认证类型, Password,GitHub、QQ、WeiXin等")] 42 | [Column(StringLength = 20)] 43 | public string IdentityType { get; set; } 44 | 45 | /// 46 | /// 认证者,例如 用户名,手机号,邮件等, 47 | /// 48 | [Description("认证者,例如 用户名,手机号,邮件等,")] 49 | [Column(StringLength = 24)] 50 | public string Identifier { get; set; } 51 | 52 | /// 53 | /// 凭证,例如 密码,存OpenId、Id,同一IdentityType的OpenId的值是唯一的 54 | /// 55 | [Description("凭证,例如 密码,存OpenId、Id,同一IdentityType的OpenId的值是唯一的")] 56 | [Column(StringLength = 50)] 57 | public string Credential { get; set; } 58 | 59 | /// 60 | /// 扩展属性 61 | /// 62 | [Description("扩展属性")] 63 | public string ExtraProperties { get; set; } 64 | } 65 | -------------------------------------------------------------------------------- /src/Mbill/Modules/FreeSqlModule.cs: -------------------------------------------------------------------------------- 1 | using Module = Autofac.Module; 2 | 3 | namespace Mbill.Modules; 4 | 5 | public class FreeSqlModule : Module 6 | { 7 | protected override void Load(ContainerBuilder builder) 8 | { 9 | IFreeSql fsql = new FreeSqlBuilder() 10 | .UseConnectionString() 11 | .UseNameConvert(NameConvertType.PascalCaseToUnderscoreWithLower) 12 | .UseAutoSyncStructure(true) 13 | .UseNoneCommandParameter(true) 14 | .UseMonitorCommand(cmd => 15 | { 16 | Trace.WriteLine(cmd.CommandText + ";"); 17 | } 18 | ) 19 | .CreateDatabaseIfNotExists() 20 | .Build() 21 | .SetDbContextOptions(opt => 22 | { 23 | opt.EnableCascadeSave = true; 24 | opt.OnEntityChange = rep => 25 | { 26 | //进行审计 27 | }; 28 | });//联级保存功能开启(默认为关闭) 29 | 30 | fsql.Aop.CurdAfter += (s, e) => 31 | { 32 | Log.Debug($"ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}: FullName:{e.EntityType.FullName}" + $" ElapsedMilliseconds:{e.ElapsedMilliseconds}ms, {e.Sql}"); 33 | 34 | if (e.ElapsedMilliseconds > 200) 35 | { 36 | //记录日志 37 | //发送短信给负责人 38 | } 39 | }; 40 | builder.RegisterInstance(fsql).SingleInstance();//FreeSql注册为单例 41 | builder.RegisterType(typeof(UnitOfWorkManager)).InstancePerLifetimeScope();//工作单元注册为scope 42 | fsql.GlobalFilter.Apply("IsDeleted", a => a.IsDeleted == false); // 全局过滤字段 43 | 44 | try 45 | { 46 | using var objPool = fsql.Ado.MasterPool.Get(); 47 | } 48 | catch (Exception e) 49 | { 50 | Log.Logger.Error(e + e.StackTrace + e.Message + e.InnerException); 51 | return; 52 | } 53 | 54 | //在运行时直接生成表结构 55 | try 56 | { 57 | fsql.CodeFirst 58 | .SyncStructure(DomainReflexUtil.GetTypesByTableAttribute()); 59 | } 60 | catch (Exception e) 61 | { 62 | Log.Logger.Error(e + e.StackTrace + e.Message + e.InnerException); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Mbill.Service/Bill/Category/ICategorySvc.cs: -------------------------------------------------------------------------------- 1 | namespace Mbill.Service.Bill.Category; 2 | 3 | public interface ICategorySvc 4 | { 5 | /// 6 | /// 新增账单分类 7 | /// 8 | /// 数据源 9 | /// 10 | Task> InsertAsync(CreateCategoryInput input); 11 | 12 | /// 13 | /// 删除账单分类信息 14 | /// 15 | /// 16 | /// 17 | Task DeleteAsync(long bId); 18 | 19 | /// 20 | /// 更新账单分类 21 | /// 22 | /// 账单分类信息 23 | /// 24 | Task> EditAsync(EditCategoryInput input); 25 | 26 | /// 27 | /// 获取分类 28 | /// 29 | /// 30 | /// 31 | Task> GetAsync(long bId); 32 | 33 | /// 34 | /// 获取群不分类 35 | /// 36 | /// 分类类型 0 支出, 1 收入 37 | /// 38 | Task>> GetsAsync(int type); 39 | 40 | /// 41 | /// 获取父项 by 子项 id 42 | /// 43 | /// 分类子项Id 44 | /// 45 | Task> GetParentAsync(long bId); 46 | 47 | /// 48 | /// 获取账单分类父项集合 49 | /// 50 | /// 51 | Task>> GetParentsAsync(); 52 | 53 | /// 54 | /// 获取分级后的组合类别数据 55 | /// 56 | /// 57 | /// 58 | Task>> GetGroupsAsync(int? type); 59 | 60 | /// 61 | /// 获取账单分类分页 62 | /// 63 | /// 分页参数 64 | /// 65 | Task>> GetPageAsync(CategoryPagingInput pagingDto); 66 | 67 | /// 68 | /// 排序账单分类 69 | /// 70 | /// 排序内容 71 | /// 72 | Task SortAsync(SortCategoryInput input); 73 | } 74 | --------------------------------------------------------------------------------