@ -73,7 +73,7 @@ public class PlatformQuestionBankService {
public Map < String , Object > save ( JwtUser user , Long id , Map < String , Object > payload ) {
public Map < String , Object > save ( JwtUser user , Long id , Map < String , Object > payload ) {
platformAdminService . requirePlatformAdmin ( user ) ;
platformAdminService . requirePlatformAdmin ( user ) ;
ValidQuestion q = validate ( payload ) ;
ValidQuestion q = validate ( payload ) ;
requireTask ( q . taskKey ) ;
if ( StringUtils . isNotBlank ( q . taskKey ) ) requireTask ( q . taskKey ) ;
if ( id = = null ) {
if ( id = = null ) {
jdbc . update ( "insert into exam_question(school_id,teacher_id,source_type,task_key,question_type,stem,options_json,answer_json,answer_analysis,attachment_name,attachment_url) values(?,?,?,?,?,?,?,?,?,?,?)" ,
jdbc . update ( "insert into exam_question(school_id,teacher_id,source_type,task_key,question_type,stem,options_json,answer_json,answer_analysis,attachment_name,attachment_url) values(?,?,?,?,?,?,?,?,?,?,?)" ,
PLATFORM , PLATFORM , PLATFORM , q . taskKey , q . type , q . stem , json ( q . options ) , json ( q . answer ) , q . analysis , text ( payload . get ( "attachmentName" ) ) , text ( payload . get ( "attachmentUrl" ) ) ) ;
PLATFORM , PLATFORM , PLATFORM , q . taskKey , q . type , q . stem , json ( q . options ) , json ( q . answer ) , q . analysis , text ( payload . get ( "attachmentName" ) ) , text ( payload . get ( "attachmentUrl" ) ) ) ;
@ -93,8 +93,7 @@ public class PlatformQuestionBankService {
public Map < String , Object > aiPreview ( JwtUser user , Map < String , Object > request ) {
public Map < String , Object > aiPreview ( JwtUser user , Map < String , Object > request ) {
platformAdminService . requirePlatformAdmin ( user ) ;
platformAdminService . requirePlatformAdmin ( user ) ;
String taskKey = required ( request , "taskKey" , "请选择归属项目" ) ;
String taskKey = text ( request . get ( "taskKey" ) ) . trim ( ) ;
requireTask ( taskKey ) ;
String type = required ( request , "type" , "请选择题型" ) ; validateType ( type ) ;
String type = required ( request , "type" , "请选择题型" ) ; validateType ( type ) ;
int count ;
int count ;
try { count = Integer . parseInt ( text ( request . get ( "count" ) ) ) ; } catch ( Exception e ) { throw new IllegalArgumentException ( "题目数量必须是数字" ) ; }
try { count = Integer . parseInt ( text ( request . get ( "count" ) ) ) ; } catch ( Exception e ) { throw new IllegalArgumentException ( "题目数量必须是数字" ) ; }
@ -126,7 +125,7 @@ public class PlatformQuestionBankService {
@Transactional
@Transactional
public List < Map < String , Object > > importExcel ( JwtUser user , MultipartFile file , String taskKey ) {
public List < Map < String , Object > > importExcel ( JwtUser user , MultipartFile file , String taskKey ) {
platformAdminService . requirePlatformAdmin ( user ) ; requireTask ( taskKey ) ;
platformAdminService . requirePlatformAdmin ( user ) ; if ( StringUtils . isNotBlank ( taskKey ) ) requireTask ( taskKey ) ;
if ( file = = null | | file . isEmpty ( ) ) throw new IllegalArgumentException ( "请选择Word或Excel文件" ) ;
if ( file = = null | | file . isEmpty ( ) ) throw new IllegalArgumentException ( "请选择Word或Excel文件" ) ;
String name = StringUtils . defaultString ( file . getOriginalFilename ( ) ) . toLowerCase ( Locale . ROOT ) ;
String name = StringUtils . defaultString ( file . getOriginalFilename ( ) ) . toLowerCase ( Locale . ROOT ) ;
if ( name . endsWith ( ".docx" ) ) return importWord ( user , file , taskKey ) ;
if ( name . endsWith ( ".docx" ) ) return importWord ( user , file , taskKey ) ;
@ -158,7 +157,7 @@ public class PlatformQuestionBankService {
} catch ( IllegalArgumentException e ) { throw e ; } catch ( Exception e ) { throw new IllegalArgumentException ( "Word导入失败, 请检查模板" ) ; }
} catch ( IllegalArgumentException e ) { throw e ; } catch ( Exception e ) { throw new IllegalArgumentException ( "Word导入失败, 请检查模板" ) ; }
}
}
private ValidQuestion validate ( Map < String , Object > p ) { String type = required ( p , "type" , "请选择题型" ) ; validateType ( type ) ; String stem = required ( p , "stem" , "题干不能为空" ) ; if ( StringUtils . isBlank ( plain ( stem ) ) ) throw new IllegalArgumentException ( "题干不能为空" ) ; List < Map < String , Object > > options = objectMapper . convertValue ( p . getOrDefault ( "options" , Collections . emptyList ( ) ) , new TypeReference < List < Map < String , Object > > > ( ) { } ) ; Object answer = p . get ( "answer" ) ; if ( type . equals ( "SINGLE" ) | | type . equals ( "MULTIPLE" ) ) { if ( options . size ( ) < 2 ) throw new IllegalArgumentException ( "选择题至少需要两个选项" ) ; Set < String > labels = new LinkedHashSet < > ( ) ; List < Map < String , Object > > normalized = new ArrayList < > ( ) ; for ( Map < String , Object > o : options ) { String label = text ( o . get ( "label" ) ) . trim ( ) . toUpperCase ( ) ; String content = text ( o . get ( "content" ) ) . trim ( ) ; if ( ! label . matches ( "[A-H]" ) | | StringUtils . isBlank ( plain ( content ) ) | | ! labels . add ( label ) ) throw new IllegalArgumentException ( "选项格式不正确" ) ; normalized . add ( map ( "label" , label , "content" , content ) ) ; } List < String > answers = list ( answer ) ; if ( type . equals ( "SINGLE" ) & & answers . size ( ) ! = 1 ) throw new IllegalArgumentException ( "单选题只能设置一个正确答案" ) ; if ( answers . isEmpty ( ) | | ! labels . containsAll ( answers ) ) throw new IllegalArgumentException ( "正确答案必须来自题目选项" ) ; return new ValidQuestion ( type , stem , normalized , answers , text ( p . get ( "analysis" ) ) , required( p , "taskKey" , "请选择归属项目" ) ) ; } if ( type . equals ( "TRUE_FALSE" ) ) { String v = text ( answer ) ; if ( ! "true" . equalsIgnoreCase ( v ) & & ! "false" . equalsIgnoreCase ( v ) & & ! "正确" . equals ( v ) & & ! "错误" . equals ( v ) ) throw new IllegalArgumentException ( "判断题答案格式不正确" ) ; return new ValidQuestion ( type , stem , Collections . emptyList ( ) , "正确" . equals ( v ) | | "true" . equalsIgnoreCase ( v ) , text ( p . get ( "analysis" ) ) , required( p , "taskKey" , "请选择归属项目" ) ) ; } if ( StringUtils . isBlank ( plain ( text ( answer ) ) ) ) throw new IllegalArgumentException ( "参考答案不能为空" ) ; return new ValidQuestion ( type , stem , Collections . emptyList ( ) , text ( answer ) , text ( p . get ( "analysis" ) ) , required( p , "taskKey" , "请选择归属项目" ) ) ; }
private ValidQuestion validate ( Map < String , Object > p ) { String type = required ( p , "type" , "请选择题型" ) ; validateType ( type ) ; String stem = required ( p , "stem" , "题干不能为空" ) ; if ( StringUtils . isBlank ( plain ( stem ) ) ) throw new IllegalArgumentException ( "题干不能为空" ) ; List < Map < String , Object > > options = objectMapper . convertValue ( p . getOrDefault ( "options" , Collections . emptyList ( ) ) , new TypeReference < List < Map < String , Object > > > ( ) { } ) ; Object answer = p . get ( "answer" ) ; if ( type . equals ( "SINGLE" ) | | type . equals ( "MULTIPLE" ) ) { if ( options . size ( ) < 2 ) throw new IllegalArgumentException ( "选择题至少需要两个选项" ) ; Set < String > labels = new LinkedHashSet < > ( ) ; List < Map < String , Object > > normalized = new ArrayList < > ( ) ; for ( Map < String , Object > o : options ) { String label = text ( o . get ( "label" ) ) . trim ( ) . toUpperCase ( ) ; String content = text ( o . get ( "content" ) ) . trim ( ) ; if ( ! label . matches ( "[A-H]" ) | | StringUtils . isBlank ( plain ( content ) ) | | ! labels . add ( label ) ) throw new IllegalArgumentException ( "选项格式不正确" ) ; normalized . add ( map ( "label" , label , "content" , content ) ) ; } List < String > answers = list ( answer ) ; if ( type . equals ( "SINGLE" ) & & answers . size ( ) ! = 1 ) throw new IllegalArgumentException ( "单选题只能设置一个正确答案" ) ; if ( answers . isEmpty ( ) | | ! labels . containsAll ( answers ) ) throw new IllegalArgumentException ( "正确答案必须来自题目选项" ) ; return new ValidQuestion ( type , stem , normalized , answers , text ( p . get ( "analysis" ) ) , text( p . get ( "taskKey" ) ) . trim ( ) ) ; } if ( type . equals ( "TRUE_FALSE" ) ) { String v = text ( answer ) ; if ( ! "true" . equalsIgnoreCase ( v ) & & ! "false" . equalsIgnoreCase ( v ) & & ! "正确" . equals ( v ) & & ! "错误" . equals ( v ) ) throw new IllegalArgumentException ( "判断题答案格式不正确" ) ; return new ValidQuestion ( type , stem , Collections . emptyList ( ) , "正确" . equals ( v ) | | "true" . equalsIgnoreCase ( v ) , text ( p . get ( "analysis" ) ) , text( p . get ( "taskKey" ) ) . trim ( ) ) ; } if ( StringUtils . isBlank ( plain ( text ( answer ) ) ) ) throw new IllegalArgumentException ( "参考答案不能为空" ) ; return new ValidQuestion ( type , stem , Collections . emptyList ( ) , text ( answer ) , text ( p . get ( "analysis" ) ) , text( p . get ( "taskKey" ) ) . trim ( ) ) ; }
private Map < String , Object > normalize ( Map < String , Object > p ) { ValidQuestion q = validate ( p ) ; return map ( "type" , q . type , "stem" , q . stem , "options" , q . options , "answer" , q . answer , "analysis" , q . analysis , "taskKey" , q . taskKey ) ; }
private Map < String , Object > normalize ( Map < String , Object > p ) { ValidQuestion q = validate ( p ) ; return map ( "type" , q . type , "stem" , q . stem , "options" , q . options , "answer" , q . answer , "analysis" , q . analysis , "taskKey" , q . taskKey ) ; }
private void requireTask ( String key ) { if ( jdbc . queryForObject ( "select count(*) from training_task where task_key=?" , Integer . class , key ) = = 0 ) throw new IllegalArgumentException ( "归属项目不存在" ) ; }
private void requireTask ( String key ) { if ( jdbc . queryForObject ( "select count(*) from training_task where task_key=?" , Integer . class , key ) = = 0 ) throw new IllegalArgumentException ( "归属项目不存在" ) ; }
private Map < String , Object > row ( java . sql . ResultSet rs ) throws java . sql . SQLException { return map ( "id" , rs . getLong ( "id" ) , "type" , rs . getString ( "question_type" ) , "stem" , rs . getString ( "stem" ) , "options" , parse ( rs . getString ( "options_json" ) ) , "answer" , parse ( rs . getString ( "answer_json" ) ) , "analysis" , rs . getString ( "answer_analysis" ) , "attachmentName" , rs . getString ( "attachment_name" ) , "attachmentUrl" , rs . getString ( "attachment_url" ) , "sourceType" , rs . getString ( "source_type" ) , "taskKey" , rs . getString ( "task_key" ) , "projectName" , rs . getString ( "project_name" ) , "taskName" , rs . getString ( "task_name" ) , "updatedAt" , rs . getTimestamp ( "update_time" ) ) ; }
private Map < String , Object > row ( java . sql . ResultSet rs ) throws java . sql . SQLException { return map ( "id" , rs . getLong ( "id" ) , "type" , rs . getString ( "question_type" ) , "stem" , rs . getString ( "stem" ) , "options" , parse ( rs . getString ( "options_json" ) ) , "answer" , parse ( rs . getString ( "answer_json" ) ) , "analysis" , rs . getString ( "answer_analysis" ) , "attachmentName" , rs . getString ( "attachment_name" ) , "attachmentUrl" , rs . getString ( "attachment_url" ) , "sourceType" , rs . getString ( "source_type" ) , "taskKey" , rs . getString ( "task_key" ) , "projectName" , rs . getString ( "project_name" ) , "taskName" , rs . getString ( "task_name" ) , "updatedAt" , rs . getTimestamp ( "update_time" ) ) ; }