feat: 完成配置中心重构和命名规范优化
- 重构config层为配置中心架构,支持动态配置管理 - 统一core层命名规范(event-bus→event, circuit-breaker→breaker, domain-sdk→sdk) - 修复数据库连接配置路径问题 - 实现配置中心完整功能:系统配置、动态配置、配置验证、统计 - 优化目录结构,为微服务架构做准备 - 修复TypeScript编译错误和依赖注入问题
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
||||
|
||||
export const UserContext = createParamDecorator(
|
||||
(data: unknown, ctx: ExecutionContext) => {
|
||||
const request = ctx.switchToHttp().getRequest();
|
||||
return request.user;
|
||||
},
|
||||
);
|
||||
@@ -2,6 +2,7 @@
|
||||
export * from './admin/admin.module';
|
||||
export * from './member/member.module';
|
||||
export * from './rbac/rbac.module';
|
||||
export * from './user/user.module';
|
||||
export * from './auth/auth.module';
|
||||
export * from './upload/upload.module';
|
||||
export * from './jobs/jobs.module';
|
||||
@@ -16,5 +17,4 @@ export * from './auth/decorators/RolesDecorator';
|
||||
// 导出设置相关模块
|
||||
export * from './settings';
|
||||
|
||||
// 导出常量
|
||||
export * from '../config/common/constants';
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Site } from './site.entity';
|
||||
import { UpdateSiteSettingsDto } from './site-settings.dto';
|
||||
import {
|
||||
DEFAULT_SITE_CONFIG,
|
||||
SYSTEM_CONSTANTS,
|
||||
} from '@wwjConfig/common/constants';
|
||||
|
||||
|
||||
// 不允许硬编码,从配置系统获取
|
||||
// TODO: 配置系统重构中,此功能暂时不可用
|
||||
|
||||
@Injectable()
|
||||
export class SiteSettingsService {
|
||||
@@ -18,103 +18,24 @@ export class SiteSettingsService {
|
||||
/**
|
||||
* 获取站点设置
|
||||
*/
|
||||
async getSiteSettings() {
|
||||
// 获取默认站点(id = 1)
|
||||
const site = await this.siteRepository.findOne({
|
||||
where: { site_id: SYSTEM_CONSTANTS.DEFAULT_SITE_ID },
|
||||
});
|
||||
|
||||
if (!site) {
|
||||
// 如果没有找到站点,返回默认值
|
||||
return { ...DEFAULT_SITE_CONFIG };
|
||||
}
|
||||
|
||||
return {
|
||||
site_name: site.site_name || DEFAULT_SITE_CONFIG.site_name,
|
||||
site_title: site.site_title || DEFAULT_SITE_CONFIG.site_title,
|
||||
site_keywords: site.site_keywords || DEFAULT_SITE_CONFIG.site_keywords,
|
||||
site_description:
|
||||
site.site_description || DEFAULT_SITE_CONFIG.site_description,
|
||||
site_logo: site.site_logo || DEFAULT_SITE_CONFIG.site_logo,
|
||||
site_favicon: site.site_favicon || DEFAULT_SITE_CONFIG.site_favicon,
|
||||
icp_number: site.icp_number || DEFAULT_SITE_CONFIG.icp_number,
|
||||
copyright: site.copyright || DEFAULT_SITE_CONFIG.copyright,
|
||||
site_status: site.site_status || DEFAULT_SITE_CONFIG.site_status,
|
||||
close_reason: site.close_reason || DEFAULT_SITE_CONFIG.close_reason,
|
||||
};
|
||||
getSiteSettings() {
|
||||
// 配置系统重构中,此功能暂时不可用
|
||||
throw new Error('配置系统重构中,站点设置功能暂时不可用');
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新站点设置
|
||||
*/
|
||||
async updateSiteSettings(updateSiteSettingsDto: UpdateSiteSettingsDto) {
|
||||
const {
|
||||
site_name,
|
||||
site_title,
|
||||
site_keywords,
|
||||
site_description,
|
||||
site_logo,
|
||||
site_favicon,
|
||||
icp_number,
|
||||
copyright,
|
||||
site_status,
|
||||
close_reason,
|
||||
} = updateSiteSettingsDto;
|
||||
|
||||
// 查找或创建默认站点
|
||||
let site = await this.siteRepository.findOne({
|
||||
where: { id: SYSTEM_CONSTANTS.DEFAULT_SITE_ID },
|
||||
});
|
||||
|
||||
if (!site) {
|
||||
// 创建默认站点
|
||||
site = this.siteRepository.create({
|
||||
id: SYSTEM_CONSTANTS.DEFAULT_SITE_ID,
|
||||
site_name: site_name || DEFAULT_SITE_CONFIG.site_name,
|
||||
site_title: site_title || DEFAULT_SITE_CONFIG.site_title,
|
||||
site_keywords: site_keywords || DEFAULT_SITE_CONFIG.site_keywords,
|
||||
site_description:
|
||||
site_description || DEFAULT_SITE_CONFIG.site_description,
|
||||
site_logo: site_logo || DEFAULT_SITE_CONFIG.site_logo,
|
||||
site_favicon: site_favicon || DEFAULT_SITE_CONFIG.site_favicon,
|
||||
icp_number: icp_number || DEFAULT_SITE_CONFIG.icp_number,
|
||||
copyright: copyright || DEFAULT_SITE_CONFIG.copyright,
|
||||
site_status: site_status || DEFAULT_SITE_CONFIG.site_status,
|
||||
close_reason: close_reason || DEFAULT_SITE_CONFIG.close_reason,
|
||||
});
|
||||
} else {
|
||||
// 更新现有站点
|
||||
if (site_name !== undefined) site.site_name = site_name;
|
||||
if (site_title !== undefined) site.site_title = site_title;
|
||||
if (site_keywords !== undefined) site.site_keywords = site_keywords;
|
||||
if (site_description !== undefined)
|
||||
site.site_description = site_description;
|
||||
if (site_logo !== undefined) site.site_logo = site_logo;
|
||||
if (site_favicon !== undefined) site.site_favicon = site_favicon;
|
||||
if (icp_number !== undefined) site.icp_number = icp_number;
|
||||
if (copyright !== undefined) site.copyright = copyright;
|
||||
if (site_status !== undefined) site.site_status = site_status;
|
||||
if (close_reason !== undefined) site.close_reason = close_reason;
|
||||
}
|
||||
|
||||
await this.siteRepository.save(site);
|
||||
return { message: '站点设置更新成功' };
|
||||
updateSiteSettings(updateSiteSettingsDto: UpdateSiteSettingsDto) {
|
||||
// 配置系统重构中,此功能暂时不可用
|
||||
throw new Error('配置系统重构中,站点设置更新功能暂时不可用');
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置站点设置为默认值
|
||||
*/
|
||||
async resetSiteSettings() {
|
||||
// 删除现有站点配置
|
||||
await this.siteRepository.delete({ id: SYSTEM_CONSTANTS.DEFAULT_SITE_ID });
|
||||
|
||||
// 创建默认站点配置
|
||||
const defaultSite = this.siteRepository.create({
|
||||
id: SYSTEM_CONSTANTS.DEFAULT_SITE_ID,
|
||||
...DEFAULT_SITE_CONFIG,
|
||||
});
|
||||
|
||||
await this.siteRepository.save(defaultSite);
|
||||
return { message: '站点设置重置成功' };
|
||||
resetSiteSettings() {
|
||||
// 配置系统重构中,此功能暂时不可用
|
||||
throw new Error('配置系统重构中,站点设置重置功能暂时不可用');
|
||||
}
|
||||
}
|
||||
|
||||
110
wwjcloud/src/common/user/controllers/adminapi/UserController.ts
Normal file
110
wwjcloud/src/common/user/controllers/adminapi/UserController.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
UseGuards,
|
||||
ParseIntPipe,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
|
||||
import { JwtAuthGuard } from '../../../auth/guards/JwtAuthGuard';
|
||||
import { RolesGuard } from '../../../auth/guards/RolesGuard';
|
||||
import { Roles } from '../../../auth/decorators/RolesDecorator';
|
||||
import { UserContext } from '../../../auth/decorators/user-context.decorator';
|
||||
import { UserContextDto } from '../../dto/UserContextDto';
|
||||
import { UserAdminService } from '../../services/admin/UserAdminService';
|
||||
import {
|
||||
CreateUserAdminDto,
|
||||
UpdateUserAdminDto,
|
||||
GetUserListAdminDto,
|
||||
BatchUpdateUserStatusAdminDto,
|
||||
ResetUserPasswordAdminDto,
|
||||
} from '../../dto/admin/UserDto';
|
||||
|
||||
@ApiTags('用户管理')
|
||||
@Controller('adminapi/user')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
export class UserController {
|
||||
constructor(private readonly userAdminService: UserAdminService) {}
|
||||
|
||||
@Post()
|
||||
@Roles('admin')
|
||||
@ApiOperation({ summary: '创建用户' })
|
||||
@ApiResponse({ status: 201, description: '用户创建成功' })
|
||||
async createUser(
|
||||
@Body() createUserDto: CreateUserAdminDto,
|
||||
@UserContext() userContext: UserContextDto,
|
||||
) {
|
||||
return await this.userAdminService.createUser(createUserDto, userContext);
|
||||
}
|
||||
|
||||
@Put()
|
||||
@Roles('admin')
|
||||
@ApiOperation({ summary: '更新用户' })
|
||||
@ApiResponse({ status: 200, description: '用户更新成功' })
|
||||
async updateUser(
|
||||
@Body() updateUserDto: UpdateUserAdminDto,
|
||||
@UserContext() userContext: UserContextDto,
|
||||
) {
|
||||
return await this.userAdminService.updateUser(updateUserDto, userContext);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@Roles('admin')
|
||||
@ApiOperation({ summary: '获取用户列表' })
|
||||
@ApiResponse({ status: 200, description: '获取用户列表成功' })
|
||||
async getUserList(
|
||||
@Query() queryDto: GetUserListAdminDto,
|
||||
@UserContext() userContext: UserContextDto,
|
||||
) {
|
||||
return await this.userAdminService.getUserList(queryDto, userContext);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@Roles('admin')
|
||||
@ApiOperation({ summary: '根据ID获取用户' })
|
||||
@ApiResponse({ status: 200, description: '获取用户成功' })
|
||||
async getUserById(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@UserContext() userContext: UserContextDto,
|
||||
) {
|
||||
return await this.userAdminService.getUserById(id, userContext);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@Roles('admin')
|
||||
@ApiOperation({ summary: '删除用户' })
|
||||
@ApiResponse({ status: 200, description: '用户删除成功' })
|
||||
async deleteUser(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@UserContext() userContext: UserContextDto,
|
||||
) {
|
||||
return await this.userAdminService.deleteUser(id, userContext);
|
||||
}
|
||||
|
||||
@Post('batch-update-status')
|
||||
@Roles('admin')
|
||||
@ApiOperation({ summary: '批量更新用户状态' })
|
||||
@ApiResponse({ status: 200, description: '批量更新状态成功' })
|
||||
async batchUpdateStatus(
|
||||
@Body() batchUpdateDto: BatchUpdateUserStatusAdminDto,
|
||||
@UserContext() userContext: UserContextDto,
|
||||
) {
|
||||
return await this.userAdminService.batchUpdateStatus(batchUpdateDto, userContext);
|
||||
}
|
||||
|
||||
@Post('reset-password')
|
||||
@Roles('admin')
|
||||
@ApiOperation({ summary: '重置用户密码' })
|
||||
@ApiResponse({ status: 200, description: '密码重置成功' })
|
||||
async resetPassword(
|
||||
@Body() resetPasswordDto: ResetUserPasswordAdminDto,
|
||||
@UserContext() userContext: UserContextDto,
|
||||
) {
|
||||
return await this.userAdminService.resetPassword(resetPasswordDto, userContext);
|
||||
}
|
||||
}
|
||||
6
wwjcloud/src/common/user/dto/UserContextDto.ts
Normal file
6
wwjcloud/src/common/user/dto/UserContextDto.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export class UserContextDto {
|
||||
userId: number;
|
||||
siteId: number;
|
||||
username: string;
|
||||
roles: string[];
|
||||
}
|
||||
189
wwjcloud/src/common/user/dto/admin/UserDto.ts
Normal file
189
wwjcloud/src/common/user/dto/admin/UserDto.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsOptional, IsNumber, IsEmail, IsDateString, IsArray } from 'class-validator';
|
||||
|
||||
export class CreateUserAdminDto {
|
||||
@ApiProperty({ description: '用户名' })
|
||||
@IsString()
|
||||
username: string;
|
||||
|
||||
@ApiProperty({ description: '密码' })
|
||||
@IsString()
|
||||
password: string;
|
||||
|
||||
@ApiProperty({ description: '昵称' })
|
||||
@IsString()
|
||||
nickname: string;
|
||||
|
||||
@ApiProperty({ description: '邮箱', required: false })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
email?: string;
|
||||
|
||||
@ApiProperty({ description: '手机号', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
mobile?: string;
|
||||
|
||||
@ApiProperty({ description: '头像', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
avatar?: string;
|
||||
|
||||
@ApiProperty({ description: '状态:0-禁用,1-启用', default: 1 })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
status?: number;
|
||||
|
||||
@ApiProperty({ description: '性别:0-未知,1-男,2-女', default: 0 })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
gender?: number;
|
||||
|
||||
@ApiProperty({ description: '生日', required: false })
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
birthday?: string;
|
||||
|
||||
@ApiProperty({ description: '备注', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
remark?: string;
|
||||
|
||||
@ApiProperty({ description: '排序', default: 0 })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
sort?: number;
|
||||
|
||||
@ApiProperty({ description: '部门ID', required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
dept_id?: number;
|
||||
|
||||
@ApiProperty({ description: '角色ID列表', required: false, type: [Number] })
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
role_ids?: number[];
|
||||
}
|
||||
|
||||
export class UpdateUserAdminDto {
|
||||
@ApiProperty({ description: 'ID' })
|
||||
@IsNumber()
|
||||
id: number;
|
||||
|
||||
@ApiProperty({ description: '昵称', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
nickname?: string;
|
||||
|
||||
@ApiProperty({ description: '邮箱', required: false })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
email?: string;
|
||||
|
||||
@ApiProperty({ description: '手机号', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
mobile?: string;
|
||||
|
||||
@ApiProperty({ description: '头像', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
avatar?: string;
|
||||
|
||||
@ApiProperty({ description: '状态:0-禁用,1-启用', required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
status?: number;
|
||||
|
||||
@ApiProperty({ description: '性别:0-未知,1-男,2-女', required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
gender?: number;
|
||||
|
||||
@ApiProperty({ description: '生日', required: false })
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
birthday?: string;
|
||||
|
||||
@ApiProperty({ description: '备注', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
remark?: string;
|
||||
|
||||
@ApiProperty({ description: '排序', required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
sort?: number;
|
||||
|
||||
@ApiProperty({ description: '部门ID', required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
dept_id?: number;
|
||||
|
||||
@ApiProperty({ description: '角色ID列表', required: false, type: [Number] })
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
role_ids?: number[];
|
||||
}
|
||||
|
||||
export class GetUserListAdminDto {
|
||||
@ApiProperty({ description: '页码', default: 1 })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
page?: number;
|
||||
|
||||
@ApiProperty({ description: '每页数量', default: 20 })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
pageSize?: number;
|
||||
|
||||
@ApiProperty({ description: '用户名', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
username?: string;
|
||||
|
||||
@ApiProperty({ description: '昵称', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
nickname?: string;
|
||||
|
||||
@ApiProperty({ description: '邮箱', required: false })
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
email?: string;
|
||||
|
||||
@ApiProperty({ description: '手机号', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
mobile?: string;
|
||||
|
||||
@ApiProperty({ description: '状态', required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
status?: number;
|
||||
|
||||
@ApiProperty({ description: '部门ID', required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
dept_id?: number;
|
||||
}
|
||||
|
||||
export class BatchUpdateUserStatusAdminDto {
|
||||
@ApiProperty({ description: '用户ID列表', type: [Number] })
|
||||
@IsArray()
|
||||
ids: number[];
|
||||
|
||||
@ApiProperty({ description: '状态:0-禁用,1-启用' })
|
||||
@IsNumber()
|
||||
status: number;
|
||||
}
|
||||
|
||||
export class ResetUserPasswordAdminDto {
|
||||
@ApiProperty({ description: '用户ID' })
|
||||
@IsNumber()
|
||||
id: number;
|
||||
|
||||
@ApiProperty({ description: '新密码' })
|
||||
@IsString()
|
||||
password: string;
|
||||
}
|
||||
82
wwjcloud/src/common/user/entities/SysUser.ts
Normal file
82
wwjcloud/src/common/user/entities/SysUser.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
DeleteDateColumn,
|
||||
ManyToOne,
|
||||
JoinColumn,
|
||||
ManyToMany,
|
||||
JoinTable,
|
||||
} from 'typeorm';
|
||||
import { SysRole } from '../../rbac/entities/SysRole';
|
||||
|
||||
@Entity('sys_user')
|
||||
export class SysUser {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ length: 50, unique: true, comment: '用户名' })
|
||||
username: string;
|
||||
|
||||
@Column({ length: 100, comment: '密码' })
|
||||
password: string;
|
||||
|
||||
@Column({ length: 50, comment: '昵称' })
|
||||
nickname: string;
|
||||
|
||||
@Column({ length: 100, nullable: true, comment: '邮箱' })
|
||||
email: string;
|
||||
|
||||
@Column({ length: 20, nullable: true, comment: '手机号' })
|
||||
mobile: string;
|
||||
|
||||
@Column({ length: 200, nullable: true, comment: '头像' })
|
||||
avatar: string;
|
||||
|
||||
@Column({ type: 'tinyint', default: 1, comment: '状态:0-禁用,1-启用' })
|
||||
status: number;
|
||||
|
||||
@Column({ type: 'tinyint', default: 0, comment: '性别:0-未知,1-男,2-女' })
|
||||
gender: number;
|
||||
|
||||
@Column({ type: 'date', nullable: true, comment: '生日' })
|
||||
birthday: Date;
|
||||
|
||||
@Column({ length: 500, nullable: true, comment: '备注' })
|
||||
remark: string;
|
||||
|
||||
@Column({ type: 'int', default: 0, comment: '排序' })
|
||||
sort: number;
|
||||
|
||||
@Column({ type: 'int', default: 0, comment: '站点ID' })
|
||||
site_id: number;
|
||||
|
||||
@Column({ type: 'int', nullable: true, comment: '部门ID' })
|
||||
dept_id: number;
|
||||
|
||||
@Column({ type: 'int', nullable: true, comment: '创建人ID' })
|
||||
create_user_id: number;
|
||||
|
||||
@Column({ type: 'int', nullable: true, comment: '更新人ID' })
|
||||
update_user_id: number;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
create_time: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
update_time: Date;
|
||||
|
||||
@DeleteDateColumn({ comment: '删除时间' })
|
||||
delete_time: Date;
|
||||
|
||||
// 关联关系
|
||||
@ManyToMany(() => SysRole)
|
||||
@JoinTable({
|
||||
name: 'sys_user_role',
|
||||
joinColumn: { name: 'user_id', referencedColumnName: 'id' },
|
||||
inverseJoinColumn: { name: 'role_id', referencedColumnName: 'role_id' },
|
||||
})
|
||||
roles: SysRole[];
|
||||
}
|
||||
76
wwjcloud/src/common/user/services/admin/UserAdminService.ts
Normal file
76
wwjcloud/src/common/user/services/admin/UserAdminService.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CoreUserService } from '../core/CoreUserService';
|
||||
import { CreateUserAdminDto, UpdateUserAdminDto, GetUserListAdminDto, BatchUpdateUserStatusAdminDto, ResetUserPasswordAdminDto } from '../../dto/admin/UserDto';
|
||||
import { UserContextDto } from '../../dto/UserContextDto';
|
||||
|
||||
@Injectable()
|
||||
export class UserAdminService {
|
||||
constructor(
|
||||
private readonly coreUserService: CoreUserService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 创建用户
|
||||
*/
|
||||
async createUser(createUserDto: CreateUserAdminDto, userContext: UserContextDto) {
|
||||
return await this.coreUserService.createUser(
|
||||
createUserDto,
|
||||
userContext.siteId,
|
||||
userContext.userId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户
|
||||
*/
|
||||
async updateUser(updateUserDto: UpdateUserAdminDto, userContext: UserContextDto) {
|
||||
return await this.coreUserService.updateUser(
|
||||
updateUserDto,
|
||||
userContext.siteId,
|
||||
userContext.userId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户列表
|
||||
*/
|
||||
async getUserList(queryDto: GetUserListAdminDto, userContext: UserContextDto) {
|
||||
return await this.coreUserService.getUserList(queryDto, userContext.siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取用户
|
||||
*/
|
||||
async getUserById(id: number, userContext: UserContextDto) {
|
||||
return await this.coreUserService.getUserById(id, userContext.siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
async deleteUser(id: number, userContext: UserContextDto) {
|
||||
return await this.coreUserService.deleteUser(id, userContext.siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新用户状态
|
||||
*/
|
||||
async batchUpdateStatus(batchUpdateDto: BatchUpdateUserStatusAdminDto, userContext: UserContextDto) {
|
||||
return await this.coreUserService.batchUpdateStatus(
|
||||
batchUpdateDto.ids,
|
||||
batchUpdateDto.status,
|
||||
userContext.siteId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置用户密码
|
||||
*/
|
||||
async resetPassword(resetPasswordDto: ResetUserPasswordAdminDto, userContext: UserContextDto) {
|
||||
return await this.coreUserService.resetPassword(
|
||||
resetPasswordDto.id,
|
||||
resetPasswordDto.password,
|
||||
userContext.siteId,
|
||||
);
|
||||
}
|
||||
}
|
||||
171
wwjcloud/src/common/user/services/core/CoreUserService.ts
Normal file
171
wwjcloud/src/common/user/services/core/CoreUserService.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { SysUser } from '../../entities/SysUser';
|
||||
import { CreateUserAdminDto, UpdateUserAdminDto, GetUserListAdminDto } from '../../dto/admin/UserDto';
|
||||
import { TransactionManager } from '@wwjCore/database/transactionManager';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
|
||||
@Injectable()
|
||||
export class CoreUserService {
|
||||
constructor(
|
||||
@InjectRepository(SysUser)
|
||||
private readonly userRepository: Repository<SysUser>,
|
||||
private readonly transactionManager: TransactionManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 创建用户
|
||||
*/
|
||||
async createUser(createUserDto: CreateUserAdminDto, siteId: number, userId: number): Promise<SysUser> {
|
||||
const { password, role_ids, ...userData } = createUserDto;
|
||||
|
||||
// 加密密码
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
|
||||
const user = this.userRepository.create({
|
||||
...userData,
|
||||
password: hashedPassword,
|
||||
site_id: siteId,
|
||||
create_user_id: userId,
|
||||
update_user_id: userId,
|
||||
});
|
||||
|
||||
return await this.userRepository.save(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户
|
||||
*/
|
||||
async updateUser(updateUserDto: UpdateUserAdminDto, siteId: number, userId: number): Promise<SysUser> {
|
||||
const { id, role_ids, ...updateData } = updateUserDto;
|
||||
|
||||
const user = await this.userRepository.findOne({
|
||||
where: { id, site_id: siteId },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new Error('用户不存在');
|
||||
}
|
||||
|
||||
Object.assign(user, {
|
||||
...updateData,
|
||||
update_user_id: userId,
|
||||
});
|
||||
|
||||
return await this.userRepository.save(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户列表
|
||||
*/
|
||||
async getUserList(queryDto: GetUserListAdminDto, siteId: number) {
|
||||
const { page = 1, pageSize = 20, username, nickname, email, mobile, status, dept_id } = queryDto;
|
||||
|
||||
const queryBuilder = this.userRepository
|
||||
.createQueryBuilder('user')
|
||||
.leftJoinAndSelect('user.roles', 'roles')
|
||||
.where('user.site_id = :siteId', { siteId })
|
||||
.andWhere('user.delete_time IS NULL');
|
||||
|
||||
if (username) {
|
||||
queryBuilder.andWhere('user.username LIKE :username', { username: `%${username}%` });
|
||||
}
|
||||
|
||||
if (nickname) {
|
||||
queryBuilder.andWhere('user.nickname LIKE :nickname', { nickname: `%${nickname}%` });
|
||||
}
|
||||
|
||||
if (email) {
|
||||
queryBuilder.andWhere('user.email LIKE :email', { email: `%${email}%` });
|
||||
}
|
||||
|
||||
if (mobile) {
|
||||
queryBuilder.andWhere('user.mobile LIKE :mobile', { mobile: `%${mobile}%` });
|
||||
}
|
||||
|
||||
if (status !== undefined) {
|
||||
queryBuilder.andWhere('user.status = :status', { status });
|
||||
}
|
||||
|
||||
if (dept_id) {
|
||||
queryBuilder.andWhere('user.dept_id = :dept_id', { dept_id });
|
||||
}
|
||||
|
||||
const [users, total] = await queryBuilder
|
||||
.orderBy('user.sort', 'ASC')
|
||||
.addOrderBy('user.id', 'DESC')
|
||||
.skip((page - 1) * pageSize)
|
||||
.take(pageSize)
|
||||
.getManyAndCount();
|
||||
|
||||
return {
|
||||
list: users,
|
||||
total,
|
||||
page,
|
||||
pageSize,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取用户
|
||||
*/
|
||||
async getUserById(id: number, siteId: number): Promise<SysUser | null> {
|
||||
return await this.userRepository.findOne({
|
||||
where: { id, site_id: siteId },
|
||||
relations: ['roles'],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户名获取用户
|
||||
*/
|
||||
async getUserByUsername(username: string, siteId: number): Promise<SysUser | null> {
|
||||
return await this.userRepository.findOne({
|
||||
where: { username, site_id: siteId },
|
||||
relations: ['roles'],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
async deleteUser(id: number, siteId: number): Promise<void> {
|
||||
await this.userRepository.softDelete({ id, site_id: siteId });
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新用户状态
|
||||
*/
|
||||
async batchUpdateStatus(ids: number[], status: number, siteId: number): Promise<void> {
|
||||
await this.userRepository
|
||||
.createQueryBuilder()
|
||||
.update(SysUser)
|
||||
.set({ status })
|
||||
.whereInIds(ids)
|
||||
.andWhere('site_id = :siteId', { siteId })
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置用户密码
|
||||
*/
|
||||
async resetPassword(id: number, password: string, siteId: number): Promise<void> {
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
|
||||
await this.userRepository
|
||||
.createQueryBuilder()
|
||||
.update(SysUser)
|
||||
.set({ password: hashedPassword })
|
||||
.where('id = :id', { id })
|
||||
.andWhere('site_id = :siteId', { siteId })
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户密码
|
||||
*/
|
||||
async validatePassword(user: SysUser, password: string): Promise<boolean> {
|
||||
return await bcrypt.compare(password, user.password);
|
||||
}
|
||||
}
|
||||
40
wwjcloud/src/common/user/user.module.ts
Normal file
40
wwjcloud/src/common/user/user.module.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Module, forwardRef } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
import { RbacModule } from '../rbac/rbac.module';
|
||||
import { DatabaseModule } from '@wwjCore/database/databaseModule';
|
||||
import { SysUser } from './entities/SysUser';
|
||||
|
||||
// Core Services
|
||||
import { CoreUserService } from './services/core/CoreUserService';
|
||||
|
||||
// Admin Services
|
||||
import { UserAdminService } from './services/admin/UserAdminService';
|
||||
|
||||
// Controllers
|
||||
import { UserController } from './controllers/adminapi/UserController';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
forwardRef(() => AuthModule),
|
||||
forwardRef(() => RbacModule),
|
||||
DatabaseModule,
|
||||
TypeOrmModule.forFeature([SysUser]),
|
||||
],
|
||||
providers: [
|
||||
// Core Services
|
||||
CoreUserService,
|
||||
|
||||
// Admin Services
|
||||
UserAdminService,
|
||||
],
|
||||
controllers: [UserController],
|
||||
exports: [
|
||||
// Core Services
|
||||
CoreUserService,
|
||||
|
||||
// Admin Services
|
||||
UserAdminService,
|
||||
],
|
||||
})
|
||||
export class UserModule {}
|
||||
Reference in New Issue
Block a user