Files
visual-vue-v1/scripts/generate-guide-docx.mjs
2026-07-26 14:46:36 +08:00

219 lines
11 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import {
Document, Packer, Paragraph, TextRun, Header, Footer,
AlignmentType, PageNumber, PageBreak, HeadingLevel,
Table, TableRow, TableCell, WidthType, BorderStyle,
LevelFormat, ShadingType,
} from 'docx';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const OUT = path.resolve(__dirname, '..', 'docs', '软著登记申请表填写指南.docx');
const PAGE_W = 11906;
const PAGE_H = 16838;
const MARGIN = 1440;
const CONTENT_W = PAGE_W - MARGIN * 2;
const border = { style: BorderStyle.SINGLE, size: 1, color: '999999' };
const borders = { top: border, bottom: border, left: border, right: border };
function h(level, text) {
const sizes = { 1: 36, 2: 30, 3: 26 };
const map = { 1: HeadingLevel.HEADING_1, 2: HeadingLevel.HEADING_2, 3: HeadingLevel.HEADING_3 };
return new Paragraph({
heading: map[level],
spacing: { before: 240, after: 160 },
children: [new TextRun({ text, font: 'SimHei', size: sizes[level], bold: true })],
});
}
function p(text) {
return new Paragraph({
spacing: { before: 60, after: 60 },
children: [new TextRun({ text, font: 'SimSun', size: 24 })],
});
}
function bullet(text) {
return new Paragraph({
numbering: { reference: 'bullets', level: 0 },
spacing: { before: 40, after: 40 },
children: [new TextRun({ text, font: 'SimSun', size: 24 })],
});
}
function checklist(text) {
return new Paragraph({
spacing: { before: 40, after: 40 },
children: [new TextRun({ text: `□ ${text}`, font: 'SimSun', size: 24 })],
});
}
function tableRow(cells, isHeader = false) {
const colW = Math.floor(CONTENT_W / cells.length);
return new TableRow({
children: cells.map((c, i) => new TableCell({
borders,
width: { size: colW, type: WidthType.DXA },
shading: isHeader ? { fill: '2B579A', type: ShadingType.CLEAR } : undefined,
margins: { top: 80, bottom: 80, left: 100, right: 100 },
children: [new Paragraph({
spacing: { before: 20, after: 20 },
children: [new TextRun({ text: c, font: isHeader ? 'SimHei' : 'SimSun', size: 20, bold: isHeader, color: isHeader ? 'FFFFFF' : '333333' })],
})],
})),
});
}
const sections = [];
sections.push({
properties: {
page: { size: { width: PAGE_W, height: PAGE_H }, margin: { top: MARGIN, right: MARGIN, bottom: MARGIN, left: MARGIN } },
headers: {
default: new Header({
children: [new Paragraph({
alignment: AlignmentType.CENTER,
border: { bottom: { style: BorderStyle.SINGLE, size: 2, color: '2B579A', space: 4 } },
children: [new TextRun({ text: '软著登记申请表填写指南', font: 'SimSun', size: 18, color: '666666' })],
})],
}),
},
footers: {
default: new Footer({
children: [new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({ text: '第 ', font: 'SimSun', size: 18, color: '888888' }),
new TextRun({ children: [PageNumber.CURRENT], font: 'SimSun', size: 18, color: '888888' }),
new TextRun({ text: ' 页', font: 'SimSun', size: 18, color: '888888' }),
],
})],
}),
},
},
children: [
new Paragraph({ spacing: { before: 1200 }, children: [] }),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { after: 200 },
children: [new TextRun({ text: '中国版权保护中心', font: 'SimHei', size: 32, bold: true, color: '2B579A' })],
}),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { after: 200 },
children: [new TextRun({ text: '软件著作权登记申请表填写指南', font: 'SimHei', size: 40, bold: true, color: '333333' })],
}),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { after: 100 },
children: [new TextRun({ text: '对应项目:可视化大屏模板系统 V1.0', font: 'SimSun', size: 24, color: '555555' })],
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '生成日期:2026年7月26日', font: 'SimSun', size: 24, color: '555555' })],
}),
new Paragraph({ children: [new PageBreak()] }),
h(1, '一、软件基本信息'),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow(['表单字段', '建议填写内容', '说明'], true),
tableRow(['软件全称', '可视化大屏模板系统', '']),
tableRow(['软件简称', '大屏模板系统', '可留空;填写便于识别']),
tableRow(['版本号', 'V1.0', '与材料中版本号保持一致']),
tableRow(['权利范围', '全部权利', '原创作品,选择全部权利']),
tableRow(['软件分类', '应用软件', '在系统中选择对应分类']),
tableRow(['软件说明', '原创', '本项目为原创开发']),
tableRow(['开发方式', '单独开发', '个人著作权人,选择单独开发']),
tableRow(['开发完成日期', '2026-07-26', '以最终改造完成日期为准']),
tableRow(['发表状态', '未发表', '如尚未公开发布,选择未发表']),
],
}),
h(1, '二、著作权人信息'),
p('截图中已填写:中国 / 湖北武汉 / 自然人 / 陈银军 / 居民身份证。'),
p('请务必核对姓名、身份证号与身份证正反面扫描件完全一致;身份证需在有效期内、四角完整、文字清晰。'),
h(1, '三、开发/运行环境'),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow(['表单字段', '建议填写内容'], true),
tableRow(['开发的硬件环境', 'PC 机;Intel Core i5 及以上 CPU;内存 8GB 及以上;硬盘 256GB 及以上;显示器分辨率 1920×1080 及以上。']),
tableRow(['运行的硬件环境', 'PC 机或服务器;Intel Core i5 及以上 CPU;内存 8GB 及以上;硬盘 256GB 及以上;支持 WebGL 的显卡;显示器分辨率 1920×1080 及以上。']),
tableRow(['开发该软件的操作系统', 'macOS 12 / Windows 10 / Windows 11']),
tableRow(['软件开发环境 / 开发工具', 'Node.js 18+、npm 9+、Vite 5、Visual Studio Code、TypeScript 5.7']),
tableRow(['该软件的运行平台 / 操作系统', 'Windows 10/11、macOS 11+、Linux 各发行版']),
tableRow(['软件运行支撑环境 / 支持软件', 'Chrome 90+、Edge 90+、Firefox 88+、Safari 14+']),
tableRow(['编程语言', 'TypeScript、HTML、CSS、Vue']),
tableRow(['源程序量', '约 105,000 行(197 个源文件)']),
],
}),
h(1, '四、软件功能与技术特点'),
h(2, '4.1 开发目的'),
p('为企业和个人提供一套开箱即用的数据可视化大屏模板集合,降低大屏开发成本,提升数据展示效率,适用于车辆监控、农业数据、交通运输、物流数据、电商数据、政务大数据、通用模板、大数据分析、行业垂直应用及布局组件等多种场景。'),
h(2, '4.2 面向领域 / 行业'),
p('数据可视化、大数据分析、企业监控、智慧城市、指挥调度、态势感知、物联网、电子商务、政务管理、物流运输。'),
h(2, '4.3 软件的主要功能'),
bullet('大屏模板导航:首页以卡片形式展示 10 大分类、66 个数据大屏模板,支持分类筛选、关键词搜索、滚动浏览。'),
bullet('模板预览:每个模板卡片展示预览图、名称和描述,帮助用户快速识别目标大屏。'),
bullet('大屏页面展示:点击卡片进入对应大屏详情页,集成 ECharts 图表、地图、数字滚动、轮播切换等可视化效果。'),
bullet('多屏模板支持:部分复杂模板包含多个子页面,支持自动轮播或手动切换。'),
bullet('独立页面封装:每个大屏页面自包含样式、图片、数据配置及子组件,便于单独拷贝复用。'),
bullet('响应式图表:图表随浏览器窗口尺寸变化自动缩放,适配主流显示分辨率。'),
bullet('路由管理:基于 Vue Router 实现单页面应用路由,共注册 85 条路由。'),
h(2, '4.4 软件的技术特点'),
bullet('前端框架:基于 Vue 3 + TypeScript + Vite 构建,采用 Composition API 与 <script setup> 语法。'),
bullet('路由方案:使用 Vue Router 4 实现 SPA 路由管理。'),
bullet('可视化引擎:集成 ECharts 4.x,支持柱状图、折线图、饼图、地图、雷达图、仪表盘、水球图、词云图等 20 余种图表。'),
bullet('地图能力:支持中国地图、省级地图及 GIS 地图展示。'),
bullet('组件化设计:公共组件(NavBar、CategorySection、TemplateCard)与页面组件解耦。'),
bullet('自包含结构:每个大屏模板独立存放,可单独拷贝使用。'),
bullet('代码规模:源程序约 105,000 行,197 个源文件,覆盖 85 条路由页面。'),
p('表单中「软件的技术特点」若为多选,可勾选:大数据软件、智慧城市软件、物联网软件;并在文本框中补充上述说明。'),
h(1, '五、鉴别材料上传'),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow(['上传项', '应上传文件', '文件状态'], true),
tableRow(['程序鉴别材料', 'docs/源程序文档.pdf', '已生成,60 页(前 30 页 + 后 30 页),每页 60 行']),
tableRow(['文档鉴别材料', 'docs/软件说明书.pdf', '已生成,5 页(不足 60 页,全部提交)']),
tableRow(['其他相关证明文件', '无需上传', '个人原创单独开发,无合作/委托/任务开发协议']),
],
}),
p('注意:版权中心要求上传 PDF 格式。已生成的 PDF 文件位于 docs/ 目录下,请在上传前再次检查文件名、页数及清晰度。'),
h(1, '六、提交前核对清单'),
checklist('软件全称、版本号、开发完成日期与鉴别材料中一致'),
checklist('著作权人姓名、身份证号与身份证正反面扫描件一致'),
checklist('身份证扫描件四角完整、文字清晰、在有效期内'),
checklist('源程序文档 PDF 为 60 页(前 30 + 后 30)'),
checklist('软件说明书 PDF 已全部包含(5 页)'),
checklist('上传文件均为 PDF 格式,大小符合系统限制'),
checklist('申请表中所有带 * 号字段均已填写'),
checklist('确认「发表状态」选择正确(未发表/已发表)'),
],
});
const doc = new Document({
styles: {
default: { document: { run: { font: 'SimSun', size: 24 } } },
},
numbering: {
config: [{
reference: 'bullets',
levels: [{
level: 0, format: LevelFormat.BULLET, text: '•', alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } },
}],
}],
},
sections,
});
if (!fs.existsSync(path.dirname(OUT))) fs.mkdirSync(path.dirname(OUT), { recursive: true });
const buffer = await Packer.toBuffer(doc);
fs.writeFileSync(OUT, buffer);
console.log(`Saved ${OUT}`);