leiyun 1 miesiąc temu
rodzic
commit
8f83338b5d
3 zmienionych plików z 144 dodań i 0 usunięć
  1. +1
    -0
      src/config/router.js
  2. +50
    -0
      src/controller/mp.js
  3. +93
    -0
      src/service/screenshot.js

+ 1
- 0
src/config/router.js Wyświetl plik

@@ -74,6 +74,7 @@ module.exports = [
['/api/mp/messageDetail', 'mp/messageDetail'],
['/api/mp/unreadCount', 'mp/unreadCount'],
['/api/mp/subscribeConfig', 'mp/subscribeConfig'],
['/api/mp/regenerateSign', 'mp/regenerateSign'],

// 瘤种管理
['/admin/tag', 'admin/tag/index'],


+ 50
- 0
src/controller/mp.js Wyświetl plik

@@ -631,6 +631,56 @@ module.exports = class extends Base {
}
}

/**
* 批量重新生成声明与承诺签署图并更新数据库
* GET /api/mp/regenerateSign
*/
async regenerateSignAction() {
return false;
try {
const patients = await this.model('patient')
.field('id, name, sign_promise')
.where({ is_deleted: 0, sign_promise: ['!=', ''] })
.select();

if (!patients.length) return this.json({ code: 1, msg: '没有需要处理的患者' });

const doc = await this.model('content').getByKey('sign_promise');
if (think.isEmpty(doc)) return this.json({ code: 1, msg: '协议内容未配置' });

const screenshotService = this.service('screenshot');
const results = [];
let successCount = 0;
let failCount = 0;

for (const patient of patients) {
try {
const newUrl = await screenshotService.regenerate({
originalImageUrl: patient.sign_promise,
title: doc.title,
content: doc.content
});
await this.model('patient').where({ id: patient.id }).update({ sign_promise: newUrl });
successCount++;
results.push({ id: patient.id, name: patient.name, status: 'ok' });
} catch (e) {
failCount++;
results.push({ id: patient.id, name: patient.name, status: 'fail', error: e.message });
think.logger.error(`regenerateSign patient ${patient.id} error:`, e);
}
}

return this.json({
code: 0,
data: { total: patients.length, success: successCount, fail: failCount, results },
msg: `处理完成:成功${successCount},失败${failCount}`
});
} catch (error) {
think.logger.error('regenerateSign error:', error);
return this.json({ code: 1, msg: '执行失败: ' + error.message });
}
}

// @private
async _verifyIdCard(name, idCard) {
const faceidConfig = require('../config/faceid.js');


+ 93
- 0
src/service/screenshot.js Wyświetl plik

@@ -155,6 +155,99 @@ module.exports = class extends think.Service {
</html>`;
}

/**
* 重新生成签署图(保留原图签名区域,替换上方内容)
* 原理:原图做背景 bottom 对齐,白色 overlay 覆盖上方内容区,
* placeholder 撑出签名区高度让背景图底部签名露出
* @param {Object} params
* @param {string} params.originalImageUrl - 原合成图URL
* @param {string} params.title - 新协议标题
* @param {string} params.content - 新协议富文本内容
* @returns {string} 新合成图COS URL
*/
async regenerate({ originalImageUrl, title, content }) {
const puppeteer = require('puppeteer');

const html = `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
width: 750px;
overflow: hidden;
font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
background-image: url('${originalImageUrl}');
background-size: 100% auto;
background-repeat: no-repeat;
background-position: bottom center;
position: relative;
}
.overlay {
width: 100%;
background: #fff;
padding: 60px;
}
.title {
text-align: center;
font-size: 36px;
font-weight: bold;
margin-bottom: 40px;
color: #222;
}
.content {
font-size: 28px;
line-height: 2;
color: #444;
}
.content p {
margin-bottom: 16px;
text-indent: 2em;
}
.sign-area-placeholder {
height: 360px;
}
</style>
</head>
<body>
<div class="overlay">
<div class="title">${title}</div>
<div class="content">${content}</div>
</div>
<div class="sign-area-placeholder"></div>
</body>
</html>`;

let browser;
try {
browser = await puppeteer.launch({
headless: 'new',
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-gpu',
'--disable-dev-shm-usage',
'--font-render-hinting=none'
]
});

const page = await browser.newPage();
await page.setViewport({ width: 750, height: 1000, deviceScaleFactor: 2 });
await page.setContent(html, { waitUntil: 'networkidle0', timeout: 15000 });

const screenshot = await page.screenshot({ fullPage: true, type: 'png' });
await browser.close();
browser = null;

const url = await this._uploadToCos(screenshot);
return url;
} catch (error) {
if (browser) await browser.close().catch(() => {});
throw error;
}
}

/**
* 上传截图到 COS
*/


Ładowanie…
Anuluj
Zapisz