- 新增用户详情页,支持编辑(状态切换/密码确认)、键盘导航 - Modal/Button 拆分为独立文件,样式与 assets-ai 对齐 - LDAP 邮箱三路径同步:密码登录、SSO 免登录、批量同步接口 - 角色权限页:Badge 按角色分色、增加保存 loading、checkbox dark 样式 - API Key 页:成功提示颜色对齐、取消按钮 ghost 统一 - 全站字体/颜色一致:text-sm、dark mode 补全 - 删除确认统一改用 Modal 替换原生 confirm |
||
|---|---|---|
| .superpowers/brainstorm | ||
| public | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| Caddyfile | ||
| Dockerfile | ||
| README.md | ||
| docker-compose.yml | ||
| next-env.d.ts | ||
| next.config.ts | ||
| oa-cloud-fixed.png | ||
| oa-cloud-login.png | ||
| oa-login-current.png | ||
| oa-login-page.png | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| report-54-light.png | ||
| report-preview-53.png | ||
| tailwind.config.js | ||
| tsconfig.json | ||
README.md
IT 工单跟踪系统
基于 Next.js + SQLite 的 IT 基础设施工单跟踪管理系统,域名为 issue.tlyq.ai,用于记录和管理故障工单,支持与 assets.tlyq.ai 资产管理系统联动。
技术栈
| 分类 | 技术 |
|---|---|
| 框架 | Next.js 15 + TypeScript |
| UI | React 19 + Tailwind CSS v4 + lucide-react |
| 数据库 | SQLite(better-sqlite3,WAL 模式) |
| 认证 | JWT(cookie 方式)+ 自定义 session |
| 文档导出 | docx + ECharts + Puppeteer(图表渲染) |
功能
- 工单 CRUD(创建、编辑、删除、状态流转)
- Excel 批量导入工单
- 仪表盘统计(整体可用性、故障分类、SLA 达标率)
- 月报/周报生成(DOCX 格式,含封面、目录/图表(月报)、数据表格)
- 与 assets-ai 资产管理系统双向联动
- 用户/角色权限管理
- API Key 管理(支持服务间调用认证)
……
月报设计规则
概述
月报按自然月生成,统计当月已结单工单及跨月进行中工单,输出为 DOCX 文档。包含封面、目录及四个章节。
报告结构
| 章节 | 内容 |
|---|---|
| 封面 | 标题、时间范围、公司名称、生成月份 |
| 目录 | Word 目录域(打开后需更新域以刷新) |
| 第一章 — 总体运营概况 | GPU 服务器 / 存储服务器每日在线节点数折线图 |
| 第二章 — 运营数据总览 | 按日期 + 设备类型分组,自然语言描述故障及恢复情况 |
| 第三章 — 运营故障概览 | 故障工单表格(GPU 故障 / 存储故障 / 其他工单三类) |
| 第四章 — 服务可用性说明 | 每台设备服务可用性计算公式及百分比 |
数据采集规则
设备清单:从 assets-ai 拉取 filter_status=腾讯使用 的设备,按 filter_device_type=GPU服务器 / 存储服务器 分类,构建 business_ip → device_type 映射。
工单筛选:按 close_time 与 assign_time 双条件查询,同时覆盖当月结单工单和跨月进行中工单:
SELECT * FROM tickets WHERE (
(close_time >= periodStart AND close_time <= periodEnd + ' 23:59:59')
OR
(assign_time <= periodEnd + ' 23:59:59' AND (close_time IS NULL OR close_time > periodEnd + ' 23:59:59'))
)
ORDER BY assign_time
- 第一条件:当月内结单的工单(含上月派发本月恢复的跨月工单)
- 第二条件:当月结束时仍未结单的工单(含当月派发和上月派发的进行中工单)
- 使用
close_time比较而非current_status,保证事后补生成报告时判断不变
工单分类:按 device_ip 在设备清单中查找对应 device_type(gpu / storage / other)。
第一章规则
- 遍历当月每一天,计算当日在线节点数
- 统计范围:排除
fault_category = '无故障'或fault_subcategory = '其他'的工单("其他"工单不计入节点在线数;跨月工单如 7/31 故障 8/3 恢复正常计入,8/1、8/2 各减 1 台) - 不在线判断:
assign_time日期 ≤ 当前日期 < close_time日期- 当日发生故障次日恢复 → 发生日计入不在线,恢复日不计入
- 当日发生故障当日恢复 → 不计入不在线
- 在线 = 总节点数 - 不在线节点数
- 分别统计 GPU 和存储,生成两张 ECharts 折线图
- Y 轴动态范围:根据实际数据波动自动调整 min/max/interval,避免总节点数较大时微小变化无法分辨
- 无波动时 Y 轴范围 = total ± 2
- 有波动时根据实际最值加 buffer,确保 8~15 个刻度
- 报告预览"无故障天数"与 DOCX 图表计算方式不同:
- 预览:按故障完整日期范围(
assign ~ close,含 close 当天)计算,当日恢复也计入故障天数 - DOCX 图表:按
assign ≤ date < close计算,当日恢复不计入离线节点
- 预览:按故障完整日期范围(
第二章规则
- 仅统计 GPU / 存储工单,排除
fault_category = '无故障'或fault_subcategory = '其他' - 按
device_type + assign_time日期分组 - 每条格式:
X月X日发生1次<故障子类>,故障节点为<IP>,<恢复描述>。 - 恢复描述:
- 已结单:
assign_date与close_date天数差,0 → 当日,1 → 次日,≥2 → N日后 - 进行中:固定显示
处理中。(不含恢复描述)
- 已结单:
第三章规则
分流逻辑:
| 条件 | 归类 |
|---|---|
fault_subcategory = '其他' |
其他工单 |
fault_subcategory ≠ '其他' 且 device_type 为 gpu |
GPU 故障 |
fault_subcategory ≠ '其他' 且 device_type 为 storage |
存储故障 |
fault_subcategory ≠ '其他' 且 device_type 为 other |
其他工单 |
GPU/存储故障表(7 列):
| 列 | 来源 | 进行中工单 |
|---|---|---|
| 工单编号 | ticket_id |
正常显示 |
| 故障节点 | device_ip |
正常显示 |
| 故障日期 | assign_time(完整时间,精确到秒) |
正常显示 |
| 故障问题 | fault_subcategory |
正常显示 |
| 故障原因 | parts_name 有值 → 更换{parts_name},否则 → - |
正常显示 |
| 处理时长(分钟) | duration_minutes(已结单) |
显示 进行中 |
| 是否计入 SLA | 见下方 SLA 规则 | 显示 — |
其他工单表(7 列):
| 列 | 来源 | 进行中工单 |
|---|---|---|
| 工单编号 | ticket_id |
正常显示 |
| 设备 IP 地址 | device_ip |
正常显示 |
| 工单日期 | assign_time(完整时间,精确到秒) |
正常显示 |
| 工单内容 | content |
正常显示 |
| 工单结论 | conclusion |
正常显示 |
| 处理时长(分钟) | duration_minutes(已结单) |
显示 进行中 |
| 是否计入 SLA | 见下方 SLA 规则 | 显示 — |
第四章规则
- 排除
fault_category = '无故障'的工单 - 按 device_ip 分组求和故障时长:
- 已结单工单:使用实际
duration_minutes - 进行中工单:仅计算本月内部分,时长 =
(min(assign_date, 月初) → 月末最后一天) × 24 × 60分钟
- 已结单工单:使用实际
- 公式:
可用性 = (monthDays × 24 × 60 - totalDurationMinutes) / (monthDays × 24 × 60) × 100 - monthDays 为当月实际天数(动态计算)
- 百分比 < 99% 时,该值以黄底红字加粗标记
- 百分比 ≥ 99% 时,正常样式
- 该 IP 存在进行中工单时,公式后追加橙色标注
(故障处理中,仅计本月部分)
SLA 判定规则
是否计入SLA 字段判定逻辑:
IF availability IS NULL OR availability >= 0.99 → 否
IF availability < 0.99 AND conclusion 包含 "无异常" → 否
IF availability < 0.99 AND conclusion 不包含 "无异常" → 是
排版规范
| 元素 | 字体 | 字号 | 行距 | 其他 |
|---|---|---|---|---|
| 封面标题 | SimHei(黑体) | 22pt / 26pt | 1.5x | 居中 |
| 章标题(Heading 1) | SimSun | 14pt | 1.5x | 加粗 |
| 节标题(Heading 2) | SimSun | 12pt | 1.5x | 加粗 |
| 正文 | SimSun | 11pt | 1.5x | 首行缩进 2 字符 |
| 表格表头 | SimSun | 10pt | 1.5x | 蓝底白字加粗 |
| 表格内容 | SimSun | 9pt | 1.15x | 垂直居中 |
| 目录 TOC1/TOC2 | SimSun | 11pt | 1.5x | — |
周报设计规则
概述
周报按自然周(周一至周日)生成,统计当周活跃工单(含处理中和已结单),输出为 DOCX 文档。包含封面及四个章节,不含目录和图表。
报告结构
| 章节 | 内容 |
|---|---|
| 封面 | 标题、报告周期、生成时间、公司名称 |
| 一、总体运营概况 | GPU/存储服务器总数 + 本周故障摘要 + 每日在线节点数表格 |
| 二、GPU 服务器故障 | 故障概况表 + 已恢复工单的故障详情表 |
| 三、存储服务器故障 | 故障概况表 + 已恢复工单的故障详情表 |
| 四、其他工单 | 工单概况表 + 已恢复工单的工单详情表 |
数据采集规则
设备清单:与月报相同,从 assets-ai 拉取 GPU/存储设备,构建 IP → device_type 映射。
工单筛选:按周期内活跃度查询,含处理中工单(区别于月报仅统计已结单):
-- 周期内结单的工单,或周期内仍在处理中的工单
(close_time >= periodStart AND close_time <= periodEnd + ' 23:59:59')
OR
(assign_time <= periodEnd + ' 23:59:59' AND (current_status NOT IN ('resolved','closed') OR close_time > periodEnd + ' 23:59:59'))
工单分类(三路分流):
| 条件 | 归类 |
|---|---|
ticket_type = 'OEM维修' 且 fault_category ≠ '无故障' 且 device_type = gpu |
GPU 服务器故障 |
ticket_type = 'OEM维修' 且 fault_category ≠ '无故障' 且 device_type = storage |
存储服务器故障 |
ticket_type = 'OEM诊断' 或(ticket_type = 'OEM维修' 且 fault_category = '无故障') |
其他工单 |
第一章规则(总体运营概况)
1.1 本周概览:展示 GPU/存储服务器总数,本周故障次数及恢复/处理中数量。
1.2 / 1.3 每日运行状态表:遍历周期内每一天,计算当日在线节点数。
- 不在线判断:
assign_time日期 ≤ 当前日期 < close_time日期(与月报逻辑一致) - 当日有故障节点时:日期/在线数/故障数三列纵向合并,最后一列逐行列出故障 IP
- 当日无故障时:单行显示,故障 IP 列填
/ - 在线 = 总节点数 - 不在线节点数
第二/三/四章规则(故障详情)
故障概况表(5 列):
| 列 | 来源 | 列宽 |
|---|---|---|
| 工单号 | ticketNo |
15%(2.41cm) |
| 设备 IP | deviceIp |
15%(2.41cm) |
| 工单内容 | content 或 faultSubcategory |
40%(6.29cm) |
| 工单时间 | assignTime |
15%(2.41cm) |
| 目前状态 | 已恢复 / 处理中 | 15%(2.41cm) |
故障详情表(4 列,仅已恢复工单展示):
- 基本信息区:工单号、设备 IP、工单内容(3 列合并)、派单/结单时间
- 工单流程区:第一列纵向合并为「工单流程」标签,后三列为时间节点、发现人/处理人、处理过程/处理结果
- 若 steps 中无「下发工单」步骤,自动补一行
- 若 steps 中无「结单」步骤,自动补一行
- 工单结论区:标签 + 结论文字(3 列合并,居中)
表格列宽实现
故障概况表采用 DXA 绝对值 + 固定布局 方式确保列宽精确:
// 15:15:40:15:15 比例换算 DXA(A4 内容宽度 9026 DXA)
const colDxa = [1354, 1354, 3610, 1354, 1354]
new Table({
width: { size: 9026, type: WidthType.DXA },
columnWidths: colDxa,
layout: TableLayoutType.FIXED, // 关键:禁止 Word 自动调整列宽
rows: [...],
})
每个单元格必须同时设置 width: { size: colDxa[i], type: WidthType.DXA },确保 gridCol、表头 tcW、数据 tcW 三者值完全一致。
与月报的关键差异
| 维度 | 月报 | 周报 |
|---|---|---|
| 统计范围 | 自然月,仅已结单 | 自然周(周一~周日),含处理中 |
| 目录 | 有(TOC 域) | 无 |
| 图表 | ECharts 折线图(第一章) | 无(纯表格) |
| 服务可用性 | 第四章 SLA 计算 | 无 |
| 故障详情展开 | 无(仅概况表) | 有(完整工单流程时间线) |
| 表格布局 | 百分比自适应 | DXA 固定列宽 + Fixed Layout |