MesEmpUserExportService.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. package com.jeesite.modules.mes.service;
  2. import cn.hutool.extra.qrcode.QrCodeUtil;
  3. import com.jeesite.common.codec.DesUtils;
  4. import com.jeesite.common.collect.ListUtils;
  5. import com.jeesite.common.config.Global;
  6. import com.jeesite.common.lang.DateUtils;
  7. import com.jeesite.common.lang.StringUtils;
  8. import com.jeesite.common.utils.excel.ExcelExport;
  9. import com.jeesite.modules.mes.entity.MesLineProcessUser;
  10. import com.jeesite.modules.mes.entity.MesUserAuthExport;
  11. import com.jeesite.modules.sys.dao.UserRoleDao;
  12. import com.jeesite.modules.sys.entity.EmpUser;
  13. import com.jeesite.modules.sys.entity.Role;
  14. import com.jeesite.modules.sys.entity.User;
  15. import com.jeesite.modules.sys.entity.UserRole;
  16. import com.jeesite.modules.sys.service.EmpUserService;
  17. import com.jeesite.modules.sys.service.RoleService;
  18. import com.jeesite.modules.sys.service.UserService;
  19. import org.apache.poi.ss.usermodel.Cell;
  20. import org.apache.poi.ss.usermodel.CellStyle;
  21. import org.apache.poi.ss.usermodel.CellType;
  22. import org.apache.poi.ss.usermodel.ClientAnchor;
  23. import org.apache.poi.ss.usermodel.Drawing;
  24. import org.apache.poi.ss.usermodel.HorizontalAlignment;
  25. import org.apache.poi.ss.usermodel.Row;
  26. import org.apache.poi.ss.usermodel.Sheet;
  27. import org.apache.poi.ss.usermodel.VerticalAlignment;
  28. import org.apache.poi.ss.usermodel.Workbook;
  29. import org.apache.poi.util.Units;
  30. import org.springframework.beans.factory.annotation.Autowired;
  31. import org.springframework.stereotype.Service;
  32. import javax.servlet.http.HttpServletResponse;
  33. import java.util.ArrayList;
  34. import java.util.HashMap;
  35. import java.util.LinkedHashSet;
  36. import java.util.List;
  37. import java.util.Map;
  38. import java.util.Set;
  39. import java.util.stream.Collectors;
  40. /**
  41. * 员工权限导出 Service
  42. */
  43. @Service
  44. public class MesEmpUserExportService {
  45. private static final int QRCODE_COLUMN_INDEX = 2;
  46. private static final int QRCODE_SIZE = 200;
  47. private static final int QRCODE_DISPLAY_SIZE_PX = 120;
  48. private static final float QRCODE_ROW_HEIGHT = 95F;
  49. private static final float MIN_ROW_HEIGHT = 15F;
  50. private static final float LINE_HEIGHT = 15F;
  51. /** ExcelExport 会先写标题行和表头行,数据从第 3 行开始 */
  52. private static final int DATA_ROW_OFFSET = 2;
  53. private static final int[] COLUMN_WIDTH_CHARS = {14, 18, 22, 50};
  54. private static final String MULTI_VALUE_SEPARATOR = "、";
  55. @Autowired
  56. private EmpUserService empUserService;
  57. @Autowired
  58. private UserService userService;
  59. @Autowired
  60. private RoleService roleService;
  61. @Autowired
  62. private UserRoleDao userRoleDao;
  63. @Autowired
  64. private MesLineProcessUserService mesLineProcessUserService;
  65. /**
  66. * 组装员工权限导出数据(一行一个用户)
  67. */
  68. public List<MesUserAuthExport> findUserAuthExportList() {
  69. List<EmpUser> userList = empUserService.findList(new EmpUser());
  70. if (ListUtils.isEmpty(userList)) {
  71. return new ArrayList<>();
  72. }
  73. Map<String, String> loginCodeMap = buildLoginCodeMap(userList);
  74. Map<String, String> roleNameMap = buildRoleNameMap();
  75. Map<String, List<String>> userRoleMap = buildUserRoleMap(roleNameMap);
  76. Map<String, List<MesLineProcessUser>> userOprnoMap = buildUserOprnoMap();
  77. String secretKey = Global.getConfig("shiro.loginSubmit.secretKey");
  78. List<MesUserAuthExport> result = new ArrayList<>();
  79. for (EmpUser user : userList) {
  80. if (user == null || StringUtils.isBlank(user.getUserCode())) {
  81. continue;
  82. }
  83. MesUserAuthExport row = new MesUserAuthExport();
  84. row.setUserName(user.getUserName());
  85. row.setRoleNames(joinList(userRoleMap.get(user.getUserCode())));
  86. row.setOprnoAuth(defaultDisplay(formatOprnos(userOprnoMap.get(user.getUserCode()))));
  87. String loginCode = loginCodeMap.get(user.getUserCode());
  88. if (StringUtils.isNotBlank(loginCode)) {
  89. row.setQrcode(DesUtils.encode(loginCode, secretKey));
  90. }
  91. result.add(row);
  92. }
  93. return result;
  94. }
  95. /**
  96. * 导出员工权限 Excel(二维码列嵌入图片)
  97. */
  98. public void exportUserAuth(HttpServletResponse response) {
  99. List<MesUserAuthExport> list = findUserAuthExportList();
  100. List<String> qrcodeContents = new ArrayList<>(list.size());
  101. for (MesUserAuthExport row : list) {
  102. qrcodeContents.add(row.getQrcode());
  103. row.setQrcode("");
  104. }
  105. String fileName = "员工权限导出" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
  106. try (ExcelExport ee = new ExcelExport("员工权限导出", MesUserAuthExport.class)) {
  107. ee.setDataList(list);
  108. finalizeExportSheet(ee.getWorkbook(), list.size(), qrcodeContents);
  109. ee.write(response, fileName);
  110. }
  111. }
  112. private void finalizeExportSheet(Workbook workbook, int dataSize, List<String> qrcodeContents) {
  113. if (workbook == null || dataSize <= 0) {
  114. return;
  115. }
  116. Sheet sheet = workbook.getNumberOfSheets() > 0 ? workbook.getSheetAt(0) : null;
  117. if (sheet == null) {
  118. return;
  119. }
  120. for (int i = 0; i < COLUMN_WIDTH_CHARS.length; i++) {
  121. sheet.setColumnWidth(i, COLUMN_WIDTH_CHARS[i] * 256);
  122. }
  123. Drawing<?> drawing = sheet.createDrawingPatriarch();
  124. for (int i = 0; i < dataSize; i++) {
  125. int rowIndex = i + DATA_ROW_OFFSET;
  126. Row row = sheet.getRow(rowIndex);
  127. if (row == null) {
  128. continue;
  129. }
  130. float textHeight = MIN_ROW_HEIGHT;
  131. for (int col = 0; col < COLUMN_WIDTH_CHARS.length; col++) {
  132. if (col == QRCODE_COLUMN_INDEX) {
  133. continue;
  134. }
  135. Cell cell = row.getCell(col);
  136. if (cell == null) {
  137. continue;
  138. }
  139. applyWrapStyle(workbook, cell);
  140. textHeight = Math.max(textHeight, calculateWrapHeight(getCellStringValue(cell), COLUMN_WIDTH_CHARS[col]));
  141. }
  142. boolean hasQrcode = i < qrcodeContents.size() && StringUtils.isNotBlank(qrcodeContents.get(i));
  143. float rowHeight = Math.max(textHeight, hasQrcode ? QRCODE_ROW_HEIGHT : MIN_ROW_HEIGHT);
  144. row.setHeightInPoints(rowHeight);
  145. if (hasQrcode) {
  146. appendQrcodeImage(workbook, drawing, row, rowIndex, qrcodeContents.get(i));
  147. }
  148. }
  149. }
  150. private void applyWrapStyle(Workbook workbook, Cell cell) {
  151. CellStyle style = workbook.createCellStyle();
  152. CellStyle existing = cell.getCellStyle();
  153. if (existing != null) {
  154. style.cloneStyleFrom(existing);
  155. }
  156. style.setWrapText(true);
  157. style.setVerticalAlignment(VerticalAlignment.CENTER);
  158. style.setAlignment(HorizontalAlignment.CENTER);
  159. cell.setCellStyle(style);
  160. }
  161. private void appendQrcodeImage(Workbook workbook, Drawing<?> drawing, Row row, int rowIndex, String content) {
  162. Cell cell = row.getCell(QRCODE_COLUMN_INDEX);
  163. if (cell == null) {
  164. cell = row.createCell(QRCODE_COLUMN_INDEX);
  165. }
  166. cell.setCellValue("");
  167. byte[] pngBytes = QrCodeUtil.generatePng(content, QRCODE_SIZE, QRCODE_SIZE);
  168. int pictureIndex = workbook.addPicture(pngBytes, Workbook.PICTURE_TYPE_PNG);
  169. int margin = Units.pixelToEMU(4);
  170. int size = Units.pixelToEMU(QRCODE_DISPLAY_SIZE_PX);
  171. ClientAnchor anchor = drawing.createAnchor(margin, margin, margin + size, margin + size,
  172. QRCODE_COLUMN_INDEX, rowIndex, QRCODE_COLUMN_INDEX, rowIndex);
  173. drawing.createPicture(anchor, pictureIndex);
  174. }
  175. private float calculateWrapHeight(String text, int columnWidthChars) {
  176. if (StringUtils.isBlank(text)) {
  177. return MIN_ROW_HEIGHT;
  178. }
  179. int maxLineLength = Math.max(columnWidthChars, 1);
  180. String[] lines = text.split("\\R");
  181. int totalLines = 0;
  182. for (String line : lines) {
  183. totalLines += Math.max(1, (int) Math.ceil((double) line.length() / maxLineLength));
  184. }
  185. return Math.min(totalLines * LINE_HEIGHT + 5F, 409F);
  186. }
  187. private String getCellStringValue(Cell cell) {
  188. if (cell == null) {
  189. return "";
  190. }
  191. if (cell.getCellType() == CellType.STRING) {
  192. return cell.getStringCellValue();
  193. }
  194. if (cell.getCellType() == CellType.NUMERIC) {
  195. return String.valueOf(cell.getNumericCellValue());
  196. }
  197. return "";
  198. }
  199. private Map<String, String> buildLoginCodeMap(List<EmpUser> userList) {
  200. Map<String, String> loginCodeMap = new HashMap<>();
  201. for (EmpUser user : userList) {
  202. if (user == null || StringUtils.isBlank(user.getUserCode())) {
  203. continue;
  204. }
  205. if (StringUtils.isNotBlank(user.getLoginCode())) {
  206. loginCodeMap.put(user.getUserCode(), user.getLoginCode());
  207. continue;
  208. }
  209. User fullUser = userService.get(user.getUserCode());
  210. if (fullUser != null && StringUtils.isNotBlank(fullUser.getLoginCode())) {
  211. loginCodeMap.put(user.getUserCode(), fullUser.getLoginCode());
  212. }
  213. }
  214. return loginCodeMap;
  215. }
  216. private Map<String, String> buildRoleNameMap() {
  217. Map<String, String> roleNameMap = new HashMap<>();
  218. List<Role> roleList = roleService.findList(new Role());
  219. if (ListUtils.isEmpty(roleList)) {
  220. return roleNameMap;
  221. }
  222. for (Role role : roleList) {
  223. if (role != null && StringUtils.isNotBlank(role.getRoleCode())) {
  224. roleNameMap.put(role.getRoleCode(), StringUtils.defaultString(role.getRoleName(), role.getRoleCode()));
  225. }
  226. }
  227. return roleNameMap;
  228. }
  229. private Map<String, List<String>> buildUserRoleMap(Map<String, String> roleNameMap) {
  230. Map<String, List<String>> userRoleMap = new HashMap<>();
  231. List<UserRole> userRoleList = userRoleDao.findList(new UserRole());
  232. if (ListUtils.isEmpty(userRoleList)) {
  233. return userRoleMap;
  234. }
  235. for (UserRole userRole : userRoleList) {
  236. if (userRole == null || StringUtils.isBlank(userRole.getUserCode())) {
  237. continue;
  238. }
  239. String roleName = roleNameMap.getOrDefault(userRole.getRoleCode(), userRole.getRoleCode());
  240. userRoleMap.computeIfAbsent(userRole.getUserCode(), k -> new ArrayList<>()).add(roleName);
  241. }
  242. return userRoleMap;
  243. }
  244. private Map<String, List<MesLineProcessUser>> buildUserOprnoMap() {
  245. return mesLineProcessUserService.findList(new MesLineProcessUser()).stream()
  246. .filter(item -> item != null && StringUtils.isNotBlank(item.getUserCode()))
  247. .collect(Collectors.groupingBy(MesLineProcessUser::getUserCode));
  248. }
  249. private String formatOprnos(List<MesLineProcessUser> processUsers) {
  250. if (ListUtils.isEmpty(processUsers)) {
  251. return "";
  252. }
  253. Set<String> items = new LinkedHashSet<>();
  254. for (MesLineProcessUser processUser : processUsers) {
  255. if (processUser != null && StringUtils.isNotBlank(processUser.getOprno())) {
  256. items.add(processUser.getOprno());
  257. }
  258. }
  259. return joinSet(items);
  260. }
  261. private String joinList(List<String> list) {
  262. if (ListUtils.isEmpty(list)) {
  263. return "";
  264. }
  265. return String.join(MULTI_VALUE_SEPARATOR, list);
  266. }
  267. private String joinSet(Set<String> set) {
  268. if (set == null || set.isEmpty()) {
  269. return "";
  270. }
  271. return String.join(MULTI_VALUE_SEPARATOR, set);
  272. }
  273. private String defaultDisplay(String value) {
  274. return StringUtils.isBlank(value) ? "无" : value;
  275. }
  276. }