func-tbook-export.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. const { replaceDocx, docsToPdf, createZip, uploadFileToOSS } = require("../../lib/docs");
  2. const Parse = global.Parse;
  3. const path = require("path")
  4. const TemplateDocxPath = path.join(__dirname,"template/模板-推荐申报表.docx")
  5. /**
  6. * 导出流程教材申报文件
  7. * @returns
  8. * docsList
  9. * zipUrl
  10. */
  11. async function exportProcessReportDocs(processId) {
  12. let query = new Parse.Query("EduTextbook")
  13. query.equalTo("eduProcess",processId);
  14. let textbookList = await query.find();
  15. let docsList = []
  16. for (let index = 0; index < textbookList.length; index++) {
  17. let textbook = textbookList[index];
  18. let result = await renderReportDocsByTextbook(textbook);
  19. docsList.push(result)
  20. }
  21. console.log(textbookList);
  22. console.log(docsList)
  23. let zipPath,zipUrl
  24. if(docsList?.length){
  25. zipPath = await createZip(docsList?.map(item=>item?.filePath),`流程合集-${processId}.zip`)
  26. if(zipPath){
  27. zipUrl = (await uploadFileToOSS(zipPath))?.url || null
  28. }
  29. docsList = docsList.map(item=>{return {code:item.code,title:item.title,url:item?.url}})
  30. }
  31. let result = {
  32. docsList,
  33. zipUrl
  34. }
  35. return result
  36. }
  37. module.exports.exportProcessReportDocs = exportProcessReportDocs
  38. function renderReportDocsByTextbook(textbook){
  39. let json = textbook.toJSON();
  40. // 圆圈选中未选 ○ 未选 ● 选中
  41. let circleCheck = ["○","●"];
  42. // 方块选中未选 ○ 未选 ● 选中
  43. let squareCheck = [``,`☑`];
  44. // 联系电话:默认为作者首个存在的电话;
  45. let mobile = json?.authorList?.find(item => item.mobile)?.mobile || ""
  46. // 填报时间:默认为创建时间
  47. let createdAt = new Date(textbook?.createdAt);
  48. let createdDate = `${createdAt?.getFullYear()}年${createdAt?.getMonth()+1}月${createdAt?.getDate()}日`;
  49. // 专业代码:前四位
  50. let majorCode = json?.majorId || json?.major?.code
  51. if(majorCode?.length>4){
  52. majorCode = majorCode.slice(0,4)
  53. }
  54. let majorName = json?.majorName || json?.major?.name
  55. // 是否重点立项
  56. let isJC = circleCheck[(json?.approval?.indexOf("基础")>-1)?1:0];
  57. let isZL = circleCheck[(json?.approval?.indexOf("战略")>-1)?1:0];
  58. let isSX = circleCheck[(json?.approval?.indexOf("四新")>-1)?1:0];
  59. let isNotImpt = (json?.approval?.indexOf("基础")==-1) && (json?.approval?.indexOf("战略")==-1) && (json?.approval?.indexOf("四新")==-1)
  60. isNotImpt = circleCheck[isNotImpt?1:0];
  61. // 初版时间
  62. let firstDate = new Date(textbook?.get("editionFirst"));
  63. let firstYear = firstDate?.getFullYear();
  64. let firstMonth = firstDate?.getMonth()+1;
  65. // 本版时间印次
  66. let currentDate = new Date(textbook?.get("editionDate"));
  67. let currentYear = currentDate?.getFullYear();
  68. let currentMonth = currentDate?.getMonth()+1;
  69. // 最新时间印次
  70. let latestDate = new Date(textbook?.get("printDate"));
  71. let latestYear = latestDate?.getFullYear();
  72. let latestMonth = latestDate?.getMonth()+1;
  73. // 初版至今重点项目
  74. let isBSQT = !((json?.importantProject?.indexOf("建设")>-1) || (json?.importantProject?.indexOf("本科国家")>-1) || (json?.importantProject?.indexOf("省级优秀")>-1) || (json?.importantProject?.indexOf("省级规划")>-1))// 是否其他省级奖项
  75. let bookData = {
  76. // 封面信息
  77. titlePad:padString(json?.title,21),
  78. ISBN:padString(json?.ISBN,21),
  79. one:squareCheck[(json?.type=="单本"||json?.type=="单册")?1:0], // 单本/单册 方框
  80. full:squareCheck[json?.type=="全册"?1:0], // 全册
  81. oneCircle:circleCheck[(json?.type=="单本"||json?.type=="单册")?1:0], // 单本/单册 圆圈
  82. fullCircle:circleCheck[json?.type=="全册"?1:0], // 全册
  83. tn:json?.typeNumber,
  84. authorPad:padString(json?.author,21),
  85. mobile:padString(mobile,21),
  86. authorUnit:padString(json?.unit,21),
  87. publisherPad:padString(json?.editionUnit,21),
  88. recommandUnit:padString("",21), // 未找到
  89. majorCodePad:padString((majorCode),14),
  90. createdDate:padString(createdDate,21),
  91. // 基本信息
  92. title:json?.title,
  93. author:json?.author,
  94. unit:json?.unit,
  95. mc:majorCode,
  96. mn:majorName,
  97. lCN:circleCheck[(json?.lang=="中文")?1:0],
  98. lEN:circleCheck[(json?.lang=="英文")?1:0],
  99. lOT:circleCheck[(json?.lang?.indexOf("其他")>-1)?1:0],
  100. lSS:circleCheck[(json?.lang?.indexOf("少数")>-1)?1:0],
  101. authors:json?.authors, // 其他主编
  102. editor:json?.editor, // 其他编者
  103. isJC:isJC,
  104. isZL:isZL,
  105. isSX:isSX,
  106. isNotImpt:isNotImpt,
  107. publisher:json?.editionUnit,
  108. firstYear:firstYear,
  109. firstMonth:firstMonth,
  110. isZZ:circleCheck[(json?.carrierShape?.indexOf("纸质")>-1)?1:0],
  111. isDZ:circleCheck[(json?.carrierShape?.indexOf("电子")>-1)?1:0],
  112. isSZ:circleCheck[(json?.carrierShape?.indexOf("数字")>-1)?1:0],
  113. isQT:circleCheck[(json?.carrierShape?.indexOf("附带")>-1)?1:0],
  114. isFD:circleCheck[(json?.carrierShape?.indexOf("其他")>-1)?1:0],
  115. latestY:latestYear,
  116. latestM:latestMonth,
  117. latestNum:json?.printNumber || "",
  118. currentY:currentYear,
  119. currentM:currentMonth,
  120. currentNum:json?.editionNumber || "",
  121. printSum:json?.printSum || "",
  122. isJS:circleCheck[(json?.importantProject?.indexOf("建设")>-1)?1:0],
  123. isBGJ:circleCheck[(json?.importantProject?.indexOf("本科国家")>-1)?1:0],
  124. isBSYX:circleCheck[(json?.importantProject?.indexOf("省级优秀")>-1)?1:0],
  125. isBSGH:circleCheck[(json?.importantProject?.indexOf("省级规划")>-1)?1:0],
  126. isBSQT:circleCheck[isBSQT?1:0],
  127. bsqtName:isBSQT?json?.importantProject:"",
  128. isFirstNot:circleCheck[json?.importantProject?0:1],
  129. }
  130. console.log(bookData)
  131. let bookid = json.code || json?.objectId;
  132. let tempFileName = path.join(`${bookid}${json.title}.docx`)
  133. return new Promise((resolve)=>{
  134. replaceDocx(TemplateDocxPath,tempFileName,bookData,{onDocxComplete:async (filePath)=>{
  135. // 需要API支持
  136. // docsToPdf(filePath)
  137. let url = (await uploadFileToOSS(filePath))?.url || null
  138. resolve({
  139. code:bookid,
  140. title:json?.title,
  141. filePath,
  142. url
  143. })
  144. }})
  145. })
  146. }
  147. function padString(str,width) {
  148. str = str || ""
  149. str = String(str)
  150. width = width || 21 // 目标宽度为21个单位
  151. spaceChar = "&#160;" // 占位符
  152. // 计算字符串的宽度
  153. let strWidth = 0;
  154. console.log(str)
  155. for (let char of str) {
  156. // 判断字符是否为中文
  157. if (char.match(/[\u4e00-\u9fa5]/)) {
  158. strWidth += 2; // 中文字符占4个单位
  159. } else {
  160. strWidth += 1; // 英文字符占1个单位
  161. }
  162. }
  163. const totalPadding = width - strWidth;
  164. // 如果已经达到或超过目标宽度,直接返回原字符串
  165. if (totalPadding <= 0) {
  166. return str;
  167. }
  168. // 计算左右两侧的空格数
  169. const leftPadding = Math.floor(totalPadding / 2) * 3;
  170. const rightPadding = Math.ceil(totalPadding / 2) * 3;
  171. // 生成填充空格的字符串
  172. const leftSpaces = spaceChar.repeat(leftPadding);
  173. const rightSpaces = spaceChar.repeat(rightPadding);
  174. // 返回补充后的字符串
  175. return leftSpaces + str + rightSpaces;
  176. }