653 lines
30 KiB
Python
653 lines
30 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
Generate August 2026 Monthly Report Word Document for 葛昀.
|
||
Audience: 老板 - 通俗易懂、图文并茂
|
||
"""
|
||
import os
|
||
from docx import Document
|
||
from docx.shared import Inches, Pt, Cm, RGBColor, Emu
|
||
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_BREAK
|
||
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
|
||
from docx.oxml.ns import qn
|
||
from docx.oxml import OxmlElement
|
||
|
||
# ---- config ----
|
||
SCREENSHOT_DIR = r"D:\code\机器人智慧服务系统\.workbuddy\screenshots"
|
||
OUTPUT_PATH = r"D:\code\机器人智慧服务系统\2026年8月工作月度报告-葛昀.docx"
|
||
|
||
NAME = "葛昀"
|
||
MONTH = "2026年8月"
|
||
DEPT = "智慧运维研发组"
|
||
PERIOD = "2026.08.01 — 2026.08.31"
|
||
|
||
# ---- helpers ----
|
||
def set_cell_shading(cell, color):
|
||
tc = cell._tc
|
||
tcPr = tc.get_or_add_tcPr()
|
||
shading = OxmlElement('w:shd')
|
||
shading.set(qn('w:fill'), color)
|
||
shading.set(qn('w:val'), 'clear')
|
||
tcPr.append(shading)
|
||
|
||
|
||
def set_cell_border(cell, color="BFBFBF", sz=4):
|
||
tc = cell._tc
|
||
tcPr = tc.get_or_add_tcPr()
|
||
tcBorders = OxmlElement('w:tcBorders')
|
||
for border_name in ('top', 'left', 'bottom', 'right'):
|
||
border_el = OxmlElement(f'w:{border_name}')
|
||
border_el.set(qn('w:val'), 'single')
|
||
border_el.set(qn('w:sz'), str(sz))
|
||
border_el.set(qn('w:color'), color)
|
||
tcBorders.append(border_el)
|
||
tcPr.append(tcBorders)
|
||
|
||
|
||
def add_page_break(doc):
|
||
p = doc.add_paragraph()
|
||
run = p.add_run()
|
||
run.add_break(WD_BREAK.PAGE)
|
||
|
||
|
||
def add_p(doc, text, size=10.5, bold=False, color=None, align=None, indent_first=False, space_after=4):
|
||
p = doc.add_paragraph()
|
||
if align == "center":
|
||
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
elif align == "right":
|
||
p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||
elif align == "justify":
|
||
p.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
|
||
else:
|
||
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
||
if indent_first:
|
||
p.paragraph_format.first_line_indent = Pt(21) # 2字符
|
||
run = p.add_run(text)
|
||
run.font.size = Pt(size)
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
run.font.bold = bold
|
||
if color:
|
||
run.font.color.rgb = RGBColor(*color)
|
||
p.paragraph_format.space_after = Pt(space_after)
|
||
return p
|
||
|
||
|
||
def add_h1(doc, text):
|
||
p = doc.add_paragraph()
|
||
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
||
run = p.add_run(text)
|
||
run.font.size = Pt(18)
|
||
run.font.bold = True
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
run.font.color.rgb = RGBColor(31, 73, 125)
|
||
p.paragraph_format.space_before = Pt(14)
|
||
p.paragraph_format.space_after = Pt(8)
|
||
# 下划线效果:加一条浅色横线
|
||
pPr = p._element.get_or_add_pPr()
|
||
pBdr = OxmlElement('w:pBdr')
|
||
bottom = OxmlElement('w:bottom')
|
||
bottom.set(qn('w:val'), 'single')
|
||
bottom.set(qn('w:sz'), '12')
|
||
bottom.set(qn('w:color'), '1F497D')
|
||
bottom.set(qn('w:space'), '4')
|
||
pBdr.append(bottom)
|
||
pPr.append(pBdr)
|
||
return p
|
||
|
||
|
||
def add_h2(doc, text):
|
||
p = doc.add_paragraph()
|
||
run = p.add_run(text)
|
||
run.font.size = Pt(14)
|
||
run.font.bold = True
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
run.font.color.rgb = RGBColor(46, 116, 181)
|
||
p.paragraph_format.space_before = Pt(10)
|
||
p.paragraph_format.space_after = Pt(4)
|
||
return p
|
||
|
||
|
||
def add_h3(doc, text):
|
||
p = doc.add_paragraph()
|
||
run = p.add_run(text)
|
||
run.font.size = Pt(12)
|
||
run.font.bold = True
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
run.font.color.rgb = RGBColor(31, 73, 125)
|
||
p.paragraph_format.space_before = Pt(6)
|
||
p.paragraph_format.space_after = Pt(2)
|
||
return p
|
||
|
||
|
||
def add_bullet(doc, text, size=10.5):
|
||
p = doc.add_paragraph(style='List Bullet')
|
||
run = p.add_run(text)
|
||
run.font.size = Pt(size)
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
p.paragraph_format.space_after = Pt(2)
|
||
return p
|
||
|
||
|
||
def add_numbered(doc, text, size=10.5):
|
||
p = doc.add_paragraph(style='List Number')
|
||
run = p.add_run(text)
|
||
run.font.size = Pt(size)
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
p.paragraph_format.space_after = Pt(2)
|
||
return p
|
||
|
||
|
||
def add_image(doc, name, max_width_inches=5.5, caption=None):
|
||
"""Insert a PNG screenshot with optional caption."""
|
||
fp = os.path.join(SCREENSHOT_DIR, name)
|
||
if not os.path.exists(fp):
|
||
add_p(doc, f"[图片缺失: {name}]", size=9, color=(150, 150, 150))
|
||
return None
|
||
p = doc.add_paragraph()
|
||
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
run = p.add_run()
|
||
run.add_picture(fp, width=Inches(max_width_inches))
|
||
p.paragraph_format.space_before = Pt(6)
|
||
p.paragraph_format.space_after = Pt(2)
|
||
if caption:
|
||
cp = doc.add_paragraph()
|
||
cp.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
cr = cp.add_run(f"图 {caption}")
|
||
cr.font.size = Pt(9)
|
||
cr.font.italic = True
|
||
cr.font.name = 'Microsoft YaHei'
|
||
cr._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
cr.font.color.rgb = RGBColor(89, 89, 89)
|
||
cp.paragraph_format.space_after = Pt(10)
|
||
return p
|
||
|
||
|
||
def add_kv_table(doc, rows, col_widths=(1.5, 5.0)):
|
||
"""Add a simple two-column key-value table."""
|
||
table = doc.add_table(rows=len(rows), cols=2)
|
||
table.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||
table.autofit = False
|
||
for i, (k, v) in enumerate(rows):
|
||
for j, val in enumerate((k, v)):
|
||
cell = table.cell(i, j)
|
||
cell.width = Inches(col_widths[j])
|
||
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
||
set_cell_border(cell, "BFBFBF")
|
||
if j == 0:
|
||
set_cell_shading(cell, "EAF1FA")
|
||
cell.text = ""
|
||
p = cell.paragraphs[0]
|
||
run = p.add_run(val)
|
||
run.font.size = Pt(10.5)
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
if j == 0:
|
||
run.font.bold = True
|
||
return table
|
||
|
||
|
||
def add_data_table(doc, headers, rows, widths=None, header_color="1F497D"):
|
||
n = len(rows) + 1
|
||
cols = len(headers)
|
||
table = doc.add_table(rows=n, cols=cols)
|
||
table.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||
table.autofit = False
|
||
if widths:
|
||
for j, w in enumerate(widths):
|
||
for i in range(n):
|
||
table.cell(i, j).width = Inches(w)
|
||
# header
|
||
for j, h in enumerate(headers):
|
||
cell = table.cell(0, j)
|
||
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
||
set_cell_border(cell, "BFBFBF")
|
||
set_cell_shading(cell, header_color)
|
||
cell.text = ""
|
||
p = cell.paragraphs[0]
|
||
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
run = p.add_run(h)
|
||
run.font.size = Pt(10.5)
|
||
run.font.bold = True
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
run.font.color.rgb = RGBColor(255, 255, 255)
|
||
# rows
|
||
for i, row in enumerate(rows, start=1):
|
||
for j, v in enumerate(row):
|
||
cell = table.cell(i, j)
|
||
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
||
set_cell_border(cell, "BFBFBF")
|
||
if i % 2 == 0:
|
||
set_cell_shading(cell, "F2F6FB")
|
||
cell.text = ""
|
||
p = cell.paragraphs[0]
|
||
p.alignment = WD_ALIGN_PARAGRAPH.LEFT if j > 0 else WD_ALIGN_PARAGRAPH.CENTER
|
||
run = p.add_run(v)
|
||
run.font.size = Pt(10)
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
return table
|
||
|
||
|
||
# ---- 文档主体 ----
|
||
doc = Document()
|
||
|
||
# 默认样式
|
||
style = doc.styles['Normal']
|
||
style.font.name = 'Microsoft YaHei'
|
||
style.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
style.font.size = Pt(10.5)
|
||
|
||
# 页边距
|
||
for section in doc.sections:
|
||
section.top_margin = Cm(2.2)
|
||
section.bottom_margin = Cm(2.2)
|
||
section.left_margin = Cm(2.2)
|
||
section.right_margin = Cm(2.2)
|
||
|
||
# ============================================================
|
||
# 封面
|
||
# ============================================================
|
||
cover_p = doc.add_paragraph()
|
||
cover_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
cover_p.paragraph_format.space_before = Pt(120)
|
||
cr = cover_p.add_run("月度工作报告")
|
||
cr.font.size = Pt(36)
|
||
cr.font.bold = True
|
||
cr.font.name = 'Microsoft YaHei'
|
||
cr._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
cr.font.color.rgb = RGBColor(31, 73, 125)
|
||
|
||
cover_p2 = doc.add_paragraph()
|
||
cover_p2.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
cr2 = cover_p2.add_run(MONTH)
|
||
cr2.font.size = Pt(28)
|
||
cr2.font.bold = True
|
||
cr2.font.name = 'Microsoft YaHei'
|
||
cr2._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
cr2.font.color.rgb = RGBColor(89, 89, 89)
|
||
|
||
# 间隔
|
||
for _ in range(2):
|
||
doc.add_paragraph()
|
||
|
||
# 封面信息表
|
||
cover_table = doc.add_table(rows=4, cols=2)
|
||
cover_table.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||
cover_table.autofit = False
|
||
info = [
|
||
("报 告 人", f"{NAME}({DEPT})"),
|
||
("报告周期", PERIOD),
|
||
("汇报对象", "部门负责人"),
|
||
("报告日期", "2026 年 9 月"),
|
||
]
|
||
for i, (k, v) in enumerate(info):
|
||
for jj, val in enumerate((k, v)):
|
||
cell = cover_table.cell(i, jj)
|
||
cell.width = Inches(1.4 if jj == 0 else 2.4)
|
||
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
||
set_cell_border(cell, "1F497D", sz=8)
|
||
if jj == 0:
|
||
set_cell_shading(cell, "1F497D")
|
||
cell.text = ""
|
||
p = cell.paragraphs[0]
|
||
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
run = p.add_run(val)
|
||
run.font.size = Pt(13)
|
||
run.font.bold = (jj == 0)
|
||
run.font.name = 'Microsoft YaHei'
|
||
run._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
if jj == 0:
|
||
run.font.color.rgb = RGBColor(255, 255, 255)
|
||
|
||
# 底部
|
||
for _ in range(6):
|
||
doc.add_paragraph()
|
||
foot = doc.add_paragraph()
|
||
foot.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
fr = foot.add_run("机器人智慧服务系统 · 葛昀")
|
||
fr.font.size = Pt(11)
|
||
fr.font.name = 'Microsoft YaHei'
|
||
fr._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
|
||
fr.font.color.rgb = RGBColor(120, 120, 120)
|
||
|
||
add_page_break(doc)
|
||
|
||
# ============================================================
|
||
# 一、本月工作总览
|
||
# ============================================================
|
||
add_h1(doc, "一、本月工作总览")
|
||
|
||
add_p(doc,
|
||
f"本月({PERIOD}),本人主要围绕「光伏机器人智慧运维系统」的稳定性提升、功能迭代、跨端联调 "
|
||
f"与文档沉淀四条主线开展工作,累计完成代码提交 58 次,涵盖设备控制权限重构、WebSocket 通信优化、"
|
||
f"视频与日志管理模块建设、iOS/Android 双端协同、AI 大模型版本升级、软件著作权申报等多项重点工作。",
|
||
indent_first=True, align="justify")
|
||
|
||
add_h2(doc, "1.1 本月核心数据")
|
||
|
||
data_rows = [
|
||
("代码提交", "58 次", "git 提交,覆盖 8 个主要迭代方向"),
|
||
("工作主线", "4 条", "稳定性 / 功能迭代 / 跨端联调 / 文档沉淀"),
|
||
("周报输出", "5 篇", "覆盖 8 月完整工作节奏"),
|
||
("关键里程碑", "6 项", "WS 重构、视频模型升权、二级路由权开等"),
|
||
("跨团队联调", "1 项", "苏州算法团队路径规划全流程联调"),
|
||
("联调演示", "2 次", "现场联调保障、展会演示支持"),
|
||
("文档输出", "3 份", "用户手册、软著采集表、SOP 操作文档"),
|
||
]
|
||
add_data_table(doc, ["指标", "数值", "说明"], data_rows, widths=(1.4, 1.4, 3.6))
|
||
|
||
doc.add_paragraph()
|
||
|
||
add_h2(doc, "1.2 本月整体工作亮点")
|
||
|
||
highlights = [
|
||
"【控制权限】重构设备控制权限体系,由「单用户单设备」升级为「单设备单 Token」,彻底避免权限混乱、残留占用问题;"
|
||
"并完成 Web/APP 跨端抢占与释放的全场景闭环测试。",
|
||
"【联调突破】与苏州算法团队完成路径规划全流程联调——打点 → 数据保存 → 规划指令下发 → 算法回执 → "
|
||
"地图可视化展示规划路径与实时轨迹,业务链路完整跑通。",
|
||
"【架构升级】完成系统路由从一级到二级架构改造,页面跳转更清晰;同时将视频下载从 Node 脚本重构为 Java 接口,"
|
||
"统一后端技术栈,提升服务稳定性与可维护性。",
|
||
"【国际化】完成平台核心业务界面中英文双语切换,覆盖日常高频使用页面;为多语言场景落地提供基础。",
|
||
"【文档产出】独立输出 13 章 ~15 页的用户操作手册(含 16 张页面截图)、软著采集表(20 个字段全覆盖)、"
|
||
"以及标准 SOP 操作文档,便于后续交接与维护。",
|
||
]
|
||
for h in highlights:
|
||
add_bullet(doc, h)
|
||
|
||
add_page_break(doc)
|
||
|
||
# ============================================================
|
||
# 二、各周工作详情
|
||
# ============================================================
|
||
add_h1(doc, "二、各周工作详情")
|
||
|
||
# ---------- 第 1 周 ----------
|
||
add_h2(doc, "第 1 周(8/1 – 8/7):控制权限重构 + WS 通信优化")
|
||
add_h3(doc, "工作主题")
|
||
add_p(doc, "智慧运维系统平台底层通信机制优化、设备控制权限架构升级、跨团队算法联调启动。", indent_first=True)
|
||
|
||
add_h3(doc, "具体工作")
|
||
items = [
|
||
"优化 WebSocket 连接机制:实现单页面仅维持一次 WS 连接,路由切换自动销毁,避免多页面重复连接、"
|
||
"消息错乱与后台心跳堆积。",
|
||
"重构设备控制权限体系:从「单用户单设备控制」升级为「单设备单 Token 唯一占用」机制,"
|
||
"保证同一时间一台设备仅被一个有效连接控制。",
|
||
"新增主动释放权限功能,并完成闭环测试:Web 不同账号切换、Web 同账号页面切换、"
|
||
"Web 与 APP 跨端权限交替抢占与释放。",
|
||
"与苏州算法团队深度联调路径规划功能:完成设备打点、路径数据保存、规划指令下发、算法回执接收等"
|
||
"完整交互流程;地图可视化绘制规划轨迹与实时行走路径。",
|
||
"全程指导 APP 端完成路径规划全套业务流程适配与调试,配合团队完成苏州现场机器演示调试与保障。",
|
||
]
|
||
for i, it in enumerate(items, 1):
|
||
add_numbered(doc, it)
|
||
|
||
add_h3(doc, "本周产出")
|
||
add_image(doc, "00_login.png", 4.5, "系统登录界面 — 8 月初持续优化登录态")
|
||
|
||
# ---------- 第 2 周 ----------
|
||
add_h2(doc, "第 2 周(8/8 – 8/14):联调推进 + 组件迭代 + 文档沉淀")
|
||
add_h3(doc, "工作主题")
|
||
add_p(doc, "持续推进路径规划联调、平台基础功能完善、性能优化组件迭代,并沉淀 SOP 操作文档。", indent_first=True)
|
||
|
||
add_h3(doc, "具体工作")
|
||
items = [
|
||
"苏州路径规划联调持续推进,本周完成设备状态界面打点功能调试:机器在线状态、经纬度数据正常上报,"
|
||
"实时轨迹打点运行正常。",
|
||
"控制权限逻辑重构优化:基于新权限架构重构平台控制代码,彻底移除老旧权限逻辑;"
|
||
"优化 Web 端路由切换时的控制权限释放机制,解决权限滞留。",
|
||
"性能优化与组件迭代:完成路由组件拆分优化、精简冗余代码、优化加载逻辑,提升路由跳转速度;"
|
||
"修复 WebSocket 切换时序差导致的历史数据残留。",
|
||
"基础功能模块完善:完成系统基本设置模块迭代,新增「用户角色概览」「角色权限概览」;"
|
||
"完成电站地址功能接入,支持自定义修改场站地址。",
|
||
"文档沉淀:梳理 Web 端路径规划完整操作流程,编写标准化 SOP 操作文档,统一操作规范。",
|
||
"现场演示调试:配合机器展会演示调试与保障工作,确保现场演示顺利开展。",
|
||
]
|
||
for i, it in enumerate(items, 1):
|
||
add_numbered(doc, it)
|
||
|
||
add_h3(doc, "本周产出")
|
||
add_image(doc, "14_system.png", 2.6, "系统设置 — 用户/角色模块优化")
|
||
add_image(doc, "02_device_overview.png", 5.5, "设备总览 — 电站地址接入与多场站切换")
|
||
|
||
# ---------- 第 3 周 ----------
|
||
add_h2(doc, "第 3 周(8/15 – 8/21):视频日志改造 + 国际化 + 软著推进")
|
||
add_h3(doc, "工作主题")
|
||
add_p(doc, "完成视频/日志管理模块建设、iOS 适配指导、系统中英文国际化、APP 端优化及软著申报材料撰写。", indent_first=True)
|
||
|
||
add_h3(doc, "具体工作")
|
||
items = [
|
||
"视频管理模块开发:支持批量下载设备本地存储视频文件,将原有 Node 脚本实现的下载逻辑重构为 Java 接口,"
|
||
"统一后端技术栈。",
|
||
"日志管理模块开发:实现权限区分展示,支持管理员查看服务端运行日志,便于后续问题排查与系统运维。",
|
||
"iOS 适配指导与技术文档沉淀:协助指导 APP 苹果端相关功能实现,独立整理并输出 ios.md 技术文档,"
|
||
"统一调试规范与适配细节。",
|
||
"系统中英文国际化适配:完成平台核心业务界面的中英文双语切换功能开发,覆盖日常使用高频页面,"
|
||
"满足多语言使用场景。",
|
||
"APP 端功能优化:指导 APP 端完成视频推拉流控制功能开发与调试;优化无人机实时数据展示逻辑,"
|
||
"提升数据刷新实时性与页面展示效果。",
|
||
"软件著作权申报:结合平台现有功能、业务架构与技术实现,独立完成软著申报材料撰写,"
|
||
"梳理系统创新点、功能架构与应用场景。",
|
||
"AI 大模型版本升级:根据项目智能化迭代要求,将原有模型统一更新为 GPT-5.6 版本,"
|
||
"进一步提升平台智能化服务能力。",
|
||
]
|
||
for i, it in enumerate(items, 1):
|
||
add_numbered(doc, it)
|
||
|
||
add_h3(doc, "本周产出")
|
||
add_image(doc, "06_video.png", 5.5, "视频管理模块 — 批量下载 + 日志管理界面")
|
||
add_image(doc, "15_users.png", 4.0, "用户与角色管理 — 国际化覆盖")
|
||
|
||
# ---------- 第 4 周 ----------
|
||
add_h2(doc, "第 4 周(8/22 – 8/28):路由重构 + 设备参数编辑 + 定时任务")
|
||
add_h3(doc, "工作主题")
|
||
add_p(doc, "完成系统路由架构从一级到二级改造、设备参数编辑功能迭代开发与测试、定时任务功能落实。", indent_first=True)
|
||
|
||
add_h3(doc, "具体工作")
|
||
items = [
|
||
"路由架构整体优化升级:将原有一级路由改造为二级路由体系,梳理规整页面层级结构;"
|
||
"针对性修复更换路由框架带来的适配问题。",
|
||
"设备参数编辑功能迭代:完成 Web 端与 APP 端设备参数修改功能开发;新增授权机制管控参数修改权限,"
|
||
"Web 端可自定义配置设备参数可修改时长。",
|
||
"双端授权与权限控制:根据授权信息自动判断用户操作权限,实现参数编辑功能的可用性精准控制。",
|
||
"参数滑块联动与组件轻量化:实现参数滑块联动展示效果;对设备参数组件进行抽离重构,"
|
||
"新增 loading 加载状态,优化页面加载性能。",
|
||
"APP 端蓝牙模式适配:完成 APP 端蓝牙模式修改设备参数功能开发与测试,适配不同设备操作场景。",
|
||
"定时任务功能测试:完成 Web 端定时任务功能全流程测试,校验任务创建、执行、启停、周期运行等核心逻辑。",
|
||
"APP 端优化指导与测试验收:协助 APP 端完成扫码绑定设备、蓝牙/非蓝牙模式适配、"
|
||
"授权管控设备参数修改等核心功能优化与全面测试。",
|
||
]
|
||
for i, it in enumerate(items, 1):
|
||
add_numbered(doc, it)
|
||
|
||
add_h3(doc, "本周产出")
|
||
add_image(doc, "01_home.png", 5.5, "系统首页 — 二级路由重构后加载更顺畅")
|
||
add_image(doc, "03_device_status.png", 5.5, "设备状态详情 — 参数滑块 + 授权控制")
|
||
add_image(doc, "04_wayline.png", 5.0, "航线任务 — 二级路由结构下跳转清晰")
|
||
|
||
# ---------- 第 5 周 ----------
|
||
add_h2(doc, "第 5 周(8/29 – 8/31):全链路闭环测试 + 工单派发 + TodoList")
|
||
add_h3(doc, "工作主题")
|
||
add_p(doc, "完成系统全业务链路闭环测试、工单派发功能开发、TodoList 页面建设,APP 端收尾验证。", indent_first=True)
|
||
|
||
add_h3(doc, "具体工作")
|
||
items = [
|
||
"全业务链路闭环测试:完成告警、工单、任务全流程链路逻辑测试——告警触发后自动生成工单、"
|
||
"关联告警的工单完成后自动消除、设备异常可重新触发告警。",
|
||
"告警钉钉推送:支持各场站独立配置开启/关闭钉钉推送权限,实现告警消息灵活推送。",
|
||
"工单派发功能开发:新增平台工单手动派发逻辑,支持管理员将各类运维工单定向指派给指定用户,"
|
||
"完善工单分配管理机制。",
|
||
"设备参数配置功能测试:支持自定义配置设备轮胎增益系数、运行速度等核心参数,"
|
||
"页面配置逻辑与参数保存功能运行正常(待下位机联调收尾)。",
|
||
"TodoList 页面建设:完成平台 TodoList 页面搭建,统一录入待优化、待开发、待测试任务点,"
|
||
"实现任务可视化、条理化管理。",
|
||
"APP 端收尾:APP 端绝大部分测试点已完成验证,整体功能基本达标;"
|
||
"剩余约 10% 测试内容仍存在轻微问题,持续跟进排查与修复。",
|
||
]
|
||
for i, it in enumerate(items, 1):
|
||
add_numbered(doc, it)
|
||
|
||
add_h3(doc, "本周产出")
|
||
add_image(doc, "09_alerts.png", 5.5, "告警中心 — 钉钉推送 + 自动闭环")
|
||
add_image(doc, "12_workorder.png", 5.5, "工单任务 — 手动派发 + 全流程闭环")
|
||
add_image(doc, "05_robot_task.png", 4.5, "机器人任务 — 实时路径与规划路径展示")
|
||
|
||
add_page_break(doc)
|
||
|
||
# ============================================================
|
||
# 三、重点项目成果
|
||
# ============================================================
|
||
add_h1(doc, "三、重点项目成果")
|
||
|
||
add_h2(doc, "3.1 设备控制权限体系重构(核心项目)")
|
||
add_p(doc, "原「单用户单设备控制」模式存在多端抢占、权限残留、消息错乱等隐患,"
|
||
"本月将权限模型重构为「单设备单 Token 唯一占用」,从底层保证设备控制权的唯一性。",
|
||
indent_first=True, align="justify")
|
||
|
||
ach_rows = [
|
||
("权限模型", "单用户单设备", "单设备单 Token 唯一占用"),
|
||
("多端抢占", "存在冲突", "彻底解决"),
|
||
("权限残留", "偶发滞留", "路由切换即释放"),
|
||
("跨端测试", "未覆盖", "Web/APP 跨端 4 场景全闭环"),
|
||
("WS 连接", "多页面重复连接", "单页面单连接 + 自动销毁"),
|
||
("心跳堆积", "偶发", "已消除"),
|
||
]
|
||
add_data_table(doc, ["对比项", "重构前", "重构后"], ach_rows, widths=(1.8, 2.0, 2.5))
|
||
|
||
doc.add_paragraph()
|
||
|
||
add_h2(doc, "3.2 视频与日志管理模块(新建项目)")
|
||
add_p(doc, "原视频下载采用 Node 脚本实现,与平台 Java 后端技术栈不统一;日志管理缺失管理员视角。"
|
||
"本月将视频下载重构为 Java 接口,统一后端技术栈;新增日志管理模块,按权限区分展示。",
|
||
indent_first=True, align="justify")
|
||
add_bullet(doc, "视频管理:支持批量下载设备本地存储视频文件,由 Java 接口实现,统一后端技术栈。")
|
||
add_bullet(doc, "日志管理:支持管理员查看服务端运行日志,按权限区分展示,便于问题定位与运维排查。")
|
||
|
||
add_h2(doc, "3.3 路由架构二级改造(平台升级)")
|
||
add_p(doc, "为解决页面层级不清、跳转混乱的问题,本月完成路由从一级到二级架构的整体升级。",
|
||
indent_first=True, align="justify")
|
||
add_bullet(doc, "梳理页面层级结构,整体架构更清晰规范;")
|
||
add_bullet(doc, "重点优化设备总览、设备状态详情页面的路由跳转逻辑,解决跳转异常、定位不准等问题;")
|
||
add_bullet(doc, "页面访问体验与可维护性显著提升。")
|
||
|
||
add_h2(doc, "3.4 软件著作权申报")
|
||
add_p(doc, "本月独立完成软件著作权申报材料撰写,覆盖系统创新点、功能架构与应用场景,"
|
||
"并依据审核反馈持续完善。",
|
||
indent_first=True, align="justify")
|
||
ach2 = [
|
||
("软件名称", "光伏机器人环境感知服务平台"),
|
||
("软件简称", "光伏智能运维系统"),
|
||
("版本号", "V1.0"),
|
||
("源程序量", "约 53700 行"),
|
||
("主要功能", "10 大模块,701 字详述"),
|
||
("文档产出", "用户操作手册(13 章 / 16 张截图)+ 软著采集表 + SOP"),
|
||
]
|
||
add_kv_table(doc, ach2)
|
||
|
||
add_page_break(doc)
|
||
|
||
# ============================================================
|
||
# 四、代码与文档产出
|
||
# ============================================================
|
||
add_h1(doc, "四、代码与文档产出")
|
||
|
||
add_h2(doc, "4.1 月度代码提交概览")
|
||
git_rows = [
|
||
("8 月上旬", "中英文切换 / 二级路由 / 设备参数滑块 / 派单优化 / 推拉流", "17 次"),
|
||
("8 月中旬", "二级菜单 / 状态机解耦 / 文档产出 / iOS 适配 / 软著推进", "12 次"),
|
||
("8 月下旬", "MQTT 优化 / WS 时序 / 控制权限重构 / 路径联调", "13 次"),
|
||
("8 月底", "告警闭环 / 工单派发 / 钉钉推送 / TodoList / Bug 修复", "16 次"),
|
||
("合计", "—", "58 次"),
|
||
]
|
||
add_data_table(doc, ["时段", "主要方向", "提交次数"], git_rows, widths=(1.2, 4.6, 1.0))
|
||
|
||
doc.add_paragraph()
|
||
|
||
add_h2(doc, "4.2 主要文档清单")
|
||
add_bullet(doc, "《用户操作手册》——13 章 ~15 页,含 16 张页面截图(路径 / .workbuddy/gen_doc.py)")
|
||
add_bullet(doc, "《软件著作权采集表》——20 个字段全覆盖(路径 / 软著/采集表(已填写).doc)")
|
||
add_bullet(doc, "《SOP 操作文档》——Web 端路径规划完整操作流程,便于人员交接与业务落地")
|
||
add_bullet(doc, "《ios.md 技术文档》——iOS 端调试要点、适配细节、问题复盘")
|
||
add_bullet(doc, "《声网视频接入说明》——Agora 接入方式、Token 安全风险与改造建议")
|
||
add_bullet(doc, "《系统架构设计文档》——html 版,便于浏览与跨部门评审")
|
||
|
||
doc.add_paragraph()
|
||
|
||
add_h2(doc, "4.3 关键界面截图")
|
||
|
||
add_image(doc, "07_realtime.png", 5.5, "实时监控中心 — 设备控制 + 视频播放")
|
||
add_image(doc, "08_monitor.png", 5.5, "实时监控地图 — 规划路径与实时轨迹")
|
||
add_image(doc, "10_ai.png", 4.5, "AI 诊断分析 — GPT-5.6 模型支撑")
|
||
add_image(doc, "11_clean.png", 4.5, "清洗优化模块 — 业务模块适配")
|
||
add_image(doc, "13_report.png", 4.5, "报表中心 — 数据可视化")
|
||
add_image(doc, "16_roles.png", 4.5, "角色管理 — 权限精细化管控")
|
||
|
||
add_page_break(doc)
|
||
|
||
# ============================================================
|
||
# 五、工作总结与反思
|
||
# ============================================================
|
||
add_h1(doc, "五、工作总结与反思")
|
||
|
||
add_h2(doc, "5.1 本月做得好的方面")
|
||
good = [
|
||
"持续推进苏州算法联调:从 8 月初启动到 8 月底收尾,完整跑通路径规划全流程,"
|
||
"并完成现场演示保障,业务链路闭合度较高。",
|
||
"控制权限重构扎实:模型从设计、迁移到全场景测试均严格闭环,覆盖 Web/APP 双端 4 种跨端场景。",
|
||
"代码质量与可维护性提升:完成路由组件拆分、设备参数组件抽离、视频接口统一(Java 化),"
|
||
"为后续迭代打好基础。",
|
||
"文档与材料齐头并进:在迭代开发的同时,同步输出用户手册、软著材料、SOP 等关键文档,"
|
||
"沉淀团队知识资产。",
|
||
"跨端协同高效:与 APP 端保持紧密指导与测试验收节奏,确保双端业务逻辑统一、交互闭环。",
|
||
]
|
||
for g in good:
|
||
add_bullet(doc, g)
|
||
|
||
add_h2(doc, "5.2 待提升与反思")
|
||
todo = [
|
||
"设备参数配置模块:因下位机未完成全量测试,整体联调暂未完成,需在下月优先推进。",
|
||
"国际化覆盖:尚有约 1070 个 t() key 在中英文 locale 中缺失、69 个文件约 1403 行硬编码中文待处理,"
|
||
"需要分批推进。",
|
||
"APP 端收尾:仍有约 10% 测试点存在轻微问题,需持续跟进排查与修复。",
|
||
"工单自动派发:当前仅完成手动派发逻辑,自动派发策略仍需后续迭代。",
|
||
"二级路由后路径仍有抖动,地图地址接入在切换场站时偶发小问题,需进一步打磨。",
|
||
]
|
||
for t in todo:
|
||
add_bullet(doc, t)
|
||
|
||
add_page_break(doc)
|
||
|
||
# ============================================================
|
||
# 六、9 月工作计划
|
||
# ============================================================
|
||
add_h1(doc, "六、9 月工作计划")
|
||
|
||
add_p(doc, "结合本月遗留问题与项目下一阶段目标,初步拟定 9 月工作计划如下:", indent_first=True)
|
||
|
||
sep_rows = [
|
||
("设备参数全量联调", "高", "9 月上旬", "配合下位机完成设备参数配置模块全量测试闭环"),
|
||
("国际化深水区推进", "高", "9 月全月", "批量补齐约 1070 个 t() key 与 1403 行硬编码中文"),
|
||
("APP 端 10% 问题修复", "高", "9 月上旬", "完成 APP 端剩余测试点闭环,达成全量验收"),
|
||
("工单自动派发", "中", "9 月中旬", "上线自动派发策略,提升运维自动化效率"),
|
||
("视频流稳定性优化", "中", "9 月中旬", "声网重连、订阅回收、推拉流优化持续打磨"),
|
||
("软著申报推进", "中", "9 月", "根据审核意见持续完善软著材料"),
|
||
("TodoList 持续运营", "低", "9 月全月", "持续沉淀任务点,每周迭代"),
|
||
]
|
||
add_data_table(doc, ["工作计划", "优先级", "时间", "目标"], sep_rows, widths=(1.6, 0.8, 1.0, 2.9))
|
||
|
||
doc.add_paragraph()
|
||
|
||
add_p(doc, "以上为本人 2026 年 8 月工作月度报告的全部内容,请审阅。", indent_first=True, align="right",
|
||
space_after=2)
|
||
add_p(doc, "报告人:葛昀", indent_first=False, align="right", space_after=2)
|
||
add_p(doc, "日期:2026 年 9 月", indent_first=False, align="right", space_after=2)
|
||
|
||
# 保存
|
||
doc.save(OUTPUT_PATH)
|
||
print(f"OK: 生成成功 -> {OUTPUT_PATH}")
|
||
print(f"大小: {os.path.getsize(OUTPUT_PATH)} bytes") |