Browse Source

Merge branch 'master' of http://git.fmode.cn:3000/bin/edu-textbook

xll 7 months ago
parent
commit
a95a0c6286

+ 56 - 25
server/cloud/tbook/func-tbook-export.js

@@ -1,12 +1,14 @@
-import { replaceDocx, createZip, uploadFileToOSS, docxToPdf, renderDocx } from "../../lib/docs";
+import { replaceDocx, createZip, uploadFileToOSS, docxToPdf, renderDocx, toBarCode } 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")
+var TemplateDocxDir = path.join(__dirname,"template")
+if(!fs.existsSync(TemplateDocxDir)){
+    TemplateDocxDir = path.join(__dirname,"../../template")
 }
+const tempDir = path.join(__dirname , "temp");
+
 /**
  * 定义导出申报合集文档云函数
  * @example
@@ -98,12 +100,14 @@ export async function exportProcessReportDocs(processId,bookList) {
     let textbookList
     if(processId){ // 流程读取教材列表
         let query = new Parse.Query("EduTextbook")
+        query.include("childrens")
         query.equalTo("recommend",true);
         query.equalTo("eduProcess",processId);
         textbookList = await query.find();
     }
     if(bookList?.length){ // 直接导出教材列表
         let query = new Parse.Query("EduTextbook")
+        query.include("childrens")
         query.containedIn("objectId",bookList);
         textbookList = await query.find();
     }
@@ -146,7 +150,19 @@ module.exports.exportProcessReportDocs = exportProcessReportDocs
 
 function renderReportDocsByTextbook(textbook){
     console.log("renderReportDocsByTextbook")
-    let json = textbook.toJSON();
+    return new Promise(async (resolve)=>{
+        let json = textbook.toJSON();
+    let bookid = json.code || json?.objectId;
+
+    // 默认单册为第一分册
+    let book1Data = json?.childrens?.[0]
+    if(book1Data){
+        Object.keys(book1Data).forEach(key=>{
+            json[key] = book1Data[key] || json[key] || ""
+        })
+    }
+
+    
     // console.log(json)
     // 圆圈选中未选 ○ 未选 ● 选中
     let circleCheck = ["○","●"];
@@ -159,14 +175,13 @@ function renderReportDocsByTextbook(textbook){
     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
+    // 专业代码:前四位 majorPoniter
+    let majorCode4 = json?.majorPoniter?.code?.slice(0,4) || ""
+    let majorName4 = json?.majorPoniter?.name || ""
+    // 专业代码:前六位 major
+    let majorCode6 = json?.major?.code?.slice(0,6) || ""
+    let majorName6 = json?.major?.name || ""
+    
     // 是否重点立项
     let importantProject = json?.importantProject?.join();
 
@@ -176,20 +191,21 @@ function renderReportDocsByTextbook(textbook){
     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[(importantProject?.indexOf("建设")>-1)?1:0];
+    let isJS = circleCheck[(json?.approval?.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 firstDate = new Date(book1Data?.editionFirst.iso);
     let firstYear = firstDate?.getFullYear();
     let firstMonth = firstDate?.getMonth()+1;
     // 本版时间印次
-    let currentDate = new Date(textbook?.get("editionDate"));
+    let currentDate = new Date(book1Data?.editionDate.iso);
     let currentYear = currentDate?.getFullYear();
     let currentMonth = currentDate?.getMonth()+1;
     // 最新时间印次
-    let latestDate = new Date(textbook?.get("printDate"));
+    let latestDate = new Date(book1Data?.printDate.iso);
     let latestYear = latestDate?.getFullYear();
     let latestMonth = latestDate?.getMonth()+1;
     // 初版至今重点项目
@@ -242,9 +258,17 @@ function renderReportDocsByTextbook(textbook){
         })
     }
 
+    let codePngBuffer = await toBarCode(json?.code);
+    let codePngPath = path.join(tempDir,bookid+"code.png")
+    fs.writeFileSync(codePngPath,codePngBuffer)
+    // let codeBarImg = 
+    // console.log(codeBarImg)
     // (其他佐证材料,限两份以内。)
+    console.log(codePngPath)
 
     let fixData = {
+        // 图片信息
+        codeBarImg:codePngPath,
         // 封面信息
         titlePad:padString(json?.title,21),
         ISBNPad:padString(json?.ISBN,21),
@@ -259,8 +283,6 @@ function renderReportDocsByTextbook(textbook){
         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,
@@ -270,11 +292,13 @@ function renderReportDocsByTextbook(textbook){
         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,
+        mc4:majorCode4,
+        mn4:majorName4,
         mc6:majorCode6,
-        mn:majorName,
+        mn6:majorName6,
         lCN:circleCheck[(json?.lang=="中文")?1:0],
         lEN:circleCheck[(json?.lang=="英文")?1:0],
+        lMW:circleCheck[(json?.lang=="盲文")?1:0],
         lOT:circleCheck[(json?.lang?.indexOf("其他")>-1)?1:0],
         lSS:circleCheck[(json?.lang?.indexOf("少数")>-1)?1:0],
         authors:json?.authors, // 其他主编
@@ -291,7 +315,7 @@ function renderReportDocsByTextbook(textbook){
         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],
+        isSZ:circleCheck[(json?.carrierShape?.indexOf("数字")>-1 || json?.carrierShape?.indexOf("电子")>-1)?1:0],
         isQT:circleCheck[(json?.carrierShape?.indexOf("附带")>-1)?1:0],
         isFD:circleCheck[(json?.carrierShape?.indexOf("其他")>-1)?1:0],
         latestY:latestYear,
@@ -338,15 +362,22 @@ function renderReportDocsByTextbook(textbook){
 
     }
     let bookData = json;
+    
     Object.keys(fixData).forEach(key=>{
-        bookData[key] = fixData[key]
+        bookData[key] = fixData[key] || bookData[key] || ""
     })
     // console.log(bookData)
     // console.log(json)
-    let bookid = json.code || json?.objectId;
     let tempFileName = path.join(`${bookid}${json.title}.docx`)
-    return new Promise(async (resolve)=>{
+
+    // 开始文件合并导出
         let filePath,pdfPath,urlDocx,urlPdf
+        let TemplateDocxPath
+        if(json?.childrens?.length>1){
+            TemplateDocxPath = path.join(TemplateDocxDir,"模板-本科教材申报书-全册.docx")
+        }else{
+            TemplateDocxPath = path.join(TemplateDocxDir,"模板-本科教材申报书-单册.docx")
+        }
         try{
             // DOCX模板合成 速度2-3秒
             filePath = renderDocx(TemplateDocxPath,tempFileName,bookData)

BIN
server/cloud/tbook/template/blank.docx


BIN
server/cloud/tbook/template/模板-本科教材申报书-单册.docx


+ 1 - 1
server/cloud/tbook/test/test-export.js

@@ -22,7 +22,7 @@ async function main(){
         // console.log(await exportProcessReportDocs("FR7KZtefyR"))
         // console.log("测试列表")
         // console.log(await exportProcessReportDocs(null,["9V575dapEM"]))
-        console.log(await exportProcessReportDocs(null,["cEMD7kHdzc"]))
+        console.log(await exportProcessReportDocs(null,["3vSurc0lUy"]))
     }catch(err){
         console.error(err)
     }

+ 39 - 0
server/lib/docs/index.js

@@ -24,6 +24,27 @@ const ALI_OSS_BUCKET = process.env.ALI_OSS_BUCKET || "hep-textbook"
 const ALI_OSS_ACCESS_KEY_ID = process.env.ALI_OSS_ACCESS_KEY_ID || "LTAI5t6AbTiAvXmeoVdJZhL3"
 const ALI_OSS_ACCESS_KEY_SECRET = process.env.ALI_OSS_ACCESS_KEY_SECRET || "KLtQRdIW69KLP7jnzHNUf7eKmdptxH"
 
+const bwipjs = require("bwip-js")
+export async function toBarCode(text){
+    return new Promise(resolve=>{
+        bwipjs.toBuffer({
+            bcid:"code128",
+            text:text,
+            scale:1.5,
+            height:3,
+            includetext:false,
+            textalign:"center"
+        },(err,png)=>{
+            if(err){
+                console.error(err)
+                resolve(null)
+            }else{
+                resolve(png)
+            }
+        })
+    })
+}
+
 export async function uploadFileToOSS(filePath){
     let client = new OSS({
         // yourRegion填写Bucket所在地域。以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。
@@ -192,8 +213,25 @@ async function downloadUrl(url) {
 }
 module.exports.docxToPdf = docxToPdf
 
+const ImageModule = require("@slosarek/docxtemplater-image-module-free");
+const sizeOf = require("image-size");
+
 
 export function renderDocx(inputDocxPath, outputDocxName, options){
+    let imageOptions = {
+        getImage(tagValue,tagName) {
+            if(!fs.existsSync(tagValue)){
+                throw new Error(`Image not found: ${tagValue}`);
+            }
+            return fs.readFileSync(tagValue);
+        },
+        getSize(img) {
+            const sizeObj = sizeOf(img);
+            console.log(sizeObj);
+            return [sizeObj.width, sizeObj.height];
+        },
+    };
+    
     let outputDocxPath = path.join(tempDir,outputDocxName)
     // Load the docx file as binary content
     let content = fs.readFileSync(
@@ -206,6 +244,7 @@ export function renderDocx(inputDocxPath, outputDocxName, options){
     let doc = new Docxtemplater(zip, {
         paragraphLoop: true,
         linebreaks: true,
+        modules: [new ImageModule(imageOptions)],
     });
 
     // Render the document (Replace {first_name} by John, {last_name} by Doe, ...)

+ 3 - 0
server/package.json

@@ -28,14 +28,17 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
+    "@slosarek/docxtemplater-image-module-free": "^1.2.0",
     "ali-oss": "^6.20.0",
     "ali-sms": "^1.0.3",
     "authing-js-sdk": "^4.23.51",
     "authing-node-sdk": "^3.1.0",
+    "bwip-js": "^4.5.0",
     "chromiumly": "^3.6.0",
     "compressing": "^1.10.1",
     "docxtemplater": "^3.49.1",
     "download": "^8.0.0",
+    "image-size": "^1.1.1",
     "node-schedule": "^2.1.1",
     "parse-dashboard": "^5.4.0",
     "parse-server": "^7.0.0",