9fd503b42b
P0 — 答题体验优化: - 题序导航点:题目进度可视化,标记题目标记 - 标记回头检查: 点击🏷️按钮标记当前题,导航点变黄色 - 提交确认弹窗: 未答完时提交弹出确认对话框 P1 — 题库管理增强: - QuestionBankItem 新增 tags 字段(多标签过滤) - 新增 question_bank_templates 联表(题库跨模板复用) P2 — 考试配置增强: - AssessmentTemplate 新增字段: - attemptLimit (尝试次数限制) - scheduledStart/scheduledEnd (预约时段) - reviewMode (回顾模式: none/after_completion/per_question) - shuffleQuestions (每题随机排序) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
114 lines
2.5 KiB
TypeScript
114 lines
2.5 KiB
TypeScript
import {
|
|
Entity,
|
|
PrimaryGeneratedColumn,
|
|
Column,
|
|
CreateDateColumn,
|
|
UpdateDateColumn,
|
|
ManyToOne,
|
|
JoinColumn,
|
|
} from 'typeorm';
|
|
import { QuestionBank } from './question-bank.entity';
|
|
|
|
export enum QuestionBankItemStatus {
|
|
PENDING_REVIEW = 'PENDING_REVIEW',
|
|
PUBLISHED = 'PUBLISHED',
|
|
}
|
|
|
|
export enum QuestionType {
|
|
SHORT_ANSWER = 'SHORT_ANSWER',
|
|
MULTIPLE_CHOICE = 'MULTIPLE_CHOICE',
|
|
TRUE_FALSE = 'TRUE_FALSE',
|
|
}
|
|
|
|
export enum QuestionDifficulty {
|
|
STANDARD = 'STANDARD',
|
|
ADVANCED = 'ADVANCED',
|
|
SPECIALIST = 'SPECIALIST',
|
|
}
|
|
|
|
export enum QuestionDimension {
|
|
PROMPT = 'PROMPT',
|
|
LLM = 'LLM',
|
|
IDE = 'IDE',
|
|
DEV_PATTERN = 'DEV_PATTERN',
|
|
WORK_CAPABILITY = 'WORK_CAPABILITY',
|
|
}
|
|
|
|
@Entity('question_bank_items')
|
|
export class QuestionBankItem {
|
|
@PrimaryGeneratedColumn('uuid')
|
|
id: string;
|
|
|
|
@Column({ name: 'bank_id' })
|
|
bankId: string;
|
|
|
|
@ManyToOne(
|
|
() => QuestionBank,
|
|
(bank: QuestionBank) => bank.items,
|
|
{ onDelete: 'CASCADE' },
|
|
)
|
|
@JoinColumn({ name: 'bank_id' })
|
|
bank: QuestionBank;
|
|
|
|
@Column({ type: 'text', name: 'question_text' })
|
|
questionText: string;
|
|
|
|
@Column({
|
|
type: 'simple-enum',
|
|
enum: QuestionType,
|
|
default: QuestionType.SHORT_ANSWER,
|
|
})
|
|
questionType: QuestionType;
|
|
|
|
@Column({ type: 'simple-json', nullable: true })
|
|
options: string[] | null;
|
|
|
|
@Column({ type: 'text', nullable: true })
|
|
correctAnswer: string | null;
|
|
|
|
@Column({ type: 'simple-json', name: 'key_points' })
|
|
keyPoints: string[];
|
|
|
|
@Column({
|
|
type: 'simple-enum',
|
|
enum: QuestionDifficulty,
|
|
default: QuestionDifficulty.STANDARD,
|
|
})
|
|
difficulty: QuestionDifficulty;
|
|
|
|
@Column({
|
|
type: 'simple-enum',
|
|
enum: QuestionDimension,
|
|
default: QuestionDimension.PROMPT,
|
|
})
|
|
dimension: QuestionDimension;
|
|
|
|
@Column({ type: 'text', nullable: true })
|
|
basis: string | null;
|
|
|
|
@Column({ type: 'text', nullable: true })
|
|
judgment: string | null;
|
|
|
|
@Column({ type: 'simple-json', nullable: true, name: 'followup_hints' })
|
|
followupHints: string[] | null;
|
|
|
|
/** P1: Tags for cross-category filtering */
|
|
@Column({ type: 'simple-json', nullable: true })
|
|
tags: string[] | null;
|
|
|
|
@Column({ name: 'created_by', nullable: true, type: 'text' })
|
|
createdBy: string | null;
|
|
|
|
@Column({
|
|
type: 'simple-enum',
|
|
enum: QuestionBankItemStatus,
|
|
default: QuestionBankItemStatus.PENDING_REVIEW,
|
|
})
|
|
status: QuestionBankItemStatus;
|
|
|
|
@CreateDateColumn({ name: 'created_at' })
|
|
createdAt: Date;
|
|
|
|
@UpdateDateColumn({ name: 'updated_at' })
|
|
updatedAt: Date;
|
|
} |