123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- import { replaceDocx, createZip, uploadFileToOSS, docxToPdf, renderDocx } from "../../lib/docs";
- const path = require("path")
- const fs = require("fs")
- var TemplateDocxPath = path.join(__dirname,"template/模板-推荐申报表.docx")
- if(!fs.existsSync(TemplateDocxPath)){
- TemplateDocxPath = path.join(__dirname,"../../template/模板-推荐申报表.docx")
- }
- export function defineTbookExportReport(app){
- app.post("/parse/api/tbook/export",async (request,res)=>{
- let processId = request.body.processId;
- let bookList = request.body.bookList;
- console.log(request.body)
- try{
- let result
- if(processId){
- result = await exportProcessReportDocs(processId)
- }
- if(bookList?.length){
- result = await exportProcessReportDocs(null,bookList)
- }
- if(result?.docsList?.length==0){
-
- res.json({
- code:400,
- err:"合集内无申报教材"
- })
- }
-
- res.json({
- code:200,
- result:result
- })
- }catch(err){
- console.error(err)
- res.json({
- code:400,
- err:err
- })
-
- }
-
-
- })
- Parse.Cloud.define("tbookExportReport", async (request) => {
- let processId = request.params.processId;
- let bookList = request.params.bookList;
- try{
- let result
- if(processId){
- result = await exportProcessReportDocs(processId)
- }
- if(bookList?.length){
- result = await exportProcessReportDocs(null,bookList)
- }
- if(result?.docsList?.length==0){
- throw new Parse.Error(404,"合集内无申报教材")
- }
- return result
- }catch(err){
- console.error(err)
- throw new Parse.Error(404,"导出申报合集失败")
- }
- throw new Parse.Error(404,"未找到该流程合集")
- },{
- fields : {
- processId:{
- required:false
- },
- }
- });
- }
-
- export async function exportProcessReportDocs(processId,bookList) {
- if(!processId && !bookList?.length) return {}
- let textbookList
- if(processId){
- let query = new Parse.Query("EduTextbook")
- query.equalTo("eduProcess",processId);
- textbookList = await query.find();
- }
- if(bookList?.length){
- let query = new Parse.Query("EduTextbook")
- query.containedIn("objectId",bookList);
- textbookList = await query.find();
- }
- let docsList = []
- let plist = []
- for (let index = 0; index < textbookList.length; index++) {
- let textbook = textbookList[index];
- console.log("textbook",index)
-
- plist.push(renderReportDocsByTextbook(textbook));
- }
- let presults = await Promise.all(plist);
- presults.forEach(result=>{
- if(result?.filePath){
- docsList.push(result)
- }
- })
- let zipPath,zipUrl
- if(docsList?.length){
- let now = new Date();
- let fileList = docsList?.map(item=>item?.pdfPath);
- let zipName = `申报书导出-${now.getFullYear()}${now.getMonth()+1}${now.getDate()}-${now.getHours()}${now.getMinutes()}${now.getSeconds()}.zip`
- zipPath = await createZip(fileList,zipName)
- if(zipPath){
- zipUrl = (await uploadFileToOSS(zipPath))?.url || null
- }
- docsList = docsList.map(item=>{return {code:item.code,title:item.title,url:item?.url}})
- }
- let result = {
- docsList,
- zipUrl
- }
- return result
- }
- module.exports.exportProcessReportDocs = exportProcessReportDocs
- function renderReportDocsByTextbook(textbook){
- console.log("renderReportDocsByTextbook")
- let json = textbook.toJSON();
-
-
- let circleCheck = ["○","●"];
-
- let squareCheck = [`□`,String.fromCharCode(0xFE)];
-
- let mobile = json?.authorList?.find(item => item.mobile)?.mobile || ""
-
- let createdAt = new Date(textbook?.createdAt);
- let createdDate = `${createdAt?.getFullYear()}年${createdAt?.getMonth()+1}月${createdAt?.getDate()}日`;
-
- let majorCode = json?.majorId || json?.major?.code
- let majorCode6
- if(majorCode?.length>4){
- majorCode = majorCode.slice(0,4)
- majorCode6 = majorCode.slice(0,6)
- }
- let majorName = json?.majorName || json?.major?.name
-
- let importantProject = json?.importantProject?.join();
- let isJC = circleCheck[(json?.approval?.indexOf("基础")>-1)?1:0];
- let isZL = circleCheck[(json?.approval?.indexOf("战略")>-1)?1:0];
-
- let is101 = circleCheck[(json?.approval?.indexOf("101计划")>-1)?1:0];
- let isZY = circleCheck[(json?.approval?.indexOf("中央")>-1)?1:0];
- let isSX = circleCheck[(json?.approval?.indexOf("四新")>-1)?1:0];
- let isJS = circleCheck[(importantProject?.indexOf("建设")>-1)?1:0];
- let isNotImpt = (json?.approval?.indexOf("101计划")==-1) && (json?.approval?.indexOf("中央")==-1) && (json?.approval?.indexOf("四新")==-1) && (json?.approval?.indexOf("建设")==-1)
- isNotImpt = circleCheck[isNotImpt?1:0];
-
- let firstDate = new Date(textbook?.get("editionFirst"));
- let firstYear = firstDate?.getFullYear();
- let firstMonth = firstDate?.getMonth()+1;
-
- let currentDate = new Date(textbook?.get("editionDate"));
- let currentYear = currentDate?.getFullYear();
- let currentMonth = currentDate?.getMonth()+1;
-
- let latestDate = new Date(textbook?.get("printDate"));
- let latestYear = latestDate?.getFullYear();
- let latestMonth = latestDate?.getMonth()+1;
-
- let isBSQT = !((importantProject?.indexOf("建设")>-1) || (importantProject?.indexOf("本科国家")>-1) || (importantProject?.indexOf("省级优秀")>-1) || (importantProject?.indexOf("省级规划")>-1))
- let bsqtName = (json?.importantProject || [])?.filter(item=>(item?.indexOf("建设")==-1&&item?.indexOf("本科国家")==-1&&item?.indexOf("省级优秀")==-1&&item?.indexOf("省级规划")==-1));
-
- let characteristic = (json?.characteristic?.filter(item=>item?.checked).map(item=>item.label) || [])?.join(",")
-
- let alist = []
- for (let index = 0; index < 9; index++) {
- alist[index] = [json?.authorList?.[index]?.name||" ",json?.authorList?.[index]?.unit||" ",toYearMonth(json?.authorList?.[index]?.birth)||" ",json?.authorList?.[index]?.nationality||" ",json?.authorList?.[index]?.job||" ",json?.authorList?.[index]?.title||" ",json?.authorList?.[index]?.mobile||" ",json?.authorList?.[index]?.email||" ",json?.authorList?.[index]?.work||" "]
- }
-
- let aclist = []
- for (let index = 0; index < 5; index++) {
- aclist[index] = [json?.achievementOptions?.[index]?.name||" ",json?.achievementOptions?.[index]?.unit||" ",toYearMonth(json?.achievementOptions?.[index]?.date)||" "]
- }
-
- let clist = []
- for (let index = 0; index < 4; index++) {
- let num = json?.courses?.[index]?(index+1):" ";
- clist[index] = [num,toYearMonth(json?.courses?.[index]?.date)||" ",json?.courses?.[index]?.wordage||" ",json?.courses?.[index]?.num||" ",json?.courses?.[index]?.sumNum||" ",json?.courses?.[index]?.accolade||" "]
- }
-
-
- let mergeFiles = []
-
-
-
-
-
-
- if(json?.selfResults?.url){mergeFiles.push(json?.selfResults?.url)}
-
-
- if(json?.expertOpinion?.url){mergeFiles.push(json?.expertOpinion?.url)}
-
-
- if(json?.evidence?.url){mergeFiles.push(json?.evidence?.url)}
-
-
- if(json?.CIPImgUrl){mergeFiles.push(json?.CIPImgUrl)}
-
- if(json?.moreMaterial?.length){
- json?.moreMaterial.forEach(doc=>{
- if(doc?.url){
- mergeFiles.push(doc?.url)
- }
- })
- }
-
- let fixData = {
-
- titlePad:padString(json?.title,21),
- ISBNPad:padString(json?.ISBN,21),
- ISBN:json?.ISBN,
- inviteUnit:json?.inviteUnit||"",
- one:squareCheck[(json?.type=="单本"||json?.type=="单册")?1:0],
- full:squareCheck[json?.type=="全册"?1:0],
- oneCircle:circleCheck[(json?.type=="单本"||json?.type=="单册")?1:0],
- fullCircle:circleCheck[json?.type=="全册"?1:0],
- tn:json?.typeNumber,
- authorPad:padString(json?.author,21),
- mobile:padString(mobile,21),
- authorUnit:padString(json?.unit,21),
- publisherPad:padString(json?.editionUnit,21),
- recommandUnit:padString("",14),
- majorCodePad:padString((majorCode),6),
- createdDate:padString(createdDate,21),
-
- title:json?.title,
- author:json?.author,
- unit:json?.unit,
- uBS:circleCheck[(json?.unitType?.indexOf("部属")>-1)?1:0],
- uHJ:circleCheck[(json?.unitType?.indexOf("合建")>-1)?1:0],
- uGJ:circleCheck[(json?.unitType?.indexOf("共建")>-1)?1:0],
- uQT:circleCheck[(json?.unitType?.indexOf("其他")>-1)?1:0],
- mc:majorCode,
- mc6:majorCode6,
- mn:majorName,
- lCN:circleCheck[(json?.lang=="中文")?1:0],
- lEN:circleCheck[(json?.lang=="英文")?1:0],
- lOT:circleCheck[(json?.lang?.indexOf("其他")>-1)?1:0],
- lSS:circleCheck[(json?.lang?.indexOf("少数")>-1)?1:0],
- authors:json?.authors,
- editor:json?.editor,
- isJC:isJC,
- isZL:isZL,
- isSX:isSX,
- is101:is101,
- isZY:isZY,
- isJS:isJS,
- isNotImpt:isNotImpt,
- publisher:json?.editionUnit,
- firstYear:firstYear,
- firstMonth:firstMonth,
- isZZ:circleCheck[(json?.carrierShape?.indexOf("纸质")>-1)?1:0],
- isDZ:circleCheck[(json?.carrierShape?.indexOf("电子")>-1)?1:0],
- isSZ:circleCheck[(json?.carrierShape?.indexOf("数字")>-1)?1:0],
- isQT:circleCheck[(json?.carrierShape?.indexOf("附带")>-1)?1:0],
- isFD:circleCheck[(json?.carrierShape?.indexOf("其他")>-1)?1:0],
- latestY:latestYear,
- latestM:latestMonth,
- latestNum:json?.printNumber || "",
- currentY:currentYear,
- currentM:currentMonth,
- currentNum:json?.editionNumber || "",
- printSum:json?.printSum || "",
- isBGJ:circleCheck[(importantProject?.indexOf("本科国家")>-1)?1:0],
- isBSYX:circleCheck[(importantProject?.indexOf("省级优秀")>-1)?1:0],
- isBSGH:circleCheck[(importantProject?.indexOf("省级规划")>-1)?1:0],
- isBSQT:circleCheck[isBSQT?1:0],
- bsqtName:bsqtName||"",
- isFirstNot:circleCheck[json?.importantProject?0:1],
-
- lessons:json?.lessons||[],
- period:json?.period||"",
- isBX:squareCheck[(characteristic?.indexOf("必修")>-1)?1:0],
- isXX:squareCheck[(characteristic?.indexOf("选修")>-1)?1:0],
- isTS:circleCheck[(characteristic?.indexOf("通识")>-1)?1:0],
- isGG:circleCheck[(characteristic?.indexOf("公共")>-1)?1:0],
- isZY:circleCheck[(characteristic?.indexOf("专业")>-1)?1:0],
- isSXZZ:squareCheck[(characteristic?.indexOf("思想")>-1)?1:0],
- isSY:squareCheck[(characteristic?.indexOf("实验")>-1)?1:0],
-
- a11:alist[0][0],a12:alist[0][1],a13:alist[0][2],a14:alist[0][3],a15:alist[0][4],a16:alist[0][5],a17:alist[0][6],a18:alist[0][7],a19:alist[0][8],
- a21:alist[1][0],a22:alist[1][1],a23:alist[1][2],a24:alist[1][3],a25:alist[1][4],a26:alist[1][5],a27:alist[1][6],a28:alist[1][7],a29:alist[1][8],
- a31:alist[2][0],a32:alist[2][1],a33:alist[2][2],a34:alist[2][3],a35:alist[2][4],a36:alist[2][5],a37:alist[2][6],a38:alist[2][7],a39:alist[2][8],
- a41:alist[3][0],a42:alist[3][1],a43:alist[3][2],a44:alist[3][3],a45:alist[3][4],a46:alist[3][5],a47:alist[3][6],a48:alist[3][7],a49:alist[3][8],
- a51:alist[4][0],a52:alist[4][1],a53:alist[4][2],a54:alist[4][3],a55:alist[4][4],a56:alist[4][5],a57:alist[4][6],a58:alist[4][7],a59:alist[4][8],
- a61:alist[5][0],a62:alist[5][1],a63:alist[5][2],a64:alist[5][3],a65:alist[5][4],a66:alist[5][5],a67:alist[5][6],a68:alist[5][7],a69:alist[5][8],
-
- ac11:aclist[0][0],ac12:aclist[0][1],ac13:aclist[0][2],
- ac21:aclist[1][0],ac22:aclist[1][1],ac23:aclist[1][2],
- ac31:aclist[2][0],ac32:aclist[2][1],ac33:aclist[2][2],
- ac41:aclist[3][0],ac42:aclist[3][1],ac43:aclist[3][2],
- ac51:aclist[4][0],ac52:aclist[4][1],ac53:aclist[4][2],
-
- c11:clist[0][0],c12:clist[0][1],c13:clist[0][2],c14:clist[0][3],c15:clist[0][4],c16:clist[0][5],
- c21:clist[1][0],c22:clist[1][1],c23:clist[1][2],c24:clist[1][3],c25:clist[1][4],c26:clist[1][5],
- c31:clist[2][0],c32:clist[2][1],c33:clist[2][2],c34:clist[2][3],c35:clist[2][4],c36:clist[2][5],
- c41:clist[3][0],c42:clist[3][1],c43:clist[3][2],c44:clist[3][3],c45:clist[3][4],c46:clist[3][5],
- }
- let bookData = json;
- Object.keys(fixData).forEach(key=>{
- bookData[key] = fixData[key]
- })
-
-
- let bookid = json.code || json?.objectId;
- let tempFileName = path.join(`${bookid}${json.title}.docx`)
- return new Promise(async (resolve)=>{
- let filePath,pdfPath,urlDocx,urlPdf
- try{
-
- filePath = renderDocx(TemplateDocxPath,tempFileName,bookData)
- urlDocx = (await uploadFileToOSS(filePath))?.url || null
- console.log("DOCX CREATED:",filePath)
-
- pdfPath = filePath.replaceAll(".docx",".pdf")
- let options = {
- mergeFiles:mergeFiles
- }
- pdfPath = await docxToPdf(filePath,pdfPath,options) || filePath
- console.log("PDF CREATED:",filePath)
- if(pdfPath){
- urlPdf = (await uploadFileToOSS(pdfPath))?.url || null
- }
- }catch(err){
- console.error(err)
- }
- resolve({
- code:bookid,
- title:json?.title,
- filePath,
- pdfPath,
- urlDocx,
- urlPdf,
- })
- return
- replaceDocx(TemplateDocxPath,tempFileName,bookData,{onDocxComplete:async (filePath)=>{
-
- let pdfPath = filePath.replaceAll(".docx",".pdf")
- filePath = await docxToPdf(filePath,pdfPath) || filePath
- let url = (await uploadFileToOSS(pdfPath))?.url || null
- resolve({
- code:bookid,
- title:json?.title,
- filePath,
- url
- })
- }})
- })
- }
- function toYearMonth(date){
- if(!date) return ""
- date = new Date(date?.iso||date);
- return `${date.getFullYear()}年${date.getMonth()+1}月`
- }
- function padString(str,width) {
- str = str || ""
- return str
- str = String(str)
- width = width || 21
- let spaceChar = " "
-
- const charWidth = {
- 'space': 1,
- 'zh': 3,
- 'en': 1,
- 'other': 1
- };
- let strWidth = 0;
-
-
- for (let char of str) {
- if (/\s/.test(char)) {
- strWidth += charWidth.space;
- } else if (/[\u4e00-\u9fa5]/.test(char)) {
- strWidth += charWidth.zh;
- } else if (/[a-zA-Z]/.test(char)) {
- strWidth += charWidth.en;
- } else {
- strWidth += charWidth.other;
- }
- }
-
-
-
-
-
-
-
-
- const totalPadding = width - strWidth;
-
- if (totalPadding <= 0) {
- return str;
- }
-
- const leftPadding = Math.floor(totalPadding / 2) * 3;
- const rightPadding = Math.ceil(totalPadding / 2) * 3;
-
- const leftSpaces = spaceChar.repeat(leftPadding);
- const rightSpaces = spaceChar.repeat(rightPadding);
-
- return leftSpaces + str + rightSpaces;
- }
|