From 37839c1e8661f39a52fc5151594598213fab3efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E8=BF=9B?= Date: Thu, 23 Jul 2026 19:04:31 +0800 Subject: [PATCH] clean: remove experimental scripts, keep only knowledge base + schema + renderer --- bin/html2pptx.js | 415 ------------- schema/examples/tencent-icp.json | 984 +++++++++++++++++++++++++++++++ 2 files changed, 984 insertions(+), 415 deletions(-) delete mode 100644 bin/html2pptx.js create mode 100644 schema/examples/tencent-icp.json diff --git a/bin/html2pptx.js b/bin/html2pptx.js deleted file mode 100644 index 5588cfb..0000000 --- a/bin/html2pptx.js +++ /dev/null @@ -1,415 +0,0 @@ -#!/usr/bin/env node -/** - * html2pptx — HTML to editable PPTX export engine - * - * Usage: - * html2pptx [output.pptx] - * html2pptx -o -p - * - * Process: - * 1. Start local HTTP server to host the HTML - * 2. Chrome headless (Playwright) opens the page - * 3. Extract each slide's element positions, text, and styles - * 4. Generate PPTX with pptxgenjs - */ - -const { chromium } = require('playwright'); -const http = require('http'); -const fs = require('fs'); -const path = require('path'); -const PptxGenJS = require('pptxgenjs'); - -// ====== CLI argument parsing ====== - -function parseArgs() { - const args = process.argv.slice(2); - if (args.length === 0) { - console.error('Usage: html2pptx [output.pptx]'); - console.error(' html2pptx -o -p '); - process.exit(1); - } - - const inputPath = path.resolve(args[0]); - const parsed = path.parse(inputPath); - let outputPath = path.join(parsed.dir, parsed.name + '.pptx'); - let port; - - for (let i = 1; i < args.length; i++) { - if (args[i] === '-o' && i + 1 < args.length) { - outputPath = path.resolve(args[++i]); - } else if (args[i] === '-p' && i + 1 < args.length) { - port = parseInt(args[++i], 10); - } else if (!args[i].startsWith('-')) { - outputPath = path.resolve(args[i]); - } - } - - return { inputPath, outputPath, port }; -} - -// ====== Color parsing (Node.js side) ====== - -function parseCSSColor(color, fallback) { - if (!color || color === 'transparent' || color === 'rgba(0, 0, 0, 0)') return fallback || '#000000'; - - // Already #rrggbb - if (/^#[0-9a-f]{6}$/i.test(color)) return color.toLowerCase(); - // #rgb → #rrggbb - if (/^#[0-9a-f]{3}$/i.test(color)) { - return '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3]; - } - - // rgb(r, g, b) / rgba(r, g, b, a) - const m = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/); - if (m) { - return '#' + m.slice(1, 4).map(c => parseInt(c).toString(16).padStart(2, '0')).join(''); - } - - return fallback || '#000000'; -} - -function parseFontWeight(w) { - if (w === 'bold') return true; - const n = parseInt(w, 10); - return n >= 600; -} - -function normalizeAlign(align) { - switch (align) { - case 'left': case 'center': case 'right': case 'justify': return align; - case 'start': return 'left'; - case 'end': return 'right'; - default: return 'left'; - } -} - -// ====== Main ====== - -async function main() { - const { inputPath, outputPath, port: cliPort } = parseArgs(); - - if (!fs.existsSync(inputPath)) { - console.error('文件不存在:', inputPath); - process.exit(1); - } - - const TIMEOUT_MS = 30000; - const startTime = Date.now(); - let server, browser; - - try { - // ------ 1. HTTP server ------ - const baseDir = path.dirname(inputPath); - const MIME = { - '.html': 'text/html; charset=utf-8', - '.css': 'text/css; charset=utf-8', - '.js': 'application/javascript; charset=utf-8', - '.png': 'image/png', - '.jpg': 'image/jpeg', - '.jpeg': 'image/jpeg', - '.svg': 'image/svg+xml', - }; - - server = http.createServer((req, res) => { - const reqPath = req.url === '/' ? '/' + path.basename(inputPath) : req.url; - const filePath = path.join(baseDir, reqPath); - // Prevent directory traversal - if (!filePath.startsWith(baseDir)) { - res.writeHead(404); - res.end('Not Found'); - return; - } - if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) { - const ext = path.extname(filePath).toLowerCase(); - res.writeHead(200, { 'Content-Type': MIME[ext] || 'application/octet-stream' }); - res.end(fs.readFileSync(filePath)); - } else { - res.writeHead(404); - res.end('Not Found'); - } - }); - - const port = cliPort || 0; - await new Promise((resolve, reject) => { - server.listen(port, '127.0.0.1', resolve); - server.on('error', reject); - }); - const actualPort = server.address().port; - console.log('HTTP 服务已启动: http://127.0.0.1:' + actualPort + '/'); - - if (Date.now() - startTime > TIMEOUT_MS) throw new Error('导出超时'); - - // ------ 2. Chrome headless ------ - browser = await chromium.launch({ headless: true }); - const page = await browser.newPage({ viewport: { width: 1280, height: 720 } }); - - if (Date.now() - startTime > TIMEOUT_MS) throw new Error('导出超时'); - - await page.goto('http://127.0.0.1:' + actualPort + '/', { - waitUntil: 'networkidle', - timeout: 15000, - }); - console.log('页面加载完成'); - - // ------ 3. DOM extraction (in-browser) ------ - const slidesData = await page.evaluate(() => { - // ----- Slide detection ----- - var slides; - // DashiAI format: .imported-theme-root > .slide.imported-theme-slide - var themeRoot = document.querySelector('.imported-theme-root'); - if (themeRoot) { - slides = themeRoot.querySelectorAll(':scope > .slide.imported-theme-slide'); - } - if (!slides || slides.length <= 1) { - // DashiAI old format: .ppt-deck > .ppt-slide - var deck = document.querySelector('.ppt-deck'); - if (deck) { - slides = deck.querySelectorAll(':scope > .ppt-slide'); - } - } - if (!slides || slides.length <= 1) { - slides = document.querySelectorAll( - 'section[data-slide], section.slide, section' - ); - } - if (slides.length <= 1) { - slides = document.querySelectorAll('[data-slide]'); - } - slides = Array.from(slides).filter(function (s) { - var r = s.getBoundingClientRect(); - var style = window.getComputedStyle(s); - return r.width > 0 && r.height > 0 && - style.opacity !== '0' && - style.display !== 'none' && - style.visibility !== 'hidden'; - }); - - // Recursively extract inline text runs with computed styles - function extractRuns(node) { - var runs = []; - for (var ri = 0; ri < node.childNodes.length; ri++) { - var child = node.childNodes[ri]; - if (child.nodeType === 3) { - var t = (child.textContent || '').trim(); - if (t) runs.push({ text: t }); - } else if (child.nodeType === 1) { - var cs = window.getComputedStyle(child); - var childRuns = extractRuns(child); - for (var cj = 0; cj < childRuns.length; cj++) { - childRuns[cj].bold = childRuns[cj].bold || parseInt(cs.fontWeight) >= 600; - childRuns[cj].italic = childRuns[cj].italic || cs.fontStyle === 'italic'; - childRuns[cj].color = childRuns[cj].color || cs.color; - childRuns[cj].fontSize = childRuns[cj].fontSize || parseFloat(cs.fontSize); - childRuns[cj].fontFamily = childRuns[cj].fontFamily || cs.fontFamily; - } - runs = runs.concat(childRuns); - } - } - return runs.length > 0 ? runs : [{ text: node.textContent || '' }]; - } - - // Tags whose full text content should be a single text box - var TEXT_BLOCK_TAGS = new Set([ - 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', - 'li', 'td', 'th', 'blockquote', 'figcaption', 'dt', 'dd', 'caption', - ]); - - return slides.map(function (slide) { - var slideRect = slide.getBoundingClientRect(); - var elements = []; - - // Collect block-level text containers; each becomes one text box - var textBlocks = slide.querySelectorAll( - 'p, h1, h2, h3, h4, h5, h6, li, td, th, blockquote, ' + - 'figcaption, dt, dd, caption' - ); - - for (var i = 0; i < textBlocks.length; i++) { - var el = textBlocks[i]; - // Skip if this block is nested inside another text block (e.g. li inside another li) - var parent = el.parentElement; - var skip = false; - while (parent && parent !== slide) { - if (TEXT_BLOCK_TAGS.has(parent.tagName.toLowerCase())) { - skip = true; - break; - } - parent = parent.parentElement; - } - if (skip) continue; - - var runs = extractRuns(el); - if (!runs || runs.length === 0) continue; - var text = runs.map(function (r) { return r.text || ''; }).join(' ').trim(); - if (!text) continue; - - var rect = el.getBoundingClientRect(); - if (rect.width === 0 || rect.height === 0) continue; - - var style = window.getComputedStyle(el); - - // Truncate overly long runs - runs.forEach(function (r) { - if (r.text && r.text.length > 2000) r.text = r.text.substring(0, 2000); - }); - - elements.push({ - runs: runs, - text: text.substring(0, 2000), - x: rect.left - slideRect.left, - y: rect.top - slideRect.top, - width: rect.width, - height: rect.height, - fontSize: parseFloat(style.fontSize) || 14, - fontFamily: style.fontFamily || 'Arial', - color: style.color || '#000000', - fontWeight: style.fontWeight || 'normal', - fontStyle: style.fontStyle || 'normal', - textAlign: style.textAlign || 'left', - backgroundColor: style.backgroundColor || 'transparent', - }); - } - - // Slide background - var bg = window.getComputedStyle(slide).backgroundColor; - var bgColor = - bg && - bg !== 'rgba(0, 0, 0, 0)' && - bg !== 'transparent' - ? bg - : '#FFFFFF'; - - return { - width: slideRect.width, - height: slideRect.height, - bgColor: bgColor, - elements: elements, - }; - }); - }); - - console.log('提取到 ' + slidesData.length + ' 页幻灯片'); - - if (Date.now() - startTime > TIMEOUT_MS) throw new Error('导出超时'); - - // ------ 4. PPTX generation ------ - var pptx = new PptxGenJS(); - pptx.defineLayout({ name: 'CUSTOM', width: 10, height: 5.625 }); - pptx.layout = 'CUSTOM'; - - for (var s = 0; s < slidesData.length; s++) { - var slideData = slidesData[s]; - var slide = pptx.addSlide(); - - // Background - slide.background = { fill: parseCSSColor(slideData.bgColor, '#FFFFFF') }; - - // Scale factors: HTML pixels → PPT inches - var scaleX = 10 / slideData.width; - var scaleY = 5.625 / slideData.height; - - // Sort top-to-bottom, left-to-right - slideData.elements.sort(function (a, b) { - return a.y - b.y || a.x - b.x; - }); - - for (var e = 0; e < slideData.elements.length; e++) { - var el = slideData.elements[e]; - var t = (el.text || '').trim(); - if (!t) continue; - - try { - var x = Math.max(el.x * scaleX, 0); - var y = Math.max(el.y * scaleY, 0); - var w = Math.max(el.width * scaleX, 0.3); - var h = Math.max(el.height * scaleY, 0.2); - - // Bounds constraints: prevent textbox from overflowing slide - var MAX_W = 10 - x; - var MAX_H = 5.625 - y; - w = Math.min(w, MAX_W); - h = Math.min(h, MAX_H); - - // Base font size: CSS px → pt (1pt = 1/72in, CSS 1px = 1/96in) - var fontSize = el.fontSize * 72 / 96; - fontSize = Math.max(fontSize, 8); - - // Check if rich text is needed (runs with differing styles) - var hasRuns = el.runs && el.runs.length > 0; - var isSimpleRun = hasRuns && el.runs.length === 1 && - el.runs[0].bold === undefined && - el.runs[0].italic === undefined && - el.runs[0].color === undefined && - el.runs[0].fontSize === undefined && - el.runs[0].fontFamily === undefined; - - if (hasRuns && !isSimpleRun && el.runs.length > 1) { - // Rich text: render each run with its own style - var pptxRuns = el.runs.map(function (run) { - if (!run.text || !run.text.trim()) return null; - var baseSize = el.fontSize * 72 / 96; - return { - text: run.text, - options: { - fontSize: run.fontSize ? Math.max(run.fontSize * 72 / 96, 8) : baseSize, - bold: run.bold === true || (run.bold === undefined && parseFontWeight(el.fontWeight)), - italic: run.italic === true || (run.italic === undefined && (el.fontStyle === 'italic' || el.fontStyle === 'oblique')), - color: run.color ? parseCSSColor(run.color, '#000000') : parseCSSColor(el.color, '#000000'), - fontFace: run.fontFamily - ? run.fontFamily.split(',')[0].trim().replace(/['"]/g, '') - : (el.fontFamily || 'Arial').split(',')[0].trim().replace(/['"]/g, ''), - }, - }; - }).filter(Boolean); - - if (pptxRuns.length > 0) { - slide.addText(pptxRuns, { - x: x, - y: y, - w: w, - h: h, - align: normalizeAlign(el.textAlign), - valign: 'top', - wrap: true, - margin: 0, - }); - } - } else { - // Plain text: original single-style logic - slide.addText(t, { - x: x, - y: y, - w: w, - h: h, - fontSize: fontSize, - fontFace: (el.fontFamily || 'Arial').split(',')[0].trim().replace(/['"]/g, ''), - color: parseCSSColor(el.color, '#000000'), - bold: parseFontWeight(el.fontWeight), - italic: el.fontStyle === 'italic' || el.fontStyle === 'oblique', - align: normalizeAlign(el.textAlign), - valign: 'top', - wrap: true, - margin: 0, - }); - } - } catch (err) { - // Skip individual element failure - } - } - } - - await pptx.writeFile({ fileName: outputPath }); - console.log('\nPPTX 已导出: ' + outputPath); - } finally { - if (browser) await browser.close().catch(function () {}); - if (server) - await new Promise(function (resolve) { - server.close(resolve); - }); - } -} - -main().catch(function (err) { - console.error('导出失败:', err.message); - process.exit(1); -}); diff --git a/schema/examples/tencent-icp.json b/schema/examples/tencent-icp.json new file mode 100644 index 0000000..a42e876 --- /dev/null +++ b/schema/examples/tencent-icp.json @@ -0,0 +1,984 @@ +{ + "presentation": { + "layout": "CUSTOM" + }, + "slides": [ + { + "background": { + "color": "F5F6F8" + }, + "objects": [ + { + "type": "shape", + "shapeName": "rect", + "options": { + "x": 0, + "y": 0, + "w": 24.14, + "h": 0.667, + "fill": { + "color": "1A1A2E" + } + } + }, + { + "type": "text", + "text": "\u817e\u8baf\u4e91", + "options": { + "x": 0.542, + "y": 0.056, + "w": 1.499, + "h": 0.278, + "fontSize": 16, + "color": "FFFFFF", + "bold": true + } + }, + { + "type": "text", + "text": "\u63a7\u5236\u53f0", + "options": { + "x": 2.278, + "y": 0.056, + "w": 1.201, + "h": 0.278, + "fontSize": 13, + "color": "FFFFFF" + } + }, + { + "type": "text", + "text": "\u641c\u7d22\u4e91\u4ea7\u54c1\u3001\u8d44\u6e90\u4e0eAPI", + "options": { + "x": 6.875, + "y": 0.056, + "w": 7.0, + "h": 0.278, + "fontSize": 13, + "color": "8E95A1" + } + }, + { + "type": "text", + "text": "\u96c6\u56e2\u8d26\u53f7", + "options": { + "x": 8.986, + "y": 0.056, + "w": 1.049, + "h": 0.278, + "fontSize": 13, + "color": "FFFFFF" + } + }, + { + "type": "text", + "text": "\u5907\u6848", + "options": { + "x": 9.708, + "y": 0.056, + "w": 0.526, + "h": 0.278, + "fontSize": 13, + "color": "FFFFFF" + } + }, + { + "type": "text", + "text": "\u5de5\u5177", + "options": { + "x": 10.153, + "y": 0.056, + "w": 0.526, + "h": 0.278, + "fontSize": 13, + "color": "FFFFFF" + } + }, + { + "type": "text", + "text": "\u5ba2\u670d\u652f\u6301", + "options": { + "x": 10.583, + "y": 0.056, + "w": 1.049, + "h": 0.278, + "fontSize": 13, + "color": "FFFFFF" + } + }, + { + "type": "text", + "text": "\u8bd5\u7528", + "options": { + "x": 11.167, + "y": 0.056, + "w": 0.526, + "h": 0.278, + "fontSize": 13, + "color": "FFFFFF" + } + }, + { + "type": "text", + "text": "\u8d39\u7528", + "options": { + "x": 11.667, + "y": 0.056, + "w": 0.526, + "h": 0.278, + "fontSize": 13, + "color": "FFFFFF" + } + }, + { + "type": "shape", + "shapeName": "ellipse", + "options": { + "x": 12.917, + "y": 0.042, + "w": 0.25, + "h": 0.25, + "fill": { + "color": "FF4D4F" + } + } + }, + { + "type": "text", + "text": "1", + "options": { + "x": 12.917, + "y": 0.042, + "w": 0.45, + "h": 0.25, + "fontSize": 8, + "color": "FFFFFF", + "bold": true, + "align": "center" + } + }, + { + "type": "text", + "text": "oldi \u4e3b\u8d26\u53f7", + "options": { + "x": 13.431, + "y": 0.056, + "w": 1.049, + "h": 0.278, + "fontSize": 11, + "color": "FFFFFF", + "align": "right" + } + }, + { + "type": "shape", + "shapeName": "rect", + "options": { + "x": 0, + "y": 0.667, + "w": 2.403, + "h": 13.306, + "fill": { + "color": "1A1A2E" + } + } + }, + { + "type": "text", + "text": "ICP\u5907\u6848", + "options": { + "x": 0.333, + "y": 0.944, + "w": 1.201, + "h": 0.236, + "fontSize": 13, + "color": "FFFFFF", + "bold": true + } + }, + { + "type": "shape", + "shapeName": "rect", + "options": { + "x": 0, + "y": 1.389, + "w": 2.403, + "h": 0.528, + "fill": { + "color": "2D2D44" + } + } + }, + { + "type": "text", + "text": "\u6211\u7684\u5907\u6848", + "options": { + "x": 0.514, + "y": 1.528, + "w": 1.1, + "h": 0.236, + "fontSize": 13, + "color": "FFFFFF" + } + }, + { + "type": "text", + "text": "\u5907\u6848\u77e5\u8bc6\u5e93", + "options": { + "x": 0.514, + "y": 2.056, + "w": 1.474, + "h": 0.236, + "fontSize": 13, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u5907\u6848\u67e5\u8be2", + "options": { + "x": 0.514, + "y": 2.583, + "w": 1.249, + "h": 0.236, + "fontSize": 13, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u5907\u6848\u8ba2\u5355", + "options": { + "x": 0.514, + "y": 3.111, + "w": 1.249, + "h": 0.236, + "fontSize": 13, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u5907\u6848\u6388\u6743\u7801", + "options": { + "x": 0.514, + "y": 3.639, + "w": 1.474, + "h": 0.236, + "fontSize": 13, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u5907\u6848\u8bb0\u5f55", + "options": { + "x": 0.514, + "y": 4.167, + "w": 1.249, + "h": 0.236, + "fontSize": 13, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u6536\u8d77", + "options": { + "x": 0.514, + "y": 13.583, + "w": 0.526, + "h": 0.236, + "fontSize": 13, + "color": "8E95A1" + } + }, + { + "type": "text", + "text": "WorkBuddy \u4f60\u7684\u529e\u516c\u597d\u642d\u5b50\uff0c\u4e00\u4eba\u6307\u6325\uff0cAI\u4e13\u5bb6\u56e2\u6267\u884c\uff0c\u6587\u6863/\u8bbe\u8ba1/\u5f00\u53d1\u4e00\u53e5\u8bdd\u4ea4\u4ed8\uff0c\u9650\u65f6\u4eab\u53cc\u500d Credits \u67e5\u770b\u8be6\u60c5 \u203a", + "options": { + "x": 3.028, + "y": 0.986, + "w": 18.751, + "h": 0.208, + "fontSize": 10, + "color": "333333" + } + }, + { + "type": "text", + "text": "\u6211\u7684\u5907\u6848", + "options": { + "x": 1.75, + "y": 1.625, + "w": 1.201, + "h": 0.278, + "fontSize": 14, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u63a5\u5165\u5907\u6848 - \u5ba1\u6838\u4e2d", + "options": { + "x": 2.556, + "y": 2.569, + "w": 3.499, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u5907\u6848\u8ba2\u5355\u53f7 30178470045009931 \u8ba2\u5355\u7c7b\u578b \u63a5\u5165\u5907\u6848 \u63d0\u4ea4\u5ba1\u6838\u65f6\u95f4 2026-07-23 06:20:29", + "options": { + "x": 2.556, + "y": 2.986, + "w": 17.5, + "h": 0.208, + "fontSize": 11, + "color": "666666" + } + }, + { + "type": "shape", + "shapeName": "ellipse", + "options": { + "x": 4.306, + "y": 3.611, + "w": 0.333, + "h": 0.333, + "fill": { + "color": "1677FF" + } + } + }, + { + "type": "text", + "text": "\u2713", + "options": { + "x": 4.306, + "y": 3.611, + "w": 0.599, + "h": 0.333, + "fontSize": 11, + "color": "FFFFFF", + "bold": true, + "align": "center" + } + }, + { + "type": "text", + "text": "\u63d0\u4ea4\u521d\u5ba1", + "options": { + "x": 4.722, + "y": 3.611, + "w": 1.049, + "h": 0.208, + "fontSize": 11, + "color": "333333" + } + }, + { + "type": "text", + "text": "\u5df2\u63d0\u4ea4", + "options": { + "x": 4.722, + "y": 3.819, + "w": 1.049, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "shape", + "shapeName": "ellipse", + "options": { + "x": 6.667, + "y": 3.611, + "w": 0.333, + "h": 0.333, + "fill": { + "color": "1677FF" + } + } + }, + { + "type": "text", + "text": "\u2713", + "options": { + "x": 6.667, + "y": 3.611, + "w": 0.599, + "h": 0.333, + "fontSize": 11, + "color": "FFFFFF", + "bold": true, + "align": "center" + } + }, + { + "type": "text", + "text": "\u817e\u8baf\u4e91\u5ba1\u6838", + "options": { + "x": 7.083, + "y": 3.611, + "w": 1.249, + "h": 0.208, + "fontSize": 11, + "color": "333333" + } + }, + { + "type": "text", + "text": "\u5df2\u901a\u8fc7", + "options": { + "x": 7.083, + "y": 3.819, + "w": 1.249, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "shape", + "shapeName": "ellipse", + "options": { + "x": 9.028, + "y": 3.611, + "w": 0.333, + "h": 0.333, + "fill": { + "color": "1677FF" + } + } + }, + { + "type": "text", + "text": "\u2713", + "options": { + "x": 9.028, + "y": 3.611, + "w": 0.599, + "h": 0.333, + "fontSize": 11, + "color": "FFFFFF", + "bold": true, + "align": "center" + } + }, + { + "type": "text", + "text": "\u5f85\u63d0\u4ea4\u7ba1\u5c40", + "options": { + "x": 9.444, + "y": 3.611, + "w": 1.249, + "h": 0.208, + "fontSize": 11, + "color": "333333" + } + }, + { + "type": "text", + "text": "\u5df2\u63d0\u4ea4", + "options": { + "x": 9.444, + "y": 3.819, + "w": 1.249, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "shape", + "shapeName": "ellipse", + "options": { + "x": 11.389, + "y": 3.611, + "w": 0.333, + "h": 0.333, + "fill": { + "color": "1677FF" + } + } + }, + { + "type": "text", + "text": "\u2713", + "options": { + "x": 11.389, + "y": 3.611, + "w": 0.599, + "h": 0.333, + "fontSize": 11, + "color": "FFFFFF", + "bold": true, + "align": "center" + } + }, + { + "type": "text", + "text": "\u5de5\u4fe1\u90e8\u77ed\u4fe1\u6838\u9a8c", + "options": { + "x": 11.806, + "y": 3.611, + "w": 1.499, + "h": 0.208, + "fontSize": 11, + "color": "333333" + } + }, + { + "type": "text", + "text": "\u5df2\u6838\u9a8c", + "options": { + "x": 11.806, + "y": 3.819, + "w": 1.499, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "shape", + "shapeName": "ellipse", + "options": { + "x": 13.75, + "y": 3.611, + "w": 0.333, + "h": 0.333, + "fill": { + "color": "FF9800" + } + } + }, + { + "type": "text", + "text": "5", + "options": { + "x": 13.75, + "y": 3.611, + "w": 0.599, + "h": 0.333, + "fontSize": 11, + "color": "FFFFFF", + "bold": true, + "align": "center" + } + }, + { + "type": "text", + "text": "\u7ba1\u5c40\u5ba1\u6838", + "options": { + "x": 14.167, + "y": 3.611, + "w": 1.049, + "h": 0.208, + "fontSize": 11, + "color": "333333" + } + }, + { + "type": "text", + "text": "\u5ba1\u6838\u4e2d | \u8fdb\u5ea6\u54a8\u8be2 \u25be", + "options": { + "x": 14.167, + "y": 3.819, + "w": 1.35, + "h": 0.167, + "fontSize": 10, + "color": "1677FF" + } + }, + { + "type": "text", + "text": "\u5ba1\u6838\u8bf4\u660e", + "options": { + "x": 2.556, + "y": 5.0, + "w": 1.249, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u6839\u636e\u8ba2\u5355\u91cf\u63a8\u7b97\uff0c\u7ba1\u5c40\u5ba1\u6838\u9884\u8ba18\u4e2a\u5de5\u4f5c\u65e5\u5de6\u53f3\u5b8c\u6210\u5ba1\u6838\uff0c\u6700\u957f\u4e0d\u8d85\u8fc720\u4e2a\u5de5\u4f5c\u65e5\uff0c\u5177\u4f53\u4ee5\u5b9e\u9645\u5ba1\u6838\u65f6\u95f4\u4e3a\u51c6\uff0c\u8bf7\u60a8\u8010\u5fc3\u7b49\u5f85", + "options": { + "x": 2.556, + "y": 5.417, + "w": 17.5, + "h": 0.25, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u7531\u4e8e\u7ba1\u5c40\u4e0b\u53d1\u5b58\u5728\u5ef6\u8fdf\uff0c\u5982\u6536\u5230\u5de5\u4fe1\u90e8\u201c\u9a73\u56de\u201d\u3001\u201c\u5df2\u53d8\u66f4\u201d\u6216\u201c\u6210\u529f\u201d\u7684\u77ed\u4fe1\u901a\u77e5\uff0c\u817e\u8baf\u4e91\u4f1a\u57286-24\u5c0f\u65f6\u5185\u6536\u5230\u53cd\u9988\uff08\u9ad8\u5cf0\u671f\u53ef\u80fd\u66f4\u957f\uff09\uff0c\u5e76\u66f4\u65b0\u72b6\u6001\uff0c\u6b64\u8fc7\u7a0b\u65e0\u6cd5\u52a0\u901f\uff0c\u8bf7\u7a0d\u540e\u518d\u67e5\u8be2\uff0c\u611f\u8c22\u60a8\u7684\u7406\u89e3\u3002", + "options": { + "x": 2.556, + "y": 5.833, + "w": 17.5, + "h": 0.25, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u5f53\u524d\u8ba2\u5355\u6b63\u5728\u901a\u4fe1\u7ba1\u7406\u5c40\u5ba1\u6838\u4e2d\u3002\u5ba1\u6838\u671f\u95f4\u8ba2\u5355\u5c06\u88ab\u9501\u5b9a\uff0c\u4e0d\u652f\u6301\u64a4\u56de\u6216\u4fee\u6539\u5907\u6848\u4fe1\u606f\uff0c\u8bf7\u7b49\u5f85\u5ba1\u6838\u5b8c\u6210\u540e\u518d\u8fdb\u884c\u540e\u7eed\u64cd\u4f5c\u3002", + "options": { + "x": 2.556, + "y": 6.25, + "w": 17.5, + "h": 0.25, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u7ba1\u5c40\u65e0\u6cd5\u50ac\u5ba1", + "options": { + "x": 2.556, + "y": 6.944, + "w": 1.499, + "h": 0.333, + "fontSize": 11, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u67e5\u770b\u5907\u6848\u4fe1\u606f", + "options": { + "x": 3.889, + "y": 6.944, + "w": 1.499, + "h": 0.333, + "fontSize": 11, + "color": "1677FF" + } + }, + { + "type": "text", + "text": "\u4e3b\u4f53\u4fe1\u606f", + "options": { + "x": 2.556, + "y": 7.778, + "w": 1.249, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u53d8\u66f4\u5907\u6848", + "options": { + "x": 8.056, + "y": 7.778, + "w": 1.001, + "h": 0.167, + "fontSize": 10, + "color": "1677FF" + } + }, + { + "type": "text", + "text": "\u6ce8\u9500\u4e3b\u4f53", + "options": { + "x": 8.889, + "y": 7.778, + "w": 1.001, + "h": 0.167, + "fontSize": 10, + "color": "1677FF" + } + }, + { + "type": "text", + "text": "\u8fc1\u79fb\u5907\u6848\u8d26\u53f7", + "options": { + "x": 9.722, + "y": 7.778, + "w": 1.249, + "h": 0.167, + "fontSize": 10, + "color": "1677FF" + } + }, + { + "type": "text", + "text": "\u5bfc\u51fa\u57fa\u7840\u4fe1\u606f", + "options": { + "x": 10.694, + "y": 7.778, + "w": 1.249, + "h": 0.167, + "fontSize": 10, + "color": "1677FF" + } + }, + { + "type": "text", + "text": "\u6682\u65e0\u5907\u6848", + "options": { + "x": 6.25, + "y": 8.611, + "w": 1.001, + "h": 0.167, + "fontSize": 11, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u4e92\u8054\u7f51\u4fe1\u606f\u670d\u52a1", + "options": { + "x": 2.556, + "y": 9.306, + "w": 2.0, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u65b0\u589e/\u63a5\u5165\u670d\u52a1", + "options": { + "x": 7.361, + "y": 9.306, + "w": 1.499, + "h": 0.333, + "fontSize": 11, + "color": "1677FF" + } + }, + { + "type": "text", + "text": "\u6ce8\u9500\u670d\u52a1", + "options": { + "x": 8.472, + "y": 9.306, + "w": 1.001, + "h": 0.333, + "fontSize": 11, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u53d6\u6d88\u817e\u8baf\u4e91\u63a5\u5165", + "options": { + "x": 9.306, + "y": 9.306, + "w": 1.75, + "h": 0.333, + "fontSize": 11, + "color": "999999" + } + }, + { + "type": "text", + "text": "\u901a\u77e5\u516c\u544a", + "options": { + "x": 18.056, + "y": 1.042, + "w": 1.499, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u5173\u4e8e\u5b58\u91cfAPP\u5907\u6848\u901a\u77e5", + "options": { + "x": 18.056, + "y": 1.458, + "w": 3.749, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u817e\u8baf\u4e91\u4e13\u9879\u6838\u67e5\u901a\u77e5", + "options": { + "x": 18.056, + "y": 1.806, + "w": 3.749, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u5173\u4e8e\u9884\u9632\u5907\u6848\u8fc7\u7a0b\u4e2d\u906d\u9047\u5feb\u9012\u8bc8\u9a97\u7684\u516c\u544a", + "options": { + "x": 18.056, + "y": 2.153, + "w": 3.749, + "h": 0.208, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u8d26\u53f7\u76f8\u5173\u95ee\u9898", + "options": { + "x": 18.056, + "y": 2.778, + "w": 1.75, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u4e00\u4e2a\u8d26\u53f7\u53ef\u4ee5\u7ed9\u591a\u4e2a\u4e0d\u540c\u4e3b\u4f53\u5907\u6848\u5417\uff1f", + "options": { + "x": 18.056, + "y": 3.194, + "w": 3.749, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u4e91\u8d44\u6e90\u76f8\u5173\u95ee\u9898", + "options": { + "x": 18.056, + "y": 3.819, + "w": 1.75, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u5982\u4f55\u83b7\u53d6\u548c\u4f7f\u7528\u201c\u5907\u6848\u6388\u6743\u7801\u201d\uff1f", + "options": { + "x": 18.056, + "y": 4.236, + "w": 3.749, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u4e00\u53f0\u670d\u52a1\u5668\u53ef\u4ee5\u5907\u6848\u51e0\u4e2a\u7f51\u7ad9\u6216APP\uff1f", + "options": { + "x": 18.056, + "y": 4.514, + "w": 3.749, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u57df\u540d\u76f8\u5173\u95ee\u9898", + "options": { + "x": 18.056, + "y": 4.931, + "w": 1.499, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u5907\u6848\u524d\u57df\u540d\u5fc5\u987b\u5b9e\u540d\u8ba4\u8bc1\u5417\uff1f", + "options": { + "x": 18.056, + "y": 5.347, + "w": 3.749, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u515a\u653f\u673a\u5173\u6216\u4e8b\u4e1a\u5355\u4f4d\u6027\u8d28\u5907\u6848\uff08\u7f51\u7ad9\u6216APP\uff09\u57df\u540d\u6709\u4ec0\u4e48\u8981\u6c42\uff1f", + "options": { + "x": 18.056, + "y": 5.625, + "w": 3.749, + "h": 0.25, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u65b0\u589e\u5907\u6848\u76f8\u5173\u95ee\u9898", + "options": { + "x": 18.056, + "y": 6.181, + "w": 2.0, + "h": 0.208, + "fontSize": 13, + "color": "333333", + "bold": true + } + }, + { + "type": "text", + "text": "\u4e00\u4e2a\u8ba2\u5355\u53ef\u4ee5\u65b0\u589e\u51e0\u4e2a\u7f51\u7ad9\u4e0eAPP\uff1f", + "options": { + "x": 18.056, + "y": 6.597, + "w": 3.749, + "h": 0.167, + "fontSize": 10, + "color": "666666" + } + }, + { + "type": "text", + "text": "\u65b0\u589e\u7f51\u7ad9\u6216 APP \u8fc7\u7a0b\u4e2d\uff0c\u7f51\u7ad9\u6216 APP \u662f\u5426\u80fd\u591f\u8bbf\u95ee\uff1f", + "options": { + "x": 18.056, + "y": 6.875, + "w": 3.749, + "h": 0.208, + "fontSize": 10, + "color": "666666" + } + } + ] + } + ] +} \ No newline at end of file