From 61825be40bf894e61db47fc54df2a44911dafd2f Mon Sep 17 00:00:00 2001 From: cs <2268380485@qq.com> Date: Tue, 29 Apr 2025 18:32:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E:=E6=B7=BB=E5=8A=A0service,ut?= =?UTF-8?q?il=E5=8C=85=E5=92=8C=E4=B8=BB=E7=B1=BB(=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E7=B1=BB)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/hfbu/recruit/RecruitApplication.java | 17 + .../recruit/service/AdminServiceImpl.java | 54 + .../recruit/service/ThingServiceImpl.java | 251 ++ .../hfbu/recruit/service/UserServiceImpl.java | 356 ++ .../hfbu/recruit/service/api/ApiService.java | 29 + .../service/api/MockApiServiceImpl.java | 59 + .../service/api/RealApiServiceImpl.java | 140 + .../recruit/util/AdmissionTicketCreater.java | 147 + .../edu/hfbu/recruit/util/ExcelExporter.java | 173 + .../java/edu/hfbu/recruit/util/ExcelUtil.java | 1174 ++++++ .../edu/hfbu/recruit/util/IdNumChecker.java | 3270 +++++++++++++++++ .../java/edu/hfbu/recruit/util/JwtUtil.java | 92 + .../edu/hfbu/recruit/util/file/FilePatch.java | 132 + .../hfbu/recruit/util/file/FilePathModel.java | 28 + .../util/file/UserQualificationsCreator.java | 513 +++ 15 files changed, 6435 insertions(+) create mode 100644 src/main/java/edu/hfbu/recruit/RecruitApplication.java create mode 100644 src/main/java/edu/hfbu/recruit/service/AdminServiceImpl.java create mode 100644 src/main/java/edu/hfbu/recruit/service/ThingServiceImpl.java create mode 100644 src/main/java/edu/hfbu/recruit/service/UserServiceImpl.java create mode 100644 src/main/java/edu/hfbu/recruit/service/api/ApiService.java create mode 100644 src/main/java/edu/hfbu/recruit/service/api/MockApiServiceImpl.java create mode 100644 src/main/java/edu/hfbu/recruit/service/api/RealApiServiceImpl.java create mode 100644 src/main/java/edu/hfbu/recruit/util/AdmissionTicketCreater.java create mode 100644 src/main/java/edu/hfbu/recruit/util/ExcelExporter.java create mode 100644 src/main/java/edu/hfbu/recruit/util/ExcelUtil.java create mode 100644 src/main/java/edu/hfbu/recruit/util/IdNumChecker.java create mode 100644 src/main/java/edu/hfbu/recruit/util/JwtUtil.java create mode 100644 src/main/java/edu/hfbu/recruit/util/file/FilePatch.java create mode 100644 src/main/java/edu/hfbu/recruit/util/file/FilePathModel.java create mode 100644 src/main/java/edu/hfbu/recruit/util/file/UserQualificationsCreator.java diff --git a/src/main/java/edu/hfbu/recruit/RecruitApplication.java b/src/main/java/edu/hfbu/recruit/RecruitApplication.java new file mode 100644 index 0000000..a4c5e60 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/RecruitApplication.java @@ -0,0 +1,17 @@ +package edu.ahbvc.recruit; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author c215 + */ +@SpringBootApplication +@MapperScan(basePackages = "edu.ahbvc.recruit.mapper") +public class RecruitApplication { + + public static void main(String[] args) { + SpringApplication.run(RecruitApplication.class, args); + } +} diff --git a/src/main/java/edu/hfbu/recruit/service/AdminServiceImpl.java b/src/main/java/edu/hfbu/recruit/service/AdminServiceImpl.java new file mode 100644 index 0000000..1e71486 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/service/AdminServiceImpl.java @@ -0,0 +1,54 @@ +package edu.ahbvc.recruit.service; + +import java.util.List; + +import edu.ahbvc.recruit.mapper.AdminInter; +import org.springframework.stereotype.Service; + +import edu.ahbvc.recruit.model.Admin; + +/** + * @author c215 + */ +@Service +public class AdminServiceImpl { + + private final AdminInter mapper; + + public AdminServiceImpl(AdminInter mapper) { + this.mapper = mapper; + } + + public Admin getOne(int id) { + return mapper.getOne(id); + } + + public String isAdmin(String phone) { + return mapper.isAdmin(phone); + } + + public Integer getAdminsNum(String name,String phone) { + return mapper.getAdminsNum(name, phone); + } + + public Admin login(String num, String pwd) { + return mapper.login(num, pwd); + } + + public List getAdmins(int offset, int size, String name, String phone) { + return mapper.getAdmins(offset, size, name, phone); + } + + public int addAdmin(Admin admin) { + return mapper.addAdmin(admin); + } + + public int delAdmin(int id) { + return mapper.delAdmin(id); + } + + public int updateAdmin(Admin ad) { + return mapper.updateAdmin(ad); + } + +} diff --git a/src/main/java/edu/hfbu/recruit/service/ThingServiceImpl.java b/src/main/java/edu/hfbu/recruit/service/ThingServiceImpl.java new file mode 100644 index 0000000..bd3c41f --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/service/ThingServiceImpl.java @@ -0,0 +1,251 @@ +package edu.ahbvc.recruit.service; + +import edu.ahbvc.recruit.mapper.ThingInter; +import edu.ahbvc.recruit.model.Batch; +import edu.ahbvc.recruit.model.Position; +import edu.ahbvc.recruit.model.Thing; +import edu.ahbvc.recruit.model.ThingWithUser; +import edu.ahbvc.recruit.model.export.Excel; +import edu.ahbvc.recruit.model.export.Ticket; +import edu.ahbvc.recruit.util.AdmissionTicketCreater; +import edu.ahbvc.recruit.util.ExcelExporter; +import edu.ahbvc.recruit.util.file.FilePatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author c215 + */ +@Service +public class ThingServiceImpl { + + private static final Logger log = LoggerFactory.getLogger(ThingServiceImpl.class); + private final ThingInter mapper; + + @Autowired + public ThingServiceImpl(ThingInter mapper) { + this.mapper = mapper; + } + + + + public List getThings(List id) { + return mapper.getThingsById(id); + } + + public List getThings(int currentPage, int size, List jobTitles, + List batch, List status, String name) { + List list = mapper.getThings(currentPage, size, jobTitles, batch, status, name); + if(!list.isEmpty()) { + System.out.println(list.get(list.size()-1).getTime()); + } + return list; + } + + public List getAuditThings(int currentPage, int size, List jobTitles, + List batch) { + return mapper.getAuditThings(currentPage, size, jobTitles, batch); + } + + public Integer getThingsNum(List jobTitles, List batch, List status, String name) { + return mapper.getThingsNum(jobTitles, batch, status, name); + } + + public int getUnsettledThingsNum() { + return mapper.getUnsettledThingsNum(); + } + + + public List getBatchOption() { + return mapper.getBatchOption(); + } + + public Batch getBatch(int id) { + return mapper.getBatch(id); + } + + public int updateBatch(Batch batch) { + return mapper.updateBatch(batch); + } + + public int switchBatchOpen(int id) { + mapper.updateBatchClose(); + return mapper.updateBatchOpen(id); + } + + public int addBatch(Batch batch) { + return mapper.addBatch(batch); + } + + public int delBatch(int id) { + return mapper.delBatch(id); + } + + public List getBatches(int currentPage, int size, String key, Integer state) { + return mapper.getBatches(currentPage, size, key, state); + } + + public Batch getCurrentBatches() { + return mapper.getCurrentBatch(); + } + + public List getOpenBatches() { + return mapper.getBatches(0, Integer.MAX_VALUE, null, 1); + } + + public int getBatchesNum(String key, Integer state) { + return mapper.getBatchesNum(key, state); + } + + public List getPositionOption() { + return mapper.getPositionOption(); + } + + public List getPositions(int currentPage, int size) { + return mapper.getPositions(currentPage, size); + } + + public int getPositionsNum() { + return mapper.getPositionsNum(); + } + + public List getSomePosition(int batchId, int offset, int size) { + return mapper.getSomePosition(batchId, offset, size); + } + + public Position getOnePosition(int id) { + return mapper.getOnePosition(id); + } + + public int addPosition(Position p) { + return mapper.addPosition(p); + } + + public int delPosition(int id) { + return mapper.delPosition(id); + } + + public int delPositions(List id) { + int i; + try { + i = mapper.delPositions(id); + } catch (DataIntegrityViolationException e) { + // 记录异常信息 + log.error(e.getMessage()); + // 返回一个错误标志 + return -1; + } + return i; + } + + public int updatePosition(Position p) { + return mapper.updatePosition(p); + } + + public List getthingForuser(int userid, int batch) { + return mapper.getthingForuser(userid, batch); + } + + public int refuseThing(int thingid, int status, String qualificationResult) { + return mapper.refuseThing(thingid, status, qualificationResult); + } + + public int updateThingStatus(int thingid, int status) { + return mapper.updateThingStatus(thingid, status); + } + + public int updateThingInfo(int thingid, String awardsAndPunishments, String note, String qualificationResult) { + return mapper.updateThingInfo(thingid, awardsAndPunishments, note, qualificationResult); + } + + + public int updateThingInfo(int thingid, String qualificationResult) { + return mapper.updateThingQualification(thingid, qualificationResult); + } + + public ThingWithUser getOneThing(int thingid) { + return mapper.getOneThing(thingid); + } + + public List getThingAboutUser(int userid) { + return mapper.getThingAboutUser(userid); + } + + public List getRecruits(int currentPage, int size, List jobTitles, List batch) { + return mapper.getRecruits(currentPage, size, jobTitles, batch); + } + + public int getRecruitNum(List jobTitles, List batch) { + return mapper.getRecruitNum(jobTitles, batch); + } + + public int addRecruit(Integer batchid, Integer positionid) { + return mapper.addRecruit(batchid, positionid); + } + + public int updateRecruit(Integer id, Integer batchid, Integer positionid) { + return mapper.updateRecruit(id, batchid, positionid); + } + + public int deleteRecruit(int id) { + try { + return mapper.deleteRecruit(id); + } catch (DataIntegrityViolationException e) { + // 捕获外键约束违反异常 + log.error(e.getMessage()); + // 返回一个错误标志 + return -1; + } + } + + public String outPutExcel() { + String saveExcelFilePath = FilePatch.SaveExcelFilePath; + ArrayList printData = mapper.getPrintData(); + int excelFile = ExcelExporter.getExcelFile(saveExcelFilePath); + + int excel = ExcelExporter.exportToExcel(printData,saveExcelFilePath); + if(excel!=0) { + return null; + } + + return saveExcelFilePath + "招聘总表.xlsx"; + } + + public String previewTicket(Integer id, Integer recruitid) { + Ticket ticketData = mapper.getTicketData(recruitid, id); + return AdmissionTicketCreater.generateUserDocument(ticketData); + } + + public int conformPrintTicket(Integer thingid, Integer recruitid) { + int ticketNum = mapper.getTicketNum(recruitid); + int printedTicket = mapper.isPrintedTicket(thingid); + int ticketData; + if(printedTicket==0) +// 如果是没有打印过准考证的,就去当前岗位中的最大值加一 + { + ticketData = mapper.setTicketPrinted(ticketNum+1, thingid); + } else +// 否则就使用原来的准考证序号 + { + ticketData = mapper.setTicketPrinted(printedTicket, thingid); + } + return ticketData; + } + + + public int getOldTicketNum(Integer thingid, Integer recruitid) { + return mapper.isPrintedTicket(thingid); + } + + public boolean isPrintedTicket(Integer thingid) { + int ticketData = mapper.isPrintedTicket(thingid); + return ticketData!=0; + } + +} diff --git a/src/main/java/edu/hfbu/recruit/service/UserServiceImpl.java b/src/main/java/edu/hfbu/recruit/service/UserServiceImpl.java new file mode 100644 index 0000000..d2fd764 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/service/UserServiceImpl.java @@ -0,0 +1,356 @@ +package edu.ahbvc.recruit.service; + +import ch.qos.logback.classic.Logger; +import edu.ahbvc.recruit.mapper.UserInter; +import edu.ahbvc.recruit.model.ThingWithUser; +import edu.ahbvc.recruit.model.User; +import edu.ahbvc.recruit.model.resume.*; +import edu.ahbvc.recruit.util.file.FilePatch; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * @author c215 + */ +@Service +public class UserServiceImpl { + + private static final org.slf4j.Logger log = LoggerFactory.getLogger(UserServiceImpl.class); + private final UserInter mapper; + private boolean isDev; + + @Autowired + public UserServiceImpl(UserInter mapper) { + this.mapper = mapper; + } + + public User getOne(int id) { + return mapper.getOne(id); + } + + public UserInfo getOneInfo(int id) { + return mapper.getOneInfo(id); + } + + public List getUsers(int offset, int size, String name, String tel, String idNum, Integer degree) { + return mapper.getUsers(offset, size, name, tel, idNum); + } + + public int getUsersNum(String name, String tel, String idNum, Integer degree) { + return mapper.getUsersNum(name, tel, idNum, degree); + } + + public int getUsersNum() { + return mapper.getUsersNum(null, null, null, null); + } + + public User login(String account, String pwd) { + return mapper.login(account, pwd); + + } + + /** + * @param phone 注册手机号 + * @param pwd 注册密码 + * @return 如果新的信信息插入数据库成功,返回newUser,否则返回空 + * + */ + public User registerByPhone(String phone, String pwd) { + int i = mapper.registerByPhone(phone, pwd); + if (i == 1) { + return getNewUser(); + } + return null; + } + + public int abandon(int userid, int thingId) { + return mapper.abandon(thingId, userid); + } + + public int applyJob(int userid, int recruitId) { + int thingExist = mapper.thingExist(userid, recruitId); + if (thingExist == 1) { + return 2; + } + return mapper.applyJob(userid, recruitId); + } + + public int applyJob2(int userid, int recruitId, String awardsAndPunishments, String note) { + int thingExist = mapper.thingExist(userid, recruitId); + if (thingExist == 1) { + return 2; + } + return mapper.applyJob2(userid, recruitId, awardsAndPunishments, note); + } + + public int reTryJob(int userid, int thingId) { + int thingExist = mapper.thingExist2(thingId); + System.out.println(thingExist + "thingExist"); + if (thingExist == 1) { + return mapper.reTryJob(thingId); + } + return thingExist; + } + + public List getThingUsers(int thingId) { + return mapper.getThingUsers(thingId); + } + + /** + * @param idNum 身份证号码 + * @return 查询数据库中该身份证号的个数,一般为0或1 + */ + public int exists(String idNum) { + return mapper.exists(idNum); + } + + /** + * @param userId 用户id + * @return boolean:用户是否有正在进行的投递 + */ + public boolean alreadyRecruit(String userId) { + int i = mapper.alreadyRecruit(userId); + return i != 0; + } + + public int existsByPhone(String phone) { + return mapper.existsByPhone(phone); + } + + public User getNewUser() { + return mapper.getNewUser(); + } + + public int addUser(User u) { + return mapper.addUser(u); + } + + public int delUser(int id) { + try { + return mapper.delUser(id); + } catch (DataIntegrityViolationException e) { + // 捕获外键约束违反异常 + log.error(e.getMessage()); + // 返回一个错误标志 + return -1; + } + } + + public int updateUserName(User user) { + return mapper.updateUserName(user); + } + + public int updateUserPwd(int id, String pwd) { + return mapper.updateUserPwd(id, pwd); + } + + public int updateUserPwdByOld(int id, String oldPwd, String pwd) { + return mapper.updateUserPwdByOld(id, pwd, oldPwd); + } + + public int updateUser2(User user) { + return mapper.updateUser2(user); + } + + public int updateUser(UserInfo user) { + return mapper.updateUser(user); + } + + public int updateRealName(int id, String idNum, String name) { + int exist = mapper.exists(idNum); + if (exist != 0) { + return 2; + } + return mapper.updateRealName(id, idNum, name); + } + + public void delUserResumeAllData(int processedUserid) { + mapper.delUserResumeAllData(processedUserid); + } + + + public int addEducation(int userId, ArrayList e) { + if (e.isEmpty()) { + return 0; + } + for (Education education : e) { + education.setId(userId); + } + return mapper.addEducation(e); + } + + public ArrayList getEducation(int userId) { + return mapper.getEducation(userId); + } + + public int addWorkExperience(int userId, ArrayList e) { + if (e.isEmpty()) { + return 0; + } + for (WorkExperience workExperience : e) { + workExperience.setId(userId); + } + return mapper.addWorkExperience(e); + } + + public ArrayList getWorkExperience(int userId) { + return mapper.getWorkExperience(userId); + } + + public int addPaper(int userId, ArrayList e) { + if (e.isEmpty()) { + return 0; + } + for (Paper paper : e) { + paper.setId(userId); + } + return mapper.addPaper(e); + } + + public ArrayList getPaper(int userId) { + return mapper.getPaper(userId); + } + + public int addProject(int userId, ArrayList e) { + if (e.isEmpty()) { + return 0; + } + for (Project project : e) { + project.setId(userId); + } + return mapper.addProject(e); + } + + public ArrayList getProject(int userId) { + return mapper.getProject(userId); + } + + public int addResearch(int userId, ArrayList e) { + if (e.isEmpty()) { + return 0; + } + for (Research research : e) { + research.setId(userId); + } + return mapper.addResearch(e); + } + + public ArrayList getResearch(int userId) { + return mapper.getResearch(userId); + } + + public int addFamilyConnections(int userId, ArrayList e) { + if (e.isEmpty()) { + return 0; + } + for (FamilyConnections familyConnections : e) { + familyConnections.setId(userId); + } + return mapper.addFamilyConnections(e); + } + + /** + * 获取当前进行会话的用户 + * + * @return 当前正在会话的用户 + */ + public User getCurrentUser() { + Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + if (principal == null) { + return null; + } + if (principal instanceof User) { + return (User) principal; + } else { + log.warn("当前用户不是 User 类型"); + throw new IllegalStateException("用户状态异常:非User类型"); + } + } + + public ArrayList getFamilyConnections(int userId) { + return mapper.getFamilyConnections(userId); + } + + + public static void writeFileToResponse(boolean isExcel,String filePath, HttpServletResponse response) throws IOException { + System.out.println(filePath); + filePath = filePath.replaceAll("\\\\", "/"); + + // 设置响应类型(根据实际情况调整) + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment; filename=\"" + + filePath.substring(filePath.lastIndexOf('/') + 1) + "\""); + OutputStream outputStream = response.getOutputStream(); + + try (FileInputStream fileInputStream = new FileInputStream(filePath)) { + + byte[] buffer; + if (isExcel) { + // 针对excel文件,缓冲区大小设置为1.6kb + buffer = new byte[4096 * 4]; + } else { + // 针对其他文件,缓冲区大小设置为4K + buffer = new byte[4096]; + } + int bytesRead; + while ((bytesRead = fileInputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + } finally { + // 刷新缓冲区 + outputStream.flush(); + } + } + + /** + * 获取用户的投递详情,包括用户个人信息,简历信息,资历文件url等等 + * @param thingInfo 投递对象 + * @return 用户个人信息,简历信息,资历文件url等等 + */ + public HashMap getThingAndResume(ThingWithUser thingInfo) { + Integer userId = thingInfo.getUserId(); + String code = thingInfo.getCode(); + User user = this.getOne(userId); + ArrayList education = this.getEducation(userId); + ArrayList workExperience = this.getWorkExperience(userId); + ArrayList paper = this.getPaper(userId); + ArrayList project = this.getProject(userId); + ArrayList research = this.getResearch(userId); + ArrayList familyConnections = this.getFamilyConnections(userId); + HashMap map = new HashMap<>(); + for (int i = 0; i < 7; i++) { + List fileUrl = FilePatch.getFileUrl(code, userId, i, isDev, false); + map.put("file" + i, fileUrl); + } + List IDPhotos = FilePatch.getFileUrl(code, userId, 0, isDev, true); + String onePhoto = null; + if (IDPhotos != null && !IDPhotos.isEmpty()) { + onePhoto = IDPhotos.get(IDPhotos.size() - 1); + } + map.put("userinfo", user); + map.put("education", education); + map.put("workExperience", workExperience); + map.put("paper", paper); + map.put("project", project); + map.put("research", research); + map.put("family", familyConnections); + map.put("note", thingInfo.getNote()); + map.put("qualificationResult", thingInfo.getQualificationResult()); + map.put("awardsAndPunishments", thingInfo.getAwardsAndPunishments()); + map.put("IDPhoto", onePhoto); + return map; + } + + +} diff --git a/src/main/java/edu/hfbu/recruit/service/api/ApiService.java b/src/main/java/edu/hfbu/recruit/service/api/ApiService.java new file mode 100644 index 0000000..ebd2be3 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/service/api/ApiService.java @@ -0,0 +1,29 @@ +package edu.ahbvc.recruit.service.api; + +import edu.ahbvc.recruit.model.api.ImageCaptchaResponse; +import edu.ahbvc.recruit.model.api.SMApiResponse; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Repository; +import org.springframework.stereotype.Service; + +/** + * 封装了第三方API服务 + * @author c215 + */ +@Service +public interface ApiService { + String MOCK_CAPTCHA = "1"; + /** + * 获取图片验证码 + * @return 图片验证码 + */ + ImageCaptchaResponse getImgCode(); + + /** + * 发送短信验证码 + * @param captcha 图片验证码 + * @param tel 手机号 + * @return 封装好的短信验证码响应 + */ + SMApiResponse sendSM(String captcha, String tel); +} diff --git a/src/main/java/edu/hfbu/recruit/service/api/MockApiServiceImpl.java b/src/main/java/edu/hfbu/recruit/service/api/MockApiServiceImpl.java new file mode 100644 index 0000000..9665c33 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/service/api/MockApiServiceImpl.java @@ -0,0 +1,59 @@ +package edu.ahbvc.recruit.service.api; + +import edu.ahbvc.recruit.model.api.ImageCaptchaResponse; +import edu.ahbvc.recruit.model.api.JsonReader; +import edu.ahbvc.recruit.model.api.SMApiResponse; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +/** + * @author c215 + */ +@Profile("dev") +//上方注解表示该类在开发环境下才会被加载 +@Repository +//上方注解表示该类是一个Repository, 用于数据访问 +public class MockApiServiceImpl implements ApiService { + + /** + * 使用Log4j2 LogManager获取Logger实例 + * 提供日志服务 + */ + private static final Logger logger = LogManager.getLogger(MockApiServiceImpl.class); + + + /** + * 图片验证码 + * Image verification code + * @return 自定义包装类, 包含图片验证码相关信息 + * @see 接口文档 + */ + @Override + public ImageCaptchaResponse getImgCode() { + + + JsonReader jsonReader = new JsonReader<>(); + + String json = "{\"statusCode\":\"000000\",\"desc\":\"请求成功\",\"result\":{\"fileName\":\"https://data.apishop.net/checkcode/ar4wb9us16f5ezn3.png\",\"verifyCode\":\"1\"}}"; +// 输出api返回的结果 + logger.debug("开发模式,图片验证码api返回模拟数据"); + + return jsonReader.processApiResponse(json, ImageCaptchaResponse.class); + + } + + @Override + public SMApiResponse sendSM(String captcha, String tel){ +// 开发环境下直接返回 +// String json = "{\"code\":\"0\",\"msg\":\"SUCCESS\",\"smUuid\":\"38801_1_0_17756800661_1_4lDRlmcSyW_1\"}"; + SMApiResponse processApiResponse = new SMApiResponse(); + processApiResponse.setCode("0"); + processApiResponse.setMessage("SUCCESS"); + processApiResponse.setSmUuid("38801_1_0_17756800661_1_4lDRlmcSyW_1"); + return processApiResponse; + } +} + diff --git a/src/main/java/edu/hfbu/recruit/service/api/RealApiServiceImpl.java b/src/main/java/edu/hfbu/recruit/service/api/RealApiServiceImpl.java new file mode 100644 index 0000000..9d32cf7 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/service/api/RealApiServiceImpl.java @@ -0,0 +1,140 @@ +package edu.ahbvc.recruit.service.api; + +import edu.ahbvc.recruit.model.api.ImageCaptchaResponse; +import edu.ahbvc.recruit.model.api.JsonReader; +import edu.ahbvc.recruit.model.api.SMApiResponse; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.context.annotation.Profile; +import org.springframework.http.*; +import org.springframework.stereotype.Repository; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * @author c215 + */ +@Profile("prod") +@Repository +public class RealApiServiceImpl implements ApiService { + + /** + * 使用Log4j2 LogManager获取Logger实例 + * 提供日志服务 + */ + private static final Logger logger = LogManager.getLogger(RealApiServiceImpl.class); + + + /** + * 图片验证码 + * Image verification code + * @return 自定义包装类, 包含图片验证码相关信息 + * @see 接口文档 + */ + @Override + public ImageCaptchaResponse getImgCode() { + + URI url = null; + try { + url = new URI("https://eolink.o.apispace.com/lwtpyzmsc/common/verify/getComplicateVerifyImage"); + } catch (URISyntaxException e) { + logger.error("图片验证码URI异常"); + logger.error(e); + } + +// 准备调用api的请求头 + HttpHeaders headers = new HttpHeaders(); + String MyKey = "p4jb13padiv8g31wdaqlva6xoeoygdnw"; + headers.add("X-APISpace-Token", MyKey); + headers.add("Authorization-Type", "apikey"); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + JsonReader jsonReader = new JsonReader<>(); + +// 准备调用api的请求体 + MultiValueMap requestBody = new LinkedMultiValueMap<>(); + //验证码类型 + // (1:纯数字,2:小写字母,3:大写字母,4:数字+小写字母,5:数字+大写字母,6:数字+大小写字母,7:大小写字母) + requestBody.add("codeType", "1"); + RestTemplate restTemplate = new RestTemplate(); + +// 发送调用api请求 + RequestEntity> requestEntity = new RequestEntity<>( + requestBody, headers, HttpMethod.POST, url); + +// 返回结果是JSON,转换成字符串 + ResponseEntity responseEntity = restTemplate.exchange(requestEntity, String.class); + +// api返回的内容是JSON + String responseData = responseEntity.getBody(); + +// 输出api返回的结果 + logger.debug("图片验证码api返回结果" + responseData); + + ImageCaptchaResponse processApiResponse; + + processApiResponse = jsonReader.processApiResponse(responseData, ImageCaptchaResponse.class); + + return processApiResponse; + } + + @Override + public SMApiResponse sendSM(String captcha, String tel){ + URI url = null; + + try { + url = new URI("http://api.1cloudsp.com/api/v2/single_send"); + } catch (URISyntaxException e) { + logger.info("短信验证码URI异常"); + logger.error(e); + } + +// 准备调用api的请求头 + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization-Type", "apikey"); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + // 用户开发key + String accesskey = "nBWSTPoSwKmBbP81"; + // 用户开发秘钥 + String accessSecret = "Tp5u0ff4K3qpzoqDcxtHaDgcTYGphSQw"; + +// 准备调用api的请求体 + MultiValueMap requestBody = new LinkedMultiValueMap<>(); + requestBody.add("accesskey", accesskey); + requestBody.add("secret", accessSecret); + requestBody.add("sign", "299439"); + requestBody.add("templateId", "277804"); + requestBody.add("mobile", tel); + requestBody.add("content", URLEncoder.encode(captcha, StandardCharsets.UTF_8)); + RestTemplate restTemplate = new RestTemplate(); + + JsonReader jsonReader = new JsonReader<>(); + +// 发送调用api请求 + RequestEntity> requestEntity = new RequestEntity<>( + requestBody, headers, HttpMethod.POST, url); + +// 返回结果是JSON,转换成字符串 + ResponseEntity responseEntity = restTemplate.exchange(requestEntity, String.class); + +// api返回的内容是JSON + String responseData = responseEntity.getBody(); + +// 输出api返回的结果 + logger.info("短信验证码api返回结果" + responseData); + + SMApiResponse processApiResponse; + + processApiResponse = jsonReader.processApiResponse(responseData, SMApiResponse.class); + + return processApiResponse; + } +} + diff --git a/src/main/java/edu/hfbu/recruit/util/AdmissionTicketCreater.java b/src/main/java/edu/hfbu/recruit/util/AdmissionTicketCreater.java new file mode 100644 index 0000000..8df4078 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/util/AdmissionTicketCreater.java @@ -0,0 +1,147 @@ +package edu.ahbvc.recruit.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +import edu.ahbvc.recruit.model.export.Ticket; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.poi.xwpf.usermodel.ParagraphAlignment; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.apache.poi.xwpf.usermodel.XWPFRun; +import org.apache.poi.xwpf.usermodel.XWPFTable; +import org.apache.poi.xwpf.usermodel.XWPFTableCell; +import org.apache.poi.xwpf.usermodel.XWPFTableRow; + +/** + * @author c215 + */ +public class AdmissionTicketCreater { + + private static final Logger logger = LogManager.getLogger(AdmissionTicketCreater.class); + + /** + * 模板地址 + */ + public static final String templatePath + = "C:/ahbvcSystem/Recruit/template/template.docx"; + + /** + * 生成的准考证地址 + */ + public static final String outputBasePath + = "C:/ahbvcSystem/Recruit/admission_ticket"; + + /** + * @param data 要打印的用户信息 + * @return 若成功,返回docx文件路径 + */ + public static String generateUserDocument(Ticket data) { + if (data == null) { + throw new IllegalArgumentException("data cannot be null"); + } + XWPFDocument document = null; + + String result; + try { + // 读取模板文件 + FileInputStream templateFile = new FileInputStream(templatePath); + document = new XWPFDocument(templateFile); + + String ticketNum = null; + // 处理模板中的表格 + for (XWPFTable table : document.getTables()) { + for (XWPFTableRow row : table.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + String text = cell.getText(); + if (!text.startsWith("{{")) { + continue; + } + + List paragraphs = cell.getParagraphs(); + XWPFParagraph paragraph = paragraphs.get(0); + List runs = paragraph.getRuns(); + XWPFRun templateXwpfRun = runs.get(0); + // 保存文本对齐方式 + ParagraphAlignment alignment = paragraph.getAlignment(); + // 添加新段落 + XWPFParagraph addParagraph = cell.addParagraph(); + // 重新应用文本对齐方式 + addParagraph.setAlignment(alignment); + + if (data.getTicketNumber().length() == 1) { + ticketNum = data.getCode() + "000" + data.getTicketNumber(); + } else if (data.getTicketNumber().length() == 2) { + ticketNum = data.getCode() + "00" + data.getTicketNumber(); + } else if (data.getTicketNumber().length() == 3) { + ticketNum = data.getCode() + "0" + data.getTicketNumber(); + } + if (ticketNum != null) { + text = text.replace("{{ticketNum}}", ticketNum); + } + text = text.replace("{{name}}", data.getName()); + text = text.replace("{{idnum}}", data.getIdnum()); + text = text.replace("{{positionid}}", data.getCode()); + populateCellWithFormattedText(cell, text, templateXwpfRun, addParagraph); + } + } + } + logger.info("准考证填充完成,准备保存"); + String path = outputBasePath + File.separatorChar + data.getCode() + File.separatorChar; + File folder = new File(path); + boolean success = folder.mkdir(); + if (success) { + logger.info("文件夹创建成功"); + } else { + if (folder.exists()) { + logger.info("文件夹已经存在"); + } else { + logger.info("文件夹创建失败"); + } + } + // 保存生成的文档 + FileOutputStream outputFile = new FileOutputStream( + path + data.getName() + "_" + ticketNum + ".docx"); + //admission_ticket\null3416212.docx (系统找不到指定的路径。) + document.write(outputFile); + result = path + data.getName() + "_" + ticketNum + ".docx"; + /* + * C:\ahbvcSystem\Recruit\admission_ticket\4000189\341621200302160414.docx + * C:\ahbvcSystem\Recruit\admission_ticket\4000189\341621200302160414.docx + */ + logger.info(result + "保存成功"); + outputFile.close(); + + } catch (IOException e) { + logger.error("生成准考证失败", e); + return null; + } finally { + if (document != null) { + try { + document.close(); + } catch (IOException e) { + logger.error("关闭文档失败", e); + } + } + } + return result; + } + + public static void populateCellWithFormattedText(XWPFTableCell cell, String text, XWPFRun templateXwpfRun, XWPFParagraph addParagraph) { + for (int i = 0; i < text.length(); i++) { + XWPFRun newRun = addParagraph.createRun(); + newRun.setText(String.valueOf(text.charAt(i))); + newRun.setFontFamily(templateXwpfRun.getFontFamily()); + Double fontSize = templateXwpfRun.getFontSizeAsDouble(); + if (fontSize != null) { + newRun.setFontSize(fontSize); + } + newRun.setBold(templateXwpfRun.isBold()); + } + cell.removeParagraph(0); + } +} diff --git a/src/main/java/edu/hfbu/recruit/util/ExcelExporter.java b/src/main/java/edu/hfbu/recruit/util/ExcelExporter.java new file mode 100644 index 0000000..159e59d --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/util/ExcelExporter.java @@ -0,0 +1,173 @@ +package edu.ahbvc.recruit.util; + + +import edu.ahbvc.recruit.model.export.Excel; +import edu.ahbvc.recruit.model.resume.Education; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +/** + * @author c215 + */ +public class ExcelExporter { + + /** + * 使用Log4j2 LogManager获取Logger实例 + */ + private static final Logger logger = LogManager.getLogger(ExcelExporter.class); + + /** + * @param data 导出的Excel的数据 + * @param path 导出的Excel的路径 + * @return 0:正常,,-1:异常 + */ + public static int exportToExcel(ArrayList data, String path) { + if (data == null) { + logger.warn("传入数据为空"); + return -1; + } + logger.info("开始生成总表"); + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet("Data"); +// 设置样式解决含有'\n'不自动换行的问题 + CellStyle cellStyle = workbook.createCellStyle(); + // 设置单元格样式为自动换行 + cellStyle.setWrapText(true); + // Create header row + Row headerRow = sheet.createRow(0); + // Assuming first column is "No", second is "Code", etc. + String[] columnHeaders = {"序号", "岗位代码", "姓名", "性别", "出生日期", "身份证号码", "政治面貌", "民族", "毕业学校", "所学专业", "学历", "学位", + "毕业时间", "联系电话", "资格审查结果", "备注"}; + for (int i = 0; i < columnHeaders.length; i++) { + Cell cell = headerRow.createCell(i); + cell.setCellValue(columnHeaders[i]); + } + + // Fill data + int rowNum = 1; + for (Excel item : data) { + Row row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue(rowNum - 1); + row.createCell(1).setCellValue(item.getCode()); + row.createCell(2).setCellValue(item.getName()); + row.createCell(3).setCellValue(item.getSex() == 1 ? "男" : "女"); + row.createCell(4).setCellValue(item.getBirthday()); + row.createCell(5).setCellValue(item.getIdnum()); + row.createCell(6).setCellValue(item.getZzmm()); + row.createCell(7).setCellValue(item.getNation()); + StringBuilder school = new StringBuilder(); + StringBuilder specialty = new StringBuilder(); + StringBuilder education = new StringBuilder(); + StringBuilder degree = new StringBuilder(); + StringBuilder graduationTime = new StringBuilder(); + for (int i = 0; i < item.getEducation().size(); i++) { + boolean end = i == item.getEducation().size() - 1; + Education e = item.getEducation().get(i); + + String educations = switch (e.getEducation()) { + case 0 -> "专科"; + case 1 -> "本科"; + case 2 -> "研究生"; + default -> "异常"; + }; + /* 将学历转换成汉字 */ + String degrees = switch (e.getDegree()) { + case 0 -> "暂无"; + case 1 -> "学士"; + case 2 -> "硕士"; + case 3 -> "博士"; + default -> "异常"; + }; + school.append(e.getSchool()); + specialty.append(e.getSpecialty()); + education.append(educations); + degree.append(degrees); + graduationTime.append(e.getGraduationTime()); + + if (!end) { + school.append("\n"); + specialty.append("\n"); + education.append("\n"); + degree.append("\n"); + graduationTime.append("\n"); + } + } + Cell schoolcell = row.createCell(8); + schoolcell.setCellStyle(cellStyle); + schoolcell.setCellValue(school.toString()); + Cell specialtycell = row.createCell(9); + specialtycell.setCellStyle(cellStyle); + specialtycell.setCellValue(specialty.toString()); + Cell educationcell = row.createCell(10); + educationcell.setCellStyle(cellStyle); + educationcell.setCellValue(education.toString()); + Cell degreecell = row.createCell(11); + degreecell.setCellStyle(cellStyle); + degreecell.setCellValue(degree.toString()); + Cell graduationTimecell = row.createCell(12); + graduationTimecell.setCellStyle(cellStyle); + graduationTimecell.setCellValue(graduationTime.toString()); + row.createCell(13).setCellValue(item.getPhone()); + + + String sta = switch (item.getStatus()) { + case -2 -> "已拒绝"; + case -1 -> "拒绝待确认"; + case 0 -> "未处理"; + case 1 -> "同意待确认"; + case 2 -> "已同意"; + default -> "异常"; + }; + row.createCell(14).setCellValue(sta); + + row.createCell(15).setCellValue(item.getNote()); + } + + int graduationTimeColumnIndex = 12; + // 生日列设12个字符宽 + sheet.setColumnWidth(4, 12 * 256); + // 身份证号列设18个字符宽 + sheet.setColumnWidth(5, 20 * 256); + // 毕业院校列设18个字符宽 + sheet.setColumnWidth(8, 18 * 256); + // 专业列设18个字符宽 + sheet.setColumnWidth(9, 18 * 256); + // 毕业时间列设8个字符宽 + sheet.setColumnWidth(12, 8 * 256); + // 手机号列设12个字符宽 + sheet.setColumnWidth(13, 12 * 256); + sheet.setColumnWidth(graduationTimeColumnIndex, 20 * 256); + logger.error("生成总表Excel成功,开始保存 "); + // Write the workbook to a file + try { + FileOutputStream outputStream = new FileOutputStream(path + "招聘总表.xlsx"); + workbook.write(outputStream); + workbook.close(); + } catch (IOException e) { + logger.error("保存导出的Excel发生IO错误"); + return -1; + } + return 0; + } + + public static int getExcelFile(String path) { + + File folder = new File(path); + File[] fileList = folder.listFiles(); + if (fileList == null || fileList.length == 0) { + return 0; + } else if (fileList.length > 1) { + return 2; + } + return 1; + } + + +} diff --git a/src/main/java/edu/hfbu/recruit/util/ExcelUtil.java b/src/main/java/edu/hfbu/recruit/util/ExcelUtil.java new file mode 100644 index 0000000..fa006a3 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/util/ExcelUtil.java @@ -0,0 +1,1174 @@ +package edu.ahbvc.recruit.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//import com.neu.common.annotation.Excel; +//import com.neu.common.annotation.Excels; +//import com.neu.common.annotation.Excel.ColumnType; +//import com.neu.common.annotation.Excel.Type; +//import com.neu.common.config.NeuConfig; +//import com.neu.common.core.domain.AjaxResult; +//import com.neu.common.core.text.Convert; +//import com.neu.common.exception.CustomException; +//import com.neu.common.utils.DateUtils; +//import com.neu.common.utils.DictUtils; +//import com.neu.common.utils.StringUtils; +//import com.neu.common.utils.file.FileTypeUtils; +//import com.neu.common.utils.file.ImageUtils; +//import com.neu.common.utils.reflect.ReflectUtils; + +/** + * Excel相关处理 + * + * @author neusoft + */ +public class ExcelUtil +{ + private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + + /** + * Excel sheet最大行数,默认65536 + */ + public static final int sheetSize = 65536; + + /** + * 工作表名称 + */ + private String sheetName; + + /** + * 导出类型(EXPORT:导出数据;IMPORT:导入模板) + */ + private Type type; + + /** + * 工作薄对象 + */ + private Workbook wb; + + /** + * 工作表对象 + */ + private Sheet sheet; + + /** + * 样式列表 + */ + private Map styles; + + /** + * 导入导出数据列表 + */ + private List list; + + /** + * 注解列表 + */ + private List fields; + + /** + * 最大高度 + */ + private short maxHeight; + + /** + * 统计列表 + */ + private Map statistics = new HashMap(); + + /** + * 数字格式 + */ + private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + + /** + * 实体对象 + */ + public Class clazz; + + public ExcelUtil(Class clazz) + { + this.clazz = clazz; + } + + public void init(List list, String sheetName, Type type) + { + if (list == null) + { + list = new ArrayList(); + } + this.list = list; + this.sheetName = sheetName; + this.type = type; + createExcelField(); + createWorkbook(); + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(InputStream is) throws Exception + { + return importExcel(StringUtils.EMPTY, is); + } + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(String sheetName, InputStream is) throws Exception + { + this.type = Type.IMPORT; + this.wb = WorkbookFactory.create(is); + List list = new ArrayList(); + Sheet sheet = null; + if (StringUtils.isNotEmpty(sheetName)) + { + // 如果指定sheet名,则取指定sheet中的内容. + sheet = wb.getSheet(sheetName); + } + else + { + // 如果传入的sheet名不存在则默认指向第1个sheet. + sheet = wb.getSheetAt(0); + } + + if (sheet == null) + { + throw new IOException("文件sheet不存在"); + } + + int rows = sheet.getPhysicalNumberOfRows(); + + if (rows > 0) + { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + Row heard = sheet.getRow(0); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) + { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) + { + String value = this.getCellValue(heard, i).toString(); + cellMap.put(value, i); + } + else + { + cellMap.put(null, i); + } + } + // 有数据时才处理 得到类的所有field. + Field[] allFields = clazz.getDeclaredFields(); + // 定义一个map用于存放列的序号和field. + Map fieldsMap = new HashMap(); + for (int col = 0; col < allFields.length; col++) + { + Field field = allFields[col]; + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + // 设置类的私有字段属性可访问. + field.setAccessible(true); + Integer column = cellMap.get(attr.name()); + if (column != null) + { + fieldsMap.put(column, field); + } + } + } + for (int i = 1; i < rows; i++) + { + // 从第2行开始取数据,默认第一行是表头. + Row row = sheet.getRow(i); + T entity = null; + for (Map.Entry entry : fieldsMap.entrySet()) + { + Object val = this.getCellValue(row, entry.getKey()); + + // 如果不存在实例则新建. + entity = (entity == null ? clazz.newInstance() : entity); + // 从map中得到对应列的field. + Field field = fieldsMap.get(entry.getKey()); + // 取得类型,并根据对象类型设置值. + Class fieldType = field.getType(); + if (String.class == fieldType) + { + String s = Convert.toStr(val); + if (StringUtils.endsWith(s, ".0")) + { + val = StringUtils.substringBefore(s, ".0"); + } + else + { + String dateFormat = field.getAnnotation(Excel.class).dateFormat(); + if (StringUtils.isNotEmpty(dateFormat)) + { + val = DateUtils.parseDateToStr(dateFormat, (Date) val); + } + else + { + val = Convert.toStr(val); + } + } + } + else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toInt(val); + } + else if (Long.TYPE == fieldType || Long.class == fieldType) + { + val = Convert.toLong(val); + } + else if (Double.TYPE == fieldType || Double.class == fieldType) + { + val = Convert.toDouble(val); + } + else if (Float.TYPE == fieldType || Float.class == fieldType) + { + val = Convert.toFloat(val); + } + else if (BigDecimal.class == fieldType) + { + val = Convert.toBigDecimal(val); + } + else if (Date.class == fieldType) + { + if (val instanceof String) + { + val = DateUtils.parseDate(val); + } + else if (val instanceof Double) + { + val = DateUtil.getJavaDate((Double) val); + } + } + else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) + { + val = Convert.toBool(val, false); + } + if (StringUtils.isNotNull(fieldType)) + { + Excel attr = field.getAnnotation(Excel.class); + String propertyName = field.getName(); + if (StringUtils.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (StringUtils.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); + } + else if (StringUtils.isNotEmpty(attr.dictType())) + { + val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + } + ReflectUtils.invokeSetter(entity, propertyName, val); + } + } + list.add(entity); + } + } + return list; + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult exportExcel(List list, String sheetName) + { + this.init(list, sheetName, Type.EXPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName) + { + this.init(null, sheetName, Type.IMPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @return 结果 + */ + public AjaxResult exportExcel() + { + OutputStream out = null; + try + { + // 取出一共有多少个sheet. + double sheetNo = Math.ceil(list.size() / sheetSize); + for (int index = 0; index <= sheetNo; index++) + { + createSheet(sheetNo, index); + + // 产生一行 + Row row = sheet.createRow(0); + int column = 0; + // 写入各个字段的列头名称 + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + this.createCell(excel, row, column++); + } + if (Type.EXPORT.equals(type)) + { + fillExcelData(index, row); + addStatisticsRow(); + } + } + String filename = encodingFilename(sheetName); + out = new FileOutputStream(getAbsoluteFile(filename)); + wb.write(out); + return AjaxResult.success(filename); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + throw new CustomException("导出Excel失败,请联系网站管理员!"); + } + finally + { + if (wb != null) + { + try + { + wb.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + if (out != null) + { + try + { + out.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + } + } + + /** + * 填充excel数据 + * + * @param index 序号 + * @param row 单元格行 + */ + public void fillExcelData(int index, Row row) + { + int startNo = index * sheetSize; + int endNo = Math.min(startNo + sheetSize, list.size()); + for (int i = startNo; i < endNo; i++) + { + row = sheet.createRow(i + 1 - startNo); + // 得到导出对象. + T vo = (T) list.get(i); + int column = 0; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + // 设置实体类私有属性可访问 + field.setAccessible(true); + this.addCell(excel, row, vo, field, column++); + } + } + } + + /** + * 创建表格样式 + * + * @param wb 工作薄对象 + * @return 样式列表 + */ + private Map createStyles(Workbook wb) + { + // 写入各条记录,每条记录对应excel表中的一行 + Map styles = new HashMap(); + CellStyle style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + style.setFont(dataFont); + styles.put("data", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + Font headerFont = wb.createFont(); + headerFont.setFontName("Arial"); + headerFont.setFontHeightInPoints((short) 10); + headerFont.setBold(true); + headerFont.setColor(IndexedColors.WHITE.getIndex()); + style.setFont(headerFont); + styles.put("header", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font totalFont = wb.createFont(); + totalFont.setFontName("Arial"); + totalFont.setFontHeightInPoints((short) 10); + style.setFont(totalFont); + styles.put("total", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.LEFT); + styles.put("data1", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + styles.put("data2", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.RIGHT); + styles.put("data3", style); + + return styles; + } + + /** + * 创建单元格 + */ + public Cell createCell(Excel attr, Row row, int column) + { + // 创建列 + Cell cell = row.createCell(column); + // 写入列信息 + cell.setCellValue(attr.name()); + setDataValidation(attr, row, column); + cell.setCellStyle(styles.get("header")); + return cell; + } + + /** + * 设置单元格信息 + * + * @param value 单元格值 + * @param attr 注解相关 + * @param cell 单元格信息 + */ + public void setCellVo(Object value, Excel attr, Cell cell) + { + if (ColumnType.STRING == attr.cellType()) + { + cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix()); + } + else if (ColumnType.NUMERIC == attr.cellType()) + { + cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); + } + else if (ColumnType.IMAGE == attr.cellType()) + { + ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), + cell.getRow().getRowNum() + 1); + String imagePath = Convert.toStr(value); + if (StringUtils.isNotEmpty(imagePath)) + { + byte[] data = ImageUtils.getImage(imagePath); + getDrawingPatriarch(cell.getSheet()).createPicture(anchor, + cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); + } + } + } + + /** + * 获取画布 + */ + public static Drawing getDrawingPatriarch(Sheet sheet) + { + if (sheet.getDrawingPatriarch() == null) + { + sheet.createDrawingPatriarch(); + } + return sheet.getDrawingPatriarch(); + } + + /** + * 获取图片类型,设置图片插入类型 + */ + public int getImageType(byte[] value) + { + String type = FileTypeUtils.getFileExtendName(value); + if ("JPG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_JPEG; + } + else if ("PNG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_PNG; + } + return Workbook.PICTURE_TYPE_JPEG; + } + + /** + * 创建表格样式 + */ + public void setDataValidation(Excel attr, Row row, int column) + { + if (attr.name().indexOf("注:") >= 0) + { + sheet.setColumnWidth(column, 6000); + } + else + { + // 设置列宽 + sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); + } + // 如果设置了提示信息则鼠标放上去提示. + if (StringUtils.isNotEmpty(attr.prompt())) + { + // 这里默认设了2-101列提示. + setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); + } + // 如果设置了combo属性则本列只能选择不能输入 + if (attr.combo().length > 0) + { + // 这里默认设了2-101列只能选择不能输入. + setXSSFValidation(sheet, attr.combo(), 1, 100, column, column); + } + } + + /** + * 添加单元格 + */ + public Cell addCell(Excel attr, Row row, T vo, Field field, int column) + { + Cell cell = null; + try + { + // 设置行高 + row.setHeight(maxHeight); + // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. + if (attr.isExport()) + { + // 创建cell + cell = row.createCell(column); + int align = attr.align().value(); + cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : ""))); + + // 用于读取对象中的属性 + Object value = getTargetValue(vo, field, attr); + String dateFormat = attr.dateFormat(); + String readConverterExp = attr.readConverterExp(); + String separator = attr.separator(); + String dictType = attr.dictType(); + if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) + { + cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); + } + else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); + } + else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator)); + } + else if (value instanceof BigDecimal && -1 != attr.scale()) + { + cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString()); + } + else + { + // 设置列类型 + setCellVo(value, attr, cell); + } + addStatisticsData(column, Convert.toStr(value), attr); + } + } + catch (Exception e) + { + log.error("导出Excel失败{}", e); + } + return cell; + } + + /** + * 设置 POI XSSFSheet 单元格提示 + * + * @param sheet 表单 + * @param promptTitle 提示标题 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, + int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + DataValidation dataValidation = helper.createValidation(constraint, regions); + dataValidation.createPromptBox(promptTitle, promptContent); + dataValidation.setShowPromptBox(true); + sheet.addValidationData(dataValidation); + } + + /** + * 设置某些列的值只能输入预制的数据,显示下拉框. + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + * @return 设置好的sheet. + */ + public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 加载下拉列表内容 + DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // 数据有效性对象 + DataValidation dataValidation = helper.createValidation(constraint, regions); + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + + sheet.addValidationData(dataValidation); + } + + /** + * 解析导出值 0=男,1=女,2=未知 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String convertByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(separator, propertyValue)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[0].equals(value)) + { + propertyString.append(itemArray[1] + separator); + break; + } + } + } + else + { + if (itemArray[0].equals(propertyValue)) + { + return itemArray[1]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 反向解析值 男=0,女=1,未知=2 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String reverseByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(separator, propertyValue)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[1].equals(value)) + { + propertyString.append(itemArray[0] + separator); + break; + } + } + } + else + { + if (itemArray[1].equals(propertyValue)) + { + return itemArray[0]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 解析字典值 + * + * @param dictValue 字典值 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String convertDictByExp(String dictValue, String dictType, String separator) + { + return DictUtils.getDictLabel(dictType, dictValue, separator); + } + + /** + * 反向解析值字典值 + * + * @param dictLabel 字典标签 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典值 + */ + public static String reverseDictByExp(String dictLabel, String dictType, String separator) + { + return DictUtils.getDictValue(dictType, dictLabel, separator); + } + + /** + * 合计统计信息 + */ + private void addStatisticsData(Integer index, String text, Excel entity) + { + if (entity != null && entity.isStatistics()) + { + Double temp = 0D; + if (!statistics.containsKey(index)) + { + statistics.put(index, temp); + } + try + { + temp = Double.valueOf(text); + } + catch (NumberFormatException e) + { + } + statistics.put(index, statistics.get(index) + temp); + } + } + + /** + * 创建统计行 + */ + public void addStatisticsRow() + { + if (statistics.size() > 0) + { + Cell cell = null; + Row row = sheet.createRow(sheet.getLastRowNum() + 1); + Set keys = statistics.keySet(); + cell = row.createCell(0); + cell.setCellStyle(styles.get("total")); + cell.setCellValue("合计"); + + for (Integer key : keys) + { + cell = row.createCell(key); + cell.setCellStyle(styles.get("total")); + cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); + } + statistics.clear(); + } + } + + /** + * 编码文件名 + */ + public String encodingFilename(String filename) + { + filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx"; + return filename; + } + + /** + * 获取下载路径 + * + * @param filename 文件名称 + */ + public String getAbsoluteFile(String filename) + { + String downloadPath = NeuConfig.getDownloadPath() + filename; + File desc = new File(downloadPath); + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + return downloadPath; + } + + /** + * 获取bean中的属性值 + * + * @param vo 实体对象 + * @param field 字段 + * @param excel 注解 + * @return 最终的属性值 + * @throws Exception + */ + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception + { + Object o = field.get(vo); + if (StringUtils.isNotEmpty(excel.targetAttr())) + { + String target = excel.targetAttr(); + if (target.indexOf(".") > -1) + { + String[] targets = target.split("[.]"); + for (String name : targets) + { + o = getValue(o, name); + } + } + else + { + o = getValue(o, target); + } + } + return o; + } + + /** + * 以类的属性的get方法方法形式获取值 + * + * @param o + * @param name + * @return value + * @throws Exception + */ + private Object getValue(Object o, String name) throws Exception + { + if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) + { + Class clazz = o.getClass(); + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + o = field.get(o); + } + return o; + } + + /** + * 得到所有定义字段 + */ + private void createExcelField() + { + this.fields = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + putToField(field, field.getAnnotation(Excel.class)); + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel excel : excels) + { + putToField(field, excel); + } + } + } + this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); + this.maxHeight = getRowHeight(); + } + + /** + * 根据注解获取最大行高 + */ + public short getRowHeight() + { + double maxHeight = 0; + for (Object[] os : this.fields) + { + Excel excel = (Excel) os[1]; + maxHeight = maxHeight > excel.height() ? maxHeight : excel.height(); + } + return (short) (maxHeight * 20); + } + + /** + * 放到字段集合中 + */ + private void putToField(Field field, Excel attr) + { + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + this.fields.add(new Object[] { field, attr }); + } + } + + /** + * 创建一个工作簿 + */ + public void createWorkbook() + { + this.wb = new SXSSFWorkbook(500); + } + + /** + * 创建工作表 + * + * @param sheetNo sheet数量 + * @param index 序号 + */ + public void createSheet(double sheetNo, int index) + { + this.sheet = wb.createSheet(); + this.styles = createStyles(wb); + // 设置工作表的名称. + if (sheetNo == 0) + { + wb.setSheetName(index, sheetName); + } + else + { + wb.setSheetName(index, sheetName + index); + } + } + + /** + * 获取单元格值 + * + * @param row 获取的行 + * @param column 获取单元格列号 + * @return 单元格值 + */ + public Object getCellValue(Row row, int column) + { + if (row == null) + { + return row; + } + Object val = ""; + try + { + Cell cell = row.getCell(column); + if (StringUtils.isNotNull(cell)) + { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) + { + val = cell.getNumericCellValue(); + if (DateUtil.isCellDateFormatted(cell)) + { + val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 + } + else + { + if ((Double) val % 1 != 0) + { + val = new BigDecimal(val.toString()); + } + else + { + val = new DecimalFormat("0").format(val); + } + } + } + else if (cell.getCellType() == CellType.STRING) + { + val = cell.getStringCellValue(); + } + else if (cell.getCellType() == CellType.BOOLEAN) + { + val = cell.getBooleanCellValue(); + } + else if (cell.getCellType() == CellType.ERROR) + { + val = cell.getErrorCellValue(); + } + + } + } + catch (Exception e) + { + return val; + } + return val; + } + + public String getSheetName() { + return sheetName; + } + + public void setSheetName(String sheetName) { + this.sheetName = sheetName; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public Workbook getWb() { + return wb; + } + + public void setWb(Workbook wb) { + this.wb = wb; + } + + public Sheet getSheet() { + return sheet; + } + + public void setSheet(Sheet sheet) { + this.sheet = sheet; + } + + public Map getStyles() { + return styles; + } + + public void setStyles(Map styles) { + this.styles = styles; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public List getFields() { + return fields; + } + + public void setFields(List fields) { + this.fields = fields; + } + + public short getMaxHeight() { + return maxHeight; + } + + public void setMaxHeight(short maxHeight) { + this.maxHeight = maxHeight; + } + + public Map getStatistics() { + return statistics; + } + + public void setStatistics(Map statistics) { + this.statistics = statistics; + } + + public Class getClazz() { + return clazz; + } + + public void setClazz(Class clazz) { + this.clazz = clazz; + } +} \ No newline at end of file diff --git a/src/main/java/edu/hfbu/recruit/util/IdNumChecker.java b/src/main/java/edu/hfbu/recruit/util/IdNumChecker.java new file mode 100644 index 0000000..42651d2 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/util/IdNumChecker.java @@ -0,0 +1,3270 @@ +package edu.ahbvc.recruit.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 身份证号码检查工具类 + * + * @author c215 + */ +public class IdNumChecker { + + /** + * 检查身份证号是否合法 + * + * @param idNum 身份证号 + * @return 1 正常 + * 0 过期或不存在 + */ + public static int check(String idNum) { + // 1. 基本格式校验 + if (idNum == null || idNum.length() != 18) { + return 0; + } + + // 2. 校验前17位是否为数字 + for (int i = 0; i < 17; i++) { + if (!Character.isDigit(idNum.charAt(i))) { + return 0; + } + } + + // 3. 校验最后一位(可能是数字或X) + char lastChar = idNum.charAt(17); + if (!(Character.isDigit(lastChar) || lastChar == 'X' || lastChar == 'x')) { + return 0; + } + + // 4. 校验地区码(前6位)是否在有效地区列表中 + String areaCode = idNum.substring(0, 6); + boolean validArea = false; + for (String area : area_list) { + if (area.startsWith(areaCode)) { + validArea = true; + break; + } + } + if (!validArea) { + return 0; + } + + // 5. 校验出生日期是否合法 + String birthDate = idNum.substring(6, 14); + try { + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + sdf.setLenient(false); // 严格模式 + Date date = sdf.parse(birthDate); + if (date.after(new Date())) { // 出生日期不能晚于当前日期 + return 0; + } + } catch (ParseException e) { + return 0; + } + + // 6. 校验码验证(第18位) + if (!validateCheckDigit(idNum)) { + return 0; + } + + return 1; // 所有验证通过 + } + + // 校验码验证方法 + private static boolean validateCheckDigit(String idNum) { + // 校验权重因子 + int[] weight = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; + // 校验码对应值 + char[] checkCodes = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; + + int sum = 0; + for (int i = 0; i < 17; i++) { + sum += (idNum.charAt(i) - '0') * weight[i]; + } + + int mod = sum % 11; + char checkCode = checkCodes[mod]; + return Character.toUpperCase(idNum.charAt(17)) == checkCode; + } + + + static String[] area_list = {"110000,北京\n", + "110101,东城区\n", + "110102,西城区\n", + "110105,朝阳区\n", + "110106,丰台区\n", + "110107,石景山区\n", + "110108,海淀区\n", + "110109,门头沟区\n", + "110111,房山区\n", + "110112,通州区\n", + "110113,顺义区\n", + "110114,昌平区\n", + "110115,大兴区\n", + "110116,怀柔区\n", + "110117,平谷区\n", + "110228,密云县\n", + "110229,延庆县\n", + "120000,天津\n", + "120101,和平区\n", + "120102,河东区\n", + "120103,河西区\n", + "120104,南开区\n", + "120105,河北区\n", + "120106,红桥区\n", + "120110,东丽区\n", + "120111,西青区\n", + "120112,津南区\n", + "120113,北辰区\n", + "120114,武清区\n", + "120115,宝坻区\n", + "120116,滨海新区\n", + "120221,宁河区\n", + "120223,静海区\n", + "120225,蓟县\n", + "130000,河北\n", + "130100,石家庄\n", + "130102,长安区\n", + "130103,桥东区\n", + "130104,桥西区\n", + "130105,新华区\n", + "130107,井陉矿区\n", + "130108,裕华区\n", + "130109,藁城区\n", + "130110,鹿泉区\n", + "130111,栾城区\n", + "130121,井陉县\n", + "130123,正定县\n", + "130125,行唐县\n", + "130126,灵寿县\n", + "130127,高邑县\n", + "130128,深泽县\n", + "130129,赞皇县\n", + "130130,无极县\n", + "130131,平山县\n", + "130132,元氏县\n", + "130133,赵县\n", + "130181,辛集市\n", + "130183,晋州市\n", + "130184,新乐市\n", + "130200,唐山市\n", + "130202,路南区\n", + "130203,路北区\n", + "130204,古冶区\n", + "130205,开平区\n", + "130207,丰南区\n", + "130208,丰润区\n", + "130223,滦县\n", + "130224,滦南县\n", + "130225,乐亭县\n", + "130227,迁西县\n", + "130229,玉田县\n", + "130230,曹妃甸区\n", + "130281,遵化市\n", + "130283,迁安市\n", + "130300,秦皇岛\n", + "130302,海港区\n", + "130303,山海关区\n", + "130304,北戴河区\n", + "130321,青龙县\n", + "130322,昌黎县\n", + "130323,抚宁县\n", + "130324,卢龙县\n", + "130400,邯郸\n", + "130402,邯山区\n", + "130403,丛台区\n", + "130404,复兴区\n", + "130406,峰峰矿区\n", + "130421,邯郸县\n", + "130423,临漳县\n", + "130424,成安县\n", + "130425,大名县\n", + "130426,涉县\n", + "130427,磁县\n", + "130428,肥乡县\n", + "130429,永年县\n", + "130430,邱县\n", + "130431,鸡泽县\n", + "130432,广平县\n", + "130433,馆陶县\n", + "130434,魏县\n", + "130435,曲周县\n", + "130481,武安市\n", + "130500,邢台\n", + "130502,桥东区\n", + "130503,桥西区\n", + "130521,邢台县\n", + "130522,临城县\n", + "130523,内丘县\n", + "130524,柏乡县\n", + "130525,隆尧县\n", + "130526,任县\n", + "130527,南和县\n", + "130528,宁晋县\n", + "130529,巨鹿县\n", + "130530,新河县\n", + "130531,广宗县\n", + "130532,平乡县\n", + "130533,威县\n", + "130534,清河县\n", + "130535,临西县\n", + "130581,南宫市\n", + "130582,沙河市\n", + "130600,保定\n", + "130602,竞秀区\n", + "130603,莲池区\n", + "130604,南市区\n", + "130621,满城区\n", + "130622,清苑区\n", + "130623,涞水县\n", + "130624,阜平县\n", + "130625,徐水区\n", + "130626,定兴县\n", + "130627,唐县\n", + "130628,高阳县\n", + "130629,容城县\n", + "130630,涞源县\n", + "130631,望都县\n", + "130632,安新县\n", + "130633,易县\n", + "130634,曲阳县\n", + "130635,蠡县\n", + "130636,顺平县\n", + "130637,博野县\n", + "130638,雄县\n", + "130681,涿州市\n", + "130682,定州市\n", + "130683,安国市\n", + "130684,高碑店市\n", + "130700,张家口\n", + "130702,桥东区\n", + "130703,桥西区\n", + "130705,宣化区\n", + "130706,下花园区\n", + "130721,宣化县\n", + "130722,张北县\n", + "130723,康保县\n", + "130724,沽源县\n", + "130725,尚义县\n", + "130726,蔚县\n", + "130727,阳原县\n", + "130728,怀安县\n", + "130729,万全县\n", + "130730,怀来县\n", + "130731,涿鹿县\n", + "130732,赤城县\n", + "130733,崇礼县\n", + "130800,承德\n", + "130802,双桥区\n", + "130803,双滦区\n", + "130804,鹰手营子矿区\n", + "130821,承德县\n", + "130822,兴隆县\n", + "130823,平泉县\n", + "130824,滦平县\n", + "130825,隆化县\n", + "130826,丰宁满族自治县\n", + "130827,宽城县\n", + "130828,围场县\n", + "130900,沧州\n", + "130902,新华区\n", + "130903,运河区\n", + "130921,沧县\n", + "130922,青县\n", + "130923,东光县\n", + "130924,海兴县\n", + "130925,盐山县\n", + "130926,肃宁县\n", + "130927,南皮县\n", + "130928,吴桥县\n", + "130929,献县\n", + "130930,孟村回族自治县\n", + "130981,泊头市\n", + "130982,任丘市\n", + "130983,黄骅市\n", + "130984,河间市\n", + "131000,廊坊\n", + "131002,安次区\n", + "131003,广阳区\n", + "131022,固安县\n", + "131023,永清县\n", + "131024,香河县\n", + "131025,大城县\n", + "131026,文安县\n", + "131028,大厂回族自治县\n", + "131081,霸州市\n", + "131082,三河市\n", + "131100,衡水\n", + "131102,桃城区\n", + "131121,枣强县\n", + "131122,武邑县\n", + "131123,武强县\n", + "131124,饶阳县\n", + "131125,安平县\n", + "131126,故城县\n", + "131127,景县\n", + "131128,阜城县\n", + "131181,冀州市\n", + "131182,深州市\n", + "140000,山西\n", + "140100,太原\n", + "140105,小店区\n", + "140106,迎泽区\n", + "140107,杏花岭区\n", + "140108,尖草坪区\n", + "140109,万柏林区\n", + "140110,晋源区\n", + "140121,清徐县\n", + "140122,阳曲县\n", + "140123,娄烦县\n", + "140181,古交市\n", + "140200,大同\n", + "140202,城区\n", + "140203,矿区\n", + "140211,南郊区\n", + "140212,新荣区\n", + "140221,阳高县\n", + "140222,天镇县\n", + "140223,广灵县\n", + "140224,灵丘县\n", + "140225,浑源县\n", + "140226,左云县\n", + "140227,大同县\n", + "140300,阳泉\n", + "140302,城区\n", + "140303,矿区\n", + "140311,郊区\n", + "140321,平定县\n", + "140322,盂县\n", + "140400,长治\n", + "140402,城区\n", + "140411,郊区\n", + "140421,长治县\n", + "140423,襄垣县\n", + "140424,屯留县\n", + "140425,平顺县\n", + "140426,黎城县\n", + "140427,壶关县\n", + "140428,长子县\n", + "140429,武乡县\n", + "140430,沁县\n", + "140431,沁源县\n", + "140481,潞城市\n", + "140500,晋城\n", + "140502,城区\n", + "140521,沁水县\n", + "140522,阳城县\n", + "140524,陵川县\n", + "140525,泽州县\n", + "140581,高平市\n", + "140600,朔州\n", + "140602,朔城区\n", + "140603,平鲁区\n", + "140621,山阴县\n", + "140622,应县\n", + "140623,右玉县\n", + "140624,怀仁县\n", + "140700,晋中\n", + "140702,榆次区\n", + "140721,榆社县\n", + "140722,左权县\n", + "140723,和顺县\n", + "140724,昔阳县\n", + "140725,寿阳县\n", + "140726,太谷县\n", + "140727,祁县\n", + "140728,平遥县\n", + "140729,灵石县\n", + "140781,介休市\n", + "140800,运城\n", + "140802,盐湖区\n", + "140821,临猗县\n", + "140822,万荣县\n", + "140823,闻喜县\n", + "140824,稷山县\n", + "140825,新绛县\n", + "140826,绛县\n", + "140827,垣曲县\n", + "140828,夏县\n", + "140829,平陆县\n", + "140830,芮城县\n", + "140881,永济市\n", + "140882,河津市\n", + "140900,忻州\n", + "140902,忻府区\n", + "140921,定襄县\n", + "140922,五台县\n", + "140923,代县\n", + "140924,繁峙县\n", + "140925,宁武县\n", + "140926,静乐县\n", + "140927,神池县\n", + "140928,五寨县\n", + "140929,岢岚县\n", + "140930,河曲县\n", + "140931,保德县\n", + "140932,偏关县\n", + "140981,原平市\n", + "141000,临汾\n", + "141002,尧都区\n", + "141021,曲沃县\n", + "141022,翼城县\n", + "141023,襄汾县\n", + "141024,洪洞县\n", + "141025,古县\n", + "141026,安泽县\n", + "141027,浮山县\n", + "141028,吉县\n", + "141029,乡宁县\n", + "141030,大宁县\n", + "141031,隰县\n", + "141032,永和县\n", + "141033,蒲县\n", + "141034,汾西县\n", + "141081,侯马市\n", + "141082,霍州市\n", + "141100,吕梁\n", + "141102,离石区\n", + "141121,文水县\n", + "141122,交城县\n", + "141123,兴县\n", + "141124,临县\n", + "141125,柳林县\n", + "141126,石楼县\n", + "141127,岚县\n", + "141128,方山县\n", + "141129,中阳县\n", + "141130,交口县\n", + "141181,孝义市\n", + "141182,汾阳市\n", + "150000,内蒙古\n", + "150100,呼和浩特\n", + "150102,新城区\n", + "150103,回民区\n", + "150104,玉泉区\n", + "150105,赛罕区\n", + "150121,土默特左旗\n", + "150122,托克托县\n", + "150123,和林格尔县\n", + "150124,清水河县\n", + "150125,武川县\n", + "150200,包头市\n", + "150202,东河区\n", + "150203,昆都仑区\n", + "150204,青山区\n", + "150205,石拐区\n", + "150206,白云鄂博矿区\n", + "150207,九原区\n", + "150221,土默特右旗\n", + "150222,固阳县\n", + "150223,达尔罕旗\n", + "150300,乌海市\n", + "150302,海勃湾区\n", + "150303,海南区\n", + "150304,乌达区\n", + "150400,赤峰市\n", + "150402,红山区\n", + "150403,元宝山区\n", + "150404,松山区\n", + "150421,阿鲁旗\n", + "150422,巴林左旗\n", + "150423,巴林右旗\n", + "150424,林西县\n", + "150425,克什克腾旗\n", + "150426,翁牛特旗\n", + "150428,喀喇沁旗\n", + "150429,宁城县\n", + "150430,敖汉旗\n", + "150500,通辽市\n", + "150502,科尔沁区\n", + "150521,科尔沁左翼中旗\n", + "150522,科尔沁左翼后旗\n", + "150523,开鲁县\n", + "150524,库伦旗\n", + "150525,奈曼旗\n", + "150526,扎鲁特旗\n", + "150581,霍林郭勒市\n", + "150600,鄂尔多斯\n", + "150602,东胜区\n", + "150621,达拉特旗\n", + "150622,准格尔旗\n", + "150623,鄂托克前旗\n", + "150624,鄂托克旗\n", + "150625,杭锦旗\n", + "150626,乌审旗\n", + "150627,伊金霍洛旗\n", + "150700,扎赉诺尔区\n", + "150700,呼伦贝尔\n", + "150702,海拉尔区\n", + "150721,阿荣旗\n", + "150722,莫力达瓦旗\n", + "150723,鄂伦春自治旗\n", + "150724,鄂温克族自治旗\n", + "150725,陈巴尔虎旗\n", + "150726,新巴尔虎左旗\n", + "150727,新巴尔虎右旗\n", + "150781,满洲里\n", + "150782,牙克石市\n", + "150783,扎兰屯市\n", + "150784,额尔古纳市\n", + "150785,根河市\n", + "150800,巴彦淖尔\n", + "150802,临河区\n", + "150821,五原县\n", + "150822,磴口县\n", + "150823,乌拉特前旗\n", + "150824,乌拉特中旗\n", + "150825,乌拉特后旗\n", + "150826,杭锦后旗\n", + "150900,乌兰察布\n", + "150902,集宁区\n", + "150921,卓资县\n", + "150922,化德县\n", + "150923,商都县\n", + "150924,兴和县\n", + "150925,凉城县\n", + "150926,察哈尔右翼前旗\n", + "150927,察哈尔右翼中旗\n", + "150928,察哈尔右翼后旗\n", + "150929,四子王旗\n", + "150981,丰镇市\n", + "152200,兴安盟\n", + "152201,乌兰浩特市\n", + "152202,阿尔山市\n", + "152221,科尔沁右翼前旗\n", + "152222,科尔沁右翼中旗\n", + "152223,扎赉特旗\n", + "152224,突泉县\n", + "152500,锡林郭勒盟\n", + "152501,二连浩特市\n", + "152502,锡林浩特市\n", + "152522,阿巴嘎旗\n", + "152523,苏尼特左旗\n", + "152524,苏尼特右旗\n", + "152525,东乌珠穆沁旗\n", + "152526,西乌珠穆沁\n", + "152527,太仆寺旗\n", + "152528,镶黄旗\n", + "152529,正镶白旗\n", + "152530,正蓝旗\n", + "152531,多伦县\n", + "152900,阿拉善盟\n", + "152921,阿拉善左旗\n", + "152922,阿拉善右旗\n", + "152923,额济纳旗\n", + "210000,辽宁\n", + "210100,沈阳\n", + "210102,和平区\n", + "210103,沈河区\n", + "210104,大东区\n", + "210105,皇姑区\n", + "210106,铁西区\n", + "210111,苏家屯区\n", + "210112,浑南区\n", + "210113,沈北新区\n", + "210114,于洪区\n", + "210122,辽中县\n", + "210123,康平县\n", + "210124,法库县\n", + "210181,新民市\n", + "210200,大连\n", + "210202,中山区\n", + "210203,西岗区\n", + "210204,沙河口区\n", + "210211,甘井子区\n", + "210212,旅顺口区\n", + "210213,金州区\n", + "210224,长海县\n", + "210281,瓦房店市\n", + "210282,普兰店市\n", + "210283,庄河市\n", + "210300,鞍山\n", + "210302,铁东区\n", + "210303,铁西区\n", + "210304,立山区\n", + "210311,千山区\n", + "210321,台安县\n", + "210323,岫岩满族自治县\n", + "210381,海城市\n", + "210400,抚顺\n", + "210402,新抚区\n", + "210403,东洲区\n", + "210404,望花区\n", + "210411,顺城区\n", + "210421,抚顺县\n", + "210422,新宾满族自治县\n", + "210423,清原满族自治县\n", + "210500,本溪\n", + "210502,平山区\n", + "210503,溪湖区\n", + "210504,明山区\n", + "210505,南芬区\n", + "210521,本溪满族自治县\n", + "210522,桓仁满族自治县\n", + "210600,丹东\n", + "210602,元宝区\n", + "210603,振兴区\n", + "210604,振安区\n", + "210624,宽甸满族自治县\n", + "210681,东港市\n", + "210682,凤城市\n", + "210700,锦州\n", + "210702,古塔区\n", + "210703,凌河区\n", + "210711,太和区\n", + "210726,黑山县\n", + "210727,义县\n", + "210781,凌海市\n", + "210782,北镇市\n", + "210800,营口\n", + "210802,站前区\n", + "210803,西市区\n", + "210804,鲅鱼圈区\n", + "210811,老边区\n", + "210881,盖州市\n", + "210882,大石桥市\n", + "210900,阜新\n", + "210902,海州区\n", + "210903,新邱区\n", + "210904,太平区\n", + "210905,清河门区\n", + "210911,细河区\n", + "210921,阜新蒙古族自治县\n", + "210922,彰武县\n", + "211000,辽阳\n", + "211002,白塔区\n", + "211003,文圣区\n", + "211004,宏伟区\n", + "211005,弓长岭区\n", + "211011,太子河区\n", + "211021,辽阳县\n", + "211081,灯塔市\n", + "211100,盘锦\n", + "211102,双台子区\n", + "211103,兴隆台区\n", + "211121,大洼县\n", + "211122,盘山县\n", + "211200,铁岭\n", + "211202,银州区\n", + "211204,清河区\n", + "211221,铁岭县\n", + "211223,西丰县\n", + "211224,昌图县\n", + "211281,调兵山市\n", + "211282,开原市\n", + "211300,朝阳\n", + "211302,双塔区\n", + "211303,龙城区\n", + "211321,朝阳县\n", + "211322,建平县\n", + "211324,喀左县\n", + "211381,北票市\n", + "211382,凌源市\n", + "211400,葫芦岛\n", + "211402,连山区\n", + "211403,龙港区\n", + "211404,南票区\n", + "211421,绥中县\n", + "211422,建昌县\n", + "211481,兴城市\n", + "220000,吉林\n", + "220100,长春市\n", + "220102,南关区\n", + "220103,宽城区\n", + "220104,朝阳区\n", + "220105,二道区\n", + "220106,绿园区\n", + "220112,双阳区\n", + "220122,农安县\n", + "220181,九台区\n", + "220182,榆树市\n", + "220183,德惠市\n", + "220200,吉林市\n", + "220202,昌邑区\n", + "220203,龙潭区\n", + "220204,船营区\n", + "220211,丰满区\n", + "220221,永吉县\n", + "220281,蛟河市\n", + "220282,桦甸市\n", + "220283,舒兰市\n", + "220284,磐石市\n", + "220300,四平市\n", + "220302,铁西区\n", + "220303,铁东区\n", + "220322,梨树县\n", + "220323,伊通满族自治县\n", + "220381,公主岭市\n", + "220382,双辽市\n", + "220400,辽源市\n", + "220402,龙山区\n", + "220403,西安区\n", + "220421,东丰县\n", + "220422,东辽县\n", + "220500,通化市\n", + "220502,东昌区\n", + "220503,二道江区\n", + "220521,通化县\n", + "220523,辉南县\n", + "220524,柳河县\n", + "220581,梅河口市\n", + "220582,集安市\n", + "220600,白山市\n", + "220602,浑江区\n", + "220605,江源区\n", + "220621,抚松县\n", + "220622,靖宇县\n", + "220623,长白县\n", + "220681,临江市\n", + "220700,松原市\n", + "220702,宁江区\n", + "220721,前郭尔罗斯县\n", + "220722,长岭县\n", + "220723,乾安县\n", + "220724,扶余市\n", + "220800,白城市\n", + "220802,洮北区\n", + "220821,镇赉县\n", + "220822,通榆县\n", + "220881,洮南市\n", + "220882,大安市\n", + "222400,延边州\n", + "222401,延吉市\n", + "222402,图们市\n", + "222403,敦化市\n", + "222404,珲春市\n", + "222405,龙井市\n", + "222406,和龙市\n", + "222424,汪清县\n", + "222426,安图县\n", + "230000,黑龙江\n", + "230100,哈尔滨\n", + "230102,道里区\n", + "230103,南岗区\n", + "230104,道外区\n", + "230108,平房区\n", + "230109,松北区\n", + "230110,香坊区\n", + "230111,呼兰区\n", + "230112,阿城区\n", + "230113,双城区\n", + "230123,依兰县\n", + "230124,方正县\n", + "230125,宾县\n", + "230126,巴彦县\n", + "230127,木兰县\n", + "230128,通河县\n", + "230129,延寿县\n", + "230183,尚志市\n", + "230184,五常市\n", + "230200,齐齐哈尔\n", + "230202,龙沙区\n", + "230203,建华区\n", + "230204,铁锋区\n", + "230205,昂昂溪区\n", + "230206,富拉尔基区\n", + "230207,碾子山区\n", + "230208,梅里斯达斡尔族区\n", + "230221,龙江县\n", + "230223,依安县\n", + "230224,泰来县\n", + "230225,甘南县\n", + "230227,富裕县\n", + "230229,克山县\n", + "230230,克东县\n", + "230231,拜泉县\n", + "230281,讷河市\n", + "230300,鸡西\n", + "230302,鸡冠区\n", + "230303,恒山市\n", + "230304,滴道区\n", + "230305,梨树区\n", + "230306,城子河区\n", + "230307,麻山区\n", + "230321,鸡东县\n", + "230381,虎林市\n", + "230382,密山市\n", + "230400,鹤岗\n", + "230402,向阳区\n", + "230403,工农区\n", + "230404,南山区\n", + "230405,兴安区\n", + "230406,东山区\n", + "230407,兴山区\n", + "230421,萝北县\n", + "230422,绥滨县\n", + "230500,双鸭山\n", + "230502,尖山区\n", + "230503,岭东区\n", + "230505,四方台区\n", + "230506,宝山区\n", + "230521,集贤县\n", + "230522,友谊县\n", + "230523,宝清县\n", + "230524,饶河县\n", + "230600,大庆\n", + "230602,萨尔图区\n", + "230603,龙凤区\n", + "230604,让胡路区\n", + "230605,红岗区\n", + "230606,大同区\n", + "230621,肇州县\n", + "230622,肇源县\n", + "230623,林甸县\n", + "230624,杜尔伯特蒙县\n", + "230700,伊春\n", + "230702,伊春区\n", + "230703,南岔区\n", + "230704,友好区\n", + "230705,西林区\n", + "230706,翠峦区\n", + "230707,新青区\n", + "230708,美溪区\n", + "230709,金山屯\n", + "230710,五营区\n", + "230711,乌马河\n", + "230712,汤旺河\n", + "230713,带岭区\n", + "230714,乌伊岭\n", + "230715,红星区\n", + "230716,上甘岭\n", + "230722,嘉荫县\n", + "230781,铁力市\n", + "230800,佳木斯\n", + "230803,向阳区\n", + "230804,前进区\n", + "230805,东风区\n", + "230811,郊区\n", + "230822,桦南县\n", + "230826,桦川县\n", + "230828,汤原县\n", + "230833,抚远县\n", + "230881,同江市\n", + "230882,富锦市\n", + "230900,七台河\n", + "230902,新兴区\n", + "230903,桃山市\n", + "230904,茄子河区\n", + "230921,勃利县\n", + "231000,牡丹江\n", + "231002,东安区\n", + "231003,阳明区\n", + "231004,爱民区\n", + "231005,西安区\n", + "231024,东宁县\n", + "231025,林口县\n", + "231081,绥芬河市\n", + "231083,海林市\n", + "231084,宁安市\n", + "231085,穆棱市\n", + "231100,黑河\n", + "231102,爱辉区\n", + "231121,嫩江县\n", + "231123,逊克县\n", + "231124,孙吴县\n", + "231181,北安市\n", + "231182,五大连池市\n", + "231200,绥化\n", + "231202,北林区\n", + "231221,望奎县\n", + "231222,兰西县\n", + "231223,青冈县\n", + "231224,庆安县\n", + "231225,明水县\n", + "231226,绥棱县\n", + "231281,安达市\n", + "231282,肇东市\n", + "231283,海伦市\n", + "232700,大兴安岭\n", + "232701,加格达奇区\n", + "232702,松岭区\n", + "232703,新林区\n", + "232704,呼中区\n", + "232721,呼玛县\n", + "232722,塔河县\n", + "232723,漠河县\n", + "310000,上海\n", + "310101,黄浦区\n", + "310104,徐汇区\n", + "310105,长宁区\n", + "310106,静安区\n", + "310107,普陀区\n", + "310108,闸北区\n", + "310109,虹口区\n", + "310110,杨浦区\n", + "310112,闵行区\n", + "310113,宝山区\n", + "310114,嘉定区\n", + "310115,浦东新区\n", + "310116,金山区\n", + "310117,松江区\n", + "310118,青浦区\n", + "310120,奉贤区\n", + "310230,崇明县\n", + "320000,江苏\n", + "320100,南京\n", + "320102,玄武区\n", + "320104,秦淮区\n", + "320105,建邺区\n", + "320106,鼓楼区\n", + "320111,浦口区\n", + "320113,栖霞区\n", + "320114,雨花台区\n", + "320115,江宁区\n", + "320116,六合区\n", + "320124,溧水区\n", + "320125,高淳区\n", + "320200,无锡\n", + "320202,崇安区\n", + "320203,南长区\n", + "320204,北塘区\n", + "320205,锡山区\n", + "320206,惠山区\n", + "320211,滨湖区\n", + "320281,江阴市\n", + "320282,宜兴市\n", + "320300,徐州\n", + "320302,鼓楼区\n", + "320303,云龙区\n", + "320305,贾汪区\n", + "320311,泉山区\n", + "320312,铜山区\n", + "320321,丰县\n", + "320322,沛县\n", + "320324,睢宁县\n", + "320381,新沂市\n", + "320382,邳州市\n", + "320400,常州\n", + "320402,天宁区\n", + "320404,钟楼区\n", + "320405,戚墅堰区\n", + "320411,新北区\n", + "320412,武进区\n", + "320481,溧阳市\n", + "320482,金坛区\n", + "320500,苏州\n", + "320505,虎丘区\n", + "320506,吴中区\n", + "320507,相城区\n", + "320508,姑苏区\n", + "320509,吴江区\n", + "320581,常熟市\n", + "320582,张家港市\n", + "320583,昆山市\n", + "320585,太仓市\n", + "320600,南通\n", + "320602,崇川区\n", + "320611,港闸区\n", + "320612,通州区\n", + "320621,海安县\n", + "320623,如东县\n", + "320681,启东市\n", + "320682,如皋市\n", + "320684,海门市\n", + "320700,连云港\n", + "320703,连云区\n", + "320705,新浦区\n", + "320706,海州区\n", + "320721,赣榆区\n", + "320722,东海县\n", + "320723,灌云县\n", + "320724,灌南县\n", + "320800,淮安\n", + "320802,清河区\n", + "320803,淮安区\n", + "320804,淮阴区\n", + "320811,清浦区\n", + "320826,涟水县\n", + "320829,洪泽县\n", + "320830,盱眙县\n", + "320831,金湖县\n", + "320900,盐城\n", + "320902,亭湖区\n", + "320903,盐都区\n", + "320921,响水县\n", + "320922,滨海县\n", + "320923,阜宁县\n", + "320924,射阳县\n", + "320925,建湖县\n", + "320981,东台市\n", + "320982,大丰市\n", + "321000,扬州\n", + "321002,广陵区\n", + "321003,邗江区\n", + "321012,江都区\n", + "321023,宝应县\n", + "321081,仪征市\n", + "321084,高邮市\n", + "321101,镇江\n", + "321102,京口区\n", + "321111,润州区\n", + "321112,丹徒区\n", + "321181,丹阳市\n", + "321182,扬中市\n", + "321183,句容市\n", + "321200,泰州\n", + "321202,海陵区\n", + "321203,高港区\n", + "321281,兴化市\n", + "321282,靖江市\n", + "321283,泰兴市\n", + "321284,姜堰区\n", + "321300,宿迁\n", + "321302,宿城区\n", + "321311,宿豫区\n", + "321322,沭阳县\n", + "321323,泗阳县\n", + "321324,泗洪县\n", + "330000,浙江省\n", + "330100,杭州\n", + "330102,上城区\n", + "330103,下城区\n", + "330104,江干区\n", + "330105,拱墅区\n", + "330106,西湖区\n", + "330108,滨江区\n", + "330109,萧山区\n", + "330110,余杭区\n", + "330122,桐庐县\n", + "330127,淳安县\n", + "330182,建德市\n", + "330183,富阳区\n", + "330185,临安市\n", + "330200,宁波\n", + "330203,海曙区\n", + "330204,江东区\n", + "330205,江北区\n", + "330206,北仑区\n", + "330211,镇海区\n", + "330212,鄞州区\n", + "330225,象山县\n", + "330226,宁海县\n", + "330281,余姚市\n", + "330282,慈溪市\n", + "330283,奉化市\n", + "330300,温州\n", + "330302,鹿城区\n", + "330303,龙湾区\n", + "330304,瓯海区\n", + "330322,洞头区\n", + "330324,永嘉县\n", + "330326,平阳县\n", + "330327,苍南县\n", + "330328,文成县\n", + "330329,泰顺县\n", + "330381,瑞安市\n", + "330382,乐清市\n", + "330400,嘉兴\n", + "330402,南湖区\n", + "330411,秀洲区\n", + "330421,嘉善县\n", + "330424,海盐县\n", + "330481,海宁市\n", + "330482,平湖市\n", + "330483,桐乡市\n", + "330500,湖州\n", + "330502,吴兴区\n", + "330503,南浔区\n", + "330521,德清县\n", + "330522,长兴县\n", + "330523,安吉县\n", + "330600,绍兴\n", + "330602,越城区\n", + "330621,柯桥区\n", + "330624,新昌县\n", + "330681,诸暨市\n", + "330682,上虞区\n", + "330683,嵊州市\n", + "330700,金华\n", + "330702,婺城区\n", + "330703,金东区\n", + "330723,武义县\n", + "330726,浦江县\n", + "330727,磐安县\n", + "330781,兰溪市\n", + "330782,义乌市\n", + "330783,东阳市\n", + "330784,永康市\n", + "330800,衢州\n", + "330802,柯城区", + "330803,衢江区\n", + "330822,常山县\n", + "330824,开化县\n", + "330825,龙游县\n", + "330881,江山市\n", + "330900,舟山\n", + "330902,定海区\n", + "330903,普陀区\n", + "330921,岱山县\n", + "330922,嵊泗县\n", + "331000,台州\n", + "331002,椒江区\n", + "331003,黄岩区\n", + "331004,路桥区\n", + "331021,玉环县\n", + "331022,三门县\n", + "331023,天台县\n", + "331024,仙居县\n", + "331081,温岭市\n", + "331082,临海市\n", + "331100,丽水\n", + "331102,莲都区\n", + "331121,青田县\n", + "331122,缙云县\n", + "331123,遂昌县\n", + "331124,松阳县\n", + "331125,云和县\n", + "331126,庆元县\n", + "331127,景宁县\n", + "331181,龙泉市\n", + "340000,安徽\n", + "340100,合肥市\n", + "340102,瑶海区\n", + "340103,庐阳区\n", + "340104,蜀山区\n", + "340111,包河区\n", + "340121,长丰县\n", + "340122,肥东县\n", + "340123,肥西县\n", + "340124,庐江县\n", + "340181,巢湖市\n", + "340200,芜湖市\n", + "340202,镜湖区\n", + "340203,弋江区\n", + "340207,鸠江区\n", + "340208,三山区\n", + "340221,芜湖县\n", + "340222,繁昌县\n", + "340223,南陵县\n", + "340300,蚌埠市\n", + "340302,龙子湖区\n", + "340303,蚌山区\n", + "340304,禹会区\n", + "340311,淮上区\n", + "340321,怀远县\n", + "340322,五河县\n", + "340323,固镇县\n", + "340400,淮南市\n", + "340402,大通区\n", + "340403,田家庵区\n", + "340404,谢家集区\n", + "340405,八公山区\n", + "340406,潘集区\n", + "340421,凤台县\n", + "340500,马鞍山\n", + "340502,博望区\n", + "340503,花山区\n", + "340504,雨山区\n", + "340521,当涂县\n", + "340522,含山县\n", + "340600,淮北市\n", + "340602,杜集区\n", + "340603,相山区\n", + "340604,烈山区\n", + "340621,濉溪县\n", + "340700,铜陵市\n", + "340702,铜官山区\n", + "340703,狮子山区\n", + "340711,郊区\n", + "340721,铜陵县\n", + "340800,安庆市\n", + "340802,迎江区\n", + "340803,大观区\n", + "340811,宜秀区\n", + "340822,怀宁县\n", + "340823,枞阳县\n", + "340824,潜山县\n", + "340825,太湖县\n", + "340826,宿松县\n", + "340827,望江县\n", + "340828,岳西县\n", + "340881,桐城市\n", + "341000,黄山市\n", + "341002,屯溪区\n", + "341003,黄山区\n", + "341004,徽州区\n", + "341021,歙县\n", + "341022,休宁县\n", + "341023,黟县\n", + "341024,祁门县\n", + "341100,滁州市\n", + "341102,琅琊区\n", + "341103,南谯区\n", + "341122,来安县\n", + "341124,全椒县\n", + "341125,定远县\n", + "341126,凤阳县\n", + "341181,天长市\n", + "341182,明光市\n", + "341200,阜阳市\n", + "341202,颍州区\n", + "341203,颍东区\n", + "341204,颍泉区\n", + "341221,临泉县\n", + "341222,太和县\n", + "341225,阜南县\n", + "341226,颍上县\n", + "341282,界首市\n", + "341300,宿州市\n", + "341302,埇桥区\n", + "341321,砀山县\n", + "341322,萧县\n", + "341323,灵璧县\n", + "341324,泗县\n", + "341422,无为县\n", + "341424,和县\n", + "341500,六安市\n", + "341502,金安区\n", + "341503,裕安区\n", + "341521,寿县\n", + "341522,霍邱县\n", + "341523,舒城县\n", + "341524,金寨县\n", + "341525,霍山县\n", + "341600,亳州市\n", + "341602,谯城区\n", + "341621,涡阳县\n", + "341622,蒙城县\n", + "341623,利辛县\n", + "341700,池州市\n", + "341702,贵池区\n", + "341721,东至县\n", + "341722,石台县\n", + "341723,青阳县\n", + "341800,宣城市\n", + "341802,宣州区\n", + "341821,郎溪县\n", + "341822,广德县\n", + "341823,泾县\n", + "341824,绩溪县\n", + "341825,旌德县\n", + "341881,宁国市\n", + "350000,福建\n", + "350100,福州\n", + "350102,鼓楼区\n", + "350103,台江区\n", + "350104,仓山区\n", + "350105,马尾区\n", + "350111,晋安区\n", + "350121,闽侯县\n", + "350122,连江县\n", + "350123,罗源县\n", + "350124,闽清县\n", + "350125,永泰县\n", + "350128,平潭县\n", + "350181,福清市\n", + "350182,长乐市\n", + "350200,厦门\n", + "350203,思明区\n", + "350205,海沧区\n", + "350206,湖里区\n", + "350211,集美区\n", + "350212,同安区\n", + "350213,翔安区\n", + "350300,莆田\n", + "350302,城厢区\n", + "350303,涵江区\n", + "350304,荔城区\n", + "350305,秀屿区\n", + "350322,仙游县\n", + "350400,三明\n", + "350402,梅列区\n", + "350403,三元区\n", + "350421,明溪县\n", + "350423,清流县\n", + "350424,宁化县\n", + "350425,大田县\n", + "350426,尤溪县\n", + "350427,沙县\n", + "350428,将乐县\n", + "350429,泰宁县\n", + "350430,建宁县\n", + "350481,永安市\n", + "350500,泉州\n", + "350502,鲤城区\n", + "350503,丰泽区\n", + "350504,洛江区\n", + "350505,泉港区\n", + "350521,惠安县\n", + "350524,安溪县\n", + "350525,永春县\n", + "350526,德化县\n", + "350527,金门县\n", + "350581,石狮市\n", + "350582,晋江市\n", + "350583,南安市\n", + "350600,漳州\n", + "350602,芗城区\n", + "350603,龙文区\n", + "350622,云霄县\n", + "350623,漳浦县\n", + "350624,诏安县\n", + "350625,长泰县\n", + "350626,东山县\n", + "350627,南靖县\n", + "350628,平和县\n", + "350629,华安县\n", + "350681,龙海市\n", + "350700,南平\n", + "350702,延平区\n", + "350703,建阳区\n", + "350721,顺昌县\n", + "350722,浦城县\n", + "350723,光泽县\n", + "350724,松溪县\n", + "350725,政和县\n", + "350781,邵武市\n", + "350782,武夷山市\n", + "350783,建瓯市\n", + "350800,龙岩\n", + "350802,新罗区\n", + "350821,长汀县\n", + "350822,永定区\n", + "350823,上杭县\n", + "350824,武平县\n", + "350825,连城县\n", + "350881,漳平市\n", + "350900,宁德\n", + "350902,蕉城区\n", + "350921,霞浦县\n", + "350922,古田县\n", + "350923,屏南县\n", + "350924,寿宁县\n", + "350925,周宁县\n", + "350926,柘荣县\n", + "350981,福安市\n", + "350982,福鼎市\n", + "360000,江西\n", + "360100,南昌\n", + "360102,东湖区\n", + "360103,西湖区\n", + "360104,青云谱区\n", + "360105,湾里区\n", + "360111,青山湖区\n", + "360121,南昌县\n", + "360122,新建区\n", + "360123,安义县\n", + "360124,进贤县\n", + "360200,景德镇\n", + "360202,昌江区\n", + "360203,珠山区\n", + "360222,浮梁县\n", + "360281,乐平市\n", + "360300,萍乡\n", + "360302,安源区\n", + "360313,湘东区\n", + "360321,莲花县\n", + "360322,上栗县\n", + "360323,芦溪县\n", + "360400,九江\n", + "360402,庐山区\n", + "360403,浔阳区\n", + "360421,九江县\n", + "360423,武宁县\n", + "360424,修水县\n", + "360425,永修县\n", + "360426,德安县\n", + "360427,星子县\n", + "360428,都昌县\n", + "360429,湖口县\n", + "360430,彭泽县\n", + "360481,瑞昌市\n", + "360482,共青城市\n", + "360500,新余\n", + "360502,渝水区\n", + "360521,分宜县\n", + "360600,鹰潭\n", + "360602,月湖区\n", + "360622,余江县\n", + "360681,贵溪市\n", + "360700,赣州\n", + "360702,章贡区\n", + "360721,赣县\n", + "360722,信丰县\n", + "360723,大余县\n", + "360724,上犹县\n", + "360725,崇义县\n", + "360726,安远县\n", + "360727,龙南县\n", + "360728,定南县\n", + "360729,全南县\n", + "360730,宁都县\n", + "360731,于都县\n", + "360732,兴国县\n", + "360733,会昌县\n", + "360734,寻乌县\n", + "360735,石城县\n", + "360781,瑞金市\n", + "360782,南康区\n", + "360800,吉安\n", + "360802,吉州区\n", + "360803,青原区\n", + "360821,吉安县\n", + "360822,吉水县\n", + "360823,峡江县\n", + "360824,新干县\n", + "360825,永丰县\n", + "360826,泰和县\n", + "360827,遂川县\n", + "360828,万安县\n", + "360829,安福县\n", + "360830,永新县\n", + "360881,井冈山市\n", + "360900,宜春\n", + "360902,袁州区\n", + "360921,奉新县\n", + "360922,万载县\n", + "360923,上高县\n", + "360924,宜丰县\n", + "360925,靖安县\n", + "360926,铜鼓县\n", + "360981,丰城市\n", + "360982,樟树市\n", + "360983,高安市\n", + "361000,抚州\n", + "361002,临川区\n", + "361021,南城县\n", + "361022,黎川县\n", + "361023,南丰县\n", + "361024,崇仁县\n", + "361025,乐安县\n", + "361026,宜黄县\n", + "361027,金溪县\n", + "361028,资溪县\n", + "361029,东乡县\n", + "361030,广昌县\n", + "361100,上饶\n", + "361102,信州区\n", + "361121,上饶县\n", + "361122,广丰区\n", + "361123,玉山县\n", + "361124,铅山县\n", + "361125,横峰县\n", + "361126,弋阳县\n", + "361127,余干县\n", + "361128,鄱阳县\n", + "361129,万年县\n", + "361130,婺源县\n", + "361181,德兴市\n", + "370000,山东\n", + "370100,济南\n", + "370102,历下区\n", + "370103,市中区\n", + "370104,槐荫区\n", + "370105,天桥区\n", + "370112,历城区\n", + "370113,长清区\n", + "370124,平阴县\n", + "370125,济阳县\n", + "370126,商河县\n", + "370181,章丘市\n", + "370200,青岛\n", + "370202,市南区\n", + "370203,市北区\n", + "370211,黄岛区\n", + "370212,崂山区\n", + "370213,李沧区\n", + "370214,城阳区\n", + "370281,胶州市\n", + "370282,即墨市\n", + "370283,平度市\n", + "370285,莱西市\n", + "370300,淄博\n", + "370302,淄川区\n", + "370303,张店区\n", + "370304,博山区\n", + "370305,临淄区\n", + "370306,周村区\n", + "370321,桓台县\n", + "370322,高青县\n", + "370323,沂源县\n", + "370400,枣庄\n", + "370402,市中区\n", + "370403,薛城区\n", + "370404,峄城区\n", + "370405,台儿庄区\n", + "370406,山亭区\n", + "370481,滕州市\n", + "370500,东营\n", + "370502,东营区\n", + "370503,河口区\n", + "370521,垦利县\n", + "370522,利津县\n", + "370523,广饶县\n", + "370600,烟台\n", + "370602,芝罘区\n", + "370611,福山区\n", + "370612,牟平区\n", + "370613,莱山区\n", + "370634,长岛县\n", + "370681,龙口市\n", + "370682,莱阳市\n", + "370683,莱州市\n", + "370684,蓬莱市\n", + "370685,招远市\n", + "370686,栖霞市\n", + "370687,海阳市\n", + "370700,潍坊\n", + "370702,潍城区\n", + "370703,寒亭区\n", + "370704,坊子区\n", + "370705,奎文区\n", + "370724,临朐县\n", + "370725,昌乐县\n", + "370781,青州市\n", + "370782,诸城市\n", + "370783,寿光市\n", + "370784,安丘市\n", + "370785,高密市\n", + "370786,昌邑市\n", + "370800,济宁\n", + "370802,市中区\n", + "370811,任城区\n", + "370812,兖州区\n", + "370826,微山县\n", + "370827,鱼台县\n", + "370828,金乡县\n", + "370829,嘉祥县\n", + "370830,汶上县\n", + "370831,泗水县\n", + "370832,梁山县\n", + "370881,曲阜市\n", + "370883,邹城市\n", + "370900,泰安\n", + "370902,泰山区\n", + "370911,岱岳区\n", + "370921,宁阳县\n", + "370923,东平县\n", + "370982,新泰市\n", + "370983,肥城市\n", + "371000,威海\n", + "371002,环翠区\n", + "371081,文登区\n", + "371082,荣成市\n", + "371083,乳山市\n", + "371100,日照\n", + "371102,东港区\n", + "371103,岚山区\n", + "371121,五莲县\n", + "371122,莒县\n", + "371200,莱芜\n", + "371202,莱城区\n", + "371203,钢城区\n", + "371300,临沂\n", + "371302,兰山区\n", + "371311,罗庄区\n", + "371312,河东区\n", + "371321,沂南县\n", + "371322,郯城县\n", + "371323,沂水县\n", + "371324,兰陵县\n", + "371325,费县\n", + "371326,平邑县\n", + "371327,莒南县\n", + "371328,蒙阴县\n", + "371329,临沭县\n", + "371400,德州\n", + "371402,德城区\n", + "371403,陵城区\n", + "371422,宁津县\n", + "371423,庆云县\n", + "371424,临邑县\n", + "371425,齐河县\n", + "371426,平原县\n", + "371427,夏津县\n", + "371428,武城县\n", + "371481,乐陵市\n", + "371482,禹城市\n", + "371500,聊城\n", + "371502,东昌府区\n", + "371521,阳谷县\n", + "371522,莘县\n", + "371523,茌平县\n", + "371524,东阿县\n", + "371525,冠县\n", + "371526,高唐县\n", + "371581,临清市\n", + "371600,滨州\n", + "371602,滨城区\n", + "371603,沾化区\n", + "371621,惠民县\n", + "371622,阳信县\n", + "371623,无棣县\n", + "371625,博兴县\n", + "371626,邹平县\n", + "371700,菏泽\n", + "371702,牡丹区\n", + "371721,曹县\n", + "371722,单县\n", + "371723,成武县\n", + "371724,巨野县\n", + "371725,郓城县\n", + "371726,鄄城县\n", + "371727,定陶县\n", + "371728,东明县\n", + "410000,河南\n", + "410100,郑州\n", + "410102,中原区\n", + "410103,二七区\n", + "410104,管城回族区\n", + "410105,金水区\n", + "410106,上街区\n", + "410108,惠济区\n", + "410122,中牟县\n", + "410181,巩义市\n", + "410182,荥阳市\n", + "410183,新密市\n", + "410184,新郑市\n", + "410185,登封市\n", + "410200,开封\n", + "410202,龙亭区\n", + "410203,顺河回族区\n", + "410204,鼓楼区\n", + "410205,禹王台区\n", + "410211,金明区\n", + "410212,祥符区\n", + "410221,杞县\n", + "410222,通许县\n", + "410223,尉氏县\n", + "410225,兰考县\n", + "410300,洛阳\n", + "410302,老城区\n", + "410303,西工区\n", + "410304,瀍河区\n", + "410305,涧西区\n", + "410306,吉利区\n", + "410311,洛龙区\n", + "410322,孟津县\n", + "410323,新安县\n", + "410324,栾川县\n", + "410325,嵩县\n", + "410326,汝阳县\n", + "410327,宜阳县\n", + "410328,洛宁县\n", + "410329,伊川县\n", + "410381,偃师市\n", + "410400,平顶山\n", + "410402,新华区\n", + "410403,卫东区\n", + "410404,石龙区\n", + "410411,湛河区\n", + "410421,宝丰县\n", + "410422,叶县\n", + "410423,鲁山县\n", + "410425,郏县\n", + "410481,舞钢市\n", + "410482,汝州市\n", + "410500,安阳\n", + "410502,文峰区\n", + "410503,北关区\n", + "410505,殷都区\n", + "410506,龙安区\n", + "410522,安阳县\n", + "410523,汤阴县\n", + "410526,滑县\n", + "410527,内黄县\n", + "410581,林州市\n", + "410600,鹤壁\n", + "410602,鹤山区\n", + "410603,山城区\n", + "410611,淇滨区\n", + "410621,浚县\n", + "410622,淇县\n", + "410700,新乡\n", + "410702,红旗区\n", + "410703,卫滨区\n", + "410704,凤泉区\n", + "410711,牧野区\n", + "410721,新乡县\n", + "410724,获嘉县\n", + "410725,原阳县\n", + "410726,延津县\n", + "410727,封丘县\n", + "410728,长垣县\n", + "410781,卫辉市\n", + "410782,辉县市\n", + "410800,焦作\n", + "410802,解放区\n", + "410803,中站区\n", + "410804,马村区\n", + "410811,山阳区\n", + "410821,修武县\n", + "410822,博爱县\n", + "410823,武陟县\n", + "410825,温县\n", + "410882,沁阳市\n", + "410883,孟州市\n", + "410900,濮阳\n", + "410902,华龙区\n", + "410922,清丰县\n", + "410923,南乐县\n", + "410926,范县\n", + "410927,台前县\n", + "410928,濮阳县\n", + "411000,许昌市\n", + "411002,魏都区\n", + "411023,许昌县\n", + "411024,鄢陵县\n", + "411025,襄城县\n", + "411081,禹州市\n", + "411082,长葛市\n", + "411100,漯河\n", + "411102,源汇区\n", + "411103,郾城区\n", + "411104,召陵区\n", + "411121,舞阳县\n", + "411122,临颍县\n", + "411200,三门峡\n", + "411202,湖滨区\n", + "411221,渑池县\n", + "411222,陕州区\n", + "411224,卢氏县\n", + "411281,义马市\n", + "411282,灵宝市\n", + "411300,南阳\n", + "411302,宛城区\n", + "411303,卧龙区\n", + "411321,南召县\n", + "411322,方城县\n", + "411323,西峡县\n", + "411324,镇平县\n", + "411325,内乡县\n", + "411326,淅川县\n", + "411327,社旗县\n", + "411328,唐河县\n", + "411329,新野县\n", + "411330,桐柏县\n", + "411381,邓州市\n", + "411400,商丘\n", + "411402,梁园区\n", + "411403,睢阳区\n", + "411421,民权县\n", + "411422,睢县\n", + "411423,宁陵县\n", + "411424,柘城县\n", + "411425,虞城县\n", + "411426,夏邑县\n", + "411481,永城市\n", + "411500,信阳\n", + "411502,浉河区\n", + "411503,平桥区\n", + "411521,罗山县\n", + "411522,光山县\n", + "411523,新县\n", + "411524,商城县\n", + "411525,固始县\n", + "411526,潢川县\n", + "411527,淮滨县\n", + "411528,息县\n", + "411600,周口\n", + "411602,川汇区\n", + "411621,扶沟县\n", + "411622,西华县\n", + "411623,商水县\n", + "411624,沈丘县\n", + "411625,郸城县\n", + "411626,淮阳县\n", + "411627,太康县\n", + "411628,鹿邑县\n", + "411681,项城市\n", + "411700,驻马店\n", + "411702,驿城区\n", + "411721,西平县\n", + "411722,上蔡县\n", + "411723,平舆县\n", + "411724,正阳县\n", + "411725,确山县\n", + "411726,泌阳县\n", + "411727,汝南县\n", + "411728,遂平县\n", + "411729,新蔡县\n", + "419001,济源\n", + "420000,湖北\n", + "420100,武汉市\n", + "420102,江岸区\n", + "420103,江汉区\n", + "420104,硚口区\n", + "420105,汉阳区\n", + "420106,武昌区\n", + "420107,青山区\n", + "420111,洪山区\n", + "420112,东西湖区\n", + "420113,汉南区\n", + "420114,蔡甸区\n", + "420115,江夏区\n", + "420116,黄陂区\n", + "420117,新洲区\n", + "420200,黄石市\n", + "420202,黄石港区\n", + "420203,西塞山区\n", + "420204,下陆区\n", + "420205,铁山区\n", + "420222,阳新县\n", + "420281,大冶市\n", + "420300,十堰市\n", + "420302,茅箭区\n", + "420303,张湾区\n", + "420321,郧阳区\n", + "420322,郧西县\n", + "420323,竹山县\n", + "420324,竹溪县\n", + "420325,房县\n", + "420381,丹江口市\n", + "420500,宜昌市\n", + "420502,西陵区\n", + "420503,伍家岗区\n", + "420504,点军区\n", + "420505,猇亭区\n", + "420506,夷陵区\n", + "420525,远安县\n", + "420526,兴山县\n", + "420527,秭归县\n", + "420528,长阳县\n", + "420529,五峰县\n", + "420581,宜都市\n", + "420582,当阳市\n", + "420583,枝江市\n", + "420600,襄阳市\n", + "420602,襄城区\n", + "420606,樊城区\n", + "420607,襄州区\n", + "420624,南漳县\n", + "420625,谷城县\n", + "420626,保康县\n", + "420682,老河口市\n", + "420683,枣阳市\n", + "420684,宜城市\n", + "420700,鄂州市\n", + "420702,梁子湖区\n", + "420703,华容区\n", + "420704,鄂城区\n", + "420800,荆门市\n", + "420802,东宝区\n", + "420804,掇刀区\n", + "420821,京山县\n", + "420822,沙洋县\n", + "420881,钟祥市\n", + "420900,孝感市\n", + "420902,孝南区\n", + "420921,孝昌县\n", + "420922,大悟县\n", + "420923,云梦县\n", + "420981,应城市\n", + "420982,安陆市\n", + "420984,汉川市\n", + "421000,荆州市\n", + "421002,沙市区\n", + "421003,荆州区\n", + "421022,公安县\n", + "421023,监利县\n", + "421024,江陵县\n", + "421081,石首市\n", + "421083,洪湖市\n", + "421087,松滋市\n", + "421100,黄冈市\n", + "421102,黄州区\n", + "421121,团风县\n", + "421122,红安县\n", + "421123,罗田县\n", + "421124,英山县\n", + "421125,浠水县\n", + "421126,蕲春县\n", + "421127,黄梅县\n", + "421181,麻城市\n", + "421182,武穴市\n", + "421200,咸宁市\n", + "421202,咸安区\n", + "421221,嘉鱼县\n", + "421222,通城县\n", + "421223,崇阳县\n", + "421224,通山县\n", + "421281,赤壁市\n", + "421300,随州市\n", + "421302,曾都区\n", + "421321,随县\n", + "421381,广水市\n", + "422800,恩施州\n", + "422801,恩施市\n", + "422802,利川市\n", + "422822,建始县\n", + "422823,巴东县\n", + "422825,宣恩县\n", + "422826,咸丰县\n", + "422827,来凤县\n", + "422828,鹤峰县\n", + "429004,仙桃市\n", + "429005,潜江市\n", + "429006,天门市\n", + "429021,神农架\n", + "430000,湖南\n", + "430100,长沙\n", + "430102,芙蓉区\n", + "430103,天心区\n", + "430104,岳麓区\n", + "430105,开福区\n", + "430111,雨花区\n", + "430112,望城区\n", + "430121,长沙县\n", + "430124,宁乡县\n", + "430181,浏阳市\n", + "430200,株洲\n", + "430202,荷塘区\n", + "430203,芦淞区\n", + "430204,石峰区\n", + "430211,天元区\n", + "430221,株洲县\n", + "430223,攸县\n", + "430224,茶陵县\n", + "430225,炎陵县\n", + "430281,醴陵市\n", + "430300,湘潭\n", + "430302,雨湖区\n", + "430304,岳塘区\n", + "430321,湘潭县\n", + "430381,湘乡市\n", + "430382,韶山市\n", + "430400,衡阳\n", + "430405,珠晖区\n", + "430406,雁峰区\n", + "430407,石鼓区\n", + "430408,蒸湘区\n", + "430412,南岳区\n", + "430421,衡阳县\n", + "430422,衡南县\n", + "430423,衡山县\n", + "430424,衡东县\n", + "430426,祁东县\n", + "430481,耒阳市\n", + "430482,常宁市\n", + "430500,邵阳\n", + "430502,双清区\n", + "430503,大祥区\n", + "430511,北塔区\n", + "430521,邵东县\n", + "430522,新邵县\n", + "430523,邵阳县\n", + "430524,隆回县\n", + "430525,洞口县\n", + "430527,绥宁县\n", + "430528,新宁县\n", + "430529,城步苗族自治县\n", + "430581,武冈市\n", + "430600,岳阳\n", + "430602,岳阳楼区\n", + "430603,云溪区\n", + "430611,君山区\n", + "430621,岳阳县\n", + "430623,华容县\n", + "430624,湘阴县\n", + "430626,平江县\n", + "430681,汨罗市\n", + "430682,临湘市\n", + "430700,常德\n", + "430702,武陵区\n", + "430703,鼎城区\n", + "430721,安乡县\n", + "430722,汉寿县\n", + "430723,澧县\n", + "430724,临澧县\n", + "430725,桃源县\n", + "430726,石门县\n", + "430781,津市市\n", + "430800,张家界\n", + "430802,永定区\n", + "430811,武陵源区\n", + "430821,慈利县\n", + "430822,桑植县\n", + "430900,益阳\n", + "430902,资阳区\n", + "430903,赫山区\n", + "430921,南县\n", + "430922,桃江县\n", + "430923,安化县\n", + "430981,沅江市\n", + "431000,郴州\n", + "431002,北湖区\n", + "431003,苏仙区\n", + "431021,桂阳县\n", + "431022,宜章县\n", + "431023,永兴县\n", + "431024,嘉禾县\n", + "431025,临武县\n", + "431026,汝城县\n", + "431027,桂东县\n", + "431028,安仁县\n", + "431081,资兴市\n", + "431100,永州\n", + "431102,零陵区\n", + "431103,冷水滩区\n", + "431121,祁阳县\n", + "431122,东安县\n", + "431123,双牌县\n", + "431124,道县\n", + "431125,江永县\n", + "431126,宁远县\n", + "431127,蓝山县\n", + "431128,新田县\n", + "431129,江华县\n", + "431200,怀化\n", + "431202,鹤城区\n", + "431221,中方县\n", + "431222,沅陵县\n", + "431223,辰溪县\n", + "431224,溆浦县\n", + "431225,会同县\n", + "431226,麻阳县\n", + "431227,新晃县\n", + "431228,芷江县\n", + "431229,靖州县\n", + "431230,通道县\n", + "431281,洪江市\n", + "431300,娄底\n", + "431302,娄星区\n", + "431321,双峰县\n", + "431322,新化县\n", + "431381,冷水江市\n", + "431382,涟源市\n", + "433100,湘西州\n", + "433101,吉首市\n", + "433122,泸溪县\n", + "433123,凤凰县\n", + "433124,花垣县\n", + "433125,保靖县\n", + "433126,古丈县\n", + "433127,永顺县\n", + "433130,龙山县\n", + "440000,广东\n", + "440100,广州市\n", + "440103,荔湾区\n", + "440104,越秀区\n", + "440105,海珠区\n", + "440106,天河区\n", + "440111,白云区\n", + "440112,黄埔区\n", + "440113,番禺区\n", + "440114,花都区\n", + "440115,南沙区\n", + "440116,萝岗区\n", + "440183,增城区\n", + "440184,从化区\n", + "440200,韶关市\n", + "440203,武江区\n", + "440204,浈江区\n", + "440205,曲江区\n", + "440222,始兴县\n", + "440224,仁化县\n", + "440229,翁源县\n", + "440232,乳源县\n", + "440233,新丰县\n", + "440281,乐昌市\n", + "440282,南雄市\n", + "440300,深圳市\n", + "440303,罗湖区\n", + "440304,福田区\n", + "440305,南山区\n", + "440306,宝安区\n", + "440307,龙岗区\n", + "440308,盐田区\n", + "440400,珠海市\n", + "440402,香洲区\n", + "440403,斗门区\n", + "440404,金湾区\n", + "440500,汕头市\n", + "440507,龙湖区\n", + "440511,金平区\n", + "440512,濠江区\n", + "440513,潮阳区\n", + "440514,潮南区\n", + "440515,澄海区\n", + "440523,南澳县\n", + "440600,佛山市\n", + "440604,禅城区\n", + "440605,南海区\n", + "440606,顺德区\n", + "440607,三水区\n", + "440608,高明区\n", + "440700,江门市\n", + "440703,蓬江区\n", + "440704,江海区\n", + "440705,新会区\n", + "440781,台山市\n", + "440783,开平市\n", + "440784,鹤山市\n", + "440785,恩平市\n", + "440800,湛江市\n", + "440802,赤坎区\n", + "440803,霞山区\n", + "440804,坡头区\n", + "440811,麻章区\n", + "440823,遂溪县\n", + "440825,徐闻县\n", + "440881,廉江市\n", + "440882,雷州市\n", + "440883,吴川市\n", + "440900,茂名市\n", + "440902,茂南区\n", + "440903,茂港区\n", + "440923,电白区\n", + "440981,高州市\n", + "440982,化州市\n", + "440983,信宜市\n", + "441200,肇庆市\n", + "441202,端州区\n", + "441203,鼎湖区\n", + "441223,广宁县\n", + "441224,怀集县\n", + "441225,封开县\n", + "441226,德庆县\n", + "441283,高要区\n", + "441284,四会市\n", + "441300,惠州市\n", + "441302,惠城区\n", + "441303,惠阳区\n", + "441322,博罗县\n", + "441323,惠东县\n", + "441324,龙门县\n", + "441400,梅州市\n", + "441402,梅江区\n", + "441421,梅县区\n", + "441422,大埔县\n", + "441423,丰顺县\n", + "441424,五华县\n", + "441426,平远县\n", + "441427,蕉岭县\n", + "441481,兴宁市\n", + "441500,汕尾市\n", + "441502,城区\n", + "441521,海丰县\n", + "441523,陆河县\n", + "441581,陆丰市\n", + "441600,河源市\n", + "441602,源城区\n", + "441621,紫金县\n", + "441622,龙川县\n", + "441623,连平县\n", + "441624,和平县\n", + "441625,东源县\n", + "441700,阳江市\n", + "441702,江城区\n", + "441721,阳西县\n", + "441723,阳东区\n", + "441781,阳春市\n", + "441800,清远市\n", + "441802,清城区\n", + "441821,佛冈县\n", + "441823,阳山县\n", + "441825,连山县\n", + "441826,连南县\n", + "441827,清新县\n", + "441881,英德市\n", + "441882,连州市\n", + "441900,东莞市\n", + "442000,中山市\n", + "445100,潮州市\n", + "445102,湘桥区\n", + "445103,潮安区\n", + "445122,饶平县\n", + "445200,揭阳市\n", + "445202,榕城区\n", + "445221,揭东区\n", + "445222,揭西县\n", + "445224,惠来县\n", + "445281,普宁市\n", + "445300,云浮市\n", + "445302,云城区\n", + "445303,云安区\n", + "445321,新兴县\n", + "445322,郁南县\n", + "445381,罗定市\n", + "450000,广西\n", + "450100,南宁\n", + "450102,兴宁区\n", + "450103,青秀区\n", + "450105,江南区\n", + "450107,西乡塘区\n", + "450108,良庆区\n", + "450109,邕宁区\n", + "450122,武鸣区\n", + "450123,隆安县\n", + "450124,马山县\n", + "450125,上林县\n", + "450126,宾阳县\n", + "450127,横县\n", + "450200,柳州\n", + "450202,城中区\n", + "450203,鱼峰区\n", + "450204,柳南区\n", + "450205,柳北区\n", + "450221,柳江县\n", + "450222,柳城县\n", + "450223,鹿寨县\n", + "450224,融安县\n", + "450225,融水县\n", + "450226,三江县\n", + "450300,桂林\n", + "450302,秀峰区\n", + "450303,叠彩区\n", + "450304,象山区\n", + "450305,七星区\n", + "450311,雁山区\n", + "450312,临桂区\n", + "450321,阳朔县\n", + "450323,灵川县\n", + "450324,全州县\n", + "450325,兴安县\n", + "450326,永福县\n", + "450327,灌阳县\n", + "450328,龙胜县\n", + "450329,资源县\n", + "450330,平乐县\n", + "450331,荔浦县\n", + "450332,恭城县\n", + "450400,梧州\n", + "450403,万秀区\n", + "450404,龙圩区\n", + "450405,长洲区\n", + "450421,苍梧县\n", + "450422,藤县\n", + "450423,蒙山县\n", + "450481,岑溪市\n", + "450500,北海\n", + "450502,海城区\n", + "450503,银海区\n", + "450512,铁山港区\n", + "450521,合浦县\n", + "450600,防城港\n", + "450602,港口区\n", + "450603,防城区\n", + "450621,上思县\n", + "450681,东兴市\n", + "450700,钦州\n", + "450702,钦南区\n", + "450703,钦北区\n", + "450721,灵山县\n", + "450722,浦北区\n", + "450800,贵港\n", + "450802,港北区\n", + "450803,港南区\n", + "450804,覃塘区\n", + "450821,平南县\n", + "450881,桂平市\n", + "450900,玉林\n", + "450902,玉州区\n", + "450921,容县\n", + "450922,陆川县\n", + "450923,博白县\n", + "450924,兴业县\n", + "450981,北流市\n", + "451000,百色\n", + "451002,右江区\n", + "451021,田阳县\n", + "451022,田东县\n", + "451023,平果县\n", + "451024,德保县\n", + "451025,靖西县\n", + "451026,那坡县\n", + "451027,凌云县\n", + "451028,乐业县\n", + "451029,田林县\n", + "451030,西林县\n", + "451031,隆林县\n", + "451100,贺州\n", + "451102,八步区\n", + "451121,昭平县\n", + "451122,钟山县\n", + "451123,富川县\n", + "451200,河池\n", + "451202,金城江区\n", + "451221,南丹县\n", + "451222,天蛾县\n", + "451223,凤山县\n", + "451224,东兰县\n", + "451225,罗城县\n", + "451226,环江县\n", + "451227,巴马县\n", + "451228,都安县\n", + "451229,大化县\n", + "451281,宜州市\n", + "451300,来宾\n", + "451302,兴宾区\n", + "451321,忻城县\n", + "451322,象州县\n", + "451323,武宣县\n", + "451324,金秀县\n", + "451381,合山市\n", + "451400,崇左\n", + "451402,江州区\n", + "451421,扶绥县\n", + "451422,宁明县\n", + "451423,龙州县\n", + "451424,大新县\n", + "451425,天等县\n", + "451481,凭祥市\n", + "460000,海南\n", + "460100,海口市\n", + "460105,秀英区\n", + "460106,龙华区\n", + "460107,琼山区\n", + "460108,美兰区\n", + "460200,三亚市\n", + "469001,五指山市\n", + "469002,琼海市\n", + "469003,儋州市\n", + "469005,文昌市\n", + "469006,万宁市\n", + "469007,东方市\n", + "469021,定安县\n", + "469022,屯昌县\n", + "469023,澄迈县\n", + "469024,临高县\n", + "469025,白沙县\n", + "469026,昌江县\n", + "469027,乐东县\n", + "469028,陵水县\n", + "469029,保亭县\n", + "469030,琼中县\n", + "469031,西沙群岛\n", + "469031,三沙市\n", + "469032,南沙群岛\n", + "469033,中沙群岛的岛礁及其海域\n", + "500000,重庆\n", + "500101,万州区\n", + "500102,涪陵区\n", + "500103,渝中区\n", + "500104,大渡口区\n", + "500105,江北区\n", + "500106,沙坪坝区\n", + "500107,九龙坡区\n", + "500108,南岸区\n", + "500109,北碚区\n", + "500110,万盛区\n", + "500110,綦江区\n", + "500111,大足区\n", + "500111,双桥区\n", + "500112,渝北区\n", + "500113,巴南区\n", + "500114,黔江区\n", + "500115,长寿区\n", + "500116,江津区\n", + "500117,合川区\n", + "500118,永川区\n", + "500119,南川区\n", + "500120,铜梁区\n", + "500121,璧山区\n", + "500223,潼南区\n", + "500226,荣昌区\n", + "500228,梁平县\n", + "500229,城口县\n", + "500230,丰都县\n", + "500231,垫江县\n", + "500232,武隆县\n", + "500233,忠县\n", + "500234,开县\n", + "500235,云阳县\n", + "500236,奉节县\n", + "500237,巫山县\n", + "500238,巫溪县\n", + "500240,石柱县\n", + "500241,秀山县\n", + "500242,酉阳县\n", + "500243,彭水县\n", + "510000,四川\n", + "510100,成都\n", + "510104,锦江区\n", + "510105,青羊区\n", + "510106,金牛区\n", + "510107,武侯区\n", + "510108,成华区\n", + "510112,龙泉驿区\n", + "510113,青白江区\n", + "510114,新都区\n", + "510115,温江区\n", + "510121,金堂县\n", + "510122,双流县\n", + "510124,郫县\n", + "510129,大邑县\n", + "510131,蒲江县\n", + "510132,新津县\n", + "510181,都江堰市\n", + "510182,彭州市\n", + "510183,邛崃市\n", + "510184,崇州市\n", + "510300,自贡\n", + "510302,自流井区\n", + "510303,贡井区\n", + "510304,大安区\n", + "510311,沿滩区\n", + "510321,荣县\n", + "510322,富顺县\n", + "510400,攀枝花\n", + "510402,东区\n", + "510403,西区\n", + "510411,仁和区\n", + "510421,米易县\n", + "510422,盐边县\n", + "510500,泸州\n", + "510502,江阳区\n", + "510503,纳溪区\n", + "510504,龙马潭区\n", + "510521,泸县\n", + "510522,合江县\n", + "510524,叙永县\n", + "510525,古蔺县\n", + "510600,德阳\n", + "510603,旌阳区\n", + "510623,中江县\n", + "510626,罗江县\n", + "510681,广汉市\n", + "510682,什邡市\n", + "510683,绵竹市\n", + "510700,绵阳\n", + "510703,涪城区\n", + "510704,游仙区\n", + "510722,三台县\n", + "510723,盐亭县\n", + "510724,安县\n", + "510725,梓潼县\n", + "510726,北川县\n", + "510727,平武县\n", + "510781,江油市\n", + "510800,广元\n", + "510802,利州区\n", + "510811,昭化区\n", + "510812,朝天区\n", + "510821,旺苍县\n", + "510822,青川县\n", + "510823,剑阁县\n", + "510824,苍溪县\n", + "510900,遂宁\n", + "510903,船山区\n", + "510904,安居区\n", + "510921,蓬溪县\n", + "510922,射洪县\n", + "510923,大英县\n", + "511000,内江\n", + "511002,市中区\n", + "511011,东兴区\n", + "511024,威远县\n", + "511025,资中县\n", + "511028,隆昌县\n", + "511100,乐山\n", + "511102,市中区\n", + "511111,沙湾区\n", + "511112,五通桥区\n", + "511113,金口河区\n", + "511123,犍为县\n", + "511124,井研县\n", + "511126,夹江县\n", + "511129,沐川县\n", + "511132,峨边彝族自治县\n", + "511133,马边彝族自治县\n", + "511181,峨眉山市\n", + "511300,南充\n", + "511302,顺庆区\n", + "511303,高坪区\n", + "511304,嘉陵区\n", + "511321,南部县\n", + "511322,营山县\n", + "511323,蓬安县\n", + "511324,仪陇县\n", + "511325,西充县\n", + "511381,阆中市\n", + "511400,眉山\n", + "511402,东坡区\n", + "511403,彭山区\n", + "511421,仁寿县\n", + "511423,洪雅县\n", + "511424,丹棱县\n", + "511425,青神县\n", + "511500,宜宾\n", + "511502,翠屏区\n", + "511503,南溪区\n", + "511521,宜宾县\n", + "511523,江安县\n", + "511524,长宁县\n", + "511525,高县\n", + "511526,珙县\n", + "511527,筠连县\n", + "511528,兴文县\n", + "511529,屏山县\n", + "511600,广安\n", + "511600,前锋区\n", + "511602,广安区\n", + "511621,岳池县\n", + "511622,武胜县\n", + "511623,邻水县\n", + "511681,华蓥市\n", + "511700,达州\n", + "511702,通川区\n", + "511703,达川区\n", + "511722,宣汉县\n", + "511723,开江县\n", + "511724,大竹县\n", + "511725,渠县\n", + "511781,万源市\n", + "511800,雅安\n", + "511802,雨城区\n", + "511821,名山区\n", + "511822,荥经县\n", + "511823,汉源县\n", + "511824,石棉县\n", + "511825,天全县\n", + "511826,芦山县\n", + "511827,宝兴县\n", + "511900,巴中\n", + "511902,巴州区\n", + "511903,恩阳区\n", + "511921,通江县\n", + "511922,南江县\n", + "511923,平昌县\n", + "512000,资阳\n", + "512002,雁江区\n", + "512021,安岳县\n", + "512022,乐至县\n", + "512081,简阳市\n", + "513200,阿坝\n", + "513221,汶川县\n", + "513222,理县\n", + "513223,茂县\n", + "513224,松潘县\n", + "513225,九寨沟\n", + "513226,金川县\n", + "513227,小金县\n", + "513228,黑水县\n", + "513229,马尔康县\n", + "513230,壤塘县\n", + "513231,阿坝县\n", + "513232,若尔盖县\n", + "513233,红原县\n", + "513300,甘孜\n", + "513321,康定市\n", + "513322,泸定县\n", + "513323,丹巴县\n", + "513324,九龙县\n", + "513325,雅江县\n", + "513326,道孚县\n", + "513327,炉霍县\n", + "513328,甘孜县\n", + "513329,新龙县\n", + "513330,德格县\n", + "513331,白玉县\n", + "513332,石渠县\n", + "513333,色达县\n", + "513334,理塘县\n", + "513335,巴塘县\n", + "513336,乡城县\n", + "513337,稻城县\n", + "513338,得荣县\n", + "513400,凉山州\n", + "513401,西昌市\n", + "513422,木里县\n", + "513423,盐源县\n", + "513424,德昌县\n", + "513425,会理县\n", + "513426,会东县\n", + "513427,宁南县\n", + "513428,普格县\n", + "513429,布拖县\n", + "513430,金阳县\n", + "513431,昭觉县\n", + "513432,喜德县\n", + "513433,冕宁县\n", + "513434,越西县\n", + "513435,甘洛县\n", + "513436,美姑县\n", + "513437,雷波县\n", + "520000,贵州\n", + "520100,贵阳\n", + "520102,南明区\n", + "520103,云岩区\n", + "520111,花溪区\n", + "520112,乌当区\n", + "520113,白云区\n", + "520114,观山湖区\n", + "520121,开阳县\n", + "520122,息烽县\n", + "520123,修文县\n", + "520181,清镇市\n", + "520200,六盘水\n", + "520201,钟山区\n", + "520203,六枝特区\n", + "520221,水城县\n", + "520222,盘县\n", + "520300,遵义\n", + "520302,红花岗区\n", + "520303,汇川区\n", + "520321,遵义县\n", + "520322,桐梓县\n", + "520323,绥阳县\n", + "520324,正安县\n", + "520325,道真县\n", + "520326,务川县\n", + "520327,凤冈县\n", + "520328,湄潭县\n", + "520329,余庆县\n", + "520330,习水县\n", + "520381,赤水市\n", + "520382,仁怀市\n", + "520400,安顺\n", + "520402,西秀区\n", + "520421,平坝区\n", + "520422,普定县\n", + "520424,关岭县\n", + "520425,紫云县\n", + "520500,毕节市\n", + "520502,七星关区\n", + "520521,大方县\n", + "520522,黔西县\n", + "520523,金沙县\n", + "520524,织金县\n", + "520525,纳雍县\n", + "520526,威宁县\n", + "520527,赫章县\n", + "520600,铜仁市\n", + "520602,碧江区\n", + "520603,万山区\n", + "520621,江口县\n", + "520622,玉屏县\n", + "520623,石阡县\n", + "520624,思南县\n", + "520625,印江县\n", + "520626,德江县\n", + "520627,沿河县\n", + "520628,松桃县\n", + "522300,黔西南州\n", + "522301,兴义市\n", + "522322,兴仁县\n", + "522323,普安县\n", + "522324,晴隆县\n", + "522325,贞丰县\n", + "522326,望谟县\n", + "522327,册亨县\n", + "522328,安龙县\n", + "522600,黔东南州\n", + "522601,凯里市\n", + "522622,黄平县\n", + "522623,施秉县\n", + "522624,三穗县\n", + "522626,岑巩县\n", + "522627,天柱县\n", + "522628,锦屏县\n", + "522629,剑河县\n", + "522630,台江县\n", + "522631,黎平县\n", + "522632,榕江县\n", + "522633,从江县\n", + "522634,雷山县\n", + "522635,麻江县\n", + "522636,丹寨县\n", + "522700,黔南州\n", + "522701,都匀市\n", + "522702,福泉市\n", + "522722,荔波县\n", + "522723,贵定县\n", + "522725,瓮安县\n", + "522726,独山县\n", + "522727,平塘县\n", + "522728,罗甸县\n", + "522729,长顺县\n", + "522730,龙里县\n", + "522731,惠水县\n", + "522732,三都县\n", + "530000,云南\n", + "530100,昆明\n", + "530102,五华区\n", + "530103,盘龙区\n", + "530111,官渡区\n", + "530112,西山区\n", + "530113,东川区\n", + "530121,呈贡区\n", + "530122,晋宁县\n", + "530124,富民县\n", + "530125,宜良县\n", + "530126,石林彝族自治县\n", + "530127,嵩明县\n", + "530128,禄劝县\n", + "530129,寻甸县\n", + "530181,安宁市\n", + "530300,曲靖\n", + "530302,麒麟区\n", + "530321,马龙县\n", + "530322,陆良县\n", + "530323,师宗县\n", + "530324,罗平县\n", + "530325,富源县\n", + "530326,会泽县\n", + "530328,沾益县\n", + "530381,宣威市\n", + "530400,玉溪\n", + "530402,红塔区\n", + "530421,江川县\n", + "530422,澄江县\n", + "530423,通海县\n", + "530424,华宁县\n", + "530425,易门县\n", + "530426,峨山县\n", + "530427,新平县\n", + "530428,元江县\n", + "530500,保山\n", + "530502,隆阳区\n", + "530521,施甸县\n", + "530522,腾冲县\n", + "530523,龙陵县\n", + "530524,昌宁县\n", + "530600,昭通\n", + "530602,昭阳区\n", + "530621,鲁甸县\n", + "530622,巧家县\n", + "530623,盐津县\n", + "530624,大关县\n", + "530625,永善县\n", + "530626,绥江县\n", + "530627,镇雄县\n", + "530628,彝良县\n", + "530629,威信县\n", + "530630,水富县\n", + "530700,丽江\n", + "530702,古城区\n", + "530721,玉龙县\n", + "530722,永胜县\n", + "530723,华坪县\n", + "530724,宁蒗县\n", + "530800,普洱\n", + "530802,思茅区\n", + "530821,宁洱县\n", + "530822,墨江县\n", + "530823,景东县\n", + "530824,景谷县\n", + "530825,镇沅县\n", + "530826,江城县\n", + "530827,孟连县\n", + "530828,澜沧县\n", + "530829,西盟县\n", + "530900,临沧\n", + "530902,临翔区\n", + "530921,凤庆县\n", + "530922,云县\n", + "530923,永德县\n", + "530924,镇康县\n", + "530925,双江县\n", + "530926,耿马县\n", + "530927,沧源县\n", + "532300,楚雄州\n", + "532301,楚雄市\n", + "532322,双柏县\n", + "532323,牟定县\n", + "532324,南华县\n", + "532325,姚安县\n", + "532326,大姚县\n", + "532327,永仁县\n", + "532328,元谋县\n", + "532329,武定县\n", + "532331,禄丰县\n", + "532500,红河州\n", + "532501,个旧市\n", + "532502,开远市\n", + "532503,蒙自市\n", + "532523,屏边县\n", + "532524,建水县\n", + "532525,石屏县\n", + "532526,弥勒市\n", + "532527,泸西县\n", + "532528,元阳县\n", + "532529,红河县\n", + "532530,金平县\n", + "532531,绿春县\n", + "532532,河口县\n", + "532600,文山州\n", + "532621,文山县\n", + "532622,砚山县\n", + "532623,西畴县\n", + "532624,麻栗坡县\n", + "532625,马关县\n", + "532626,丘北县\n", + "532627,广南县\n", + "532628,富宁县\n", + "532800,西双版纳州\n", + "532801,景洪市\n", + "532822,勐海县\n", + "532823,勐腊县\n", + "532900,大理州\n", + "532901,大理市\n", + "532922,漾濞县\n", + "532923,祥云县\n", + "532924,宾川县\n", + "532925,弥渡县\n", + "532926,南涧县\n", + "532927,巍山县\n", + "532928,永平县\n", + "532929,云龙县\n", + "532930,洱源县\n", + "532931,剑川县\n", + "532932,鹤庆县\n", + "533100,德宏州\n", + "533102,瑞丽市\n", + "533103,芒市\n", + "533122,梁河县\n", + "533123,盈江县\n", + "533124,陇川县\n", + "533300,怒江州\n", + "533321,泸水县\n", + "533323,福贡县\n", + "533324,贡山县\n", + "533325,兰坪县\n", + "533400,迪庆州\n", + "533421,香格里拉市\n", + "533422,德钦县\n", + "533423,维西傈僳族自治县\n", + "540000,西藏\n", + "540100,拉萨\n", + "540102,城关区\n", + "540121,林周县\n", + "540122,当雄县\n", + "540123,尼木县\n", + "540124,曲水县\n", + "540125,堆龙德庆县\n", + "540126,达孜县\n", + "540127,墨竹工卡县\n", + "542100,昌都市\n", + "542121,卡若区\n", + "542122,江达县\n", + "542123,贡觉县\n", + "542124,类乌齐县\n", + "542125,丁青县\n", + "542126,察雅县\n", + "542127,八宿县\n", + "542128,左贡县\n", + "542129,芒康县\n", + "542132,洛隆县\n", + "542133,边坝县\n", + "542200,山南\n", + "542221,乃东县\n", + "542222,扎囊县\n", + "542223,贡嘎县\n", + "542224,桑日县\n", + "542225,琼结县\n", + "542226,曲松县\n", + "542227,措美县\n", + "542228,洛扎县\n", + "542229,加查县\n", + "542231,隆子县\n", + "542232,错那县\n", + "542233,浪卡子县\n", + "542300,日喀则市\n", + "542301,桑珠孜区\n", + "542322,南木林县\n", + "542323,江孜县\n", + "542324,定日县\n", + "542325,萨迦县\n", + "542326,拉孜县\n", + "542327,昂仁县\n", + "542328,谢通门县\n", + "542329,白朗县\n", + "542330,仁布县\n", + "542331,康马县\n", + "542332,定结县\n", + "542333,仲巴县\n", + "542334,亚东县\n", + "542335,吉隆县\n", + "542336,聂拉木县\n", + "542337,萨嘎县\n", + "542338,岗巴县\n", + "542400,那曲\n", + "542421,那曲县\n", + "542422,嘉黎县\n", + "542423,比如县\n", + "542424,聂荣县\n", + "542425,安多县\n", + "542426,申扎县\n", + "542427,索县\n", + "542428,班戈县\n", + "542429,巴青县\n", + "542430,尼玛县\n", + "542500,阿里\n", + "542521,普兰县\n", + "542522,札达县\n", + "542523,噶尔县\n", + "542524,日土县\n", + "542525,革吉县\n", + "542526,改则县\n", + "542527,措勤县\n", + "542600,林芝\n", + "542621,林芝县\n", + "542622,工布江达县\n", + "542623,米林县\n", + "542624,墨脱县\n", + "542625,波密县\n", + "542626,察隅县\n", + "542627,朗县\n", + "610000,陕西\n", + "610100,西安市\n", + "610102,新城区\n", + "610103,碑林区\n", + "610104,莲湖区\n", + "610111,灞桥区\n", + "610112,未央区\n", + "610113,雁塔区\n", + "610114,阎良区\n", + "610115,临潼区\n", + "610116,长安区\n", + "610122,蓝田县\n", + "610124,周至县\n", + "610125,户县\n", + "610126,高陵区\n", + "610200,铜川市\n", + "610202,王益区\n", + "610203,印台区\n", + "610204,耀州区\n", + "610222,宜君县\n", + "610300,宝鸡市\n", + "610302,渭滨区\n", + "610303,金台区\n", + "610304,陈仓区\n", + "610322,凤翔县\n", + "610323,岐山县\n", + "610324,扶风县\n", + "610326,眉县\n", + "610327,陇县\n", + "610328,千阳县\n", + "610329,麟游县\n", + "610330,凤县\n", + "610331,太白县\n", + "610400,咸阳市\n", + "610402,秦都区\n", + "610403,杨陵区\n", + "610404,渭城区\n", + "610422,三原县\n", + "610423,泾阳县\n", + "610424,乾县\n", + "610425,礼泉县\n", + "610426,永寿县\n", + "610427,彬县\n", + "610428,长武县\n", + "610429,旬邑县\n", + "610430,淳化县\n", + "610431,武功县\n", + "610481,兴平市\n", + "610500,渭南市\n", + "610502,临渭区\n", + "610521,华县\n", + "610522,潼关县\n", + "610523,大荔县\n", + "610524,合阳县\n", + "610525,澄城县\n", + "610526,蒲城县\n", + "610527,白水县\n", + "610528,富平县\n", + "610581,韩城市\n", + "610582,华阴市\n", + "610600,延安市\n", + "610602,宝塔区\n", + "610621,延长县\n", + "610622,延川县\n", + "610623,子长县\n", + "610624,安塞县\n", + "610625,志丹县\n", + "610626,吴起县\n", + "610627,甘泉县\n", + "610628,富县\n", + "610629,洛川县\n", + "610630,宜川县\n", + "610631,黄龙县\n", + "610632,黄陵县\n", + "610700,汉中市\n", + "610702,汉台区\n", + "610721,南郑县\n", + "610722,城固县\n", + "610723,洋县\n", + "610724,西乡县\n", + "610725,勉县\n", + "610726,宁强县\n", + "610727,略阳县\n", + "610728,镇巴县\n", + "610729,留坝县\n", + "610730,佛坪县\n", + "610800,榆林市\n", + "610802,榆阳区\n", + "610821,神木县\n", + "610822,府谷县\n", + "610823,横山县\n", + "610824,靖边县\n", + "610825,定边县\n", + "610826,绥德县\n", + "610827,米脂县\n", + "610828,佳县\n", + "610829,吴堡县\n", + "610830,清涧县\n", + "610831,子洲县\n", + "610900,安康市\n", + "610902,汉滨区\n", + "610921,汉阴县\n", + "610922,石泉县\n", + "610923,宁陕县\n", + "610924,紫阳县\n", + "610925,岚皋县\n", + "610926,平利县\n", + "610927,镇坪县\n", + "610928,旬阳县\n", + "610929,白河县\n", + "611000,商洛市\n", + "611002,商州区\n", + "611021,洛南县\n", + "611022,丹凤县\n", + "611023,商南县\n", + "611024,山阳县\n", + "611025,镇安县\n", + "611026,柞水县\n", + "620000,甘肃省\n", + "620100,兰州\n", + "620102,城关区\n", + "620103,七里河区\n", + "620104,西固区\n", + "620105,安宁区\n", + "620111,红古区\n", + "620121,永登县\n", + "620122,皋兰县\n", + "620123,榆中县\n", + "620200,嘉峪关\n", + "620300,金昌\n", + "620302,金川区\n", + "620321,永昌县\n", + "620400,白银\n", + "620402,白银区\n", + "620403,平川区\n", + "620421,靖远县\n", + "620422,会宁县\n", + "620423,景泰县\n", + "620500,天水\n", + "620502,秦州区\n", + "620503,麦积区\n", + "620521,清水县\n", + "620522,秦安县\n", + "620523,甘谷县\n", + "620524,武山县\n", + "620525,张家川回族自治县\n", + "620600,武威\n", + "620602,凉州区\n", + "620621,民勤县\n", + "620622,古浪县\n", + "620623,天祝藏族自治县\n", + "620700,张掖\n", + "620702,甘州区\n", + "620721,肃南县\n", + "620722,民乐县\n", + "620723,临泽县\n", + "620724,高台县\n", + "620725,山丹县\n", + "620800,平凉\n", + "620802,崆峒区\n", + "620821,泾川县\n", + "620822,灵台县\n", + "620823,崇信县\n", + "620824,华亭县\n", + "620825,庄浪县\n", + "620826,静宁县\n", + "620900,酒泉\n", + "620902,肃州区\n", + "620921,金塔县\n", + "620922,瓜州县\n", + "620923,肃北县\n", + "620924,阿克塞县\n", + "620981,玉门市\n", + "620982,敦煌市\n", + "621000,庆阳\n", + "621002,西峰区\n", + "621021,庆城县\n", + "621022,环县\n", + "621023,华池县\n", + "621024,合水县\n", + "621025,正宁县\n", + "621026,宁县\n", + "621027,镇原县\n", + "621100,定西\n", + "621102,安定区\n", + "621121,通渭县\n", + "621122,陇西县\n", + "621123,渭源县\n", + "621124,临洮县\n", + "621125,漳县\n", + "621126,岷县\n", + "621200,陇南\n", + "621202,武都区\n", + "621221,成县\n", + "621222,文县\n", + "621223,宕昌县\n", + "621224,康县\n", + "621225,西和县\n", + "621226,礼县\n", + "621227,徽县\n", + "621228,两当县\n", + "622900,临夏州\n", + "622901,临夏市\n", + "622921,临夏县\n", + "622922,康乐县\n", + "622923,永靖县\n", + "622924,广河县\n", + "622925,和政县\n", + "622926,东乡族自治县\n", + "622927,积石山县\n", + "623000,甘南州\n", + "623001,合作市\n", + "623021,临潭县\n", + "623022,卓尼县\n", + "623023,舟曲县\n", + "623024,迭部县\n", + "623025,玛曲县\n", + "623026,碌曲县\n", + "623027,夏河县\n", + "630000,青海\n", + "630100,西宁市\n", + "630102,城东区\n", + "630103,城中区\n", + "630104,城西区\n", + "630105,城北区\n", + "630121,大通县\n", + "630122,湟中县\n", + "630123,湟源县\n", + "632001,乐都区\n", + "632100,海东市\n", + "632121,平安区\n", + "632122,民和县\n", + "632126,互助土族自治县\n", + "632127,化隆回族自治县\n", + "632128,循化撒拉族自治县\n", + "632200,海北州\n", + "632221,门源回族自治县\n", + "632222,祁连县\n", + "632223,海晏县\n", + "632224,刚察县\n", + "632300,黄南州\n", + "632321,同仁县\n", + "632322,尖扎县\n", + "632323,泽库县\n", + "632324,河南蒙古族自治县\n", + "632500,海南州\n", + "632521,共和县\n", + "632522,同德县\n", + "632523,贵德县\n", + "632524,兴海县\n", + "632525,贵南县\n", + "632600,果洛州\n", + "632621,玛沁县\n", + "632622,班玛县\n", + "632623,甘德县\n", + "632624,达日县\n", + "632625,久治县\n", + "632626,玛多县\n", + "632700,玉树州\n", + "632701,玉树市\n", + "632722,杂多县\n", + "632723,称多县\n", + "632724,治多县\n", + "632725,囊谦县\n", + "632726,曲麻莱县\n", + "632800,海西州\n", + "632801,格尔木市\n", + "632802,德令哈市\n", + "632821,乌兰县\n", + "632822,都兰县\n", + "632823,天峻县\n", + "632824,冷湖行委\n", + "632825,大柴旦行委\n", + "632826,茫崖行委\n", + "640000,宁夏\n", + "640100,银川市\n", + "640104,兴庆区\n", + "640105,西夏区\n", + "640106,金凤区\n", + "640121,永宁县\n", + "640122,贺兰县\n", + "640181,灵武市\n", + "640200,石嘴山市\n", + "640202,大武口区\n", + "640205,惠农区\n", + "640221,平罗县\n", + "640300,吴忠市\n", + "640302,利通区\n", + "640303,红寺堡区\n", + "640323,盐池县\n", + "640324,同心县\n", + "640381,青铜峡市\n", + "640400,固原市\n", + "640402,原州区\n", + "640422,西吉县\n", + "640423,隆德县\n", + "640424,泾源县\n", + "640425,彭阳县\n", + "640500,中卫市\n", + "640502,沙坡头区\n", + "640521,中宁县\n", + "640522,海原县\n", + "650000,新疆\n", + "650100,乌鲁木齐市\n", + "650102,天山区\n", + "650103,沙依巴克区\n", + "650104,新市区\n", + "650105,水磨沟区\n", + "650106,头屯河区\n", + "650107,达坂城区\n", + "650109,米东区\n", + "650121,乌鲁木齐县\n", + "650200,克拉玛依市\n", + "650202,独山子区\n", + "650203,克拉玛依区\n", + "650204,白碱滩区\n", + "650205,乌尔禾区\n", + "652100,吐鲁番市\n", + "652101,高昌区\n", + "652122,鄯善县\n", + "652123,托克逊县\n", + "652200,哈密地区\n", + "652201,哈密市\n", + "652222,巴里坤县\n", + "652223,伊吾县\n", + "652300,昌吉州\n", + "652700,博尔塔拉州\n", + "652800,巴音郭楞州\n", + "652900,阿克苏地区\n", + "653000,克孜勒苏州\n", + "653100,喀什地区\n", + "653125,莎车县\n", + "653200,和田地区\n", + "653226,于田县\n", + "654000,霍尔果斯市\n", + "654000,伊犁州\n", + "654200,塔城地区\n", + "654202,乌苏市\n", + "654300,阿勒泰地区\n", + "659001,石河子市\n", + "659002,阿拉尔市\n", + "659003,图木舒克市\n", + "659004,五家渠市\n", + "710000,台湾\n", + "710000,新北市\n", + "710001,台中市\n", + "710001,嘉义县\n", + "710001,台北市\n", + "710001,高雄市\n", + "710001,南投县\n", + "710001,台南县\n", + "810000,深水埗区\n", + "810000,离岛区\n", + "810000,葵青区\n", + "810000,沙田区\n", + "810000,西贡区\n", + "810000,大埔区\n", + "810000,北区\n", + "810000,元朗区\n", + "810000,屯门区\n", + "810000,荃湾区\n", + "810000,观塘区\n", + "810000,九龙城区\n", + "810000,油尖旺区\n", + "810000,南区\n", + "810000,东区\n", + "810000,湾仔区\n", + "810000,中西区" + }; + +} diff --git a/src/main/java/edu/hfbu/recruit/util/JwtUtil.java b/src/main/java/edu/hfbu/recruit/util/JwtUtil.java new file mode 100644 index 0000000..c02c6a1 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/util/JwtUtil.java @@ -0,0 +1,92 @@ +package edu.ahbvc.recruit.util; + +import edu.ahbvc.recruit.model.token.Token; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.reflect.Field; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class JwtUtil { + + private static final Logger logger = LogManager.getLogger(JwtUtil.class); + + private static final String KEY = "321ahbvc431e21y123342h1f1u32dia2323ej322133f21h11jskl23afh1djl3a1hfj21kdlahf"; + + public static String createJWT(Token token) { + if (token.getUserId() != null) { + Date expiration = token.getExpiration(); + Map map = new HashMap<>(); + Field[] fields = token.getClass().getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + try { + map.put(field.getName(), field.get(token)); + } catch (IllegalAccessException e) { + logger.error(e); + } + } + return Jwts.builder().signWith(SignatureAlgorithm.HS256, KEY) + .setExpiration(expiration).setClaims(map).compact(); + } + return null; + } + + public static Token parseJWT(String authorizationHeader) { + String stringToken; + // 根据具体情况定义对应的对象类型 + Token token = new Token(); + if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { + stringToken = authorizationHeader.substring(7); + } else { + logger.warn("用户递交非法token请求头"); + return null; + } + + Claims claims; + try { + claims = Jwts.parser().setSigningKey(KEY).parseClaimsJws(stringToken).getBody(); + } catch (JwtException e) { + // 处理其他JwtException情况,例如签名不匹配等 + logger.warn("用户递交无效token请求头"); + return null; + } + + // 判断token是否过期 + Date expiration = claims.getExpiration(); + Date now = new Date(); + if (expiration != null && expiration.before(now)) { + // token已过期 + logger.info("用户递交token请求头已经过期"); + return null; + } + + // 读取token对应的信息 + Field[] fields = token.getClass().getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + if (claims.containsKey(field.getName())) { +// 将属性值设置到对象中 + try { + Object value = claims.get(field.getName()); + if (value instanceof Long && (field.getType().equals(Date.class))) { + value = new Date((Long) value); + } + field.set(token, value); + } catch (IllegalArgumentException | IllegalAccessException e) { + logger.error("读取token失败"); + logger.error(e); + return null; + } + } + } + return token; + } + +} diff --git a/src/main/java/edu/hfbu/recruit/util/file/FilePatch.java b/src/main/java/edu/hfbu/recruit/util/file/FilePatch.java new file mode 100644 index 0000000..3e95732 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/util/file/FilePatch.java @@ -0,0 +1,132 @@ +package edu.ahbvc.recruit.util.file; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +/** + * @author c215 + */ +public class FilePatch { + public static final String SEP = File.separator; + public static final String SaveExcelFilePath = ""; + public static final String SaveUserFileNodePath = "user_resume_files"; + private static final Logger logger = LoggerFactory.getLogger(FilePatch.class); + public static String SaveUserFileContextPath = "C:\\ahbvcSystem\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1\\wtpwebapps\\Recruit\\"; + + public static String getSaveUserFileContextPath() { + return SaveUserFileContextPath; + } + + public static void setSaveUserFileContextPath(String saveUserFileContextPath) { + SaveUserFileContextPath = saveUserFileContextPath; + } + + /** + * @param code 岗位代码 + * @param userid 用户id + * @param part 文件所属位置(0:个人照片,1:身份证正面,2:身份证反面,3:学历证书,4:学位证书,5:学位证书,6:学位证书,7:学位证书,8:学位证书,9:学位证书,10:学位证书,11:学位证书,12:学位证书,13:学位证书,14:学位证书,15:学位证书,16:学位证书,17:学位证书,18: + * @param isDev 是否是开发模式 + * @param isIdNum 是否是身份证照片文件 + * @return 根据参数指定的信息返回对应文件路径 + */ + public static List getFileUrl(String code, Integer userid, int part, boolean isDev, boolean isIdNum) { + String path; + if (isIdNum) { + path = SaveUserFileContextPath + SaveUserFileNodePath + SEP + "userPhoto" + SEP + userid; + } else { + path = SaveUserFileContextPath + SaveUserFileNodePath + SEP + code + SEP + userid + SEP + part; + } +// 获取目标路径下的文件列表 + File folder = new File(path); + File[] fileList = folder.listFiles(); + + List paths = new ArrayList<>(); + if (fileList != null) { + for (File fileItem : fileList) { + String absolutePath = fileItem.getAbsolutePath(); + logger.info("文件列表\n" + absolutePath); + System.out.println("文件列表\n" + absolutePath); + int index = absolutePath.indexOf("user_resume"); +// 相对路径(user_resume_file/1/2/3/filename.txt) + String relativePath = absolutePath.substring(index); + if (isDev) { + relativePath = "https://supposedly-credible-cougar.ngrok-free.app/Recruit/" + relativePath; + } + relativePath = relativePath.replace("\\", "/"); + paths.add(relativePath.replaceAll("\\\\", "/")); + } + return paths; + } +// 目标路径文件列表为空,返回空 + return null; + } + + public static String setFile(String realPath, String code, Integer userid, Integer part, Boolean isIdNum, + MultipartFile file) { + if (!"".equals(realPath)) { + if ("".equals(SaveUserFileContextPath)) { + SaveUserFileContextPath = realPath; + } + } + if (file != null) { + String path = buildFilePath(userid, code, part, isIdNum); + try { + // 将文件保存到指定路径 + file.transferTo(Paths.get(path, file.getOriginalFilename())); + return path; + } catch (IllegalStateException | IOException e) { + logger.error("文件保存失败", e); + return null; + } + } + return null; + } + + public static String buildFilePath(Integer userid, String code, Integer part, Boolean isIdNum) { + +// +//10:33:40.496 [http-nio-8092-exec-10] INFO edu.ahbvc.controller.UserController:系统上下文物理地址 +//10:33:40.496 [http-nio-8092-exec-10] INFO edu.ahbvc.controller.UserController:C:\ahbvcSystem\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\Recruit\ +//目录创建成功:{}C:\ahbvcSystem\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\Recruit\(Unicode 无效)user_resume_files\15\22\61\1091\img + + String path; + if (isIdNum) { + path = SaveUserFileContextPath + SaveUserFileNodePath + SEP + "userPhoto" + SEP + userid; + } else { + path = SaveUserFileContextPath + SaveUserFileNodePath + SEP + code + SEP + userid + SEP + part; + } + + File directory = new File(path); + if (!directory.exists() && directory.mkdirs()) { + logger.info("目录创建成功:{}", path); + System.out.println("目录创建成功:{}" + path); + } else { + logger.info("目录已存在或创建失败:{}", path); + System.out.println("目录已存在或创建失败:{}" + path); + } + return path; + } + + public static void modifyLogToFile(String oldIdnum, String oldName, String idnum2, String name2) { + // 声明打印流对象 + PrintStream ps = null; + // 如果现在是使用FileOuputStream实例化,意味着所有的输出是向文件之中 + try { + ps = new PrintStream(new FileOutputStream(SaveUserFileContextPath + "userModifyLog.txt")); + } catch (FileNotFoundException e) { + logger.error("修改记录的txt未找到"); + logger.error("请在" + SaveUserFileContextPath + "下建立:userModifyLog.txt"); + } + if (ps != null) { + ps.println("更改:"); + ps.println(" " + oldName + "," + oldIdnum + ",到:" + name2 + "," + idnum2); + ps.close(); + } + } +} diff --git a/src/main/java/edu/hfbu/recruit/util/file/FilePathModel.java b/src/main/java/edu/hfbu/recruit/util/file/FilePathModel.java new file mode 100644 index 0000000..f5a01df --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/util/file/FilePathModel.java @@ -0,0 +1,28 @@ +package edu.ahbvc.recruit.util.file; + +public class FilePathModel { + + private String path = ""; + + public FilePathModel() { + super(); + } + + public FilePathModel(String path) { + super(); + this.path = path; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + @Override + public String toString() { + return "FilePath [path=" + path + "]"; + } +} diff --git a/src/main/java/edu/hfbu/recruit/util/file/UserQualificationsCreator.java b/src/main/java/edu/hfbu/recruit/util/file/UserQualificationsCreator.java new file mode 100644 index 0000000..c747003 --- /dev/null +++ b/src/main/java/edu/hfbu/recruit/util/file/UserQualificationsCreator.java @@ -0,0 +1,513 @@ +package edu.ahbvc.recruit.util.file; + +import edu.ahbvc.recruit.model.resume.*; +import edu.ahbvc.recruit.util.AdmissionTicketCreater; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.poi.xwpf.usermodel.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author c215 + */ +public class UserQualificationsCreator { + + /** + * 模板地址 + */ + public static final String TEMPLATE_PATH = + "C:/ahbvcSystem/Recruit/template/uiTemplate.docx"; + /** + * 空白模板地址 + */ + public static final String BLANK_TEMPLATE_PATH = + "C:/ahbvcSystem/Recruit/template/uiTemplate2.docx"; + /** + * 生成的准考证地址 + */ + public static final String OUTPUT_BASE_PATH = "C:\\ahbvcSystem\\Recruit\\UserQualifications"; + private static final Logger logger = LogManager.getLogger(UserQualificationsCreator.class); + + /** + * @param data 要打印的用户信息集合 + * @return 若成功,返回docx文件路径 + */ + public static String generateUserDocument(UserResume data) { + XWPFDocument document = null; + String result; + + try { + // 读取模板文件 + FileInputStream templateFile = new FileInputStream(TEMPLATE_PATH); + document = new XWPFDocument(templateFile); + + // 遍历段落,查找并替换内容 + List paragraphsHead = document.getParagraphs(); + for (XWPFParagraph paragraph : paragraphsHead) { + // 获取段落中所有的运行对象 + for (XWPFRun run : paragraph.getRuns()) { + // 获取运行对象中的文本内容 + String runText = run.getText(0); + if (runText != null && runText.contains("{{code}}")) { + // 替换文本内容 + runText = runText.replace("{{code}}", data.getCode()); + // 清空运行对象中的文本内容 + run.setText("", 0); + // 添加替换后的文本内容 + run.setText(runText, 0); + } + } + } + // 处理模板中的表格 + for (XWPFTable table : document.getTables()) { + int rowOffset = 0; + + ArrayList projects = data.getProject(); + ArrayList projects0 = new ArrayList<>(); + ArrayList projects1 = new ArrayList<>(); + ArrayList projects2 = new ArrayList<>(); + for (Project project : projects) { + if (project.getType() == 0) { + projects0.add(project); + } else if (project.getType() == 1) { + projects1.add(project); + } else if (project.getType() == 2) { + projects2.add(project); + } + } + + List rows = table.getRows(); + for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) { + logger.info("总行数" + rows.size()); + XWPFTableRow row = rows.get(rowIndex); + if (rowIndex <= 8) { +// 第九行以前的 + for (XWPFTableCell cell : row.getTableCells()) { + String text = cell.getText(); + if (!text.startsWith("{{")) { + continue; + } + + UserInfo info = data.getInfo(); +// 将模板中的占位符替换成数据源中对应的数据 + text = repleteString(text, info); + if (text == null) { + text = ""; + } + List paragraphs = cell.getParagraphs(); + XWPFParagraph paragraph = paragraphs.get(0); + List runs = paragraph.getRuns(); + XWPFRun templateXwpfRun = runs.get(0); +// 保存文本对齐方式 + ParagraphAlignment alignment = paragraph.getAlignment(); +// 添加新段落 +// 重新应用文本对齐方式 + XWPFParagraph addParagraph = cell.addParagraph(); + addParagraph.setAlignment(alignment); + + AdmissionTicketCreater.populateCellWithFormattedText(cell, text, templateXwpfRun, addParagraph); + } +// } else if (lineCount == 910) { + } else if (rowIndex == 9) { + ArrayList education = data.getEducation(); + + int educationSize = education.size(); + List tableCells = row.getTableCells(); + if (educationSize == 1) { +// // 替换值 + loadEducationData(education.get(0), tableCells); + + } + if (education.size() > 1) { + XWPFTableRow backupRow = new XWPFTableRow(row.getCtRow(), table); + for (int i = 0; i < education.size() - 1; i++) { + XWPFTableRow blankRow = new XWPFTableRow(backupRow.getCtRow(), table); + loadEducationData(education.get(i), blankRow.getTableCells()); + table.addRow(blankRow, 9); + rowOffset++; + rowIndex++; + } + loadEducationData(education.get(education.size() - 1), tableCells); + } + } else if (rowIndex == 13 + rowOffset) { +// 工作经历 + ArrayList workExperiences = data.getWorkExperience(); + logger.info("准备装载" + workExperiences); + int workExperienceSize = workExperiences.size(); + List tableCells = row.getTableCells(); + if (workExperienceSize == 1) { +// 替换值 + loadWorkExperienceData(workExperiences.get(0), tableCells); + + } + if (workExperiences.size() > 1) { + XWPFTableRow backupRow = new XWPFTableRow(row.getCtRow(), table); + for (int i = 0; i < workExperiences.size() - 1; i++) { + XWPFTableRow blankRow = new XWPFTableRow(backupRow.getCtRow(), table); + loadWorkExperienceData(workExperiences.get(i), blankRow.getTableCells()); + table.addRow(blankRow, 13 + rowOffset); + rowOffset++; + rowIndex++; + } + loadWorkExperienceData(workExperiences.get(workExperiences.size() - 1), tableCells); + } + } else if (rowIndex == 16 + rowOffset) { +// 论文 + ArrayList paper = data.getPaper(); + logger.info("准备装载" + paper); + int paperSize = paper.size(); + List tableCells = row.getTableCells(); + if (paperSize == 1) { + loadPaperData(paper.get(0), tableCells); + } + if (paperSize > 1) { + XWPFTableRow backupRow = new XWPFTableRow(row.getCtRow(), table); + for (int i = 0; i < paper.size() - 1; i++) { + XWPFTableRow blankRow = new XWPFTableRow(backupRow.getCtRow(), table); + loadPaperData(paper.get(i), blankRow.getTableCells()); + table.addRow(blankRow, rowIndex); + rowOffset++; + rowIndex++; + } + loadPaperData(paper.get(paperSize - 1), tableCells); + } + } else if (rowIndex == 19 + rowOffset) { +// 教/科研项目 + logger.info("准备装载" + projects0); + int paperSize = projects0.size(); + List tableCells = row.getTableCells(); + if (paperSize == 1) { + loadProjectData(projects0.get(0), tableCells); + } + if (paperSize > 1) { + XWPFTableRow backupRow = new XWPFTableRow(row.getCtRow(), table); + for (int i = 0; i < projects0.size() - 1; i++) { + XWPFTableRow blankRow = new XWPFTableRow(backupRow.getCtRow(), table); + loadProjectData(projects0.get(i), blankRow.getTableCells()); + table.addRow(blankRow, 19 + rowOffset); + rowOffset++; + rowIndex++; + } + loadProjectData(projects0.get(paperSize - 1), tableCells); + } + } else if (rowIndex == 22 + rowOffset) { +// 4.教学成果奖或教学竞赛奖励 + logger.info("准备装载" + projects1); + int paperSize = projects1.size(); + List tableCells = row.getTableCells(); + if (paperSize == 1) { + loadProjectData(projects1.get(0), tableCells); + } + if (paperSize > 1) { + XWPFTableRow backupRow = new XWPFTableRow(row.getCtRow(), table); + for (int i = 0; i < projects1.size() - 1; i++) { + XWPFTableRow blankRow = new XWPFTableRow(backupRow.getCtRow(), table); + loadProjectData(projects1.get(i), blankRow.getTableCells()); + table.addRow(blankRow, 22 + rowOffset); + rowOffset++; + rowIndex++; + } + loadProjectData(projects1.get(paperSize - 1), tableCells); + } + } else if (rowIndex == 25 + rowOffset) { +// 5.指导竞赛 + logger.info("准备装载" + projects2); + int paperSize = projects2.size(); + List tableCells = row.getTableCells(); + if (paperSize == 1) { + loadProjectData(projects2.get(0), tableCells); + } + if (paperSize > 1) { + XWPFTableRow backupRow = new XWPFTableRow(row.getCtRow(), table); + for (int i = 0; i < projects2.size() - 1; i++) { + XWPFTableRow blankRow = new XWPFTableRow(backupRow.getCtRow(), table); + loadProjectData(projects2.get(i), blankRow.getTableCells()); + table.addRow(blankRow, 25 + rowOffset); + rowOffset++; + rowIndex++; + } + loadProjectData(projects2.get(paperSize - 1), tableCells); + } + } else if (rowIndex == 28 + rowOffset) { +// 成果推广 + ArrayList research = data.getResearch(); + logger.info("准备装载" + research); + int paperSize = research.size(); + List tableCells = row.getTableCells(); + if (paperSize == 1) { + loadResearchData(research.get(0), tableCells); + } + if (paperSize > 1) { + XWPFTableRow backupRow = new XWPFTableRow(row.getCtRow(), table); + for (int i = 0; i < research.size() - 1; i++) { + XWPFTableRow blankRow = new XWPFTableRow(backupRow.getCtRow(), table); + loadResearchData(research.get(i), blankRow.getTableCells()); + table.addRow(blankRow, 28 + rowOffset); + rowOffset++; + rowIndex++; + } + loadResearchData(research.get(paperSize - 1), tableCells); + } + } else if (rowIndex == 29 + rowOffset) { + // 奖惩 + List tableCells = row.getTableCells(); + for (XWPFTableCell tableCell : tableCells) { + if ("{{awardsAndPunishments}}".equals(tableCell.getText())) { + if (!tableCell.getParagraphs().isEmpty()) { + tableCell.removeParagraph(0); + } + tableCell.setText(data.getAwardsAndPunishments()); + } + } + } else if (rowIndex == 31 + rowOffset) { +// 家庭关系 + ArrayList familyConnections = data.getFamily(); + logger.info("准备装载" + familyConnections); + int paperSize = familyConnections.size(); + List tableCells = row.getTableCells(); + if (paperSize == 1) { + loadFamilyConnectionsData(familyConnections.get(0), tableCells); + } + if (paperSize > 1) { + XWPFTableRow backupRow = new XWPFTableRow(row.getCtRow(), table); + for (int i = 0; i < familyConnections.size() - 1; i++) { + XWPFTableRow blankRow = new XWPFTableRow(backupRow.getCtRow(), table); + loadFamilyConnectionsData(familyConnections.get(i), blankRow.getTableCells()); + table.addRow(blankRow, 31 + rowOffset); + rowOffset++; + rowIndex++; + } + loadFamilyConnectionsData(familyConnections.get(paperSize - 1), tableCells); + } + } else if (row.getTableCells().size() == 2) { + if ("{{note}}".equals(row.getCell(1).getText())) { + row.getCell(1).removeParagraph(0); + row.getCell(1).setText(data.getNote()); + } + } + } + } + + String path = OUTPUT_BASE_PATH + File.separatorChar + data.getCode() + File.separatorChar; + File folder = new File(path); + boolean success = folder.mkdir(); + if (success) { + logger.info("文件夹创建成功"); + } else { + if (folder.exists()) { + logger.info("文件夹已经存在"); + } else { + logger.info("文件夹创建失败"); + } + } + String fileName = data.getInfo().getName() + "_" + data.getInfo().getIdNum(); + + // 保存生成的文档 + FileOutputStream outputFile = new FileOutputStream(path + File.separatorChar + fileName + ".docx"); + document.write(outputFile); + // admission_ticket\null3416212.docx (系统找不到指定的路径。) + result = path + fileName + ".docx"; + logger.info(result + "保存成功"); + outputFile.close(); + + } catch (IOException e) { + logger.error(e); + return null; + } finally { + if (document != null) { + try { + document.close(); + } catch (IOException e) { + logger.error(e); + } + } + } + return result; + } + + private static void loadEducationData(Education education, List tableCells) { + String ed = degreeEducated(false, education.getEducation()); + String de = degreeEducated(true, education.getDegree()); + for (int cellIndex = 0; cellIndex < tableCells.size(); cellIndex++) { + XWPFTableCell xwpfTableCell = tableCells.get(cellIndex); + String text = ""; + switch (cellIndex) { + case 0 -> text = ed; + case 1 -> text = de; + case 2 -> text = education.getSchool(); + case 3 -> text = education.getSpecialty(); + case 4 -> text = education.getGraduationTime(); + default -> { + } + } + if (!xwpfTableCell.getParagraphs().isEmpty()) { + xwpfTableCell.removeParagraph(0); + } + xwpfTableCell.setText(text); + } + } + + private static void loadWorkExperienceData(WorkExperience experience, List tableCells) { + String workTime = experience.getWorkTimeStart() + "到" + experience.getWorkTimeEnd(); + for (int cellIndex = 0; cellIndex < tableCells.size(); cellIndex++) { + XWPFTableCell xwpfTableCell = tableCells.get(cellIndex); + String text = ""; + switch (cellIndex) { + case 0 -> text = workTime; + case 1 -> text = experience.getCompany(); + case 2 -> text = experience.getPosition(); + default -> { + } + } + if (!xwpfTableCell.getParagraphs().isEmpty()) { + xwpfTableCell.removeParagraph(0); + } + xwpfTableCell.setText(text); + } + } + + private static void loadPaperData(Paper paper, List tableCells) { + for (int cellIndex = 0; cellIndex < tableCells.size(); cellIndex++) { + XWPFTableCell xwpfTableCell = tableCells.get(cellIndex); + String text = ""; + switch (cellIndex) { + case 0 -> text = paper.getJournal(); + case 1 -> text = paper.getTitle(); + case 2 -> text = paper.getTime(); + case 3 -> text = paper.getJournalNum(); + default -> { + } + } + if (!xwpfTableCell.getParagraphs().isEmpty()) { + xwpfTableCell.removeParagraph(0); + } + xwpfTableCell.setText(text); + } + } + + private static void loadProjectData(Project project, List tableCells) { + for (int cellIndex = 0; cellIndex < tableCells.size(); cellIndex++) { + XWPFTableCell xwpfTableCell = tableCells.get(cellIndex); + String text = ""; + switch (cellIndex) { + case 0 -> text = project.getTime(); + case 1 -> text = project.getTitle(); + case 2 -> text = project.getLevel(); + case 3 -> text = project.getRank(); + default -> { + } + } + if (!xwpfTableCell.getParagraphs().isEmpty()) { + xwpfTableCell.removeParagraph(0); + } + xwpfTableCell.setText(text); + } + } + + private static void loadResearchData(Research research, List tableCells) { + for (int cellIndex = 0; cellIndex < tableCells.size(); cellIndex++) { + XWPFTableCell xwpfTableCell = tableCells.get(cellIndex); + String text = ""; + if (cellIndex == 0) { + text = research.getName(); + } + if (!xwpfTableCell.getParagraphs().isEmpty()) { + xwpfTableCell.removeParagraph(0); + } + xwpfTableCell.setText(text); + } + } + + private static void loadFamilyConnectionsData(FamilyConnections project, List tableCells) { + for (int cellIndex = 0; cellIndex < tableCells.size(); cellIndex++) { + XWPFTableCell xwpfTableCell = tableCells.get(cellIndex); + String text = ""; + switch (cellIndex) { + case 1 -> text = project.getName(); + case 2 -> text = project.getConnection(); + case 3 -> text = project.getWork(); + default -> { + } + } + if (!xwpfTableCell.getParagraphs().isEmpty()) { + xwpfTableCell.removeParagraph(0); + } + xwpfTableCell.setText(text); + } + } + + private static String repleteString(String text, UserInfo info) { + + if ("{{name}}".equals(text)) { + return info.getName(); + } + if ("{{sex}}".equals(text)) { + if (info.getSex() == 1) { + return "男"; + } else { + return "女"; + } + } + if ("{{phone}}".equals(text)) { + return info.getPhone(); + } + if ("{{birthPlace}}".equals(text)) { + return info.getBirthPlace(); + } + if ("{{nation}}".equals(text)) { + return info.getNation(); + } + if ("{{zzmm}}".equals(text)) { + return info.getPoliticalStatus(); + } + if ("{{email}}".equals(text)) { + return info.getEmail(); + } + if ("{{birthday}}".equals(text)) { + return info.getBirthday(); + } + if ("{{idnum}}".equals(text)) { + return info.getIdNum(); + } + if ("{{married}}".equals(text)) { + return info.getMarried(); + } + if ("{{native_place}}".equals(text)) { + return info.getNativePlace(); + } + if ("{{address}}".equals(text)) { + return info.getAddress(); + } + if ("{{specialtiesCertificates}}".equals(text)) { + return info.getSpecialtiesCertificates(); + } + return ""; + } + + private static String degreeEducated(Boolean isDegree, int data) { + // 填充数据 + if (isDegree) { + return switch (data) { + case 0 -> "暂无"; + case 1 -> "学士"; + case 2 -> "硕士"; + case 3 -> "博士"; + default -> "异常"; + }; + } else { + /* 将学历转换成汉字 */ + return switch (data) { + case 0 -> "专科"; + case 1 -> "本科"; + case 2 -> "研究生"; + default -> "异常"; + }; + } + } +}