Files
admin/dashboard/writings/generate_manual.py
T
2026-07-30 11:23:50 +08:00

420 lines
20 KiB
Python
Raw 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.
#!/usr/bin/env python3
"""生成 Luxsin CMS 软著操作手册 Word 文档"""
import os
from docx import Document
from docx.shared import Inches, Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn, nsdecls
from docx.oxml import parse_xml
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
SCREENSHOT_DIR = os.path.join(SCRIPT_DIR, "screenshots")
OUTPUT_PATH = os.path.join(SCRIPT_DIR, "Luxsin CMS 操作手册.docx")
doc = Document()
# ── 全局样式设置 ──────────────────────────────────────
style = doc.styles["Normal"]
style.font.name = "微软雅黑"
style.font.size = Pt(11)
style.paragraph_format.line_spacing = 1.5
style.element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
# 页面设置
section = doc.sections[0]
section.page_width = Cm(21)
section.page_height = Cm(29.7)
section.top_margin = Cm(2.54)
section.bottom_margin = Cm(2.54)
section.left_margin = Cm(3.18)
section.right_margin = Cm(3.18)
def add_heading(text, level=1):
"""添加标题"""
h = doc.add_heading(text, level=level)
for run in h.runs:
run.font.name = "微软雅黑"
run.element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
return h
def add_para(text, bold=False, align=None, font_size=None, space_after=Pt(6)):
"""添加段落"""
p = doc.add_paragraph()
if align:
p.alignment = align
run = p.add_run(text)
run.font.name = "微软雅黑"
run.element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
if bold:
run.bold = True
if font_size:
run.font.size = font_size
p.paragraph_format.space_after = space_after
return p
def add_screenshot(filename, width=Inches(5.8)):
"""添加截图"""
filepath = os.path.join(SCREENSHOT_DIR, filename)
if os.path.exists(filepath):
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run()
run.add_picture(filepath, width=width)
return p
else:
add_para(f"[截图缺失: {filename}]", align=WD_ALIGN_PARAGRAPH.CENTER)
return None
def add_table(headers, rows):
"""添加表格"""
table = doc.add_table(rows=1 + len(rows), cols=len(headers))
table.style = "Table Grid"
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# Header
for i, h in enumerate(headers):
cell = table.rows[0].cells[i]
cell.text = h
for run in cell.paragraphs[0].runs:
run.bold = True
run.font.name = "微软雅黑"
run.font.size = Pt(10)
shading = parse_xml(f'<w:shd {nsdecls("w")} w:fill="E8E8E8"/>')
cell._tc.get_or_add_tcPr().append(shading)
# Data
for r_idx, row in enumerate(rows):
for c_idx, val in enumerate(row):
cell = table.rows[r_idx + 1].cells[c_idx]
cell.text = str(val)
for run in cell.paragraphs[0].runs:
run.font.name = "微软雅黑"
run.font.size = Pt(10)
return table
# ════════════════════════════════════════════════════════
# 封面
# ════════════════════════════════════════════════════════
for _ in range(6):
doc.add_paragraph()
add_para("Luxsin CMS", bold=True, align=WD_ALIGN_PARAGRAPH.CENTER, font_size=Pt(32), space_after=Pt(12))
add_para("音频设备内容管理系统", bold=True, align=WD_ALIGN_PARAGRAPH.CENTER, font_size=Pt(18), space_after=Pt(36))
add_para("操 作 手 册", bold=True, align=WD_ALIGN_PARAGRAPH.CENTER, font_size=Pt(26), space_after=Pt(48))
for _ in range(4):
doc.add_paragraph()
add_para("软件名称:Luxsin CMS 音频设备内容管理系统", align=WD_ALIGN_PARAGRAPH.CENTER, font_size=Pt(12))
add_para("版 本 号:V1.0", align=WD_ALIGN_PARAGRAPH.CENTER, font_size=Pt(12))
add_para("编制日期:2026 年 7 月", align=WD_ALIGN_PARAGRAPH.CENTER, font_size=Pt(12))
doc.add_page_break()
# ════════════════════════════════════════════════════════
# 目录页
# ════════════════════════════════════════════════════════
add_heading("目 录", level=1)
toc_items = [
"1. 系统概述",
"2. 系统运行环境",
"3. 系统登录",
"4. 首页(仪表盘)",
"5. 耳机管理",
" 5.1 品牌管理",
" 5.2 型号管理",
"6. 升级管理",
" 6.1 OTA 管理",
" 6.2 定向升级",
" 6.3 黑名单",
"7. 分享码",
" 7.1 分享日志",
"8. 工具箱",
" 8.1 Luxsin 控制器",
"9. 系统管理",
" 9.1 账号管理",
]
for item in toc_items:
add_para(item, font_size=Pt(12), space_after=Pt(4))
doc.add_page_break()
# ════════════════════════════════════════════════════════
# 1. 系统概述
# ════════════════════════════════════════════════════════
add_heading("1. 系统概述", level=1)
add_para(
"Luxsin CMS 是一套面向音频设备(耳机)行业的内容管理系统,"
"为运营人员提供耳机品牌/型号管理、OTA 固件升级管理、分享码使用日志查询、"
"局域网设备数据同步等功能。系统采用 B/S 架构,用户通过浏览器即可访问全部功能,"
"无需安装客户端软件。"
)
add_para(
"系统主要功能模块包括:"
)
modules = [
("首页", "展示系统快捷入口、今日新增型号及 OTA 统计信息"),
("耳机管理", "维护耳机品牌信息与耳机型号数据,支持型号搜索、批量推送至搜索引擎"),
("升级管理", "管理 OTA 固件升级包版本,支持定向升级(按 MAC 地址推送)及黑名单管控"),
("分享码", "查询分享码使用日志,可按设备 MAC 和分享码进行检索"),
("工具箱", "提供 Luxsin 控制器工具,用于局域网设备数据同步与解码"),
("系统管理", "账号管理功能(仅超级管理员可见),支持用户增删改查"),
]
add_table(["模块名称", "功能说明"], modules)
doc.add_paragraph()
# ════════════════════════════════════════════════════════
# 2. 系统运行环境
# ════════════════════════════════════════════════════════
add_heading("2. 系统运行环境", level=1)
add_heading("2.1 服务端环境", level=2)
add_table(
["项目", "要求"],
[
("操作系统", "Linux (Ubuntu 20.04+) / Docker"),
("运行时", "Node.js 22+"),
("数据库", "MySQL 5.7+"),
("缓存", "Redis 6+"),
("Web 服务器", "Nginx (前端静态资源托管)"),
("容器编排", "Docker Compose V2"),
],
)
doc.add_paragraph()
add_heading("2.2 客户端环境", level=2)
add_table(
["项目", "要求"],
[
("操作系统", "Windows 10+、macOS 12+、Linux"),
("浏览器", "Chrome 90+、Edge 90+、Firefox 90+、Safari 15+"),
("分辨率", "建议 1920×1080 及以上"),
("网络", "可访问系统部署地址即可"),
],
)
doc.add_paragraph()
# ════════════════════════════════════════════════════════
# 3. 系统登录
# ════════════════════════════════════════════════════════
add_heading("3. 系统登录", level=1)
add_para(
"打开浏览器,在地址栏输入系统访问地址,系统将自动跳转至登录页面。"
"在登录页面中输入用户名和密码,点击「确认」按钮即可登录。"
)
add_para("操作步骤:", bold=True)
add_para("1. 在用户名输入框中输入您的账号。")
add_para("2. 在密码输入框中输入对应的密码。")
add_para("3. 点击「确认」按钮,系统验证通过后自动跳转至首页。")
add_para("")
add_para("登录页面截图:", bold=True)
add_screenshot("01_login_page.png")
add_para("")
add_para("注意事项:", bold=True)
add_para("• 登录状态有效期以服务端 Token 为准,过期后需重新登录。")
add_para("• 如忘记密码,请联系系统管理员重置。")
# ════════════════════════════════════════════════════════
# 4. 首页
# ════════════════════════════════════════════════════════
doc.add_page_break()
add_heading("4. 首页(仪表盘)", level=1)
add_para(
"登录系统后默认进入首页。首页为用户提供系统概览和快捷操作入口,"
"方便快速访问各功能模块。"
)
add_para("页面功能:", bold=True)
add_para("• 快捷入口卡片:提供耳机品牌管理、型号管理、OTA 管理、分享日志、Luxsin 控制器等常用功能的快捷入口,点击即可直接跳转。")
add_para("• 今日新增型号:展示当天新增的耳机型号列表。")
add_para("• 今日新增 OTA:展示当天新增的 OTA 固件版本列表。")
add_para("")
add_para("首页截图:", bold=True)
add_screenshot("02_home.png")
# ════════════════════════════════════════════════════════
# 5. 耳机管理
# ════════════════════════════════════════════════════════
doc.add_page_break()
add_heading("5. 耳机管理", level=1)
add_para(
"耳机管理模块包含品牌管理和型号管理两个子功能,"
"用于维护系统中的耳机品牌与型号数据。"
)
# 5.1 品牌管理
add_heading("5.1 品牌管理", level=2)
add_para(
"品牌管理页面用于维护系统中所有耳机品牌信息。"
"支持品牌的搜索、新增、编辑和删除操作。"
)
add_para("功能说明:", bold=True)
add_para("• 搜索:在搜索框中输入品牌名称,点击「搜索」按钮可按名称筛选品牌。点击「重置」可清除筛选条件。")
add_para("• 新增品牌:点击「新增品牌」按钮,在弹出的对话框中输入品牌名称,确认后即可创建新品牌。")
add_para("• 编辑:点击品牌列表中的「编辑」按钮,可修改品牌名称。")
add_para("• 删除:点击品牌列表中的「删除」按钮,确认后删除该品牌。请注意,已关联型号的品牌删除前需先处理关联数据。")
add_para("• 分页:列表底部提供分页控件,可切换页码和调整每页显示条数。")
add_para("")
add_para("品牌管理页面截图:", bold=True)
add_screenshot("03_headphone_brand.png")
# 5.2 型号管理
doc.add_page_break()
add_heading("5.2 型号管理", level=2)
add_para(
"型号管理页面用于维护系统中所有耳机型号数据。"
"每个型号包含品牌、型号名称、佩戴方式、来源、创建时间等信息。"
)
add_para("功能说明:", bold=True)
add_para("• 搜索:支持按品牌名称和型号名称进行组合筛选。输入条件后点击「搜索」按钮执行查询,点击「重置」清除条件。")
add_para("• 新型号:点击「新型号」按钮,在弹出的表单中填写品牌、型号名称、佩戴方式等信息。支持频响数据文件上传。")
add_para("• 编辑:点击「编辑」按钮可修改型号的详细信息。")
add_para("• 删除:点击「删除」按钮可删除单个型号记录。")
add_para("• 批量操作:通过勾选复选框可选择多个型号,执行批量复制、批量推送到搜索引擎等操作。")
add_para("• 推送搜索:选中型号后点击「推送搜索」按钮,可将型号数据批量推送至 Meilisearch 搜索引擎。")
add_para("• 更多操作:点击「更多操作」按钮可访问 EQ 缓存查看、频响 CSV 查看、搜索引擎文档查看等扩展功能。")
add_para("")
add_para("型号管理页面截图:", bold=True)
add_screenshot("04_headphone_model.png")
# ════════════════════════════════════════════════════════
# 6. 升级管理
# ════════════════════════════════════════════════════════
doc.add_page_break()
add_heading("6. 升级管理", level=1)
add_para(
"升级管理模块用于管理耳机设备的 OTA 固件升级,"
"包含 OTA 版本管理、定向升级和黑名单三个子功能。"
)
# 6.1 OTA 管理
add_heading("6.1 OTA 管理", level=2)
add_para(
"OTA 管理页面用于维护固件升级包的版本信息。"
"每条记录包含版本号、版本名称、适配设备型号、硬件版本、升级包地址、"
"是否强制升级、灰度发布状态等信息。"
)
add_para("功能说明:", bold=True)
add_para("• 搜索筛选:支持按版本名称(模糊查询)、设备型号、状态、灰度标记、版本号(精确匹配)等多维度筛选。")
add_para("• 新增 OTA:点击「新增 OTA」按钮,填写版本号、版本名称、设备型号、硬件版本等信息,并上传升级包文件。系统将自动上传升级包至云存储并生成下载链接。")
add_para("• 编辑:点击「编辑」按钮可修改 OTA 版本的各项参数。")
add_para("• 复制:点击「复制」按钮可基于当前版本快速创建新的 OTA 记录。")
add_para("• 更多操作:包括删除等操作。")
add_para("• 复制包地址:点击「复制包地址」按钮可将升级包的下载链接复制到剪贴板。")
add_para("")
add_para("OTA 管理页面截图:", bold=True)
add_screenshot("05_upgrade_ota.png")
# 6.2 定向升级
doc.add_page_break()
add_heading("6.2 定向升级", level=2)
add_para(
"定向升级功能允许管理员将特定 OTA 版本推送给指定 MAC 地址的设备。"
"适用于测试验证或小范围灰度发布场景。"
)
add_para("功能说明:", bold=True)
add_para("• 搜索筛选:支持按 OTA 版本、设备型号、MAC 地址进行筛选。")
add_para("• 新增定向设备:点击「新增定向设备」按钮,选择目标 OTA 版本并输入设备 MAC 地址,确认后即可创建定向升级记录。")
add_para("• 编辑:点击「编辑」按钮可修改已绑定的 OTA 版本或 MAC 地址。")
add_para("• 删除:点击「删除」按钮可移除定向升级记录。")
add_para("")
add_para("定向升级页面截图:", bold=True)
add_screenshot("06_upgrade_target_device.png")
# 6.3 黑名单
add_heading("6.3 黑名单", level=2)
add_para(
"黑名单功能用于禁止特定 MAC 地址的设备接收 OTA 升级,"
"防止问题设备反复触发固件更新。"
)
add_para("功能说明:", bold=True)
add_para("• 新增黑名单:点击「新增黑名单」按钮,输入需要封禁的设备 MAC 地址。")
add_para("• 编辑:点击「编辑」按钮可修改黑名单中的 MAC 地址。")
add_para("• 删除:点击「删除」按钮可将设备从黑名单中移除,恢复其 OTA 升级资格。")
add_para("")
add_para("黑名单页面截图:", bold=True)
add_screenshot("07_upgrade_blacklist.png")
# ════════════════════════════════════════════════════════
# 7. 分享码
# ════════════════════════════════════════════════════════
doc.add_page_break()
add_heading("7. 分享码", level=1)
add_para(
"分享码模块用于查看和检索设备的分享码使用记录。"
)
# 7.1 分享日志
add_heading("7.1 分享日志", level=2)
add_para(
"分享日志页面展示所有分享码的使用记录,"
"包含分享码、设备 MAC 地址、使用时间等信息。"
)
add_para("功能说明:", bold=True)
add_para("• 按 MAC 搜索:在 MAC 地址输入框中输入设备 MAC,可按设备筛选分享记录。")
add_para("• 按分享码搜索:在分享码输入框中输入分享码,可精确查找特定分享码的使用记录。")
add_para("• 搜索与重置:点击「搜索」执行查询,点击「重置」清除筛选条件。")
add_para("• 分页浏览:列表支持分页浏览,可调整每页显示条数。")
add_para("")
add_para("分享日志页面截图:", bold=True)
add_screenshot("08_share_code_log.png")
# ════════════════════════════════════════════════════════
# 8. 工具箱
# ════════════════════════════════════════════════════════
doc.add_page_break()
add_heading("8. 工具箱", level=1)
add_para(
"工具箱模块提供辅助工具,帮助运营人员进行设备调试与数据同步。"
)
# 8.1 Luxsin 控制器
add_heading("8.1 Luxsin 控制器", level=2)
add_para(
"Luxsin 控制器是一个局域网设备数据同步工具,"
"用于从局域网内的 Luxsin 设备获取数据并进行解码展示。"
)
add_para("功能说明:", bold=True)
add_para("• 同步数据:点击「同步数据」按钮,系统将从局域网内的 Luxsin 设备获取设备配置数据。")
add_para("• 同步 PEQ:点击「同步 PEQ」按钮,系统将获取设备的 PEQ(参数均衡器)配置数据。")
add_para("• 原始响应展示:系统获取到的原始 Base64 编码数据将展示在「原始响应」区域。")
add_para("• 解码结果:系统内置自定义 Base64 解码算法,将解码后的 JSON 数据格式化展示在「解码结果」区域,便于技术人员查看设备参数。")
add_para("")
add_para("Luxsin 控制器页面截图:", bold=True)
add_screenshot("09_toolbox_luxsin_controller.png")
# ════════════════════════════════════════════════════════
# 9. 系统管理
# ════════════════════════════════════════════════════════
doc.add_page_break()
add_heading("9. 系统管理", level=1)
add_para(
"系统管理模块提供后台管理功能,仅对超级管理员角色开放。"
"普通用户登录后无法看到此菜单入口。"
)
# 9.1 账号管理
add_heading("9.1 账号管理", level=2)
add_para(
"账号管理页面用于管理系统中的所有用户账号。"
"超级管理员可在此创建、编辑和删除用户。"
)
add_para("功能说明:", bold=True)
add_para("• 新增用户:点击「新增用户」按钮,填写用户名、密码、角色等信息创建新账号。")
add_para("• 编辑:点击「编辑」按钮可修改用户信息,包括重置密码、更改角色等。")
add_para("• 删除:点击「删除」按钮可删除用户账号。删除操作不可撤销,请谨慎操作。")
add_para("• 角色说明:系统支持超级管理员(R_SUPER)和普通用户(R_USER)两种角色。超级管理员拥有全部权限,普通用户无法访问系统管理等敏感功能。")
add_para("")
add_para("账号管理页面截图:", bold=True)
add_screenshot("10_system_users.png")
# ════════════════════════════════════════════════════════
# 保存文档
# ════════════════════════════════════════════════════════
doc.save(OUTPUT_PATH)
print(f"文档已生成: {OUTPUT_PATH}")