chengjie 5 月之前
父節點
當前提交
edc62b5c84
共有 4 個文件被更改,包括 101 次插入7 次删除
  1. 二進制
      public/images/acode/ScoreLineArticle_-173.png
  2. 二進制
      public/images/acode/YJBDC_QRCode.png
  3. 1 0
      src/api/yjbdc/routes.js
  4. 100 7
      src/api/yjbdc/yjbdcController.js

二進制
public/images/acode/ScoreLineArticle_-173.png


二進制
public/images/acode/YJBDC_QRCode.png


+ 1 - 0
src/api/yjbdc/routes.js

@@ -8,6 +8,7 @@ router.post('/api/OCRImageData',yjbdcController.OCRImageData);
8 8
 router.post('/api/GenerateArticle',yjbdcController.GenerateArticle);
9 9
 router.post('/api/GeneratePDF',yjbdcController.GeneratePDF);
10 10
 router.get('/api/GetYJBDCArticleList',yjbdcController.GetYJBDCArticleList);
11
+router.get('/api/BuildYJBDCQRCode',yjbdcController.BuildYJBDCQRCode);
11 12
 router.get('/api/DeleteYJBDCArticleList',yjbdcController.DeleteYJBDCArticleList);
12 13
 
13 14
 export default router;

+ 100 - 7
src/api/yjbdc/yjbdcController.js

@@ -1,4 +1,5 @@
1 1
 import moment from 'moment';
2
+import fs from 'fs';
2 3
 import commonModel from '../../model/commonModel.js';
3 4
 import config from '../../config/index.js';
4 5
 import _ from 'lodash';
