123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- import { replaceDocx, docsToPdf, createZip, uploadFileToOSS } from "../../lib/docs";
- // const Parse = global.Parse;
- 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")
- }
- /**
- * 定义导出申报合集文档云函数
- * @example
- * Cloud Code test
- 导出流程
- curl -X POST -H "Content-Type: application/json" -H 'X-Parse-Application-Id: edu-textbook' -d '{ "processId": "Wz34loxdbO" }' http://127.0.0.1:61337/parse/functions/tbookExportReport
- curl -X POST -H "Content-Type: application/json" -H 'X-Parse-Application-Id: edu-textbook' -d '{ "processId": "Wz34loxdbO" }' http://8.140.98.43/parse/functions/tbookExportReport
- 导出教材列表
- curl -X POST -H "Content-Type: application/json" -H 'X-Parse-Application-Id: edu-textbook' -d '{ "bookList": ["2YBKitpCJL","xLdiEaHGrX"] }' http://127.0.0.1:61337/parse/functions/tbookExportReport
- */
- export function defineTbookExportReport(){
- Parse.Cloud.define("tbookExportReport", async (request) => {
- let processId = request.params.processId;
- let bookList = request.params.bookList;
- try{
- let result
- if(processId){
- await exportProcessReportDocs(processId)
- }
- if(bookList?.length){
- 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
- },
- }
- });
- }
-
- /**
- * 导出流程教材申报文件
- * @returns
- * docsList
- * zipUrl
- */
- 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 = []
- for (let index = 0; index < textbookList.length; index++) {
- let textbook = textbookList[index];
- let result = await renderReportDocsByTextbook(textbook);
- docsList.push(result)
- }
- let zipPath,zipUrl
- if(docsList?.length){
- let now = new Date();
- let zipName = `申报书导出-${now.getFullYear()}${now.getMonth()+1}${now.getDate()}-${now.getHours()}${now.getMinutes()}${now.getSeconds()}.zip`
- zipPath = await createZip(docsList?.map(item=>item?.filePath),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){
- let json = textbook.toJSON();
- console.log(json)
- // 圆圈选中未选 ○ 未选 ● 选中
- let circleCheck = ["○","●"];
- // 方块选中未选 ○ 未选 ● 选中
- let squareCheck = [``,`☑`];
- // 联系电话:默认为作者首个存在的电话;
- 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
- if(majorCode?.length>4){
- majorCode = majorCode.slice(0,4)
- }
- let majorName = json?.majorName || json?.major?.name
- // 是否重点立项
- 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]; // 2024新重点
- let isZY = circleCheck[(json?.approval?.indexOf("中央")>-1)?1:0];
- let isSX = circleCheck[(json?.approval?.indexOf("四新")>-1)?1:0];
- let isJS = circleCheck[(json?.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 = !((json?.importantProject?.indexOf("建设")>-1) || (json?.importantProject?.indexOf("本科国家")>-1) || (json?.importantProject?.indexOf("省级优秀")>-1) || (json?.importantProject?.indexOf("省级规划")>-1))// 是否其他省级奖项
- let bookData = {
- // 封面信息
- titlePad:padString(json?.title,21),
- ISBN:padString(json?.ISBN,21),
- 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),14),
- createdDate:padString(createdDate,21),
- // 基本信息
- title:json?.title,
- author:json?.author,
- unit:json?.unit,
- mc:majorCode,
- 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[(json?.importantProject?.indexOf("本科国家")>-1)?1:0],
- isBSYX:circleCheck[(json?.importantProject?.indexOf("省级优秀")>-1)?1:0],
- isBSGH:circleCheck[(json?.importantProject?.indexOf("省级规划")>-1)?1:0],
- isBSQT:circleCheck[isBSQT?1:0],
- bsqtName:isBSQT?(json?.importantProject || ""):"",
- isFirstNot:circleCheck[json?.importantProject?0:1],
- }
- console.log(bookData)
- let bookid = json.code || json?.objectId;
- let tempFileName = path.join(`${bookid}${json.title}.docx`)
- return new Promise((resolve)=>{
- replaceDocx(TemplateDocxPath,tempFileName,bookData,{onDocxComplete:async (filePath)=>{
- // 需要API支持
- // docsToPdf(filePath)
- let url = (await uploadFileToOSS(filePath))?.url || null
- resolve({
- code:bookid,
- title:json?.title,
- filePath,
- url
- })
- }})
- })
- }
- function padString(str,width) {
- str = str || ""
- str = String(str)
- width = width || 21 // 目标宽度为21个单位
- let spaceChar = " " // 占位符
- // 计算字符串的宽度
- const charWidth = {
- 'space': 1, // 空格占用1个单位
- 'zh': 2, // 汉字占用2个单位
- 'en': 1, // 英文字母占用1个单位
- 'other': 1 // 其他字符(如标点符号)占用1个单位
- };
- let strWidth = 0;
- console.log(str)
- // 遍历文本中的每个字符
- 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; // 其他字符
- }
- }
- // for (let char of str) {
- // // 判断字符是否为中文
- // if (char.match(/[\u4e00-\u9fa5]/)) {
- // strWidth += 2; // 中文字符占4个单位
- // } else {
- // strWidth += 1; // 英文字符占1个单位
- // }
- // }
- 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;
- }
|