Initial commit: AuraK人才测评系统基础框架

## 已实现功能
- 题库管理后端API完整实现
- 模板管理页面(Settings-测评模板)
- 评估统计页面
- 人才测评页面(AssessmentView)
- QuestionBank前端服务层

## 技术栈
- 后端: Node.js + NestJS + TypeORM
- 前端: React + TypeScript
- 容器化: Docker Compose

## 已知待完善
- 题库列表页缺少删除按钮
- 题库详情页未实现(题目管理/AI生成/审核)
This commit is contained in:
Developer
2026-05-13 21:32:41 +08:00
parent 0a9588abb7
commit 8686d101cd
22 changed files with 727 additions and 38 deletions
@@ -12,12 +12,13 @@ import { SystemMessage, HumanMessage } from '@langchain/core/messages';
import { QuestionBank, QuestionBankStatus } from '../entities/question-bank.entity';
import {
QuestionBankItem,
QuestionBankItemStatus,
QuestionType,
QuestionDifficulty,
QuestionDimension,
} from '../entities/question-bank-item.entity';
import { ModelConfigService } from '../model-config/model-config.service';
import { ModelType } from '../types';
import { ModelConfigService } from '../../model-config/model-config.service';
import { ModelType } from '../../types';
import { safeParseJson } from '../../common/json-utils';
export interface CreateQuestionBankDto {
@@ -83,12 +84,15 @@ export class QuestionBankService {
async create(
createDto: CreateQuestionBankDto,
userId: string,
tenantId: string,
tenantId: string | null,
): Promise<QuestionBank> {
if (!createDto.name || !createDto.name.trim()) {
throw new Error('Question bank name is required');
}
const bank = this.bankRepository.create({
...createDto,
createdBy: userId,
tenantId,
tenantId: tenantId || null,
status: QuestionBankStatus.DRAFT,
});
return this.bankRepository.save(bank);
@@ -96,15 +100,22 @@ export class QuestionBankService {
async findAll(
userId: string,
tenantId: string,
tenantId: string | null,
page?: number,
limit?: number,
): Promise<{ data: QuestionBank[]; total: number } | QuestionBank[]> {
console.log('[QuestionBank findAll] userId:', userId, 'tenantId:', tenantId);
const queryBuilder = this.bankRepository
.createQueryBuilder('bank')
.leftJoinAndSelect('bank.template', 'template')
.where('bank.tenantId = :tenantId', { tenantId })
.orderBy('bank.createdAt', 'DESC');
.leftJoinAndSelect('bank.template', 'template');
if (tenantId === null) {
queryBuilder.where('bank.tenantId IS NULL');
} else {
queryBuilder.where('bank.tenantId = :tenantId', { tenantId });
}
queryBuilder.orderBy('bank.createdAt', 'DESC');
if (page !== undefined && limit !== undefined) {
const [data, total] = await queryBuilder
@@ -194,6 +205,9 @@ export class QuestionBankService {
bankId: string,
createDto: CreateQuestionBankItemDto,
): Promise<QuestionBankItem> {
if (!createDto.questionText || !createDto.questionText.trim()) {
throw new Error('Question text is required');
}
await this.findOne(bankId);
const item = this.itemRepository.create({
...createDto,
@@ -201,6 +215,7 @@ export class QuestionBankService {
questionType: createDto.questionType || QuestionType.SHORT_ANSWER,
difficulty: createDto.difficulty || QuestionDifficulty.STANDARD,
dimension: createDto.dimension || QuestionDimension.PROMPT,
status: QuestionBankItemStatus.PENDING_REVIEW,
});
return this.itemRepository.save(item);
}
@@ -321,6 +336,7 @@ export class QuestionBankService {
difficulty: difficulty as QuestionDifficulty,
dimension: dimension as QuestionDimension,
basis: q.basis,
status: QuestionBankItemStatus.PENDING_REVIEW,
});
items.push(await this.itemRepository.save(item));
}