feat(tenant): 租户品牌定制(brand_name/logo_url/theme_color/copyright + GET /auth/brand)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
bad8639175
commit
f747ad5442
@ -0,0 +1,5 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE `sys_tenant` ADD COLUMN `brand_name` VARCHAR(64) NULL,
|
||||
ADD COLUMN `copyright` VARCHAR(255) NULL,
|
||||
ADD COLUMN `logo_url` VARCHAR(255) NULL,
|
||||
ADD COLUMN `theme_color` VARCHAR(16) NULL;
|
||||
@ -12,14 +12,18 @@ datasource db {
|
||||
|
||||
/// 租户
|
||||
model Tenant {
|
||||
id String @id @default(uuid(7)) @db.VarChar(36)
|
||||
code String @unique @db.VarChar(64)
|
||||
name String @db.VarChar(128)
|
||||
status String @default("enabled") @db.VarChar(16)
|
||||
remark String? @db.VarChar(255)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
createdBy String? @map("created_by") @db.VarChar(36)
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
id String @id @default(uuid(7)) @db.VarChar(36)
|
||||
code String @unique @db.VarChar(64)
|
||||
name String @db.VarChar(128)
|
||||
status String @default("enabled") @db.VarChar(16)
|
||||
remark String? @db.VarChar(255)
|
||||
brandName String? @map("brand_name") @db.VarChar(64)
|
||||
logoUrl String? @map("logo_url") @db.VarChar(255)
|
||||
themeColor String? @map("theme_color") @db.VarChar(16)
|
||||
copyright String? @db.VarChar(255)
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
createdBy String? @map("created_by") @db.VarChar(36)
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@map("sys_tenant")
|
||||
}
|
||||
|
||||
@ -49,6 +49,14 @@ export class AuthController {
|
||||
return this.auth.getPermissionSet(ctx.tenantCode, ctx.userId);
|
||||
}
|
||||
|
||||
/** 当前租户品牌(仅需登录)。 */
|
||||
@Get('brand')
|
||||
brand() {
|
||||
const ctx = getRequestContext();
|
||||
if (!ctx) throw new UnauthorizedException('未登录');
|
||||
return this.auth.getBrand(ctx.tenantCode);
|
||||
}
|
||||
|
||||
/** 修改本人密码(仅需登录)。 */
|
||||
@Patch('me/password')
|
||||
changePassword(@Body() dto: ChangePasswordDto) {
|
||||
|
||||
@ -439,6 +439,25 @@ export class AuthService {
|
||||
return (await this.redis.getJson(sessionRevokedKey(sid))) != null;
|
||||
}
|
||||
|
||||
/** 当前租户品牌(登录后前端拉取应用)。 */
|
||||
async getBrand(tenantCode: string): Promise<{
|
||||
name: string;
|
||||
brandName: string | null;
|
||||
logoUrl: string | null;
|
||||
themeColor: string | null;
|
||||
copyright: string | null;
|
||||
}> {
|
||||
const tenant = await this.prisma.client.tenant.findUnique({ where: { code: tenantCode } });
|
||||
if (!tenant) throw new UnauthorizedException('租户不存在');
|
||||
return {
|
||||
name: tenant.name,
|
||||
brandName: tenant.brandName,
|
||||
logoUrl: tenant.logoUrl,
|
||||
themeColor: tenant.themeColor,
|
||||
copyright: tenant.copyright,
|
||||
};
|
||||
}
|
||||
|
||||
/** 聚合权限码与超管标志。 */
|
||||
private async resolveAuth(tenantCode: string, userId: string): Promise<PermissionSet> {
|
||||
const roleRows = await this.prisma.client.userRole.findMany({
|
||||
|
||||
@ -33,6 +33,26 @@ export class CreateTenantDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
remark?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: '品牌名' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
brandName?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Logo 地址' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
logoUrl?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: '主色(如 #2E7FA3)' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
themeColor?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: '版权文案' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
copyright?: string;
|
||||
}
|
||||
|
||||
export class UpdateTenantDto {
|
||||
@ -50,6 +70,26 @@ export class UpdateTenantDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
remark?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: '品牌名' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
brandName?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Logo 地址' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
logoUrl?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: '主色(如 #2E7FA3)' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
themeColor?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: '版权文案' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
copyright?: string;
|
||||
}
|
||||
|
||||
export class ListTenantQuery extends PageQuery {
|
||||
|
||||
@ -30,6 +30,10 @@ export class TenantsService extends BaseCrudService {
|
||||
name: dto.name,
|
||||
status: dto.status ?? 'enabled',
|
||||
remark: dto.remark,
|
||||
brandName: dto.brandName,
|
||||
logoUrl: dto.logoUrl,
|
||||
themeColor: dto.themeColor,
|
||||
copyright: dto.copyright,
|
||||
createdBy: ctx?.userId ?? null,
|
||||
},
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user