issue-ai/README.md

239 lines
9.7 KiB
Markdown
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.

# IT 工单跟踪系统
基于 Next.js + SQLite 的 IT 基础设施工单跟踪管理系统,域名为 `issue.tlyq.ai`,用于记录和管理故障工单,支持与 [assets.tlyq.ai](https://assets.tlyq.ai) 资产管理系统联动。
## 技术栈
| 分类 | 技术 |
|------|------|
| 框架 | Next.js 15 + TypeScript |
| UI | React 19 + Tailwind CSS v4 + lucide-react |
| 数据库 | SQLitebetter-sqlite3WAL 模式) |
| 认证 | JWTcookie 方式)+ 自定义 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` 范围查询monthly report 统计当月结单),条件:
```sql
close_time >= periodStart AND close_time <= periodEnd + ' 23:59:59'
AND current_status IN ('resolved', 'closed')
AND duration_minutes IS NOT NULL
ORDER BY assign_time
```
**工单分类**:按 device_ip 在设备清单中查找对应 device_typegpu / storage / other
### 第一章规则
- 遍历当月每一天,计算当日在线节点数
- **统计范围**:排除 `fault_category = '无故障'` 的工单(跨月工单如 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 个刻度
### 第二章规则
- 仅统计 GPU / 存储工单排除 `fault_category = '无故障'`
- `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`
- 公式:`可用性 = (monthDays × 24 × 60 - totalDurationMinutes) / (monthDays × 24 × 60) × 100`
- monthDays 为当月实际天数(动态计算)
- 百分比 **< 99%** 该值以黄底红字加粗标记
- 百分比 ** 99%** 正常样式
### 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 映射
**工单筛选**按周期内活跃度查询含处理中工单区别于月报仅统计已结单
```sql
-- 周期内结单的工单,或周期内仍在处理中的工单
(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 绝对值 + 固定布局** 方式确保列宽精确
```typescript
// 15:15:40:15:15 比例换算 DXAA4 内容宽度 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 |