forked from hangshuo652/aurak
fix: linkedGroupIds null check in validateRequiredFields
null !== undefined was true, causing false validation failure on templates without linked groups. Changed to != null check.
This commit is contained in:
@@ -77,14 +77,13 @@ export const interviewerNode = async (
|
|||||||
? `質問 ${currentQuestionIndex + 1}`
|
? `質問 ${currentQuestionIndex + 1}`
|
||||||
: `Question ${currentQuestionIndex + 1}`;
|
: `Question ${currentQuestionIndex + 1}`;
|
||||||
|
|
||||||
const optionsText = currentQuestion.options.join('\n');
|
|
||||||
const instruction = isZh
|
const instruction = isZh
|
||||||
? '请选择一个选项(输入字母 A/B/C/D)'
|
? '请选择一个选项'
|
||||||
: isJa
|
: isJa
|
||||||
? '選択肢から1つ選んでください(A/B/C/Dを入力)'
|
? '選択肢から1つ選んでください'
|
||||||
: 'Please select one option (enter A, B, C, or D)';
|
: 'Please select one option';
|
||||||
|
|
||||||
prompt = `${label}: ${currentQuestion.questionText}\n\n${optionsText}\n\n${instruction}`;
|
prompt = `${label}: ${currentQuestion.questionText}\n\n${instruction}`;
|
||||||
} else {
|
} else {
|
||||||
const label = isZh
|
const label = isZh
|
||||||
? `问题 ${currentQuestionIndex + 1}`
|
? `问题 ${currentQuestionIndex + 1}`
|
||||||
|
|||||||
@@ -20,16 +20,16 @@ export class TemplateService {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
private validateRequiredFields(data: {
|
private validateRequiredFields(data: {
|
||||||
linkedGroupIds?: string[];
|
linkedGroupIds?: string[] | null;
|
||||||
dimensions?: Array<{ name: string; label?: string; weight?: number }>;
|
dimensions?: Array<{ name: string; label?: string; weight?: number }> | null;
|
||||||
}) {
|
}) {
|
||||||
if (data.linkedGroupIds !== undefined) {
|
if (data.linkedGroupIds != null && Array.isArray(data.linkedGroupIds)) {
|
||||||
if (!Array.isArray(data.linkedGroupIds) || data.linkedGroupIds.length === 0) {
|
if (data.linkedGroupIds.length === 0) {
|
||||||
throw new BadRequestException('At least one knowledge group must be linked');
|
throw new BadRequestException('At least one knowledge group must be linked');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.dimensions !== undefined) {
|
if (data.dimensions != null && Array.isArray(data.dimensions)) {
|
||||||
if (!Array.isArray(data.dimensions) || data.dimensions.length === 0) {
|
if (data.dimensions.length === 0) {
|
||||||
throw new BadRequestException('At least one dimension must be defined');
|
throw new BadRequestException('At least one dimension must be defined');
|
||||||
}
|
}
|
||||||
for (const d of data.dimensions) {
|
for (const d of data.dimensions) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -135,9 +135,10 @@ export const AssessmentTemplateManager: React.FC = () => {
|
|||||||
}
|
}
|
||||||
setShowModal(false);
|
setShowModal(false);
|
||||||
fetchTemplates();
|
fetchTemplates();
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error('Save failed:', error);
|
console.error('Save failed:', error);
|
||||||
showError(t('actionFailed'));
|
const msg = error?.message;
|
||||||
|
showError(msg && msg !== 'Request failed' ? msg : t('actionFailed'));
|
||||||
} finally {
|
} finally {
|
||||||
setIsSaving(false);
|
setIsSaving(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -610,6 +610,7 @@ export const AssessmentView: React.FC<AssessmentViewProps> = ({
|
|||||||
{currentQuestion.options.map((opt: string, i: number) => {
|
{currentQuestion.options.map((opt: string, i: number) => {
|
||||||
const letter = optionLabels[i];
|
const letter = optionLabels[i];
|
||||||
const isSelected = selectedChoice === letter;
|
const isSelected = selectedChoice === letter;
|
||||||
|
const displayText = opt.replace(/^[A-D][.)、]\s*/, '');
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={letter}
|
key={letter}
|
||||||
@@ -626,7 +627,7 @@ export const AssessmentView: React.FC<AssessmentViewProps> = ({
|
|||||||
<span className="inline-flex items-center justify-center w-7 h-7 rounded-xl text-xs font-black mr-3 shrink-0 border-2 border-current">
|
<span className="inline-flex items-center justify-center w-7 h-7 rounded-xl text-xs font-black mr-3 shrink-0 border-2 border-current">
|
||||||
{letter}
|
{letter}
|
||||||
</span>
|
</span>
|
||||||
{opt}
|
{displayText}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -853,16 +854,17 @@ export const AssessmentView: React.FC<AssessmentViewProps> = ({
|
|||||||
<p className="font-bold text-slate-800 text-sm leading-relaxed">{q.questionText}</p>
|
<p className="font-bold text-slate-800 text-sm leading-relaxed">{q.questionText}</p>
|
||||||
{isChoice && (
|
{isChoice && (
|
||||||
<div className="mt-2 flex flex-wrap gap-2 text-xs">
|
<div className="mt-2 flex flex-wrap gap-2 text-xs">
|
||||||
{q.options?.map((opt: string, oi: number) => {
|
{q.options?.map((opt: string, oi: number) => {
|
||||||
const letter = String.fromCharCode(65 + oi);
|
const letter = String.fromCharCode(65 + oi);
|
||||||
const isAnswer = letter === q.correctAnswer;
|
const isAnswer = letter === q.correctAnswer;
|
||||||
return (
|
const displayText = opt.replace(/^[A-D][.)、]\s*/, '');
|
||||||
<span key={oi} className={cn(
|
return (
|
||||||
"px-3 py-1 rounded-lg font-medium",
|
<span key={oi} className={cn(
|
||||||
isAnswer ? "bg-emerald-100 text-emerald-700 border border-emerald-200" : "bg-slate-50 text-slate-500"
|
"px-3 py-1 rounded-lg font-medium",
|
||||||
)}>
|
isAnswer ? "bg-emerald-100 text-emerald-700 border border-emerald-200" : "bg-slate-50 text-slate-500"
|
||||||
{letter}. {opt}
|
)}>
|
||||||
</span>
|
{letter}. {displayText}
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user