feat: 质量监控/人员培训对齐程序文件,体系文件控制附件格式放开
- 质量监控:质控方式改为8种质控措施多选,统一记录名称与导出文件名
- 人员培训:支持外聘讲师,修复培训记录导出签名缺失导致的失败
- 体系文件控制:附件支持常见办公格式,修复上传/下载路径,审核预览支持Word和图片转PDF
- 模板:质量监控三个Word模板按程序文件更新
Co-Authored-By: Claude Code <noreply@anthropic.com>
| | |
| | | import com.ruoyi.common.utils.QueryWrappers; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.framework.exception.ErrorException; |
| | | import com.ruoyi.system.mapper.UserMapper; |
| | | import com.ruoyi.manage.util.DocumentPreviewUtils; |
| | | |
| | | |
| | | import com.ruoyi.manage.mapper.*; |
| | |
| | | @Override |
| | | public void checkManageDocumentAlterPdf(Long id, HttpServletResponse response) throws Exception { |
| | | ManageDocumentAlter manageDocumentAlter = manageDocumentAlterMapper.selectById(id); |
| | | File file = new File(wordUrl + "/" + manageDocumentAlter.getAlterAfterUrl()); |
| | | FileInputStream fileInputStream = new FileInputStream(file); |
| | | response.setContentType("application/pdf"); |
| | | response.setCharacterEncoding("UTF-8"); |
| | | response.setHeader("Content-disposition", "inline;filename=" + file.getName()); |
| | | response.setContentLength((int)file.length()); |
| | | OutputStream os = response.getOutputStream(); |
| | | // å°æä»¶å
容åå
¥è¾åºæµ |
| | | byte[] buffer = new byte[4096]; |
| | | int bytesRead; |
| | | while ((bytesRead = fileInputStream.read(buffer)) != -1) { |
| | | os.write(buffer, 0, bytesRead); |
| | | if (manageDocumentAlter == null || ObjectUtils.isEmpty(manageDocumentAlter.getAlterAfterUrl())) { |
| | | throw new ErrorException("æä»¶æªä¸ä¼ "); |
| | | } |
| | | os.flush(); |
| | | os.close(); |
| | | // PDF ç´æ¥è¾åºï¼Word/å¾çå¨çº¿è½¬ PDFï¼ä¾å端é¢è§çç« |
| | | DocumentPreviewUtils.writeAsPdf(new File(wordUrl + "/" + manageDocumentAlter.getAlterAfterUrl()), response); |
| | | } |
| | | |
| | | @Override |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.core.domain.entity.User; |
| | | import com.ruoyi.common.utils.QueryWrappers; |
| | | import com.ruoyi.framework.exception.ErrorException; |
| | | import com.ruoyi.manage.mapper.ManageDocumentControlledMapper; |
| | | import com.ruoyi.manage.mapper.ManageDocumentListMapper; |
| | | import com.ruoyi.manage.mapper.ManageRecordCheckMapper; |
| | |
| | | import com.ruoyi.manage.pojo.ManageDocumentList; |
| | | import com.ruoyi.manage.pojo.ManageRecordCheck; |
| | | import com.ruoyi.manage.service.ManageDocumentControlledService; |
| | | import com.ruoyi.manage.util.DocumentPreviewUtils; |
| | | import com.ruoyi.system.mapper.UserMapper; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | @Override |
| | | public void checkManageDocumentControlledPdf(Long id, HttpServletResponse response) throws Exception { |
| | | ManageDocumentControlled manageDocumentControlled = manageDocumentControlledMapper.selectById(id); |
| | | File file = new File(wordUrl + "/" + manageDocumentControlled.getUrl()); |
| | | FileInputStream fileInputStream = new FileInputStream(file); |
| | | response.setContentType("application/pdf"); |
| | | response.setCharacterEncoding("UTF-8"); |
| | | response.setHeader("Content-disposition", "inline;filename=" + file.getName()); |
| | | response.setContentLength((int)file.length()); |
| | | OutputStream os = response.getOutputStream(); |
| | | // å°æä»¶å
容åå
¥è¾åºæµ |
| | | byte[] buffer = new byte[4096]; |
| | | int bytesRead; |
| | | while ((bytesRead = fileInputStream.read(buffer)) != -1) { |
| | | os.write(buffer, 0, bytesRead); |
| | | if (manageDocumentControlled == null || ObjectUtils.isEmpty(manageDocumentControlled.getUrl())) { |
| | | throw new ErrorException("æä»¶æªä¸ä¼ "); |
| | | } |
| | | os.flush(); |
| | | os.close(); |
| | | // PDF ç´æ¥è¾åºï¼Word/å¾çå¨çº¿è½¬ PDFï¼ä¾å端é¢è§çç« |
| | | DocumentPreviewUtils.writeAsPdf(new File(wordUrl + "/" + manageDocumentControlled.getUrl()), response); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | |
| | | import com.ruoyi.common.utils.QueryWrappers; |
| | | import com.ruoyi.framework.exception.ErrorException; |
| | | import com.ruoyi.manage.mapper.ManageDocumentListMapper; |
| | | import com.ruoyi.manage.pojo.ManageDocumentList; |
| | | import com.ruoyi.manage.service.ManageDocumentListService; |
| | |
| | | import java.io.FileOutputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | |
| | | @Override |
| | | public int uploadFile(Integer id, MultipartFile file) { |
| | | String urlString; |
| | | String pathName; |
| | | String path; |
| | | ManageDocumentList manageDocumentList = manageDocumentListMapper.selectById(id); |
| | | if (ObjectUtils.isNotEmpty(manageDocumentList.getUrl())){ |
| | | // å 餿§æä»¶ |
| | | File oldFile = new File(wordUrl + "/" + manageDocumentList.getUrl()); |
| | | oldFile.delete(); |
| | | if (manageDocumentList == null) { |
| | | throw new ErrorException("æä»¶æ¸
åä¸åå¨"); |
| | | } |
| | | //ä¸ä¼ æ°æä»¶ |
| | | path = wordUrl; |
| | | if (file == null || file.isEmpty()) { |
| | | throw new ErrorException("è¯·éæ©è¦ä¸ä¼ çæä»¶"); |
| | | } |
| | | File realpath = new File(wordUrl).getAbsoluteFile(); |
| | | try { |
| | | File realpath = new File(path); |
| | | if (!realpath.exists()) { |
| | | realpath.mkdirs(); |
| | | if (!realpath.exists() && !realpath.mkdirs()) { |
| | | throw new IOException("ç®å½å建失败: " + realpath); |
| | | } |
| | | pathName = UUID.randomUUID() + "_" + file.getOriginalFilename(); |
| | | urlString = realpath + "/" + pathName; |
| | | file.transferTo(new File(urlString)); |
| | | // ç¨ Files.copy è䏿¯ transferToï¼transferTo éå°ç¸å¯¹è·¯å¾ä¼æ Tomcat 临æ¶ç®å½è§£æ |
| | | Files.copy(file.getInputStream(), new File(realpath, pathName).toPath(), StandardCopyOption.REPLACE_EXISTING); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | System.err.println("éä»¶ä¸ä¼ é误"); |
| | | return 0; |
| | | throw new ErrorException("éä»¶ä¸ä¼ é误: " + e.getMessage()); |
| | | } |
| | | if (ObjectUtils.isNotEmpty(manageDocumentList.getUrl())) { |
| | | // å 餿§æä»¶ |
| | | new File(realpath, manageDocumentList.getUrl()).delete(); |
| | | } |
| | | manageDocumentList.setUrl(pathName); |
| | | return manageDocumentListMapper.updateById(manageDocumentList); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.manage.util; |
| | | |
| | | import com.aspose.words.Document; |
| | | import com.aspose.words.DocumentBuilder; |
| | | import com.aspose.words.License; |
| | | import com.aspose.words.SaveFormat; |
| | | import com.ruoyi.framework.exception.ErrorException; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.springframework.core.io.ClassPathResource; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | |
| | | /** |
| | | * ä½ç³»æä»¶éä»¶é¢è§å·¥å
·ï¼æéä»¶ç»ä¸ä»¥ PDF æµè¾åºç»å端é¢è§/çç« ã |
| | | * PDF åæ ·è¾åºï¼Wordãå¾çç¨ Aspose.Words å¨çº¿è½¬ PDFï¼Excel/PPT çæ æ³è½¬ PDF çæ ¼å¼ç»åºæç¡®æç¤ºã |
| | | */ |
| | | public final class DocumentPreviewUtils { |
| | | |
| | | private static final String[] WORD_EXT = {".doc", ".docx", ".rtf", ".txt", ".wps"}; |
| | | private static final String[] IMAGE_EXT = {".png", ".jpg", ".jpeg", ".bmp", ".gif"}; |
| | | |
| | | private DocumentPreviewUtils() { |
| | | } |
| | | |
| | | public static void writeAsPdf(File file, HttpServletResponse response) throws Exception { |
| | | if (file == null || !file.exists()) { |
| | | throw new ErrorException("éä»¶ä¸åå¨æå·²è¢«å é¤"); |
| | | } |
| | | String name = file.getName().toLowerCase(); |
| | | if (name.endsWith(".pdf")) { |
| | | prepare(response, file.getName(), file.length()); |
| | | try (InputStream in = new FileInputStream(file); |
| | | OutputStream os = response.getOutputStream()) { |
| | | in.transferTo(os); |
| | | os.flush(); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | Document doc; |
| | | if (endsWithAny(name, WORD_EXT)) { |
| | | applyLicense(); |
| | | doc = new Document(file.getPath()); |
| | | } else if (endsWithAny(name, IMAGE_EXT)) { |
| | | applyLicense(); |
| | | doc = new Document(); |
| | | new DocumentBuilder(doc).insertImage(file.getPath()); |
| | | } else { |
| | | throw new ErrorException("该æä»¶æ ¼å¼ä¸æ¯æå¨çº¿çç« é¢è§ï¼è¯·ä¸ä¼ PDF æ Word æä»¶"); |
| | | } |
| | | |
| | | // å
转æ¢å°å
åï¼è½¬æ¢å¤±è´¥æ¶ååºå¤´è¿æ²¡æäº¤ï¼å端æè½æ¶å°éè¯¯ä¿¡æ¯ |
| | | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); |
| | | doc.save(buffer, SaveFormat.PDF); |
| | | byte[] bytes = buffer.toByteArray(); |
| | | prepare(response, file.getName() + ".pdf", bytes.length); |
| | | try (OutputStream os = response.getOutputStream()) { |
| | | os.write(bytes); |
| | | os.flush(); |
| | | } |
| | | } |
| | | |
| | | private static void prepare(HttpServletResponse response, String fileName, long length) { |
| | | response.setContentType("application/pdf"); |
| | | response.setCharacterEncoding("UTF-8"); |
| | | response.setHeader("Content-disposition", "inline;filename=" + fileName); |
| | | response.setContentLength((int) length); |
| | | } |
| | | |
| | | private static boolean endsWithAny(String name, String[] suffixes) { |
| | | for (String suffix : suffixes) { |
| | | if (name.endsWith(suffix)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private static void applyLicense() throws Exception { |
| | | // åè¯ï¼å¦å转æ¢åå¸¦æ°´å° |
| | | try (InputStream is = new ClassPathResource("lib/license.xml").getInputStream()) { |
| | | License license = new License(); |
| | | license.setLicense(is); |
| | | } |
| | | } |
| | | } |
| | |
| | | public Result<?> addOrUpdatePersonTrainingDetailed(@RequestBody PersonTrainingDetailed personTrainingDetailed) { |
| | | if (ObjectUtils.isEmpty(personTrainingDetailed.getId())) { |
| | | personTrainingDetailed.setState(3); |
| | | personTrainingDetailedService.save(personTrainingDetailed); |
| | | return Result.success(); |
| | | } |
| | | personTrainingDetailedService.saveOrUpdate(personTrainingDetailed); |
| | | // 讲å¸å¯è½å¨å
é¨äººååå¤è人åä¹é´åæ¢ï¼å
æ¾å¼è¦ç两åï¼é¿å
updateById è·³è¿ null å¯¼è´æ§å¼æ®ç |
| | | personTrainingDetailedService.update(null, Wrappers.<PersonTrainingDetailed>lambdaUpdate() |
| | | .eq(PersonTrainingDetailed::getId, personTrainingDetailed.getId()) |
| | | .set(PersonTrainingDetailed::getTrainingLecturerId, personTrainingDetailed.getTrainingLecturerId()) |
| | | .set(PersonTrainingDetailed::getTrainingLecturerName, personTrainingDetailed.getTrainingLecturerName())); |
| | | personTrainingDetailed.setTrainingLecturerId(null); |
| | | personTrainingDetailed.setTrainingLecturerName(null); |
| | | personTrainingDetailedService.updateById(personTrainingDetailed); |
| | | return Result.success(); |
| | | } |
| | | |
| | |
| | | @Schema(description = "å¹è®è®²å¸_id") |
| | | private Integer trainingLecturerId; |
| | | |
| | | @Schema(description = "å¤è/éç³»ç»è®²å¸å§åï¼å
é¨è®²å¸ä»å trainingLecturerId") |
| | | private String trainingLecturerName; |
| | | |
| | | @Schema(description = "计åå¹è®æ¥æ") |
| | | private String trainingDate; |
| | | |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | |
| | | PersonTrainingDetailed personTrainingDetailed = new PersonTrainingDetailed(); |
| | | BeanUtils.copyProperties(i, personTrainingDetailed); |
| | | |
| | | // å¹é
è®²å¸ |
| | | User user = userMapper.selectOne(Wrappers.<User>lambdaQuery() |
| | | .eq(User::getName, i.getTrainingLecturerName())); |
| | | if (ObjectUtils.isEmpty(user)) { |
| | | throw new ErrorException("æªæ¾å°è¯¥è®²å¸ï¼" + i.getTrainingLecturerName()); |
| | | // å¹é
讲å¸ï¼ç³»ç»å
å¯ä¸å¹é
çåç¨æ·IDï¼å¤è/éç³»ç»è®²å¸æå§åææ¬ä¿å |
| | | if (StringUtils.isBlank(i.getTrainingLecturerName())) { |
| | | throw new ErrorException("å¹è®è®²å¸ä¸è½ä¸ºç©º"); |
| | | } |
| | | personTrainingDetailed.setTrainingLecturerId(user.getId()); |
| | | String lecturerName = i.getTrainingLecturerName().trim(); |
| | | List<User> lecturers = userMapper.selectList(Wrappers.<User>lambdaQuery() |
| | | .eq(User::getName, lecturerName)); |
| | | if (lecturers.size() == 1) { |
| | | personTrainingDetailed.setTrainingLecturerId(lecturers.get(0).getId()); |
| | | personTrainingDetailed.setTrainingLecturerName(null); |
| | | } else { |
| | | personTrainingDetailed.setTrainingLecturerId(null); |
| | | personTrainingDetailed.setTrainingLecturerName(lecturerName); |
| | | } |
| | | personTrainingDetailed.setPlanId(planId); |
| | | personTrainingDetailed.setState(3); |
| | | |
| | |
| | | import com.ruoyi.common.utils.WxCpUtils; |
| | | import com.ruoyi.framework.exception.ErrorException; |
| | | import com.ruoyi.inspect.util.HackLoopTableRenderPolicy; |
| | | import com.ruoyi.inspect.util.UserUtils; |
| | | import com.ruoyi.personnel.dto.PersonTrainingDetailedDto; |
| | | import com.ruoyi.personnel.dto.PersonTrainingDto; |
| | | import com.ruoyi.personnel.dto.PersonTrainingRecordDto; |
| | |
| | | message += "CNASå¹è®è®¡åå®¡æ ¸éç¥"; |
| | | message += "\n请å»èµæºç®¡ç-人å-å¹è®è®¡åå¡«å"; |
| | | message += "\n" + fileName + "çå¹è®è®¡åå¾
å®¡æ ¸"; |
| | | //åéä¼ä¸å¾®ä¿¡æ¶æ¯éç¥ |
| | | //åéä¼ä¸å¾®ä¿¡æ¶æ¯éç¥ï¼æ¥æ¶äººä¸å卿åé失败ä¸å½±å导å
¥æµç¨ï¼ |
| | | if (personnel == null || StringUtils.isBlank(personnel.getAccount())) { |
| | | return; |
| | | } |
| | | try { |
| | | WxCpUtils.inform(personnel.getAccount(), message, null); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | e.printStackTrace(); |
| | | } |
| | | }); |
| | | |
| | |
| | | // æ¥è¯¢äººåå¹è®æç» |
| | | PersonTrainingDetailedDto detailedDto = personTrainingDetailedMapper.selectTrainingDetail(id); |
| | | |
| | | // çæå¹è®èå¸ç¾å |
| | | detailedDto.setTrainingLecturerRender(StringUtils.isNotBlank(detailedDto.getTrainingLecturerSignatureUrl()) |
| | | ? Pictures.ofLocal(imgUrl + "/" + detailedDto.getTrainingLecturerSignatureUrl()).create() : null); |
| | | // çæå¹è®èå¸ç¾åï¼æªé
ç½®ç¾åæ¶ç¨éæå¾çå
åºï¼æ¨¡æ¿éçå¾çå ä½ä¸è½ä¸º nullï¼ |
| | | detailedDto.setTrainingLecturerRender(UserUtils.orTransparentPicture( |
| | | StringUtils.isNotBlank(detailedDto.getTrainingLecturerSignatureUrl()) |
| | | ? Pictures.ofLocal(imgUrl + "/" + detailedDto.getTrainingLecturerSignatureUrl()).create() : null)); |
| | | |
| | | // æ¥è¯¢å¹è®ç人å |
| | | List<PersonTrainingRecordDto> recordDtos = personTrainingRecordMapper.selectListByTrainingDetailedId(id); |
| | |
| | | for (PersonTrainingRecordDto recordDto : recordDtos) { |
| | | switch (count) { |
| | | case 0: |
| | | exportDto.setUserNameRender1(StringUtils.isNotBlank(recordDto.getSignatureUrl()) |
| | | ? Pictures.ofLocal(imgUrl + "/" + recordDto.getSignatureUrl()).create() : null); |
| | | exportDto.setUserNameRender1(UserUtils.orTransparentPicture(StringUtils.isNotBlank(recordDto.getSignatureUrl()) |
| | | ? Pictures.ofLocal(imgUrl + "/" + recordDto.getSignatureUrl()).create() : null)); |
| | | exportDto.setDepartment1(recordDto.getDepartment()); |
| | | exportDto.setExaminationResults1(recordDto.getExaminationResults()); |
| | | count ++; |
| | | break; |
| | | case 1: |
| | | exportDto.setUserNameRender2(StringUtils.isNotBlank(recordDto.getSignatureUrl()) |
| | | ? Pictures.ofLocal(imgUrl + "/" + recordDto.getSignatureUrl()).create() : null); |
| | | exportDto.setUserNameRender2(UserUtils.orTransparentPicture(StringUtils.isNotBlank(recordDto.getSignatureUrl()) |
| | | ? Pictures.ofLocal(imgUrl + "/" + recordDto.getSignatureUrl()).create() : null)); |
| | | exportDto.setDepartment2(recordDto.getDepartment()); |
| | | exportDto.setExaminationResults2(recordDto.getExaminationResults()); |
| | | exportDtoList.add(exportDto); |
| | |
| | | break; |
| | | } |
| | | } |
| | | // åªæåæ°æ¡è®°å½æ¶ï¼æåä¸è¡æææ°æ®ï¼å¶æ°æ¡æ¶ exportDto æ¯ç©ºå¯¹è±¡ï¼ä¸è½å è¿è¡¨æ ¼ |
| | | if (count != 0) { |
| | | exportDtoList.add(exportDto); |
| | | } |
| | | |
| | | // è´¨éè´è´£äºº |
| | | // è´¨éè´è´£äººï¼æªç¾åæ¶ç¨éæå¾çå
åºï¼ |
| | | String assessmentUserUrl = null; |
| | | if (detailedDto.getAssessmentUserId() != null) { |
| | | assessmentUserUrl = userMapper.selectById(detailedDto.getAssessmentUserId()).getSignatureUrl(); |
| | | if (StringUtils.isBlank(assessmentUserUrl)) { |
| | | throw new ErrorException("æ¾ä¸å°è¯ä»·äººçç¾å"); |
| | | User assessmentUser = userMapper.selectById(detailedDto.getAssessmentUserId()); |
| | | if (assessmentUser != null) { |
| | | assessmentUserUrl = assessmentUser.getSignatureUrl(); |
| | | } |
| | | } |
| | | |
| | |
| | | new HashMap<String, Object>() {{ |
| | | put("trainingDetail", detailedDto); |
| | | put("trainingRecordsList", exportDtoList); |
| | | put("assessmentUserUrl", StringUtils.isNotBlank(finalAssessmentUserUrl) ? Pictures.ofLocal(imgUrl + "/" + finalAssessmentUserUrl).create() : null); |
| | | put("assessmentUserUrl", UserUtils.orTransparentPicture(StringUtils.isNotBlank(finalAssessmentUserUrl) |
| | | ? Pictures.ofLocal(imgUrl + "/" + finalAssessmentUserUrl).create() : null)); |
| | | }}); |
| | | try { |
| | | response.setContentType("application/msword"); |
| | |
| | | |
| | | <select id="queryTheAnnualPlanDetailsTable" resultType="com.ruoyi.personnel.dto.PersonTrainingDetailedDto"> |
| | | SELECT cptd.*, |
| | | u1.name training_lecturer_name, |
| | | COALESCE(u1.name, cptd.training_lecturer_name) training_lecturer_name, |
| | | dl.name holding_department_name, !isnull(cptr.training_record_id) whether_claim |
| | | FROM cnas_person_training_detailed cptd |
| | | left join user u1 on cptd.training_lecturer_id = u1.id |
| | |
| | | and u1.id = #{userId} |
| | | </if> |
| | | <if test="trainingLecturerName != null and trainingLecturerName != ''"> |
| | | and u1.name like concat('%', #{trainingLecturerName}, '%') |
| | | and COALESCE(u1.name, cptd.training_lecturer_name) like concat('%', #{trainingLecturerName}, '%') |
| | | </if> |
| | | <if test="trainingDate != null and trainingDate != ''"> |
| | | and date_format(cptd.training_date,'%Y-%m-%d') = #{trainingDate} |
| | |
| | | <!-- æ ¹æ®ä¸»è¡¨idæ¥è¯¢è¯¦æ
--> |
| | | <select id="selectTrainingList" resultType="com.ruoyi.personnel.dto.PersonTrainingDetailedDto"> |
| | | SELECT cptd.*, |
| | | u1.name training_lecturer_name |
| | | COALESCE(u1.name, cptd.training_lecturer_name) training_lecturer_name |
| | | FROM cnas_person_training_detailed cptd |
| | | left join user u1 on cptd.training_lecturer_id = u1.id |
| | | where cptd.plan_id = #{trainingId} |
| | |
| | | <!-- æ¥è¯¢è¯¦ç» --> |
| | | <select id="selectTrainingDetail" resultType="com.ruoyi.personnel.dto.PersonTrainingDetailedDto"> |
| | | SELECT cptd.*, |
| | | u1.name training_lecturer_name, |
| | | COALESCE(u1.name, cptd.training_lecturer_name) training_lecturer_name, |
| | | u1.signature_url training_lecturer_signature_url |
| | | FROM cnas_person_training_detailed cptd |
| | | left join user u1 on cptd.training_lecturer_id = u1.id |
| | |
| | | // 对象å¤å¶ |
| | | QualityMonitorDetails monitorDetails = new QualityMonitorDetails(); |
| | | BeanUtils.copyProperties(detailsUpload, monitorDetails); |
| | | monitorDetails.setMonitorWay(normalizeMonitorWay(detailsUpload.getMonitorWay())); |
| | | monitorDetails.setQualityMonitorId(qualityMonitor.getQualityMonitorId()); |
| | | if (!detailsUpload.getCompletionMonth().matches("\\d{4}-\\d{2}")) { |
| | | throw new ErrorException("宿æ¶éæ ¼å¼åºä¸ºyyyy-MM"); |
| | |
| | | throw new RuntimeException(e); |
| | | } |
| | | return qualityMonitor; |
| | | } |
| | | |
| | | /** |
| | | * è´¨æ§æ¹å¼ç»ä¸ç¨âãâåéï¼å
¼å®¹å¯¼å
¥æ¨¡æ¿é常è§çéå·/åå·åæ³ã |
| | | */ |
| | | private String normalizeMonitorWay(String value) { |
| | | if (StringUtils.isBlank(value)) { |
| | | return value; |
| | | } |
| | | return java.util.Arrays.stream(value.split("[ã,ï¼;ï¼]")) |
| | | .map(String::trim) |
| | | .filter(StringUtils::isNotBlank) |
| | | .distinct() |
| | | .collect(Collectors.joining("ã")); |
| | | } |
| | | |
| | | /** |
| | |
| | | try { |
| | | response.setContentType("application/msword"); |
| | | String fileName = URLEncoder.encode( |
| | | "è´¨éçæ§å®æ½è®¡å", "UTF-8"); |
| | | "è´¨éæ§å¶æªæ½", "UTF-8"); |
| | | response.setHeader("Content-disposition", |
| | | "attachment;filename=" + fileName + ".docx"); |
| | | OutputStream os = response.getOutputStream(); |
| | |
| | | try { |
| | | response.setContentType("application/msword"); |
| | | String fileName = URLEncoder.encode( |
| | | "çæ§è¯ä»·", "UTF-8"); |
| | | "è´¨éæ§å¶è¯ä»·è®°å½", "UTF-8"); |
| | | response.setHeader("Content-disposition", |
| | | "attachment;filename=" + fileName + ".docx"); |
| | | OutputStream os = response.getOutputStream(); |