refactor: replace UserDingMapping with StudentDingMapping entity

This commit is contained in:
2026-07-09 16:53:25 +08:00
parent 1fa336331c
commit ef1b46b9f4
18 changed files with 104 additions and 146 deletions

View File

@@ -80,20 +80,12 @@ export class UpdateProfileDto {
qualifications?: string;
}
export class CreateUserDingMappingDto {
export class CreateStudentDingMappingDto {
@IsInt()
@IsNotEmpty()
userId: number;
studentId: number;
@IsString()
@IsNotEmpty()
dingUserId: string;
@IsOptional()
@IsString()
dingName?: string;
@IsOptional()
@IsString()
dingMobile?: string;
}

View File

@@ -19,7 +19,7 @@ import {
UpdateUserDto,
ResetPasswordDto,
UpdateProfileDto,
CreateUserDingMappingDto,
CreateStudentDingMappingDto,
} from './dto/rbac.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RequirePermission } from '../auth/decorators/permission.decorator';
@@ -304,7 +304,7 @@ export class RbacController {
@Get('user-ding-mappings')
@RequirePermission('user:view')
async getUserDingMappings() {
async getStudentDingMappings() {
return this.rbacService.getUserDingMappings();
}
@@ -316,13 +316,13 @@ export class RbacController {
@Post('user-ding-mappings')
@RequirePermission('user:edit')
async createUserDingMapping(@Body() dto: CreateUserDingMappingDto) {
async createStudentDingMapping(@Body() dto: CreateStudentDingMappingDto) {
return this.rbacService.createUserDingMapping(dto);
}
@Delete('user-ding-mappings/:id')
@RequirePermission('user:delete')
async deleteUserDingMapping(@Param('id') id: string) {
async deleteStudentDingMapping(@Param('id') id: string) {
return this.rbacService.deleteUserDingMapping(+id);
}
// ---- 教师工作台 ----

View File

@@ -1,12 +1,12 @@
import { Module, OnModuleInit, forwardRef } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Permission, Role, User, Class, ClassStudent, ClassTeacher, ClassSchedule, Student, UserDingMapping } from '../entities';
import { Permission, Role, User, Class, ClassStudent, ClassTeacher, ClassSchedule, Student, StudentDingMapping } from '../entities';
import { RbacService } from './rbac.service';
import { RbacController } from './rbac.controller';
import { AuthModule } from '../auth/auth.module';
@Module({
imports: [TypeOrmModule.forFeature([Permission, Role, User, Class, ClassStudent, ClassTeacher, ClassSchedule, Student, UserDingMapping]), forwardRef(() => AuthModule)],
imports: [TypeOrmModule.forFeature([Permission, Role, User, Class, ClassStudent, ClassTeacher, ClassSchedule, Student, StudentDingMapping]), forwardRef(() => AuthModule)],
controllers: [RbacController],
providers: [RbacService],
exports: [RbacService],

View File

@@ -2,7 +2,7 @@ import { Injectable, Logger, NotFoundException, ConflictException } from '@nestj
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, In } from 'typeorm';
import * as bcrypt from 'bcryptjs';
import { Permission, Role, User, Class, ClassStudent, ClassTeacher, ClassSchedule, Student, UserDingMapping } from '../entities';
import { Permission, Role, User, Class, ClassStudent, ClassTeacher, ClassSchedule, Student, StudentDingMapping } from '../entities';
const PRESET_PERMISSIONS: Array<{ code: string; name: string; group: string }> = [
{ code: 'dashboard:view', name: '查看数据面板', group: 'dashboard' },
@@ -171,7 +171,7 @@ export class RbacService {
@InjectRepository(ClassTeacher) private classTeacherRepo: Repository<ClassTeacher>,
@InjectRepository(ClassSchedule) private classScheduleRepo: Repository<ClassSchedule>,
@InjectRepository(Student) private studentRepo: Repository<Student>,
@InjectRepository(UserDingMapping) private mappingRepo: Repository<UserDingMapping>,
@InjectRepository(StudentDingMapping) private mappingRepo: Repository<StudentDingMapping>,
) {}
async seedData(): Promise<void> {
@@ -249,15 +249,15 @@ export class RbacService {
// ---- 钉钉用户绑定 ----
async getUserDingMappings(): Promise<UserDingMapping[]> {
return this.mappingRepo.find({ relations: ['user'] });
async getUserDingMappings(): Promise<StudentDingMapping[]> {
return this.mappingRepo.find({ relations: ['student'] });
}
async createUserDingMapping(dto: { userId: number; dingUserId: string; dingName?: string; dingMobile?: string }) {
async createUserDingMapping(dto: { studentId: number; dingUserId: string }) {
const existing = await this.mappingRepo.findOne({ where: { dingUserId: dto.dingUserId } });
if (existing) throw new ConflictException(`钉钉用户 ${dto.dingUserId} 已绑定到本地用户 #${existing.userId}`);
const userExisting = await this.mappingRepo.findOne({ where: { userId: dto.userId } });
if (userExisting) throw new ConflictException(`本地用户 #${dto.userId} 已绑定到钉钉用户 ${userExisting.dingUserId}`);
if (existing) throw new ConflictException(`钉钉用户 ${dto.dingUserId} 已绑定到学生 #${existing.studentId}`);
const studentExisting = await this.mappingRepo.findOne({ where: { studentId: dto.studentId } });
if (studentExisting) throw new ConflictException(`学生 #${dto.studentId} 已绑定到钉钉用户 ${studentExisting.dingUserId}`);
const mapping = this.mappingRepo.create(dto);
return this.mappingRepo.save(mapping);
}
@@ -272,7 +272,7 @@ export class RbacService {
async getUnboundUsers(): Promise<{ id: number; username: string; name: string }[]> {
return this.userRepo
.createQueryBuilder('u')
.leftJoin(UserDingMapping, 'm', 'm.userId = u.id')
.leftJoin(StudentDingMapping, 'm', 'm.studentId = u.id')
.where('m.id IS NULL')
.andWhere('u.isArchived = false')
.select(['u.id', 'u.username', 'u.name'])