@@ -181,7 +182,7 @@ export async function GenerateArticle(ctx) {
181 182
     let result = globalCache.get(url);
182 183
     if (result === 0) {
183 184
         const params = ctx.request.body;
184
-        const words = JSON.parse(params.Words).join(",");
185
+        const words = params.Words;
185 186
         const articleStyle = params.ArticleStyle;
186 187
 
187 188
         //文章类型
@@ -199,6 +200,7 @@ export async function GenerateArticle(ctx) {
199 200
             "动物":"生活在地球上的各种生物,有的会跑,有的会飞,有的会游泳,比如猫、狗、大象、企鹅,它们都有自己的特点和习性。",
200 201
             "环保":"指环境保护、保护大自然,让地球更干净、更健康。比如节约用水、减少垃圾、种树、不乱扔塑料袋,这样空气会更清新,动物也有更好的家园。每个人都可以从小事做起爱护地球。",
201 202
         };
203
+
202 204
         //等级难度
203 205
         const LEVEL=[
204 206
             {
@@ -221,7 +223,7 @@ export async function GenerateArticle(ctx) {
221 223
 
222 224
         let content = "将"+words+"这些单词生成一篇英文文章。要求"+
223 225
         "[难度];"+
224
-        "单词若是脏话,像'f***'、's***'等,可以忽略;"+
226
+        "单词若是脏话,像'fuck'、'shit'等,可以忽略;"+
225 227
         "文章类型是'"+articleStyle+"([类型])';"+
226 228
         "文章单词数在200个左右,最多不能超过300个;"+
227 229
         "文章按每句分成数组,且每句都有中文翻译;"+
@@ -232,6 +234,8 @@ export async function GenerateArticle(ctx) {
232 234
 
233 235
         content = content.replace("[难度]",LEVEL[Number(params.Level)].Content);
234 236
         
237
+        if (articleStyle=="任意")
238
+            articleStyle=stringUtils.Random(0,ARTICLE_STYLE.length-1);
235 239
         content = content.replace("[类型]",ARTICLE_STYLE[articleStyle]);
236 240
         
237 241
 
@@ -390,7 +394,7 @@ export async function GeneratePDF(ctx) {
390 394
             try {
391 395
                 if (typeof content.Words === 'string') {
392 396
                     // 尝试解析JSON字符串
393
-                    words = JSON.parse(content.Words);
397
+                    words = content.Words.join(",");
394 398
                 } else if (Array.isArray(content.Words)) {
395 399
                     // 已经是数组
396 400
                     words = content.Words;
@@ -424,7 +428,7 @@ export async function GeneratePDF(ctx) {
424 428
            .text(articleText, pixelToPt(120), pixelToPt(250), {
425 429
                width: pixelToPt(1240),
426 430
                align: 'left',
427
-               lineGap: pixelToPt(10)  // 行间距
431
+               lineGap: pixelToPt(50)  // 行间距
428 432
            });
429 433
 
430 434
         // 记录文章结束位置的y坐标
@@ -503,8 +507,9 @@ export async function GeneratePDF(ctx) {
503 507
                        align: 'left'
504 508
                    });
505 509
                 
506
-                // 问题选项
507
-                doc.fontSize(pixelToPt(36));
510
+                // 问题选项 - 使用常规字体(Regular)
511
+                doc.font('Helvetica') // 明确设置为常规字体,不使用粗体
512
+                   .fontSize(pixelToPt(36));
508 513
                 
509 514
                 const options = questions[0].OptionsEnglish || [];
510 515
                 let optionY = doc.y + pixelToPt(20);
@@ -694,7 +699,25 @@ export async function GeneratePDF(ctx) {
694 699
                width: pixelToPt(380),
695 700
                align: 'right'
696 701
            });
697
-
702
+        
703
+        // 添加二维码图片
704
+        try {
705
+            // 计算图片位置:距离右边120像素,距离底部100像素
706
+            // 由于PDFKit使用左上角坐标系,需要计算左上角坐标
707
+            const qrCodeWidth = pixelToPt(200);
708
+            const qrCodeHeight = pixelToPt(200);
709
+            const qrCodeX = doc.page.width - pixelToPt(120) - qrCodeWidth; // 右边距离转换为左边距离
710
+            const qrCodeY = doc.page.height - pixelToPt(60) - qrCodeHeight; // 底部距离转换为顶部距离
711
+            
712
+            // 添加二维码图片
713
+            doc.image('./public/images/acode/YJBDC_QRCode.png', qrCodeX, qrCodeY, {
714
+                width: qrCodeWidth,
715
+                height: qrCodeHeight
716
+            });
717
+            console.log("QR Code added successfully");
718
+        } catch (imgError) {
719
+            console.error("Error adding QR Code image:", imgError);
720
+        }
698 721
         
699 722
         //console.log("PDF generation completed, finalizing document...");
700 723
 
@@ -735,4 +758,74 @@ export async function GeneratePDF(ctx) {
735 758
         ctx.status = 500;
736 759
         ctx.body = { error: error.message, stack: error.stack };
737 760
     }
761
+}
762
+
763
+export async function BuildYJBDCQRCode(ctx) {
764
+    try {
765
+        // 获取微信访问令牌
766
+        const tokenUrl = `https://api.weixin.qq.com/cgi-bin/token?appid=${config.wx.yjbdc_appid}&secret=${config.wx.yjbdc_appsecret}&grant_type=client_credential`;
767
+        
768
+        const tokenResponse = await axios.get(tokenUrl);
769
+        const tokenData = tokenResponse.data;
770
+        
771
+        if (!tokenData || !tokenData.access_token) {
772
+            ctx.status = 400;
773
+            ctx.body = { errcode: 101, errStr: '获取微信访问令牌失败' };
774
+            return;
775
+        }
776
+        
777
+        const accessToken = tokenData.access_token;
778
+        
779
+        // 生成小程序码
780
+        const qrCodeUrl = `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${accessToken}`;
781
+        const path = './public/images/acode/';
782
+        const imageUrl = 'YJBDC_QRCode.png';
783
+        const fullPath = path + imageUrl;
784
+        
785
+        // 确保目录存在
786
+        if (!fs.existsSync(path)) {
787
+            fs.mkdirSync(path, { recursive: true });
788
+        }
789
+        
790
+        const postData = {
791
+            width: 280,
792
+            scene: "SourceID=187"
793
+        };
794
+        
795
+        // 使用axios获取二维码并保存到文件
796
+        const qrCodeResponse = await axios({
797
+            method: 'POST',
798
+            url: qrCodeUrl,
799
+            data: postData,
800
+            responseType: 'stream'
801
+        });
802
+        
803
+        // 创建写入流
804
+        const writer = fs.createWriteStream(fullPath);
805
+        
806
+        // 将响应数据写入文件
807
+        qrCodeResponse.data.pipe(writer);
808
+        
809
+        // 返回成功响应
810
+        ctx.body = { errcode: 10000, message: "二维码生成请求已发送" };
811
+        
812
+        // 处理文件写入完成事件
813
+        writer.on('finish', () => {
814
+            console.log("二维码生成成功:", fullPath);
815
+        });
816
+        
817
+        // 处理错误
818
+        writer.on('error', (err) => {
819
+            console.error("二维码文件写入失败:", err);
820
+        });
821
+        
822
+    } catch (error) {
823
+        console.error("生成二维码失败:", error);
824
+        ctx.status = 500;
825
+        ctx.body = { 
826
+            errcode: 500, 
827
+            errStr: '生成二维码失败', 
828
+            error: error.message 
829
+        };
830
+    }
738 831
 }