Commit dc6a2eaf authored by 霍传世's avatar 霍传世

添加批量脚本接口

1.批量导入面试者信息
2.批量申请面试码
3.检查面试码是否生成完成
4.控制台日志存储级别设置
5.字段属性调整 exam_connection_code->exam_connect_code
parent 31ce2db8
......@@ -76,15 +76,32 @@
<artifactId>cos_api</artifactId>
<version>5.6.97</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos-sts_api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
......
package com.yuda.hainafacetofaceai;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
......@@ -7,9 +9,11 @@ import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class HaiNaFaceToFaceAiApplication {
private static final Logger logger = LoggerFactory.getLogger(HaiNaFaceToFaceAiApplication.class);
public static void main(String[] args) {
SpringApplication.run(HaiNaFaceToFaceAiApplication.class, args);
logger.info("海纳面试启动成功");
}
}
......@@ -29,7 +29,7 @@ public class LoginInterceptor implements HandlerInterceptor {
JSONObject jsonObject = new JSONObject(value);
String zkzNum = jsonObject.get("zkzNum").toString();
String idCard = jsonObject.get("idCard").toString();
String examConnectionCode = jsonObject.get("examConnectionCode").toString();
String examConnectionCode = jsonObject.get("examConnectCode").toString();
log.info("准考证号:"+zkzNum+"_身份证号:"+idCard+"_参加面试编号:"+examConnectionCode+"_登入");
redisTemplate.opsForValue().set(key,value,60*60*2, TimeUnit.SECONDS);
return true;
......
......@@ -80,7 +80,7 @@ public class BusinessController {
@PostMapping("/candidateGetV2")
public ResponseEntity candidateGetV2(@RequestBody String responseBody){
try{
CandidateExam candidateExam = DBOperator.queryForObject("select * from candidate_exam where exam_connection_code = ? order by create_time asc limit 1",new Object[]{new JSONObject(responseBody).getString("examConnectCode")},new BeanPropertyRowMapper<>(CandidateExam.class));
CandidateExam candidateExam = DBOperator.queryForObject("select * from candidate_exam where exam_connect_code = ? order by create_time asc limit 1",new Object[]{new JSONObject(responseBody).getString("examConnectCode")},new BeanPropertyRowMapper<>(CandidateExam.class));
long timeStamp = candidateExam.getCreateTime().toInstant().getMillis()/1000;
JSONObject requestBody = new JSONObject(responseBody);
requestBody.put("fromTimeStamp",timeStamp);
......
......@@ -40,6 +40,7 @@ public class CallBackApiController {
jsonObject.put("message","回到数据解析出错");
return ResponseEntity.ok(jsonObject.toString());
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",0);
jsonObject.put("message","收到回调");
......
......@@ -23,7 +23,7 @@ public class CommitmentLetterController {
", status_commitment = 1 \n" +
"WHERE\n" +
"\tzkz_num = ? \n" +
"\tAND exam_connection_code = ?",new Object[]{url,zkzNum,examConnectionCode});
"\tAND exam_connect_code = ?",new Object[]{url,zkzNum,examConnectionCode});
log.info("准考证:"+zkzNum+"参加面试编号:"+examConnectionCode+"上传承诺书成功");
JSONObject responseBody = new JSONObject();
responseBody.put("code",200);
......
......@@ -28,7 +28,7 @@ public class FaceMatchController {
JSONObject object = new JSONObject(images);
String faceImage = object.getString("zjImage");
try{
DBOperator.update("update candidate_exam set exam_image_face = ? where zkz_num = ? and exam_connection_code = ?",new Object[]{faceImage,zkzNum,examConnectionCode});
DBOperator.update("update candidate_exam set exam_image_face = ? where zkz_num = ? and exam_connect_code = ?",new Object[]{faceImage,zkzNum,examConnectionCode});
log.info("准考证:"+zkzNum+"参加面试编号:"+examConnectionCode+"上传实时人脸照片成功");
JSONObject responseBody = new JSONObject();
responseBody.put("code",200);
......@@ -59,7 +59,7 @@ public class FaceMatchController {
responseBody.put("code",200);
if(result[0].equals("1")){
stringRedisTemplate.opsForValue().increment("face_success:" + examConnectionCode + "_" + idCard);
DBOperator.update("update candidate_exam set status_face = 1 where exam_connection_code = ? and zkz_num = ?",new Object[]{examConnectionCode,zkzNum});
DBOperator.update("update candidate_exam set status_face = 1 where exam_connect_code = ? and zkz_num = ?",new Object[]{examConnectionCode,zkzNum});
log.info("身份证:"+idCard+"参加面试编号:"+examConnectionCode+"人脸验证成功");
responseBody.put("message","检测成功");
responseBody.put("result",true);
......
......@@ -34,7 +34,7 @@ public class LoginController {
"\tb.NAME, \n" +
"\ta.zkz_num, \n" +
"\tb.id_card, \n" +
"\ta.exam_connection_code, \n" +
"\ta.exam_connect_code, \n" +
"\ta.candidate_connect_code \n" +
"FROM\n" +
"\tcandidate_exam a join \n" +
......@@ -50,7 +50,7 @@ public class LoginController {
responseData.put("message","登录成功");
return ResponseEntity.ok(responseData.toString());
}catch (EmptyResultDataAccessException e){
log.info("准考证号:"+candidate.getZkzNum()+"_身份证号:"+candidate.getIdCard()+"_参加面试编号:"+candidate.getExamConnectionCode()+"_查询结果=>无面试者记录");
log.info("准考证号:"+candidate.getZkzNum()+"_身份证号:"+candidate.getIdCard()+"_参加面试编号:"+candidate.getExamConnectCode()+"_查询结果=>无面试者记录");
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",500);
......
......@@ -18,6 +18,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
......@@ -73,7 +74,7 @@ public class ScriptInterfaceController {
return ResponseEntity.ok("");
}
@PostMapping("/{examConnectionCode}")
public ResponseEntity importCandidates(@PathVariable String examConnectionCode, @RequestParam(value = "file") MultipartFile file) {
public ResponseEntity importCandidates(@PathVariable String examConnectionCode,MultipartFile file) {
ExcelUtil<CandidateExam> excelUtil = new ExcelUtil<>();
List<CandidateExam> candidateExamList = null ;
try{
......@@ -83,7 +84,7 @@ public class ScriptInterfaceController {
JSONObject bodyResponse = new JSONObject();
bodyResponse.put("code",500);
bodyResponse.put("message","导入失败");
return ResponseEntity.ok(bodyResponse);
return ResponseEntity.ok(bodyResponse.toString());
}
if(candidateExamList!=null&&candidateExamList.size()>0){
boolean success = scriptInterfaceService.BatchInsert(candidateExamList,examConnectionCode);
......@@ -91,29 +92,31 @@ public class ScriptInterfaceController {
JSONObject bodyResponse = new JSONObject();
bodyResponse.put("code",500);
bodyResponse.put("message","导入失败");
return ResponseEntity.ok(bodyResponse);
return ResponseEntity.ok(bodyResponse.toString());
}
}
JSONObject bodyResponse = new JSONObject();
bodyResponse.put("code",200);
bodyResponse.put("message","导入成功");
return ResponseEntity.ok("");
return ResponseEntity.ok(bodyResponse.toString());
}
@PostMapping("/genCandidateConnectionCode")
public ResponseEntity genCandidateCode(@RequestParam("candidateConnectionCode")String candidateConnectionCode){
try{
List<CandidateExam> candidateExamList = DBOperator.queryForList("select\n" +
List<CandidateExam> candidateExamList = DBOperator.query("select\n" +
"a.phone, \n" +
"b.id_card, \n" +
"b.uuid,\n" +
"b.exam_connection_code\n" +
"b.name,\n" +
"a.exam_connect_code\n" +
"from \n" +
"candidate_exam a \n" +
"left join\n" +
"candidate b on a.id_card = b.id_card\n" +
"where\n" +
"a.exam_connection_code = ?\n" +
"a.exam_connect_code = ?\n" +
"and \n" +
"a.candidate_connect_code is not null",new Object[]{candidateConnectionCode},CandidateExam.class);
"a.candidate_connect_code is null",new Object[]{candidateConnectionCode},new BeanPropertyRowMapper<>(CandidateExam.class));
if(candidateExamList.size()!=0){
for (CandidateExam candidateExam : candidateExamList) {
scriptInterfaceService.sendRequestAndSaveDB(candidateExam);
......@@ -125,31 +128,57 @@ public class ScriptInterfaceController {
JSONObject requestData = new JSONObject();
requestData.put("code",200);
requestData.put("message","指令发送成功");
return ResponseEntity.ok(requestData);
return ResponseEntity.ok(requestData.toString());
}
@PostMapping("/genBatchJsonFile")
public ResponseEntity GenBatchJsonFile(@RequestBody String examConnectionCode){
List<CandidateExam> results = DBOperator.query("select * from candidate_exam where exam_connection_code = ? and result_back = 1",new Object[]{examConnectionCode},new BeanPropertyRowMapper<>(CandidateExam.class));
@GetMapping("/{examConnectCode}")
public ResponseEntity isCandidateCodeGenSuccess(@PathVariable String examConnectCode){
Integer remain = DBOperator.queryForObject("select count(1) from candidate_exam where exam_connect_code = ? and candidate_connect_code is null",new Object[]{examConnectCode},Integer.class);
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",200);
if(remain!=0){
Integer total = DBOperator.queryForObject("select count(1) from candidate_exam where exam_connect_code = ?",new Object[]{examConnectCode},Integer.class);
jsonObject.put("desc","not finish");
jsonObject.put("message","面试候选者链接码并未生成完毕,进度"+(total-remain)+"/"+total);
}else{
jsonObject.put("desc","finish");
jsonObject.put("message","面试候选者链接码生成完毕");
}
return ResponseEntity.ok(jsonObject.toString());
}
@GetMapping("/genBatchJsonFile")
@Async
public ResponseEntity GenBatchJsonFile(@RequestParam("examConnectCode")String examConnectionCode){
List<CandidateExam> results = DBOperator.query("select candidate_connect_code,exam_connect_code,interview_results from candidate_exam where exam_connect_code = ? and result_back = 1",new Object[]{examConnectionCode},new BeanPropertyRowMapper<>(CandidateExam.class));
if(!results.isEmpty()){
int success = 0;
int fail = 0;
for (int i = 0; i < results.size(); i++) {
String jsonString = results.get(i).getInterviewResults();
try {
// 解析字段中的 JSON 字符串
JSONObject jsonObject = new JSONObject(jsonString);
String candidateConnectCode = jsonObject.getString("candidate_connect_code");
String candidateConnectCode = jsonObject.getString("candidateConnectCode");
// 生成一个单独的 JSON 文件,每条记录一个文件
File outputFile = new File("D:/jsonResults/"+examConnectionCode+"/"+candidateConnectCode+ ".json");
if(!outputFile.exists()){
outputFile.getParentFile().mkdirs();
}
// 使用 FileWriter 将 JSONObject 写入文件
try (FileWriter fileWriter = new FileWriter(outputFile)) {
fileWriter.write(jsonObject.toString(4)); // 美化输出,4为缩进空格数
}
log.info("生成进度->成功"+(++success)+"/"+results.size());
} catch (IOException e) {
log.info("生成进度->失败"+(++fail)+"/"+results.size());
e.printStackTrace();
}
}
}
return ResponseEntity.ok("");
return ResponseEntity.ok(new JSONObject(new HashMap<String,Object>(){{
put("code",200);
put("message","指令发送成功");
}}).toString());
}
}
......@@ -16,7 +16,7 @@ public class CandidateExam {
@ExcelColumn(headerName = "手机号")
private String phone;
private String candidateConnectCode;
private String examConnectionCode;
private String examConnectCode;
private String imageCommitment;
private String examImageFace;
private Integer statusFace;
......
......@@ -7,7 +7,6 @@ import com.yuda.hainafacetofaceai.util.AppUtil;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
......@@ -49,9 +48,12 @@ public class ScriptInterfaceServiceImpl implements ScriptInterfaceService {
}
List<String> finalIdCards = idCards;
List<CandidateExam> paperExamStudents = candidateExamList.stream().filter(x-> finalIdCards.contains(x.getIdCard())).collect(Collectors.toList());
List<String> alreadyExistStudentIdCards = DBOperator.queryForList("select id_card from candidate_exam where exam_connection_code = ?",new Object[]{examConnectionCode},String.class);
List<String> alreadyExistStudentIdCards = DBOperator.queryForList("select id_card from candidate_exam where exam_connect_code = ?",new Object[]{examConnectionCode},String.class);
if(!alreadyExistStudentIdCards.isEmpty()){
paperExamStudents = paperExamStudents.stream().filter(x->!alreadyExistStudentIdCards.contains(x.getIdCard())).collect(Collectors.toList());
for (CandidateExam paperExamStudent : paperExamStudents) {
paperExamStudent.setExamConnectCode(examConnectionCode);
}
}
if(!paperExamStudents.isEmpty()){
int chunkSize = 1000; // 每批插入1000条记录
......@@ -62,7 +64,7 @@ public class ScriptInterfaceServiceImpl implements ScriptInterfaceService {
try{
batchInsert(chunk);
}catch (Exception e){
log.info("候选者批量插入失败:(已插入)"+i+"/"+"(全部)"+total);
log.info("候选者批量插入失败:(已插入)"+(i>total?total:i)+"/"+"(全部)"+total);
return false;
}
}
......@@ -77,6 +79,8 @@ public class ScriptInterfaceServiceImpl implements ScriptInterfaceService {
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type","application/json");
JSONObject requestBodyObject = new JSONObject(candidateExam);
requestBodyObject.put("outId",candidateExam.getUuid());
requestBodyObject.put("showName",candidateExam.getName());
HttpEntity<String> entity = new HttpEntity<>(requestBodyObject.toString(),headers);
ResponseEntity<String> response = restTemplate.exchange(
appUtil.ApiUrlGen(AppThirdPartUrls.candidateCreate),
......@@ -86,26 +90,26 @@ public class ScriptInterfaceServiceImpl implements ScriptInterfaceService {
);
JSONObject body = new JSONObject(response.getBody());
if(body.get("code").equals(0)&&body.get("message").equals("ok")){
JSONObject data = new JSONObject(body.getString("data"));
DBOperator.update("update candidate_exam set candidate_connect_code = ? where id_card = ? and exam_connection_code = ?",new Object[]{data.get("candidateConnectCode").toString(),candidateExam.getIdCard(),candidateExam.getExamConnectionCode()});
log.info("面试编号:"+candidateExam.getExamConnectionCode()+"候选者:"+candidateExam.getIdCard()+"面试码申请成功");
JSONObject data = (JSONObject)body.get("data");
DBOperator.update("update candidate_exam set candidate_connect_code = ? where id_card = ? and exam_connect_code = ?",new Object[]{data.get("candidateConnectCode").toString(),candidateExam.getIdCard(),candidateExam.getExamConnectCode()});
log.info("面试编号:"+candidateExam.getExamConnectCode()+"候选者:"+candidateExam.getIdCard()+"面试码申请成功");
}else{
log.info("面试编号:"+candidateExam.getExamConnectionCode()+"候选者:"+candidateExam.getIdCard()+"面试码申请失败,失败原因"+body.getString("message"));
log.info("面试编号:"+candidateExam.getExamConnectCode()+"候选者:"+candidateExam.getIdCard()+"面试码申请失败,失败原因"+body.getString("message"));
}
}catch (Exception e){
e.printStackTrace();
log.info("面试编号:"+candidateExam.getExamConnectionCode()+"候选者:"+candidateExam.getIdCard()+"请求发送失败");
log.info("面试编号:"+candidateExam.getExamConnectCode()+"候选者:"+candidateExam.getIdCard()+"请求发送失败");
}
}
@Transactional // 开启事务,确保操作的一致性
public void batchInsert(List<CandidateExam> candidateExamList) {
// 批量插入 SQL 语句
String sql = "INSERT INTO candidate_exam (id_card,zkz_num,exam_connection_code) VALUES (?,?,?)";
String sql = "INSERT INTO candidate_exam (id_card,zkz_num,exam_connect_code,phone) VALUES (?,?,?,?)";
// 将 idCards 转换为批量操作所需的参数数组
List<Object[]> batchArgs = new ArrayList<>();
for (CandidateExam candidateExam : candidateExamList) {
batchArgs.add(new Object[]{candidateExam.getIdCard(),candidateExam.getZkzNum(),candidateExam.getExamConnectionCode()});
batchArgs.add(new Object[]{candidateExam.getIdCard(),candidateExam.getZkzNum(),candidateExam.getExamConnectCode(),candidateExam.getPhone()});
}
// 使用 batchUpdate 方法执行批量插入
DBOperator.batchUpdate(sql,batchArgs);
......@@ -129,10 +133,8 @@ public class ScriptInterfaceServiceImpl implements ScriptInterfaceService {
}
private List<String> queryDatabaseForIdCards(List<String> idCards) {
List<String> existingIdCards = new ArrayList<>();
String query = "SELECT idCard FROM users WHERE idCard IN (?)";
// 使用参数化查询防止 SQL 注入
String ids = String.join(",", Collections.nCopies(idCards.size(), "?"));
existingIdCards = DBOperator.queryForList(query,new Object[]{ids},String.class);
String query = "SELECT id_card FROM candidate WHERE id_card IN (" + String.join(",", Collections.nCopies(idCards.size(), "?")) + ")";
existingIdCards = DBOperator.queryForList(query, idCards.toArray(), String.class);
return existingIdCards;
}
public JSONObject senGenCandidateConnectionCode(CandidateExam candidateExam) {
......
......@@ -7,6 +7,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
......@@ -65,7 +66,7 @@ public class ExcelUtil<T> {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
return String.valueOf(cell.getNumericCellValue());
return new DataFormatter().formatCellValue(cell);
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
default:
......
......@@ -19,3 +19,8 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.idle-timeout=30000
# Spring Boot ??????
logging.level.root=INFO
logging.file.name=logs/application.log
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %level - %logger{36} - %msg%n
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment