docs: 初始化项目设计文档库

包含: 项目需求文档、数据库设计、前端全局规范、13模块功能清单(管理后台+大屏)

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
main
haoliang 1 week ago
commit 16643a2d08

35
.gitignore vendored

@ -0,0 +1,35 @@
# Dependencies
node_modules/
# Build output
dist/
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
Thumbs.db
.DS_Store
# Local config
.sisyphus/
.playwright-mcp/
# Screenshots (temp)
*.png
!docs/**/*.png
# Logs
*.log
npm-debug.log*
# Environment
.env
.env.local
.env.*.local
# TypeScript cache
*.tsbuildinfo

@ -0,0 +1,116 @@
# 项目知识库
**生成时间:** 2026-04-25
**项目:** CNC机床数据采集系统
## 概述
多品牌CNC机床统一化数据采集系统的产品设计文档库。技术栈Vue3前端 + ASP.NET Web API 2后端 + Windows Service采集服务 + MariaDB数据库。本地IIS部署局域网场景。
## 项目结构
```
.
├── docs/ # 全部设计文档
│ ├── 00-需求与设计文档.md # 核心需求、架构决策、技术选型
│ ├── 01-数据库设计.md # 双库设计(业务库+日志库)17张表DDL
│ ├── 02-功能清单/ # 按模块拆分的功能清单
│ │ ├── 02-文件夹创建规范.md # ⚠️ 文档结构规范,新增模块必读
│ │ ├── 02-前端全局规范.md # 前端全局规范+CRUD必填项+模块进度+工程开发规范
│ │ ├── 03-界面变更执行规范.md # ⚠️ AI助手执行界面变更时必读
│ │ ├── 大屏/ # 大屏看板模块
│ │ └── 管理后台/ # 12个子模块登录/仪表盘/设备/品牌/采集地址/员工/产量/告警/系统/车间/操作日志/大屏配置)
│ └── ...
├── frontend/ # 前端工程Vue3+Vite+TypeScript+Element Plus
│ ├── mock/ # Mock数据定义按模块拆分
│ ├── src/ # 源码(路由/组件/样式/类型)
│ └── vite.config.ts # Vite配置mock插件+proxy
└── 发那科系统采集示例.txt # FANUC品牌采集JSON样例数据
```
## 查找指南
| 需求 | 位置 | 备注 |
|------|------|------|
| 了解项目背景/架构决策 | `docs/00-需求与设计文档.md` | 核心文档,所有已确认决策在此 |
| 查看数据库表结构 | `docs/01-数据库设计.md` | 668行含完整DDL+字段说明 |
| 前端页面交互设计 | `docs/02-前端全局规范.md` | 全局组件规范+CRUD必填项+模块进度+工程开发规范 |
| 前端工程开发规范 | `docs/02-前端全局规范.md` → 前端工程开发规范章节 | 技术栈/Mock方案/目录结构/CSS规范 |
| 新增功能模块文档 | `docs/02-功能清单/02-文件夹创建规范.md` | 目录结构/命名/内容模板规范 |
| AI助手执行界面变更 | `docs/02-功能清单/03-界面变更执行规范.md` | ⚠️ 必读:最小必读文件+变更清单+联动同步规则 |
| 品牌采集数据格式 | `发那科系统采集示例.txt` | FANUC品牌JSON结构示例 |
| 管理后台某模块设计 | `docs/02-功能清单/管理后台/{编号}-{模块名}/` | 每模块含索引+规范+页面文件 |
| 大屏看板设计 | `docs/02-功能清单/大屏/` | 索引+规范+页面 |
## 文档规范
### 文件命名规则(必须遵循)
- 索引文件:`00-{名称}-索引.md`
- 规范文件:`01-{名称}-规范.md`
- 页面文件:`{模块号}-{页面号}-{页面名}.md`(如 `03-01-设备列表页面.md`
- 模块编号:两位数 01-99
### 三种文件分工
| 文件类型 | 内容重点 |
|---------|---------|
| 索引文件 | 功能逻辑、交互关系、路由跳转、状态机 |
| 规范文件 | 技术规范(组件、校验、布局、安全) |
| 页面文件 | 技术实现界面布局、字段定义、Mock数据 |
### 页面文件20项模板
结构定义(1-6) → 交互行为(7-12,14-15) → 技术实现(13,16-20)
详见 `docs/02-功能清单/02-文件夹创建规范.md` 第五节
## 核心业务规则
- **采集模式**HTTP拉取JSON非直连机床地址间并行、地址内串行
- **零件计数**NC程序名切换时结账上一段新程序从0开始同程序名多次出现分段记录
- **双库分离**:业务库 `cnc_business` + 日志库 `cnc_log`原始JSON存日志库解析后存业务库
- **时间标准**:以服务器时间为准
- **品牌映射**:管理后台可视化配置,修改不回溯历史数据
## 前端全局规范摘要
- 组件库Element Plus
- API响应格式`{ code: 0, message: "success", data: ... }`
- 分页默认page-sizes=[20,50,100]
- 写操作防重复loading+disabled+requestLock+axios 500ms去重
- API超时30秒
- 删除确认:`确定删除【{name}】?此操作不可恢复。`
- Layout顶部栏(系统名+管理员下拉) + 侧边栏(200px可折叠+10个菜单项) + 内容区
- 路由守卫有Token访问/login重定向/dashboard无Token访问管理后台重定向/login
## 待设计模块
- API接口设计后置界面全部确认后启动
- 采集服务核心逻辑设计(后置,界面全部确认后启动)
- 前端管理后台设计(✅ 已完成,见 `02-前端全局规范.md` + `02-功能清单/管理后台/`
- 大屏看板设计(✅ 已完成,见 `02-功能清单/大屏/`
## 强制要求(必须遵守)
- **思考过程使用中文**所有AI助手的推理、分析、思考过程必须使用中文输出
- **控制台输出中文**:所有控制台输出、日志、提示信息使用中文,不得出现乱码
- **所有文档使用中文**:项目内所有文档、注释、界面文案使用中文
- **PowerShell中文编码修复每次会话必须执行**PowerShell 5.1默认OutputEncoding为GB2312中文路径/文件名输出会乱码。在执行任何涉及中文路径的PowerShell命令前必须先设置编码
```powershell
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
```
- **文件写入编码规范**
- 禁止使用PowerShell `Out-File -Encoding utf8` 写入文件会产生UTF-8 with BOM + CRLF
- 使用Node.js `fs.writeFileSync(path, content, 'utf8')` 写入文件无BOM、LF换行
- 或使用Write/Edit工具直接写入无BOM、LF换行
- 如必须用PowerShell写入需用 `[System.IO.File]::WriteAllText($path, $content, [System.Text.UTF8Encoding]::new($false))` 避免BOM
- 已有BOM文件修复`node -e "const fs=require('fs');let b=fs.readFileSync('文件路径');if(b[0]===0xEF&&b[1]===0xBB&&b[2]===0xBF)b=b.slice(3);let t=b.toString('utf8').replace(/\r\n/g,'\n');fs.writeFileSync('文件路径',t,'utf8')"`
## 注意事项
- 部分索引/规范文件内容为空(尚未填写)→ 已全部填写
- 数据库设计为草案状态(状态:草案),界面确认后定稿
- 前端界面设计全部完成(2026-04-26)13个模块16个页面均已设计
- 品牌预置FANUC已预置其他品牌手动添加

@ -0,0 +1,62 @@
# CNC机床数据采集系统 - 文档进度总览
> 最后更新2026-04-26
---
## 状态说明
| 标记 | 含义 |
|------|------|
| ✅ 已确认 | 决策冻结,可作为开发依据 |
| 📋 草案 | 初始设计完成,待界面确认后定稿 |
| 🔄 设计中 | 内容已有但尚未确认,可能调整 |
| ✅ 已设计 | 功能清单已完成,待开发 |
| ⬜ 待设计 | 目录/文件已创建,内容待填写 |
| ⬜ 未创建 | 文件尚未创建 |
---
## 核心设计文档
| 文档 | 状态 | 最后更新 | 备注 |
|------|------|---------|------|
| [00-需求与设计文档](./00-需求与设计文档.md) | ✅ 已确认 | 2026-04-23 | 核心决策已冻结,待设计模块列表已过时 |
| [01-数据库设计](./01-数据库设计.md) | 📋 草案 | 2026-04-25 | 界面设计确认后定稿,允许根据界面需求调整 |
| [02-前端全局规范](./02-前端全局规范.md) | 🔄 设计中 | 2026-04-26 | 全局规范+Layout+路由总表已定,所有管理后台+大屏页面设计完成 |
---
## 前端功能清单(管理后台)
| 模块 | 页面文件 | 索引文件 | 设计状态 | 最后更新 |
|------|---------|---------|---------|---------|
| 01-登录 | 01-01-登录页面.md | 00-登录-索引.md | ✅ 已设计 | 2026-04-25 |
| 02-仪表盘 | 02-01-仪表盘页面.md | 00-仪表盘-索引.md | ✅ 已设计 | 2026-04-25 |
| 03-设备管理 | 03-01/03-02 | 00-设备管理-索引.md | ✅ 已设计 | 2026-04-25 |
| 04-品牌模板 | 04-01/04-02 | 00-品牌模板-索引.md | ✅ 已设计 | 2026-04-25 |
| 05-采集地址 | 05-01/05-02 | 00-采集地址-索引.md | ✅ 已设计 | 2026-04-25 |
| 06-员工管理 | 06-01/06-02 | 00-员工管理-索引.md | ✅ 已设计 | 2026-04-26 |
| 07-产量报表 | 07-01-产量报表页面.md | 00-产量报表-索引.md | ✅ 已设计 | 2026-04-26 |
| 08-告警中心 | 08-01-告警中心页面.md | 00-告警中心-索引.md | ✅ 已设计 | 2026-04-26 |
| 09-系统设置 | 09-01-系统设置页面.md | 00-系统设置-索引.md | ✅ 已设计 | 2026-04-26 |
| 10-车间管理 | 10-01-车间管理页面.md | 00-车间管理-索引.md | 🔀 已合并 | 2026-04-25 | 合并至09-系统设置 |
| 11-操作日志 | 11-01-操作日志页面.md | 00-操作日志-索引.md | ✅ 已设计 | 2026-04-26 |
| 12-大屏配置 | 12-01-大屏配置页面.md | 00-大屏配置-索引.md | ✅ 已设计 | 2026-04-25 | |
---
## 前端功能清单(大屏)
| 模块 | 页面文件 | 索引文件 | 设计状态 | 最后更新 |
|------|---------|---------|---------|---------|
| 大屏看板 | 01-01-大屏看板页面.md | 00-大屏-索引.md | ✅ 已设计 | 2026-04-26 |
---
## 待创建文档
| 文档 | 优先级 | 状态 | 说明 |
|------|--------|------|------|
| API接口设计 | P0 | 🔜 后置 | 待界面设计全部确认后启动 |
| 采集服务核心逻辑设计 | P1 | 🔜 后置 | 待界面设计全部确认后启动 |

@ -0,0 +1,133 @@
# CNC机床数据采集系统 - 需求与设计文档
> 最后更新2026-04-23
> 状态设计中数据库设计已确认API/前端/采集服务待设计)
---
## 一、项目概述
本系统用于对多台不同品牌CNC机床进行统一化、分布式、自动化数据采集实现设备状态监控、零件产量自动统计、加工过程分析、人员与设备绑定管理并通过BI大屏实时展示生产数据。
系统本地IIS部署MariaDB数据库业务库+日志库双库分离),单角色管理模式。
---
## 二、技术栈
| 层 | 技术 | 说明 |
|----|------|------|
| 前端 | Vue3 | 管理后台 + 大屏看板 |
| 后端 | ASP.NET Web API 2 (.NET Framework 4.5+) | REST API |
| 采集服务 | Windows Service (.NET Framework 4.5+) | 定时采集+数据处理 |
| 数据库 | MariaDB 10.6+ | 业务库 + 日志库 |
| 部署 | Windows Server + IIS | 局域网,同站点 |
---
## 三、系统架构
[见附图:架构图]
核心组件:
- Windows Service (CncCollector)定时拉取HTTP数据字段映射解析零件数增量计算日终汇总心跳上报
- MariaDB业务库(cnc_business) + 日志库(cnc_log)
- IIS Web API 2/api/admin/** Token认证/api/screen/** 免认证
- Vue3前端管理后台(/) + 大屏(/screen)
---
## 四、已确认的核心需求与决策
### 4.1 采集架构
| 决策 | 结论 |
|------|------|
| 采集模式 | 系统定时从一个HTTP地址拉取JSON数据非直连机床 |
| 采集地址 | 多个采集地址,每个地址关联品牌+选择要采的机床列表URL和间隔配在地址级 |
| 采集间隔 | 配置在采集地址级别,同地址统一间隔 |
| 采集并发 | 地址间并行,地址内串行 |
| Ping前置 | Ping通才采集Ping结果=在线状态 |
| 采集失败 | 自动重试3次间隔30秒连续5次失败记告警 |
| 采集认证 | HTTP采集地址无需认证 |
| 新设备发现 | 采集到未知device时记录告警不自动创建 |
### 4.2 数据格式
| 决策 | 结论 |
|------|------|
| 顶层结构 | 所有品牌统一JSON数组每台设备含device、desc、tags |
| 字段定位 | 通过tags数组中id匹配定位关键字段 |
| 字段映射 | 管理后台可视化配置品牌字段映射,实时生效不改代码 |
| device映射 | 机床表配置device_code采集时用device值匹配 |
| 原始数据 | 存原始JSON到日志库解析后结构化数据存业务库 |
| 时间标准 | 以服务器时间为准,机床时间仅存为参考字段 |
| 数值处理 | 自动去除.00000尾缀,转换为数值/字符串 |
### 4.3 零件产量统计
| 决策 | 结论 |
|------|------|
| 零件识别 | NC程序名Tag5作为零件唯一识别 |
| 计数方式 | CNC切换加工零件时NC程序名变更+零件数清零 |
| 产量计算 | 程序切换时结账上一段零件数新程序从0开始 |
| A-B-C-A-B | 同程序名多次出现,产量分段记录,日汇总时合并 |
| 手动清零 | 同程序下part_count下降视为手动清零结账前值后从0重计 |
| 设备重启 | 确认不清零零件数 |
| 跨天处理 | 零点后数据归属第二天,有问题后台手工调 |
| 日终汇总 | 按自然天汇总过0点后自动汇总前一天汇总时间后台可配 |
| 未开机机床 | 日汇总插0产量记录 |
| 采集失败机床 | Ping通但采集失败标记数据缺失前端显示-而非0 |
### 4.4 班次与工人
| 决策 | 结论 |
|------|------|
| 班次 | v1不支持班次按自然天+固定绑定汇总 |
| 工人-机床 | 固定绑定,一台机床只绑一个工人 |
| 工人归属 | 工人不归属车间 |
### 4.5 管理与监控
| 决策 | 结论 |
|------|------|
| 采集服务通信 | 心跳写DB + 轻量HTTP管理API启停控制 |
| 配置热更新 | 轮询DB每30秒+ 管理操作后API通知双保险 |
| 采集服务自恢复 | 每个采集地址任务独立线程,崩了不影响其他,自动重启间隔递增 |
| DB断连处理 | 本地文件缓存+自动补写 |
| 采集服务API认证 | 加服务间API Key配置文件中写死 |
| 手工调整产量 | 管理后台修正功能+审计日志 |
| 模板修改 | 不回溯历史数据,修改时弹提醒 |
### 4.6 前端与认证
| 决策 | 结论 |
|------|------|
| API认证 | /api/admin/** Token认证/api/screen/** 免认证 |
| 管理后台 | PC端Vue3 |
| 大屏 | Chrome无人值守提供全屏按钮免认证 |
| 大屏可配置 | 固定布局+卡片指标可配+筛选可配+图表类型可选 |
| Vue3部署 | 同IIS站点无跨域问题 |
| Excel导出 | EPPlus |
### 4.7 系统运维
| 决策 | 结论 |
|------|------|
| 日志轮转 | 按日期切割,保留天数在管理后台配置 |
| DB备份 | 每日自动全量+binlog增量保留30天需检查binlog是否开启 |
| 分区维护 | 按月创建新分区+删除过期分区 |
| 品牌预置 | 预置FANUC品牌模板其他手动添加 |
| 告警通知 | v1只做管理后台内告警列表+标记已处理,不做推送 |
| 机床停用 | 软删除(is_enabled),保留历史数据 |
---
## 五、待设计模块
> 以下模块尚未展开设计,待后续讨论确认:
- 5.1 API接口设计
- 5.2 采集服务核心逻辑设计
- 5.3 前端管理后台设计
- 5.4 大屏看板设计

@ -0,0 +1,668 @@
# CNC机床数据采集系统 - 数据库设计文档
> 最后更新2026-04-25
> 状态:草案(界面设计确认后定稿,允许根据界面需求调整表结构)
---
## 一、数据库架构
- **业务库**cnc_business
- **日志库**cnc_log
- **引擎**InnoDB字符集 utf8mb4排序 utf8mb4_unicode_ci
- **分区策略**:高写入表按月分区,定期创建新分区+删除过期分区
---
## 二、业务库 cnc_business17张表
### 2.1 车间表 cnc_workshop
``sql
CREATE TABLE cnc_workshop (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE,
sort_order INT NOT NULL DEFAULT 0,
is_enabled TINYINT(1) NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车间表';
``
无额外索引。3个车间数据量极小主键足够。
---
### 2.2 品牌模板表 cnc_brand
``sql
CREATE TABLE cnc_brand (
id INT AUTO_INCREMENT PRIMARY KEY,
brand_name VARCHAR(50) NOT NULL UNIQUE,
device_field VARCHAR(50) NOT NULL DEFAULT 'device',
tags_path VARCHAR(100) NOT NULL DEFAULT 'tags',
is_enabled TINYINT(1) NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='CNC品牌模板表';
``
所有品牌顶层结构统一device_field和tags_path默认值覆盖绝大多数品牌。品牌数量少无额外索引。
---
### 2.3 品牌字段映射表 cnc_brand_field_mapping
``sql
CREATE TABLE cnc_brand_field_mapping (
id INT AUTO_INCREMENT PRIMARY KEY,
brand_id INT NOT NULL,
standard_field VARCHAR(50) NOT NULL,
field_name VARCHAR(50) NOT NULL,
match_by VARCHAR(20) NOT NULL DEFAULT 'id',
data_type VARCHAR(20) NOT NULL DEFAULT 'string',
is_required TINYINT(1) NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (brand_id) REFERENCES cnc_brand(id) ON DELETE CASCADE,
UNIQUE KEY uk_brand_standard (brand_id, standard_field)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='品牌字段映射表';
``
**标准字段约定**(代码层面,不建表):
| standard_field | 含义 | data_type |
|----------------|------|-----------|
| program_name | NC程序名 | string |
| part_count | 当前加工零件数 | number |
| device_status | 设备状态 | number |
| run_status | 运行状态 | number |
| operate_mode | 操作模式 | number |
| spindle_speed_set | 主轴设定速度 | number |
| feed_speed_set | 进给设定速度 | number |
| spindle_speed_actual | 主轴实际速度 | number |
| feed_speed_actual | 进给实际转速 | number |
| spindle_load | 主轴负载 | number |
| spindle_override | 主轴倍率 | number |
| power_on_time | 开机时间 | number |
| run_time | 运行时间 | number |
| cutting_time | 切削时间 | number |
| cycle_time | 循环时间 | number |
| machining_status | 加工状态 | string |
索引uk_brand_standard唯一约束同时作为索引保证同一品牌下标准字段不重复采集时按brand_id查询所有映射规则。
---
### 2.4 采集地址表 cnc_collect_address
``sql
CREATE TABLE cnc_collect_address (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
url VARCHAR(500) NOT NULL,
brand_id INT NOT NULL,
collect_interval INT NOT NULL DEFAULT 30,
is_enabled TINYINT(1) NOT NULL DEFAULT 1,
last_collect_time DATETIME NULL,
last_collect_status VARCHAR(20) NULL,
fail_count INT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (brand_id) REFERENCES cnc_brand(id),
INDEX idx_brand (brand_id),
INDEX idx_enabled (is_enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采集地址表';
``
索引idx_brand用于采集服务按品牌加载地址列表idx_enabled用于只查启用的地址。last_collect_time/status/fail_count由采集服务实时更新大屏和管理后台直接查此表显示采集状态。
---
### 2.5 机床表 cnc_machine
``sql
CREATE TABLE cnc_machine (
id INT AUTO_INCREMENT PRIMARY KEY,
device_code VARCHAR(100) NOT NULL,
name VARCHAR(100) NOT NULL,
workshop_id INT NOT NULL,
collect_address_id INT NOT NULL,
ip_address VARCHAR(50) NOT NULL,
brand_id INT NOT NULL,
is_enabled TINYINT(1) NOT NULL DEFAULT 1,
is_online TINYINT(1) NOT NULL DEFAULT 0,
last_ping_time DATETIME NULL,
last_collect_time DATETIME NULL,
last_device_status VARCHAR(20) NULL,
last_run_status VARCHAR(20) NULL,
last_program_name VARCHAR(200) NULL,
last_part_count DECIMAL(15,5) NULL,
last_operate_mode VARCHAR(20) NULL,
last_machining_status VARCHAR(20) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (workshop_id) REFERENCES cnc_workshop(id),
FOREIGN KEY (collect_address_id) REFERENCES cnc_collect_address(id),
FOREIGN KEY (brand_id) REFERENCES cnc_brand(id),
UNIQUE KEY uk_device_code (device_code),
INDEX idx_workshop (workshop_id),
INDEX idx_collect_address (collect_address_id),
INDEX idx_enabled_online (is_enabled, is_online),
INDEX idx_enabled_address (is_enabled, collect_address_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='CNC机床表';
``
索引设计:
- uk_device_code采集时用device值匹配机床唯一约束防重复
- idx_workshop按车间筛选机床
- idx_enabled_online大屏查在线+可用机床列表,高频查询
- idx_enabled_address采集服务按地址查启用的机床列表
实时状态字段故意冗余到机床表大屏和首页查询只读此表不JOIN采集记录表避免高频查询大表。
---
### 2.6 工人表 cnc_worker
``sql
CREATE TABLE cnc_worker (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
code VARCHAR(50) NOT NULL UNIQUE,
is_enabled TINYINT(1) NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工人表';
``
工人不归属车间。uk_code覆盖工号查询。
---
### 2.7 工人-机床绑定表 cnc_worker_machine
``sql
CREATE TABLE cnc_worker_machine (
id INT AUTO_INCREMENT PRIMARY KEY,
worker_id INT NOT NULL,
machine_id INT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (worker_id) REFERENCES cnc_worker(id) ON DELETE CASCADE,
FOREIGN KEY (machine_id) REFERENCES cnc_machine(id) ON DELETE CASCADE,
UNIQUE KEY uk_machine (machine_id),
INDEX idx_worker (worker_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工人-机床绑定表';
``
索引uk_machine保证一对一绑定同时作为按机床查工人的索引idx_worker用于按工人查机床列表。
---
### 2.8 采集结构化记录表 cnc_collect_record按月分区高频写入
``sql
CREATE TABLE cnc_collect_record (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
machine_id INT NOT NULL,
collect_time DATETIME NOT NULL,
device_time DATETIME NULL,
program_name VARCHAR(200) NULL,
part_count DECIMAL(15,5) NULL,
device_status VARCHAR(20) NULL,
run_status VARCHAR(20) NULL,
operate_mode VARCHAR(20) NULL,
spindle_speed_set DECIMAL(15,5) NULL,
feed_speed_set DECIMAL(15,5) NULL,
spindle_speed_actual DECIMAL(15,5) NULL,
feed_speed_actual DECIMAL(15,5) NULL,
spindle_load DECIMAL(15,5) NULL,
spindle_override DECIMAL(5,2) NULL,
power_on_time DECIMAL(15,2) NULL,
run_time DECIMAL(15,2) NULL,
cutting_time DECIMAL(15,2) NULL,
cycle_time DECIMAL(15,2) NULL,
machining_status VARCHAR(20) NULL,
extra_data JSON NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (machine_id) REFERENCES cnc_machine(id),
INDEX idx_machine_time (machine_id, collect_time),
INDEX idx_collect_time (collect_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='采集结构化记录表按月分区90天自动清理'
PARTITION BY RANGE (TO_DAYS(collect_time)) (
PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')),
PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01')),
PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
``
索引设计:
- idx_machine_time最核心索引覆盖查某台机床某时间段采集数据报表、趋势图、日汇总计算
- idx_collect_time覆盖查某个时间点所有机床数据全局状态快照
分区策略按月分区删除过期数据只需DROP PARTITION避免DELETE大量行导致锁表和碎片。
数据量估算160台 x 每天约2000条 = 32万/天90天约2900万行。分区后单分区约300万行。
---
### 2.9 产量分段记录表 cnc_production_segment
``sql
CREATE TABLE cnc_production_segment (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
machine_id INT NOT NULL,
program_name VARCHAR(200) NOT NULL,
production_date DATE NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME NULL,
start_part_count DECIMAL(15,5) NOT NULL,
end_part_count DECIMAL(15,5) NULL,
quantity DECIMAL(15,5) NULL,
is_settled TINYINT(1) NOT NULL DEFAULT 0,
close_reason VARCHAR(30) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (machine_id) REFERENCES cnc_machine(id),
INDEX idx_machine_date (machine_id, production_date),
INDEX idx_machine_date_program (machine_id, production_date, program_name),
INDEX idx_active (machine_id, is_settled, end_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产量分段记录表';
``
核心逻辑:每次采集检测到以下情况时结账当前段并开新段:
1. NC程序名变化 -> close_reason = 'program_change'
2. 同程序下part_count下降 -> close_reason = 'manual_reset'
3. 日终汇总时仍在运行 -> close_reason = 'end_of_day'
4. 采集服务停止时 -> close_reason = 'service_stop'
A-B-C-A-B场景程序A第二次出现时创建新的段记录日汇总按(machine_id, production_date, program_name)合并。
索引设计:
- idx_machine_date日汇总计算时查某台机床某天的所有段
- idx_machine_date_program查某台机床某天某个程序的所有段合并计算
- idx_active采集服务运行时快速查找当前活跃段is_settled=0, end_time IS NULL
---
### 2.10 机床日状态表 cnc_machine_daily_status
``sql
CREATE TABLE cnc_machine_daily_status (
id INT AUTO_INCREMENT PRIMARY KEY,
machine_id INT NOT NULL,
production_date DATE NOT NULL,
data_status VARCHAR(20) NOT NULL DEFAULT 'normal',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (machine_id) REFERENCES cnc_machine(id),
UNIQUE KEY uk_machine_date (machine_id, production_date),
INDEX idx_date_status (production_date, data_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='机床日状态表';
``
data_status规则
- normal当天至少成功采集过一次
- offline当天从未Ping通产量=0
- data_missingPing通但采集始终失败前端显示-而非0
索引uk_machine_date保证每台机床每天只有一条状态记录idx_date_status支持按天查特定状态机床。
---
### 2.11 日汇总表 cnc_daily_production按机床+程序)
``sql
CREATE TABLE cnc_daily_production (
id INT AUTO_INCREMENT PRIMARY KEY,
machine_id INT NOT NULL,
production_date DATE NOT NULL,
program_name VARCHAR(200) NOT NULL,
total_quantity DECIMAL(15,5) NOT NULL DEFAULT 0,
segment_count INT NOT NULL DEFAULT 1,
total_run_time DECIMAL(15,2) NULL,
total_cutting_time DECIMAL(15,2) NULL,
total_cycle_time DECIMAL(15,2) NULL,
is_adjusted TINYINT(1) NOT NULL DEFAULT 0,
adjusted_quantity DECIMAL(15,5) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (machine_id) REFERENCES cnc_machine(id),
UNIQUE KEY uk_machine_date_program (machine_id, production_date, program_name),
INDEX idx_date (production_date),
INDEX idx_date_program (production_date, program_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='日汇总表(按机床+程序)';
``
索引设计:
- uk_machine_date_program唯一约束+最核心查询索引
- idx_date按日期查所有汇总
- idx_date_program按日期+程序名查汇总
---
### 2.12 工人日汇总表 cnc_worker_daily_summary
``sql
CREATE TABLE cnc_worker_daily_summary (
id INT AUTO_INCREMENT PRIMARY KEY,
worker_id INT NOT NULL,
production_date DATE NOT NULL,
total_quantity DECIMAL(15,5) NOT NULL DEFAULT 0,
machine_count INT NOT NULL DEFAULT 0,
program_count INT NOT NULL DEFAULT 0,
is_adjusted TINYINT(1) NOT NULL DEFAULT 0,
adjusted_quantity DECIMAL(15,5) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (worker_id) REFERENCES cnc_worker(id) ON DELETE CASCADE,
UNIQUE KEY uk_worker_date (worker_id, production_date),
INDEX idx_date (production_date),
INDEX idx_date_quantity (production_date, total_quantity)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工人日汇总表';
``
索引设计:
- uk_worker_date唯一约束+核心查询
- idx_date按日期查所有工人汇总
- idx_date_quantity排行榜核心索引按日期查产量排名覆盖大屏排行榜高频查询
---
### 2.13 产量修正审计表 cnc_production_adjustment
``sql
CREATE TABLE cnc_production_adjustment (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
target_table VARCHAR(30) NOT NULL,
target_id INT NOT NULL,
field_name VARCHAR(50) NOT NULL,
old_value DECIMAL(15,5) NULL,
new_value DECIMAL(15,5) NOT NULL,
reason VARCHAR(500) NOT NULL,
operator_ip VARCHAR(50) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_target (target_table, target_id),
INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产量修正审计表';
``
索引idx_target用于查某条记录的修正历史idx_created用于按时间查审计日志。
---
### 2.14 告警表 cnc_alert
``sql
CREATE TABLE cnc_alert (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
alert_type VARCHAR(30) NOT NULL,
machine_id INT NULL,
collect_address_id INT NULL,
title VARCHAR(200) NOT NULL,
detail TEXT NULL,
is_resolved TINYINT(1) NOT NULL DEFAULT 0,
resolved_at DATETIME NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (machine_id) REFERENCES cnc_machine(id) ON DELETE SET NULL,
FOREIGN KEY (collect_address_id) REFERENCES cnc_collect_address(id) ON DELETE SET NULL,
INDEX idx_type_resolved (alert_type, is_resolved),
INDEX idx_machine_time (machine_id, created_at),
INDEX idx_created (created_at),
INDEX idx_unresolved (is_resolved, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='告警表';
``
告警类型collect_fail / device_offline / production_anomaly / unknown_device / service_error
索引设计:
- idx_type_resolved按类型查未处理告警
- idx_machine_time查某台机床的告警历史
- idx_unresolved管理后台最常用查询查所有未处理告警按时间排序
---
### 2.15 系统配置表 cnc_sys_config
``sql
CREATE TABLE cnc_sys_config (
id INT AUTO_INCREMENT PRIMARY KEY,
config_key VARCHAR(100) NOT NULL UNIQUE,
config_value TEXT NOT NULL,
value_type VARCHAR(20) NOT NULL DEFAULT 'string',
description VARCHAR(200) NULL,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统配置表';
``
预置配置项:
| config_key | 默认值 | 说明 |
|------------|--------|------|
| ping_interval | 60 | Ping检测间隔(秒) |
| collect_retry_count | 3 | 采集失败重试次数 |
| collect_retry_interval | 30 | 采集重试间隔(秒) |
| collect_fail_alert_threshold | 5 | 连续失败N次触发告警 |
| heartbeat_interval | 10 | 心跳写入间隔(秒) |
| daily_summary_time | 01:00 | 日终汇总执行时间 |
| config_poll_interval | 30 | 采集服务轮询配置间隔(秒) |
| log_retention_days | 90 | 原始采集日志保留天数 |
| system_log_retention_days | 30 | 系统日志保留天数 |
| alert_log_retention_days | 180 | 异常日志保留天数 |
| heartbeat_retention_days | 7 | 心跳记录保留天数 |
| bigscreen_refresh_interval | 10 | 大屏刷新间隔(秒) |
| api_token | (自动生成) | 前端API Token |
| collector_api_port | 5800 | 采集服务管理API端口 |
| collector_api_key | (自动生成) | 采集服务间通信API Key |
| error_retry_base_interval | 60 | 任务错误重试基础间隔(秒) |
---
### 2.16 大屏配置表 cnc_screen_config
``sql
CREATE TABLE cnc_screen_config (
id INT AUTO_INCREMENT PRIMARY KEY,
card_key VARCHAR(50) NOT NULL UNIQUE,
card_type VARCHAR(30) NOT NULL,
title VARCHAR(100) NOT NULL,
metric VARCHAR(50) NOT NULL,
dimension VARCHAR(30) NULL,
sort_order INT NOT NULL DEFAULT 0,
is_enabled TINYINT(1) NOT NULL DEFAULT 1,
chart_config JSON NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='大屏卡片配置表';
``
card_type类型stat_number / bar_chart / line_chart / pie_chart / status_grid / rank_list
预置卡片:
| card_key | card_type | title | metric | dimension |
|----------|-----------|-------|--------|-----------|
| total_online | stat_number | 在线机床数 | online_count | - |
| total_production_today | stat_number | 今日总产量 | part_count | - |
| workshop_production | bar_chart | 各车间产量 | part_count | workshop |
| worker_rank | rank_list | 工人产量排行 | part_count | worker |
| machine_rank | rank_list | 机床产量排行 | part_count | machine |
| machine_status | status_grid | 机床状态总览 | - | - |
| collector_status | stat_number | 采集服务状态 | - | - |
| production_trend | line_chart | 产量趋势(7天) | part_count | - |
---
### 2.17 大屏筛选配置表 cnc_screen_filter
``sql
CREATE TABLE cnc_screen_filter (
id INT AUTO_INCREMENT PRIMARY KEY,
screen_key VARCHAR(50) NOT NULL,
filter_type VARCHAR(30) NOT NULL,
filter_value VARCHAR(100) NOT NULL,
is_default TINYINT(1) NOT NULL DEFAULT 0,
sort_order INT NOT NULL DEFAULT 0,
UNIQUE KEY uk_screen_filter (screen_key, filter_type, filter_value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='大屏筛选配置表';
``
---
## 三、日志库 cnc_log3张表
### 3.1 原始采集JSON表 log_collect_raw按月分区
``sql
CREATE TABLE log_collect_raw (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
collect_address_id INT NOT NULL,
request_time DATETIME NOT NULL,
response_time DATETIME NOT NULL,
response_duration INT NULL,
is_success TINYINT(1) NOT NULL DEFAULT 1,
status_code INT NULL,
raw_json MEDIUMTEXT NOT NULL,
error_message VARCHAR(500) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_address_time (collect_address_id, request_time),
INDEX idx_request_time (request_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='原始采集JSON表按月分区90天自动清理'
PARTITION BY RANGE (TO_DAYS(request_time)) (
PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')),
PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01')),
PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
``
数据量估算每30秒一次采集 x 5-10个地址 x 86400秒/天 = 1.4-2.9万条/天每条约20KB = 280-580MB/天。90天约25-52GB。
---
### 3.2 系统日志表 log_system按月分区
``sql
CREATE TABLE log_system (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
log_level VARCHAR(10) NOT NULL,
source VARCHAR(50) NOT NULL,
message TEXT NOT NULL,
stack_trace TEXT NULL,
extra_data JSON NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_level_time (log_level, created_at),
INDEX idx_source_time (source, created_at),
INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='系统日志表按月分区30天自动清理'
PARTITION BY RANGE (TO_DAYS(created_at)) (
PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')),
PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01')),
PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
``
---
### 3.3 采集服务心跳表 log_collector_heartbeat
``sql
CREATE TABLE log_collector_heartbeat (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
service_id VARCHAR(50) NOT NULL DEFAULT 'CncCollector',
status VARCHAR(20) NOT NULL,
collect_address_id INT NULL,
last_collect_time DATETIME NULL,
success_count INT NOT NULL DEFAULT 0,
fail_count INT NOT NULL DEFAULT 0,
uptime_seconds BIGINT NULL,
detail JSON NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_service_time (service_id, created_at),
INDEX idx_address_time (collect_address_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采集服务心跳表7天自动清理';
``
心跳检测逻辑Web API查WHERE service_id='CncCollector' AND created_at > NOW() - INTERVAL 30 SECOND有记录=运行中,无记录=已停止。
---
## 四、ER关系总览
`
cnc_workshop 1-----N cnc_machine
cnc_brand 1-----N cnc_brand_field_mapping
cnc_brand 1-----N cnc_collect_address
cnc_collect_address 1--N cnc_machine
cnc_machine 1-----1 cnc_worker_machine (uk_machine)
cnc_worker 1-----N cnc_worker_machine
cnc_machine 1-----N cnc_collect_record
cnc_machine 1-----N cnc_production_segment
cnc_machine 1-----N cnc_daily_production
cnc_machine 1-----N cnc_machine_daily_status
cnc_worker 1-----N cnc_worker_daily_summary
cnc_daily_production 1--N cnc_production_adjustment
cnc_worker_daily_summary 1--N cnc_production_adjustment
cnc_machine 1-----N cnc_alert
--- 日志库 ---
cnc_collect_address 1--N log_collect_raw (弱关联,跨库)
log_collector_heartbeat (独立弱关联collect_address_id)
log_system (独立)
`
---
## 五、分区维护策略
| 任务 | 频率 | 操作 |
|------|------|------|
| 创建新分区 | 每月1日 | 为cnc_collect_record、log_collect_raw、log_system预创建下下月分区 |
| 删除过期分区 | 每月1日 | DROP超过保留期的分区 |
| 清理心跳表 | 每天 | DELETE log_collector_heartbeat超过7天的记录 |
| 清理告警表 | 每天 | DELETE cnc_alert已处理且超过180天的记录 |
---
## 六、索引设计总览
| 表 | 索引名 | 类型 | 覆盖场景 |
|----|--------|------|---------|
| cnc_brand_field_mapping | uk_brand_standard | UNIQUE | 按品牌查映射规则 |
| cnc_collect_address | idx_brand | INDEX | 按品牌加载地址 |
| cnc_collect_address | idx_enabled | INDEX | 查启用的地址 |
| cnc_machine | uk_device_code | UNIQUE | 采集device匹配 |
| cnc_machine | idx_workshop | INDEX | 按车间筛选 |
| cnc_machine | idx_enabled_online | INDEX | 大屏在线机床查询 |
| cnc_machine | idx_enabled_address | INDEX | 采集服务按地址查机床 |
| cnc_worker_machine | uk_machine | UNIQUE | 一对一绑定+按机床查工人 |
| cnc_worker_machine | idx_worker | INDEX | 按工人查机床列表 |
| cnc_collect_record | idx_machine_time | INDEX | 报表/趋势图/汇总计算 |
| cnc_collect_record | idx_collect_time | INDEX | 全局状态快照 |
| cnc_production_segment | idx_machine_date | INDEX | 日汇总计算 |
| cnc_production_segment | idx_machine_date_program | INDEX | 按程序合并计算 |
| cnc_production_segment | idx_active | INDEX | 查找活跃段 |
| cnc_machine_daily_status | uk_machine_date | UNIQUE | 每天一条状态 |
| cnc_machine_daily_status | idx_date_status | INDEX | 按天查状态 |
| cnc_daily_production | uk_machine_date_program | UNIQUE | 机床+日+程序唯一 |
| cnc_daily_production | idx_date | INDEX | 按日期查汇总 |
| cnc_daily_production | idx_date_program | INDEX | 按日期+程序查 |
| cnc_worker_daily_summary | uk_worker_date | UNIQUE | 工人+日唯一 |
| cnc_worker_daily_summary | idx_date | INDEX | 按日期查工人汇总 |
| cnc_worker_daily_summary | idx_date_quantity | INDEX | 排行榜查询 |
| cnc_production_adjustment | idx_target | INDEX | 修正历史查询 |
| cnc_production_adjustment | idx_created | INDEX | 审计日志时间查询 |
| cnc_alert | idx_type_resolved | INDEX | 按类型查未处理 |
| cnc_alert | idx_machine_time | INDEX | 机床告警历史 |
| cnc_alert | idx_unresolved | INDEX | 未处理告警列表 |
| log_collect_raw | idx_address_time | INDEX | 按地址查原始数据 |
| log_collect_raw | idx_request_time | INDEX | 时间范围清理 |
| log_system | idx_level_time | INDEX | 按级别查错误日志 |
| log_system | idx_source_time | INDEX | 按来源查日志 |
| log_collector_heartbeat | idx_service_time | INDEX | 服务最新状态 |
| log_collector_heartbeat | idx_address_time | INDEX | 地址心跳历史 |
共计20张表34个索引含唯一索引

@ -0,0 +1,468 @@
# CNC机床数据采集系统 - 前端全局规范
> 最后更新2026-04-25
> 状态:设计中
---
## 说明
本文档为**全局规范汇总**,定义所有页面通用的技术规则。各模块的页面设计(布局、字段、交互流程等)见 `docs/02-功能清单/管理后台/``docs/02-功能清单/大屏/` 对应模块子文件。
---
## 全局规范
### 组件规范
| 组件 | 用途 | 配置参数 |
|------|------|---------|
| el-table | 列表展示 | border, stripe, size=default, header-cell-style背景#f5f7fa |
| el-table-column | 列定义 | show-overflow-tooltip=true 默认开启 |
| el-pagination | 分页 | page-sizes=[20,50,100], background=true, layout=total,sizes,prev,pager,next,jumper |
| el-form | 表单 | label-width=120px, label-position=right, size=default |
| el-dialog | 弹窗 | close-on-click-modal=false, close-on-press-escape=true, destroy-on-close=true |
| el-select | 下拉 | filterable=true, clearable=true |
| el-date-picker | 日期 | type=daterange, value-format=YYYY-MM-DD, clearable=true |
| el-input | 输入 | clearable=true, maxlength按字段定义 |
| el-button | 按钮 | size=default, 操作类type=primary, 危险类type=danger |
| el-message | 轻提示 | 成功success, 失败error, 警告warning |
| el-message-box | 确认框 | type=warning |
| el-tag | 状态标签 | size=small, 按状态配color |
| el-tooltip | 提示 | placement=top |
### 防重复请求
- 所有写操作按钮点击后立即loading=true+disabled=true
- 请求锁requestLock指令同一按钮1秒内不可重复点击
- axios拦截器相同URL+参数的请求500ms内自动去重
### 超时与加载反馈
- API超时30秒(可配置)
- 列表页v-loading指令
- 弹窗提交按钮loading+弹窗内遮罩
- 超时提示el-message error
### 操作确认机制
- 删除:确定删除【{name}】?此操作不可恢复。
- 停用/启用:确定{操作}
- 批量操作:确定对选中的{N}项执行{操作}
- 产量修正:确定修正产量?修正后将记录审计日志。
### 脏数据检测
- 编辑弹窗关闭时:若表单有未保存修改,弹出确认
- 表单组件内维护isDirty状态对比初始值与当前值
- 路由切换时beforeRouteLeave守卫
### 操作结果反馈
| 场景 | 反馈方式 | 持续时间 |
|------|---------|---------|
| 创建成功 | el-message success {资源}创建成功 | 3秒 |
| 修改成功 | el-message success 保存成功 | 3秒 |
| 删除成功 | el-message success {资源}已删除 | 3秒 |
| 操作失败 | el-message error {具体错误信息} | 5秒 |
| 批量操作 | el-message info 已{操作}{N}项 | 3秒 |
### 校验规则
| 字段类型 | 规则 | 错误提示 | 触发时机 |
|---------|------|---------|---------|
| 必填 | required | 此项为必填 | blur |
| IP地址 | pattern正则 | 请输入正确的IP地址 | blur |
| URL | pattern正则 | 请输入正确的HTTP地址 | blur |
| 数字 | type:number | 请输入数字 | blur |
| 正整数 | pattern正则 | 请输入正整数 | blur |
| 长度限制 | maxlength | 最多{N}个字符 | input |
| 编码唯一 | async validator API调用 | 此{字段}已存在 | blur |
### Mock数据规格
成功响应: code=0, message=success, data=对象
分页列表: code=0, data={items:[], total:160, page:1, pageSize:20}
失败响应: code=40001, message=具体错误, data=null
### 空状态设计
| 场景 | 展示 |
|------|------|
| 列表无数据 | el-empty description=暂无数据 image-size=120 |
| 查询无结果 | el-empty description=未找到匹配的数据,请调整查询条件 |
| 图表无数据 | 居中显示暂无数据灰色文字 |
### 错误码处理
| 错误码 | 含义 | 前端处理 |
|--------|------|---------|
| 0 | 成功 | 正常处理data |
| 40001 | 参数校验失败 | el-message error显示message |
| 40002 | 资源不存在 | el-message warning+刷新列表 |
| 40003 | 资源已存在 | el-message error+聚焦冲突字段 |
| 40101 | Token无效/过期 | 清除Token跳转登录页 |
| 50001 | 服务器内部错误 | el-message error服务器错误 |
| 50002 | 采集服务不可达 | el-message warning采集服务未响应 |
### 管理后台Layout
```
┌──────────────────────────────────────────────────────────┐
│ [顶部栏] height=48px │
│ 左系统名称「CNC机床数据采集系统」 │
│ 右:管理员 ▼ → [修改密码] [退出登录] │
├────────┬─────────────────────────────────────────────────┤
│ [侧边栏]│ [内容区] padding=20px │
│ width= │ │
│ 200px │ │
│ │ │
│ 仪表盘 │ │
│ 设备管理│ │
│ 品牌模板│ │
│ 采集地址│ │
│ 员工管理│ │
│ 产量报表│ │
│ 告警中心│ │
│ 系统设置│ │
│ 操作日志│ │
│ 大屏配置│ │
├────────┤ │
│ [折叠] │ │
└────────┴─────────────────────────────────────────────────┘
```
**顶部栏规范:**
- 高度48px背景色#409EFFElement Plus primary文字白色
- 左侧系统名称font-size=16pxfont-weight=bold
- 右侧管理员下拉菜单el-dropdowntrigger=click
- [修改密码]打开修改密码弹窗见09-系统设置)
- [退出登录]:确认"确定退出登录?" → 清除Token → 跳转/login
**侧边栏规范:**
- 宽度200px可折叠至64px仅图标
- 折叠按钮底部el-icon Fold/Expand
- 菜单项el-menubackground=#304156text=#bfcbd9active-text=#409EFF
- 当前路由自动高亮,使用 el-menu 的 default-active 绑定当前路由path
- 菜单项无子菜单(均为一级),无折叠子菜单
**侧边栏菜单项与路由映射:**
| 菜单名称 | 路由 | 图标(el-icon) |
|---------|------|-------------|
| 仪表盘 | /dashboard | Odometer |
| 设备管理 | /machine | Monitor |
| 品牌模板 | /brand | PriceTag |
| 采集地址 | /collect-address | Link |
| 员工管理 | /worker | User |
| 产量报表 | /production | DataAnalysis |
| 告警中心 | /alert | Bell |
| 系统设置 | /settings | Setting |
| 操作日志 | /log | Document |
| 大屏配置 | /screen-config | Monitor |注意与设备管理图标不同用View或FullScreen
**内容区规范:**
- padding=20px
- 最大宽度不限(全宽)
- 背景#f0f2f5
- 面包屑在内容区顶部,非顶部栏中
### 路由总表
| 路由 | 组件 | 权限 | 需Token | 重定向/备注 |
|------|------|------|---------|------------|
| /login | LoginPage | 无 | 否 | 登录页独立Layout无侧边栏 |
| / | Layout | admin | 是 | 管理后台框架,重定向→/dashboard |
| /dashboard | DashboardPage | admin | 是 | 嵌套在Layout内 |
| /machine | MachineListPage | admin | 是 | 嵌套在Layout内 |
| /machine/:id | MachineDetailPage | admin | 是 | 嵌套在Layout内 |
| /brand | BrandListPage | admin | 是 | 嵌套在Layout内 |
| /brand/create | BrandEditPage | admin | 是 | 新增品牌 |
| /brand/:id/edit | BrandEditPage | admin | 是 | 编辑品牌(复用同一组件) |
| /collect-address | CollectAddressListPage | admin | 是 | 嵌套在Layout内 |
| /collect-address/:id | CollectAddressDetailPage | admin | 是 | 嵌套在Layout内 |
| /worker | WorkerListPage | admin | 是 | 嵌套在Layout内 |
| /worker/:id | WorkerDetailPage | admin | 是 | 嵌套在Layout内 |
| /production | ProductionPage | admin | 是 | 嵌套在Layout内 |
| /alert | AlertPage | admin | 是 | 嵌套在Layout内 |
| /settings | SettingsPage | admin | 是 | 嵌套在Layout内 |
| /log | LogPage | admin | 是 | 嵌套在Layout内 |
| /screen-config | ScreenConfigPage | admin | 是 | 嵌套在Layout内 |
| /screen | ScreenPage | 无 | 否 | 大屏看板独立Layout全屏无侧边栏 |
### axios封装与路由守卫
**axios实例配置**
- baseURL'/'同IIS站点无跨域
- timeout3000030秒可通过cnc_sys_config配置
- 请求拦截:自动添加 `Authorization: Bearer {token}` header从localStorage取token
- 响应拦截:
- code=0 → 正常返回data
- code=40101 → 清除localStorage.token → router.push('/login') → 弹出el-message warning"登录已过期"
- code=40001/40002/40003/50001/50002 → 按错误码处理表执行
- HTTP状态码非200 → el-message error "网络异常"
**路由守卫router.beforeEach**
- 访问/login → 如果localStorage有token → 重定向/dashboard
- 访问/api/admin/**路由 → 如果localStorage无token → 重定向/login?redirect=当前路由
- 访问/screen → 放行(免认证)
- 其他 → 放行
**Token管理**
- 存储localStorage.setItem('token', value)
- 读取localStorage.getItem('token')
- 清除localStorage.removeItem('token')
- 登录成功后跳转redirect参数存在则跳redirect否则跳/dashboard
---
## 前端工程开发规范
> 最后更新2026-04-26
> 本章节为1:1可交互界面生成的工程实现规范
### 技术栈
| 类别 | 选型 | 版本要求 |
|------|------|---------|
| 框架 | Vue3 | >=3.4 |
| 构建工具 | Vite | >=5.0 |
| 语言 | TypeScript | >=5.0 |
| UI组件库 | Element Plus | >=2.5 |
| 路由 | Vue Router 4 | >=4.3 |
| HTTP | Axios | >=1.6 |
| 图表 | ECharts | >=5.5 |
| Mock | vite-plugin-mock | >=3.0 |
### 项目目录
```
D:\opencode\haoliang\frontend\
├── index.html
├── package.json
├── tsconfig.json
├── vite.config.ts # mock插件 + proxy配置
├── mock/ # Mock数据定义按模块拆分
│ ├── login.ts
│ ├── dashboard.ts
│ ├── machine.ts
│ ├── brand.ts
│ ├── collect-address.ts
│ ├── worker.ts
│ ├── production.ts
│ ├── alert.ts
│ ├── settings.ts
│ ├── log.ts
│ └── screen.ts
└── src/
├── main.ts
├── App.vue
├── router/
│ └── index.ts # 路由定义(双套:正常路由 + /mock前缀路由
├── composables/
│ └── useMockMode.ts # Mock模式检测
├── utils/
│ └── request.ts # axios封装根据mock模式切换baseURL
├── layouts/
│ ├── AdminLayout.vue # 管理后台Layout顶部栏+侧边栏+内容区)
│ └── ScreenLayout.vue # 大屏Layout全屏独立
├── views/ # 页面组件(按模块目录)
│ ├── login/
│ ├── dashboard/
│ ├── machine/
│ ├── brand/
│ ├── collect-address/
│ ├── worker/
│ ├── production/
│ ├── alert/
│ ├── settings/
│ ├── log/
│ ├── screen-config/
│ └── screen/
├── styles/
│ ├── admin.scss # 管理后台全局样式
│ └── screen.scss # 大屏深色主题样式
└── types/ # TypeScript类型定义
```
### Mock方案URL前缀切换
**核心规则:** 同一组件、同一套交互逻辑仅axios请求路径不同。
```
/mock/dashboard → axios请求走 /mock-api/** → vite-plugin-mock拦截返回Mock JSON
/dashboard → axios请求走 /api/** → Vite proxy转发到真实后端
```
#### 使用体验
| 阶段 | URL | 行为 |
|------|-----|------|
| 开发阶段(后端未就绪) | `http://localhost:5173/mock/dashboard` | Mock数据完整展示 |
| 开发阶段(后端未就绪) | `http://localhost:5173/dashboard` | 界面正常API请求404 |
| 后端就绪后 | `http://localhost:5173/dashboard` | 直接对接真实API |
| 后端就绪后 | `http://localhost:5173/mock/dashboard` | 仍可切回Mock对比 |
#### Mock模式检测
```typescript
// src/composables/useMockMode.ts
// 根据 route.path.startsWith('/mock') 判断是否为Mock模式
// 返回 computed<boolean> isMock
```
#### axios baseURL切换
```typescript
// src/utils/request.ts
// if (isMock) baseURL = '/mock-api'
// else baseURL = '/api'
// 其余拦截逻辑不变Token/错误码/超时等)
```
#### 路由定义
```typescript
// src/router/index.ts
// 函数生成两套路由:
// 1. 正常路由:/dashboard, /machine, /login ...
// 2. Mock前缀路由/mock/dashboard, /mock/machine, /mock/login ...
// 两套路由复用同一组件Mock路由额外注入mock标识
```
#### Mock数据文件
```
mock/*.ts 文件内容来源:
- 各页面.md中的Mock数据章节
- 数据结构严格匹配页面.md中定义的JSON
- 一个模块一个文件按API路径组织
```
#### Vite配置
```typescript
// vite.config.ts
// 1. vite-plugin-mock 配置 mock/**.ts
// 2. proxy 配置:
// /mock-api/** → mock插件拦截开发环境
// /api/** → proxy到后端可配置target默认http://localhost:5800
```
### CSS规范
- 方案Element Plus默认主题 + 局部scoped样式
- 管理后台Element Plus默认蓝色主题(#409EFF),背景#f0f2f5
- 大屏看板:独立深色主题(#0f0f1a背景/#1a1a2e卡片),样式文件 `styles/screen.scss`
- 不引入Tailwind CSS
### 大屏独立规范
- 独立Layout`ScreenLayout.vue`(全屏,无侧边栏/面包屑)
- 独立路由:`/screen` 和 `/mock/screen`
- 独立主题:深色背景,通过 `screen.scss` 覆盖Element Plus默认样式
- 免认证:`/api/screen/**` 不需要Token
- 自动刷新:定时器按卡片配置的刷新策略轮询
### 强制要求
- **思考过程使用中文**所有AI助手的推理、分析、思考过程必须使用中文输出
- **控制台输出中文**:所有控制台输出、日志、提示信息使用中文,不得出现乱码
- **所有文档使用中文**:项目内所有文档、注释、界面文案使用中文
- **组件文案中文**:所有界面文字(按钮/标签/提示/空状态/确认框)必须使用中文
- **代码注释中文**:所有代码注释使用中文
---
## CRUD页面必填项
> 页面文件完整模板见 `功能清单文件夹创建规范.md` 第五节共20项。以下为本项目CRUD页面的**最小必填项**——20项的子集。未列出的项若本模块有特殊需求则补充填写无特殊需求则省略继承全局规范即可
**默认继承全局规范、页面文件无需重复填写的项目:**
- 防重复请求(8)、超时与加载反馈(9)、操作确认机制(10)、操作结果反馈(12)、校验规则(14)、响应式布局(15)、空状态设计(18)、错误码处理(19)、安全规范(20)
- 仅当本页面有**不同于全局规范**的特殊逻辑时,才在页面文件中补充对应项
### 列表页必填项
| 序号 | 必填项 | 说明 |
|------|--------|------|
| 1 | 基本信息 | 路由、权限、入口、面包屑 |
| 2 | 界面布局 | ASCII图 |
| 3 | 查询条件 | 字段/控件/必填/默认值/校验/联动,无筛选则写"无" |
| 4 | 列表字段 | 字段名/列宽/排序/筛选/固定/超长处理/对齐 |
| 5 | 操作按钮 | 名称/权限编码/位置/显示条件/点击行为 |
| 6 | 弹窗规格 | 弹窗宽度/遮罩/ESC/表单字段定义,无弹窗则写"无" |
| 7 | 状态机 | 状态值/颜色/可用操作,无状态则写"无" |
| 8 | 交互流程 | 每个操作的主流程+异常处理 |
| 9 | 空状态 | 列表无数据/查询无结果的展示 |
**弹窗表单字段必填列:**
| 列 | 说明 |
|----|------|
| 字段 | 中文名 |
| 控件 | el-input/el-select等+具体参数 |
| 必填 | 是/否 |
| 默认值 | 无则写"-" |
| 校验 | 必填/格式/唯一性等,无则写"-" |
| 联动 | 值变化时影响哪些字段,无则写"-" |
### 详情页必填项
| 序号 | 必填项 | 说明 |
|------|--------|------|
| 1 | 基本信息 | 路由(含参数)、权限、入口、面包屑 |
| 2 | 界面布局 | ASCII图 |
| 3 | 数据区块 | 每个区块的展示字段+控件类型 |
| 4 | 操作按钮 | 名称/位置/行为 |
| 5 | 交互流程 | 加载/刷新/跳转 |
### 统计/仪表盘页必填项
| 序号 | 必填项 | 说明 |
|------|--------|------|
| 1 | 基本信息 | 路由、权限、入口、面包屑 |
| 2 | 界面布局 | ASCII图统计卡片+表格/图表区域) |
| 3 | 数据区块 | 每个区块的数据来源API+刷新策略 |
| 4 | 操作按钮 | 名称/位置/行为 |
| 5 | 状态机 | 状态值/颜色(如有) |
| 6 | 交互流程 | 加载/自动刷新/跳转 |
| 7 | 空状态 | 各区块无数据的展示 |
### 登录/特殊页必填项
| 序号 | 必填项 | 说明 |
|------|--------|------|
| 1 | 基本信息 | 路由、入口 |
| 2 | 界面布局 | ASCII图 |
| 3 | 表单字段 | 字段/控件/校验(如有表单) |
| 4 | 操作按钮 | 名称/行为 |
| 5 | 交互流程 | 成功/失败/跳转 |
| 6 | 安全规范 | Token存储/过期/登出策略 |
---
## 模块设计进度
> 具体页面设计见 `docs/02-功能清单/管理后台/{编号}-{模块名}/` 对应子文件
| 编号 | 模块 | 页面数 | 设计状态 | 备注 |
|------|------|--------|---------|------|
| 01 | 登录 | 1 | ✅ 已设计 | 见 `管理后台/01-登录/01-01-登录页面.md` |
| 02 | 仪表盘 | 1 | ✅ 已设计 | 见 `管理后台/02-仪表盘/02-01-仪表盘页面.md` |
| 03 | 设备管理 | 2 | ✅ 已设计 | 列表页+详情页,见 `管理后台/03-设备管理/` |
| 04 | 品牌模板 | 2 | ✅ 已设计 | 列表页+编辑页,见 `管理后台/04-品牌模板/` |
| 05 | 采集地址 | 2 | ✅ 已设计 | 列表页+详情页(采集历史+原始JSON),见 `管理后台/05-采集地址/` |
| 06 | 员工管理 | 2 | ✅ 已设计 | 列表页+详情页,见 `管理后台/06-员工管理/` |
| 07 | 产量报表 | 1 | ✅ 已设计 | 含修正+导出+数据缺失标记,见 `管理后台/07-产量报表/` |
| 08 | 告警中心 | 1 | ✅ 已设计 | 含批量标记+统计,见 `管理后台/08-告警中心/` |
| 09 | 系统设置 | 1 | ✅ 已设计 | 3Tab:配置项+车间管理+修改密码,见 `管理后台/09-系统设置/` |
| 10 | 车间管理 | - | 🔀 已合并 | 合并至09-系统设置 |
| 11 | 操作日志 | 1 | ✅ 已设计 | 双Tab:修正审计日志+系统运行日志,见 `管理后台/11-操作日志/` |
| 12 | 大屏配置 | 1 | ✅ 已设计 | 见 `管理后台/12-大屏配置/12-01-大屏配置页面.md` |
**大屏模块:**
| 编号 | 模块 | 页面数 | 设计状态 | 备注 |
|------|------|--------|---------|------|
| 大屏-01 | 大屏看板 | 1 | ✅ 已设计 | 免认证,深色主题,卡片式自动刷新,见 `大屏/01-01-大屏看板页面.md` |

@ -0,0 +1,15 @@
# 功能清单 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 分类
| 分类 | 类型 | 索引 |
|------|------|------|
| 管理后台 | 文件夹 | [00-管理后台-索引.md](./管理后台/00-管理后台-索引.md) |
| 大屏 | 文件夹 | [00-大屏-索引.md](./大屏/00-大屏-索引.md) |
---

@ -0,0 +1,10 @@
# 功能清单 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承 `02-前端全局规范.md` 中定义的全局规范。如有冲突按本目录规范执行。
---

@ -0,0 +1,198 @@
# 功能清单文件夹创建规范
---
### 一、目录结构模板
```
00-功能清单索引.md
01-功能清单规范.md
├── 管理后台\
│ ├── 00-管理后台-索引.md
│ ├── 01-管理后台-规范.md
│ ├── 01-登录\
│ │ ├── 00-登录-索引.md
│ │ ├── 01-登录-规范.md
│ │ └── 01-01-登录页面.md
│ ├── 02-仪表盘\
│ │ ├── 00-仪表盘-索引.md
│ │ ├── 01-仪表盘-规范.md
│ │ └── 02-01-仪表盘页面.md
│ └── ...
└── 大屏\
├── 00-大屏-索引.md
├── 01-大屏-规范.md
└── 01-01-大屏看板页面.md
```
---
### 二、文件命名规则
| 文件类型 | 命名规则 | 示例 |
|---------|---------|------|
| 总索引 | `00-功能清单索引.md` | - |
| 总规范 | `01-功能清单规范.md` | - |
| 分类索引 | `00-{分类名}-索引.md` | `00-管理后台-索引.md` |
| 分类规范 | `01-{分类名}-规范.md` | `01-管理后台-规范.md` |
| 模块索引 | `00-{模块名}-索引.md` | `00-登录-索引.md` |
| 模块规范 | `01-{模块名}-规范.md` | `01-登录-规范.md` |
| 页面文件 | `{模块号}-{页面号}-{页面名}.md` | `01-01-登录页面.md` |
**编号规则**
- 模块号01-99两位数
- 页面号01-99两位数
- 格式:`{模块号}-{页面号}-{页面名}.md`
---
### 三、索引文件内容规则
#### 1. 总索引
```markdown
# 功能清单 索引
> 版本v1.0
> 最后更新:日期
---
## 分类
| 分类 | 类型 | 索引 |
|------|------|------|
| 管理后台 | 文件夹 | [00-管理后台-索引.md](./管理后台/00-管理后台-索引.md) |
| 大屏 | 文件夹 | [00-大屏-索引.md](./大屏/00-大屏-索引.md) |
---
```
#### 2. 分类索引
```markdown
# {分类名} 索引
> 版本v1.0
> 最后更新:日期
---
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 01 | 登录 | 文件夹 | [01-登录](./01-登录) |
| 02 | 仪表盘 | 文件夹 | [02-仪表盘](./02-仪表盘) |
---
```
#### 3. 模块索引
```markdown
# {模块名} 索引
> 版本v1.0
> 最后更新:日期
---
## 模块概述
[简要说明本模块的功能定位、业务场景]
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
## 页面功能详情
### {页面号} {页面名称}
**路由**`/xxx`
**功能概述**[简要]
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
**状态机**[如有]
**路由跳转**[本模块内 + 跨模块跳转]
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
---
```
---
### 四、规范文件内容规则
| 层级 | 内容 |
|------|------|
| 总规范 | 整体规范,所有模块通用 |
| 分类规范 | 本分类通用规范 |
| 模块规范 | 无特殊规范时写"继承上级规范,如有冲突按本目录规范执行" |
---
### 五、页面文件规则20项模板按组分类
页面文件保持20项模板不变用空行分组提升可读性。
#### 【结构定义】
| 序号 | 内容 | 说明 |
|------|------|------|
| 1 | 基本信息 | 路由、权限、入口、面包屑 |
| 2 | 界面布局 | ASCII图、响应式断点 |
| 3 | 表单字段 | 字段定义、控件、校验 |
| 4 | 操作按钮 | 权限、位置、行为 |
| 5 | 弹窗规格 | 无/弹窗类型 |
| 6 | 状态机 | 状态值、颜色、流转 |
#### 【交互行为】
| 序号 | 内容 | 说明 |
|------|------|------|
| 7 | 交互流程 | 成功/失败处理 |
| 8 | 防重复请求 | 按钮禁用、AbortController |
| 9 | 超时与加载反馈 | 超时时间、loading方式 |
| 10 | 操作确认机制 | 确认文案 |
| 11 | 脏数据检测 | 快照、重置 |
| 12 | 操作结果反馈 | 反馈方式、持续时间 |
| 14 | 校验规则 | 正则、错误提示、触发时机 |
| 15 | 响应式布局 | 断点布局 |
#### 【技术实现】
| 序号 | 内容 | 说明 |
|------|------|------|
| 13 | 组件规范 | 组件选择、配置 |
| 16 | Mock数据规格 | 完整Request/Response示例 |
| 17 | 键盘操作 | 快捷键 |
| 18 | 空状态设计 | 空态展示 |
| 19 | 错误码处理 | 错误码映射 |
| 20 | 安全规范 | 加密、存储、防护 |
---
### 六、三种文件分工
| 文件类型 | 重点内容 | 所属 |
|---------|---------|------|
| 索引文件 | 功能逻辑、交互关系、路由跳转、状态机 | 模块 |
| 规范文件 | 技术规范要求(组件、校验、布局、安全) | 模块/分类 |
| 页面文件 | 技术实现界面布局、字段、Mock数据 | 页面 |
---
### 七、创建顺序
1. 创建根目录索引+规范
2. 创建分类目录+分类索引+规范
3. 创建模块目录+模块索引+规范
4. 创建页面文件

@ -0,0 +1,89 @@
# 界面变更执行规范
> 本规范供AI助手执行界面变更时遵循确保最小阅读量+最大覆盖度。
---
## 一、动手前必读(最小文件集)
AI助手执行任何界面变更前只需读以下文件
| 优先级 | 文件 | 读的目的 |
|--------|------|---------|
| 必须 | `docs/02-前端全局规范.md` | 全局规范+Layout+路由总表+CRUD必填项+模块进度+工程开发规范(确认当前状态) |
| 必须 | `docs/02-功能清单/02-文件夹创建规范.md` | 文件命名规则+创建顺序 |
| 按需 | 目标模块的 `00-{模块名}-索引.md` | 了解本模块页面清单+路由跳转 |
| 按需 | 目标模块的页面文件 | 了解要修改的页面的当前设计 |
| 按需 | `docs/00-文档进度总览.md` | 仅当涉及新增/删除/状态变更时 |
**禁止**:读 `01-数据库设计.md`、`00-需求与设计文档.md` 等大文件,除非变更确实涉及数据库或核心需求。
---
## 二、变更执行清单
### A. 新增页面
1. 确认模块编号和页面编号(读索引文件)
2. 创建页面文件,命名:`{模块号}-{页面号}-{页面名}.md`
3. 按 `02-前端全局规范.md` 中对应页面类型的必填项填写
4. 界面布局使用 box-drawing 样式(┌───┐),首行放面包屑
5. 页面末尾增加「数据需求」章节
6. 更新模块索引文件(页面清单+功能详情+子目录表)
7. 更新 `02-前端全局规范.md` 模块进度表
8. 更新 `00-文档进度总览.md`
### B. 修改页面
1. 读取目标页面文件 + 模块索引文件
2. 修改页面内容(保留已有结构,只改变更部分)
3. 如果修改涉及路由/跳转/状态机 → 同步更新模块索引文件
4. 如果修改涉及新增数据需求 → 同步更新「数据需求」章节
5. 不需要更新进度文件(修改不改状态)
### C. 新增模块
1. 读 `02-文件夹创建规范.md` 确认命名规则
2. 创建模块目录:`{编号}-{模块名}/`
3. 创建3个文件`00-{模块名}-索引.md` + `01-{模块名}-规范.md` + `{模块号}-01-{页面名}.md`
4. 规范文件写"继承上级规范"
5. 索引文件按模板填写
6. 页面文件按必填项填写
7. 更新 `管理后台/00-管理后台-索引.md`(子目录表)
8. 更新 `02-前端全局规范.md` 模块进度表
9. 更新 `00-文档进度总览.md`
---
## 三、联动同步规则
**规则1**:改了页面文件的路由或跳转 → 必须同步该模块的索引文件;如果跳转跨模块,还要同步目标模块的索引文件
**规则2**:页面新增了数据字段或接口需求 → 必须同步该页面的「数据需求」章节
**规则3**:新增或删除了页面文件 → 必须同步:模块索引文件 + `02-前端全局规范.md`的模块进度表 + `00-文档进度总览.md`
**规则4**:新增了模块目录 → 必须同步:`管理后台/00-管理后台-索引.md` + `02-前端全局规范.md`的模块进度表 + `00-文档进度总览.md`
**规则5**:修改了`02-前端全局规范.md`中的全局规范 → 必须检查各模块规范文件是否冲突
**记忆口诀**:改页面→查索引;改路由→查双向索引;增删页面/模块→三处同步(索引+进度表+总览)
---
## 四、界面布局规范
- 样式box-drawing┌───┐├───┤└───┘│不用 +---+
- 首行:面包屑,格式 `[面包屑] 首页 / 模块名 / 子页名`
- 分区标签:方括号标注,如 `[查询条件区]` `[列表区]` `[操作栏]`
- 字段对齐:用竖线 `|` 分隔,表头和数据行对齐
---
## 五、禁止事项
- 禁止读大文件获取上下文(除非变更确实涉及)
- 禁止跳过联动同步(改了页面不更新索引)
- 禁止修改全局规范而不检查模块兼容性
- 禁止在页面文件中重复全局规范已有内容
- 禁止使用旧样式 `+---+` 画界面布局

@ -0,0 +1,45 @@
# 大屏 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
生产数据大屏看板Chrome无人值守全屏展示免认证。固定布局+卡片指标可配+筛选可配+图表类型可选。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 01-01 | 大屏看板页面 | /screen | 待设计 |
## 页面功能详情
### 01-01 大屏看板页面
**路由**`/screen`
**功能概述**生产数据大屏看板Chrome无人值守全屏展示免认证。深色主题卡片式布局自动刷新
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 加载看板 | 页面进入 | 并行请求所有卡片数据+筛选配置 | GET /api/screen/* |
| F02 | 筛选切换 | 选择车间/品牌 | 刷新所有卡片数据(附加筛选参数) | 同上 |
| F03 | 自动刷新 | 定时器触发 | 按卡片刷新策略轮询 | 同上 |
**业务规则**
- 免认证访问(/api/screen/**无Token要求
- 卡片排列/启停/排序由管理后台大屏配置(cnc_screen_config)决定
- 筛选选项由管理后台大屏筛选配置(cnc_screen_filter)决定
- 全局刷新间隔由cnc_sys_config.bigscreen_refresh_interval控制默认10秒
- 1920x1080优化深色主题一屏展示
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 01-01 | 大屏看板页面 | 页面文件 | [01-01-大屏看板页面.md](./01-01-大屏看板页面.md) |
---

@ -0,0 +1,204 @@
# 大屏看板页面
> 最后更新2026-04-26
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /screen |
| 权限 | 无(免认证) |
| 入口 | 浏览器直接访问 /screen管理后台大屏配置页"预览"按钮 |
| 面包屑 | 无全屏独立Layout |
### 2. 界面布局
```
┌──────────────────────────────────────────────────────────┐
│ [顶部栏] height=50px 深色背景#1a1a2e │
│ 左CNC机床数据采集系统 │
│ 右:[车间▼A栋] [品牌▼全部] 2026-04-25 17:36:38 │
├──────────────────────────────────────────────────────────┤
│ [第一行:统计数字卡片] height=100px │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │在线机床│ │今日总产│ │采集服务│ │活跃告警│ │平均产量│ │
│ │ 142 │ │ 8,520│ │ 运行中 │ │ 3 │ │ 60 │ │
│ │ /160 │ │ │ │3天16时 │ │ │ │/台 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
├──────────────────────────────────────────────────────────┤
│ [第二行:图表区] height=300px │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ 各车间产量(柱状图) │ │ 产量趋势7天(折线图) │ │
│ │ ████ │ │ ╱╲ ╱╲ │ │
│ │ ████ ██ │ │ ╲╱╱ ╲ │ │
│ │ A栋 B栋 C栋 │ │ 4/19 ... 4/25 │ │
│ └────────────────────┘ └────────────────────┘ │
├──────────────────────────────────────────────────────────┤
│ [第三行:排行+状态] height=auto(填满剩余) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 机床产量排行 │ │ 工人产量排行 │ │ 机床状态总览 │ │
│ │ 1.西-1.8 580│ │ 1.张三 1240│ │ ■■■■□□■■■□ │ │
│ │ 2.西-1.10 420│ │ 2.李四 980│ │ ■■□□■■■■□■ │ │
│ │ 3.东-2.0 380│ │ 3.王五 870│ │ ■=在线 □=离线 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────┘
```
**布局说明:**
- 全屏展示1920x1080优化Chrome全屏模式(F11)
- 深色主题:背景#0f0f1a卡片背景#1a1a2e文字白色/浅灰
- 无侧边栏、无面包屑、无滚动条(一屏展示所有内容)
- 卡片排列由管理后台"大屏配置"页面控制(排序/启停/类型)
- 以上布局为默认配置,卡片增减/顺序由cnc_screen_config决定
### 3. 数据区块
| 区块 | card_type | 数据来源API | 刷新策略 |
|------|-----------|-----------|---------|
| 在线机床数 | stat_number | /api/screen/summary | 每10秒(可配) |
| 今日总产量 | stat_number | /api/screen/summary | 每10秒 |
| 采集服务状态 | stat_number | /api/screen/collector-status | 每10秒 |
| 活跃告警 | stat_number | /api/screen/summary | 每10秒 |
| 平均产量 | stat_number | /api/screen/summary | 每10秒 |
| 各车间产量 | bar_chart | /api/screen/workshop-production | 每60秒 |
| 产量趋势7天 | line_chart | /api/screen/production-trend | 每300秒 |
| 机床产量排行 | rank_list | /api/screen/machine-rank | 每60秒 |
| 工人产量排行 | rank_list | /api/screen/worker-rank | 每60秒 |
| 机床状态总览 | status_grid | /api/screen/machine-status | 每10秒 |
### 4. 操作按钮
| 名称 | 位置 | 显示条件 | 点击行为 |
|------|------|---------|---------|
| 车间筛选 | 顶部栏右侧 | 始终 | 下拉切换,刷新所有卡片数据 |
| 品牌筛选 | 顶部栏右侧 | 始终 | 下拉切换,刷新所有卡片数据 |
| 全屏切换 | 顶部栏右侧 | 始终 | F11全屏/退出全屏 |
说明:筛选器为只读展示,可选项由管理后台大屏配置(cnc_screen_filter)定义。默认选中项由is_default字段决定。
### 5. 状态机
采集服务状态:
- running(运行中): 绿色脉冲圆点 + "运行中" + uptime
- stopped(已停止): 红色圆点 + "已停止" + 最后心跳时间
机床状态(status_grid)
- 在线(is_online=1): 绿色方块■
- 离线(is_online=0): 灰色方块□
### 6. 交互流程
- 加载:请求筛选配置->设置默认筛选->并行请求所有卡片数据->渲染
- 自动刷新定时器按卡片配置的刷新策略轮询全局默认10秒可通过cnc_sys_config.bigscreen_refresh_interval配置
- 筛选切换:选车间/品牌->所有API请求附加筛选参数->刷新所有卡片
- 全屏:首次进入自动提示"按F11进入全屏模式"el-message info5秒后消失
- 无交互操作:鼠标悬停卡片有轻微发光效果,无点击跳转
### 7. 空状态
- 统计数字无数据:显示"--"
- 图表无数据:居中灰色文字"暂无数据"
- 排行榜无数据:灰色文字"暂无数据"
- 状态网格无机床:灰色文字"暂无机床"
### 8. Mock数据
**GET /api/screen/summary 统计摘要:**
```json
{ "code": 0, "data": { "onlineCount": 142, "totalMachines": 160, "todayProduction": 8520, "activeAlerts": 3, "avgQuantityPerMachine": 60 }}
```
**GET /api/screen/collector-status 采集服务状态:**
```json
{ "code": 0, "data": { "status": "running", "uptime": "3天16小时", "successCount": 12800, "failCount": 5, "lastCollectTime": "2026-04-25T17:36:38" }}
```
**GET /api/screen/workshop-production 各车间产量:**
```json
{ "code": 0, "data": { "items": [
{ "name": "A栋", "quantity": 3200 },
{ "name": "B栋", "quantity": 2800 },
{ "name": "C栋", "quantity": 2520 }
]}}
```
**GET /api/screen/production-trend 7天产量趋势**
```json
{ "code": 0, "data": { "items": [
{ "date": "04-19", "quantity": 8200 }, { "date": "04-20", "quantity": 7600 },
{ "date": "04-21", "quantity": 9100 }, { "date": "04-22", "quantity": 8500 },
{ "date": "04-23", "quantity": 7800 }, { "date": "04-24", "quantity": 9000 },
{ "date": "04-25", "quantity": 8520 }
]}}
```
**GET /api/screen/machine-rank 机床产量排行:**
```json
{ "code": 0, "data": { "items": [
{ "rank": 1, "machineName": "西-1.8", "quantity": 580 },
{ "rank": 2, "machineName": "西-1.10", "quantity": 420 },
{ "rank": 3, "machineName": "东-2.0", "quantity": 380 },
{ "rank": 4, "machineName": "东-2.5", "quantity": 310 },
{ "rank": 5, "machineName": "南-3.1", "quantity": 290 }
]}}
```
**GET /api/screen/worker-rank 工人产量排行:**
```json
{ "code": 0, "data": { "items": [
{ "rank": 1, "workerName": "张三", "quantity": 1240 },
{ "rank": 2, "workerName": "李四", "quantity": 980 },
{ "rank": 3, "workerName": "王五", "quantity": 870 },
{ "rank": 4, "workerName": "赵六", "quantity": 650 },
{ "rank": 5, "workerName": "孙七", "quantity": 520 }
]}}
```
**GET /api/screen/machine-status 机床状态网格:**
```json
{ "code": 0, "data": { "items": [
{ "machineId": 1, "machineName": "西-1.8", "isOnline": 1 },
{ "machineId": 2, "machineName": "西-1.10", "isOnline": 1 },
{ "machineId": 3, "machineName": "东-2.0", "isOnline": 0 },
{ "machineId": 4, "machineName": "东-2.5", "isOnline": 0 },
{ "machineId": 5, "machineName": "南-3.1", "isOnline": 1 }
]}}
```
**GET /api/screen/filters 筛选选项从cnc_screen_filter读取**
```json
{ "code": 0, "data": { "items": [
{ "filterType": "workshop", "filterValue": "A栋", "isDefault": 1 },
{ "filterType": "workshop", "filterValue": "B栋", "isDefault": 0 },
{ "filterType": "brand", "filterValue": "FANUC", "isDefault": 0 }
]}}
```
### 9. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 统计摘要 | cnc_machine + cnc_daily_production | 聚合查询 |
| 采集服务状态 | log_collector_heartbeat | 查最新一条心跳 |
| 各车间产量 | cnc_daily_production + cnc_machine + cnc_workshop | 按车间聚合 |
| 产量趋势 | cnc_daily_production | 近7天按日聚合 |
| 机床排行 | cnc_daily_production + cnc_machine | 按机床聚合TOP N |
| 工人排行 | cnc_worker_daily_summary | 按工人聚合TOP N |
| 机床状态 | cnc_machine.is_online | 全量查询 |
| 筛选配置 | cnc_screen_filter | 筛选可选项+默认值 |
| 卡片配置 | cnc_screen_config | 哪些卡片启用+排序+图表配置 |
**注意大屏API/api/screen/**)免认证,但仅限读取,不暴露管理接口。**

@ -0,0 +1,10 @@
# 大屏 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,25 @@
# 管理后台 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 01 | 登录 | 文件夹 | [01-登录](./01-登录) |
| 02 | 仪表盘 | 文件夹 | [02-仪表盘](./02-仪表盘) |
| 03 | 设备管理 | 文件夹 | [03-设备管理](./03-设备管理) |
| 04 | 品牌模板 | 文件夹 | [04-品牌模板](./04-品牌模板) |
| 05 | 采集地址 | 文件夹 | [05-采集地址](./05-采集地址) |
| 06 | 员工管理 | 文件夹 | [06-员工管理](./06-员工管理) |
| 07 | 产量报表 | 文件夹 | [07-产量报表](./07-产量报表) |
| 08 | 告警中心 | 文件夹 | [08-告警中心](./08-告警中心) |
| 09 | 系统设置 | 文件夹 | [09-系统设置](./09-系统设置) |
| 10 | 车间管理 | 文件夹 | [10-车间管理](./10-车间管理) |
| 11 | 操作日志 | 文件夹 | [11-操作日志](./11-操作日志) |
| 12 | 大屏配置 | 文件夹 | [12-大屏配置](./12-大屏配置) |
---

@ -0,0 +1,43 @@
# 登录 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
管理后台登录页单角色adminToken认证机制。未登录或Token过期自动跳转。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 01-01 | 登录页面 | /login | 用户名+密码登录Token认证记住我 |
## 页面功能详情
### 01-01 登录页面
**路由**`/login`
**功能概述**管理后台唯一入口用户名密码登录Token存localStorage支持"记住我"延长有效期
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 登录 | 点击登录按钮 | 校验->调API->存Token->跳转仪表盘 | POST /api/admin/login |
| F02 | Token过期跳转 | API返回40101 | 清除Token->跳转登录页(带redirect) | - |
| F03 | 登录失败 | API返回错误 | 显示错误提示->清空密码框 | - |
**安全规范**Token有效期默认8小时记住我7天统一错误提示防信息泄露后端IP锁定防暴力破解
**路由跳转**
- 登录成功 -> 仪表盘(/dashboard) 或 redirect参数指定的页面
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 01-01 | 登录页面 | 页面文件 | [01-01-登录页面.md](./01-01-登录页面.md) |
---

@ -0,0 +1,96 @@
# 登录页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /login |
| 入口 | 未登录时自动跳转或Token过期后跳转 |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ │
│ ┌────────────────────────┐ │
│ │ CNC机床数据采集系统 │ │
│ │ │ │
│ │ 用户名:[____________] │ │
│ │ 密 码:[____________] │ │
│ │ │ │
│ │ [√ 记住我] │ │
│ │ │ │
│ │ [登 录] │ │
│ └────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────┘
### 3. 表单字段
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 用户名 | el-input maxlength=50 | 是 | - | 必填 | - |
| 密码 | el-input type=password maxlength=50 show-password | 是 | - | 必填 | - |
| 记住我 | el-checkbox | 否 | 不勾选 | - | 勾选后Token有效期延长 |
### 4. 操作按钮
| 名称 | 位置 | 显示条件 | 点击行为 |
|------|------|---------|---------|
| 登录 | 表单底部 | 始终 | 校验→调登录API→成功存Token跳转仪表盘 |
### 5. 交互流程
- 进入未登录访问管理后台→axios拦截40101→清除旧Token→router.push(/login)
- 登录:填写用户名+密码→点击登录→loading+disabled→调登录API→成功→存Token到localStorage→跳转/dashboard
- 登录失败用户名或密码错误→el-message error显示错误信息→密码框清空+聚焦
- Token过期访问任意管理后台页面→API返回40101→清除Token→跳转/login带redirect参数登录后跳回原页面
### 6. 安全规范
| 项 | 规则 |
|----|------|
| Token存储 | localStoragekey=token |
| Token传递 | Authorization: Bearer {token} |
| Token有效期 | 默认8小时勾选"记住我"延长至7天 |
| Token刷新 | 不做刷新机制,过期直接跳转登录页 |
| 密码传输 | HTTPS生产环境开发环境HTTP |
| 登录失败提示 | 统一提示"用户名或密码错误",不区分是哪个错 |
| 防暴力破解 | 同一IP连续5次失败锁定15分钟后端实现 |
| 单角色 | 仅admin角色无角色切换无注册功能 |
### 7. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 用户名/密码验证 | 后端硬编码或配置文件 | 单角色admin无需用户表 |
| Token生成与验证 | cnc_sys_config (api_token) | Token值存配置表但登录流程需后端生成JWT或类似Token |
| Token有效期 | cnc_sys_config | 记住我模式下延长有效期 |
### 8. Mock数据
**POST /api/admin/login 成功:**
```json
{ "code": 0, "message": "success", "data": { "token": "eyJhbGciOiJIUzI1NiJ9.admin.8h", "expiresIn": 28800 }}
```
**POST /api/admin/login 成功(记住我):**
```json
{ "code": 0, "message": "success", "data": { "token": "eyJhbGciOiJIUzI1NiJ9.admin.7d", "expiresIn": 604800 }}
```
**POST /api/admin/login 失败:**
```json
{ "code": 40001, "message": "用户名或密码错误", "data": null }
```
**POST /api/admin/login 失败IP锁定**
```json
{ "code": 40003, "message": "登录失败次数过多请15分钟后重试", "data": null }
```

@ -0,0 +1,10 @@
# 登录 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,10 @@
# 管理后台 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,46 @@
# 仪表盘 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
系统首页,展示今日生产概览(在线机床数、产量、告警)及排行数据,提供采集服务状态监控与控制。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 02-01 | 仪表盘页面 | /dashboard | 统计卡片+采集服务状态+机床/工人产量排行 |
## 页面功能详情
### 02-01 仪表盘页面
**路由**`/dashboard`
**功能概述**:展示在线机床数/今日产量/活跃告警统计卡片、采集服务运行状态(可启停/刷新、机床产量排行TOP10、工人产量排行TOP10
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 加载仪表盘数据 | 页面挂载 | 4个API并行请求 | 统计卡片/机床排行/工人排行/服务状态 |
| F02 | 自动刷新 | 定时器触发 | 重新请求所有数据 | 同F01 |
| F03 | 停止采集 | 点击停止按钮+服务running | 确认->调API | 采集服务控制API |
| F04 | 启动采集 | 点击启动按钮+服务stopped/error | 确认->调API | 采集服务控制API |
| F05 | 刷新配置 | 点击刷新按钮+服务running | 确认->调API | 采集服务控制API |
**路由跳转**
- 机床名称 -> 设备详情页(/machine/:id)
- 工人名称 -> 员工详情页(待设计)
- 查看全部(机床排行) -> 产量报表(待设计)
- 查看全部(工人排行) -> 产量报表(待设计)
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 02-01 | 仪表盘页面 | 页面文件 | [02-01-仪表盘页面.md](./02-01-仪表盘页面.md) |
---

@ -0,0 +1,10 @@
# 仪表盘 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,135 @@
# 仪表盘页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /dashboard |
| 权限 | admin全局Token |
| 入口 | 侧边栏仪表盘,登录后默认页 |
| 面包屑 | 首页 / 仪表盘 |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 仪表盘 2026-04-24│
├──────────────────────────────────────────────────────────┤
│ [统计卡片区] │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ 在线机床 │ │ 今日产量 │ │ 活跃告警 │ │
│ │ 142/160 │ │ 2,847 │ │ 3 │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ 采集服务:[状态] 运行3天12小时 上次采集3秒前 │
│ [停止/启动采集] [刷新配置] │
├──────────────────────────────────────────────────────────┤
│ [机床产量排行区] [查看全部] │
│ 排名 | 机床名称 | 当前程序 | 产量 | 状态 │
│ 1 | 西-1.8 | 1566.NC | 580 | 在线 │
├──────────────────────────────────────────────────────────┤
│ [工人产量排行区] [查看全部] │
│ 排名 | 工人姓名 | 负责机床数 | 总产量 │
│ 1 | 张三 | 3 | 1,240 │
└──────────────────────────────────────────────────────────┘
### 3. 数据区块
| 区块 | 数据来源API | 刷新策略 |
|------|-----------|---------|
| 统计卡片(在线/产量/告警) | 统计卡片API | 页面挂载时加载定时N秒刷新 |
| 采集服务状态 | 服务状态API | 页面挂载时加载定时N秒刷新 |
| 机床产量排行 | 机床排行API | 页面挂载时加载定时N秒刷新 |
| 工人产量排行 | 工人排行API | 页面挂载时加载定时N秒刷新 |
> 定时刷新间隔后台可配默认10秒
### 4. 操作按钮
| 名称 | 位置 | 显示条件 | 点击行为 |
|------|------|---------|---------|
| 停止采集 | 服务状态栏 | running | 确认->调API停止 |
| 启动采集 | 服务状态栏 | stopped/error | 确认->调API启动 |
| 刷新配置 | 服务状态栏 | running | 确认->调API刷新 |
| 查看全部 | 机床排行表头 | 始终 | 跳转产量报表 |
| 查看全部 | 工人排行表头 | 始终 | 跳转产量报表 |
| 机床名称 | 行内链接 | 始终 | 跳转机床详情 |
| 工人姓名 | 行内链接 | 始终 | 跳转员工详情 |
### 5. 状态机
采集服务状态:
- running: #67C23A绿 -> 可停止/刷新
- stopped: #909399灰 -> 可启动
- error: #F56C6C红 -> 可启动
机床在线状态:
- 1(在线): el-tag success
- 0(离线): el-tag info
### 6. 交互流程
- 加载:页面挂载->4个API并行(统计卡片/机床排行/工人排行/服务状态)->渲染
- 自动刷新setInterval每N秒重新请求
- 点击机床名称router.push到机床详情
- 停止采集:确认框->调WebAPI代理->采集服务API->更新状态
- 异常:采集服务不可达->warning提示+状态显示stopped
### 7. 空状态
- 机床排行无数据el-empty 今日尚无产量数据
- 工人排行无数据el-empty 今日尚无工人产量数据
### 8. Mock数据
**GET /api/admin/dashboard/summary 统计卡片:**
```json
{ "code": 0, "data": { "onlineCount": 142, "totalMachines": 160, "todayProduction": 2847, "activeAlerts": 3 }}
```
**GET /api/admin/collector/status 采集服务状态:**
```json
{ "code": 0, "data": { "status": "running", "uptimeSeconds": 316800, "lastCollectTime": "2026-04-25T17:36:38", "successCount": 1280, "failCount": 5 }}
```
**GET /api/admin/dashboard/machine-rank 机床产量排行TOP10**
```json
{ "code": 0, "data": { "items": [
{ "rank": 1, "machineId": 1, "machineName": "西-1.8", "program": "1566.NC", "quantity": 580, "status": 1 },
{ "rank": 2, "machineId": 2, "machineName": "西-1.10", "program": "O123.NC", "quantity": 420, "status": 1 },
{ "rank": 3, "machineId": 3, "machineName": "东-2.0", "program": "A456.NC", "quantity": 380, "status": 1 },
{ "rank": 4, "machineId": 4, "machineName": "东-2.5", "program": "B789.NC", "quantity": 310, "status": 0 },
{ "rank": 5, "machineId": 5, "machineName": "南-3.1", "program": "C012.NC", "quantity": 290, "status": 1 },
{ "rank": 6, "machineId": 6, "machineName": "南-3.2", "program": "D345.NC", "quantity": 240, "status": 1 },
{ "rank": 7, "machineId": 7, "machineName": "北-4.0", "program": "E678.NC", "quantity": 210, "status": 1 },
{ "rank": 8, "machineId": 8, "machineName": "北-4.1", "program": "F901.NC", "quantity": 180, "status": 0 },
{ "rank": 9, "machineId": 9, "machineName": "西-1.5", "program": "G234.NC", "quantity": 150, "status": 1 },
{ "rank": 10, "machineId": 10, "machineName": "东-2.8", "program": "H567.NC", "quantity": 87, "status": 1 }
]}}
```
**GET /api/admin/dashboard/worker-rank 工人产量排行TOP10**
```json
{ "code": 0, "data": { "items": [
{ "rank": 1, "workerId": 1, "workerName": "张三", "machineCount": 3, "totalQuantity": 1240 },
{ "rank": 2, "workerId": 2, "workerName": "李四", "machineCount": 2, "totalQuantity": 980 },
{ "rank": 3, "workerId": 3, "workerName": "王五", "machineCount": 4, "totalQuantity": 870 },
{ "rank": 4, "workerId": 4, "workerName": "赵六", "machineCount": 2, "totalQuantity": 650 },
{ "rank": 5, "workerId": 5, "workerName": "孙七", "machineCount": 3, "totalQuantity": 520 }
]}}
### 8. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 在线机床数/总机床数 | cnc_machine.is_enabled + is_online | 统计卡片 |
| 今日总产量 | cnc_daily_production.total_quantity 合计 | 统计卡片 |
| 活跃告警数 | cnc_alert.is_resolved=0 计数 | 统计卡片 |
| 采集服务状态+运行时长+上次采集 | log_collector_heartbeat | 服务状态栏 |
| 机床产量排行TOP10 | cnc_daily_production + cnc_machine | 排行表 |
| 工人产量排行TOP10 | cnc_worker_daily_summary + cnc_worker | 排行表 |

@ -0,0 +1,65 @@
# 设备管理 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
管理CNC机床设备包括设备列表CRUD+批量操作+导入导出)和设备详情(实时状态+产量+趋势)。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 03-01 | 设备列表页面 | /machine | 机床列表+查询+CRUD+批量+导入导出 |
| 03-02 | 设备详情页面 | /machine/:id | 基本信息查看+实时状态+今日产量+7天趋势+采集记录 |
## 页面功能详情
### 03-01 设备列表页面
**路由**`/machine`
**功能概述**:机床设备列表,支持按车间/在线状态/品牌/关键字筛选,新增/编辑/删除/批量启停/导入/导出
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 查询机床 | 点击查询 | 重置page=1->请求列表API | GET /api/admin/machine |
| F02 | 新增机床 | 点击新增 | 弹窗填写->保存 | POST /api/admin/machine |
| F03 | 编辑机床 | 点击编辑 | 弹窗回填->修改->保存 | PUT /api/admin/machine/{id} |
| F04 | 删除机床 | 点击删除 | 确认->软删除 | DELETE /api/admin/machine/{id} |
| F05 | 批量启停 | 勾选+点击 | 确认->批量API | PUT /api/admin/machine/batch-toggle |
| F06 | 导出Excel | 点击导出 | 调API下载 | GET /api/admin/machine/export |
| F07 | 导入Excel | 点击导入 | 选文件->上传 | POST /api/admin/machine/import |
**状态机**机床is_enabled1(启用)/0(停用)
**路由跳转**
- 机床名称链接 -> 设备详情页(/machine/:id)
### 03-02 设备详情页面
**路由**`/machine/:id`
**功能概述**:展示机床基本信息、实时运行状态(自动刷新)、今日产量、近7天趋势图、最近采集记录
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 加载详情 | 页面挂载 | 4个API并行 | 详情/产量/采集记录/趋势 |
| F02 | 实时状态刷新 | 定时器每10秒 | 刷新实时状态区块 | GET /api/admin/machine/{id}/status |
| F03 | 查看更多采集 | 点击查看更多 | 跳转产量报表(预填机床) | - |
**路由跳转**
- 返回 -> router.back()
- 查看更多 -> 产量报表页(待设计,预填机床筛选)
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 03-01 | 设备列表页面 | 页面文件 | [03-01-设备列表页面.md](./03-01-设备列表页面.md) |
| 03-02 | 设备详情页面 | 页面文件 | [03-02-设备详情页面.md](./03-02-设备详情页面.md) |
---

@ -0,0 +1,10 @@
# 设备管理 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,159 @@
# 设备列表页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /machine |
| 权限 | admin |
| 入口 | 侧边栏设备管理 |
| 面包屑 | 首页 / 设备管理 |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 设备管理 │
├──────────────────────────────────────────────────────────┤
│ [操作栏] [+ 新增机床] [导入] [导出] │
├──────────────────────────────────────────────────────────┤
│ [查询条件区] │
│ 车间[▼全部] 在线状态[▼全部] 品牌[▼全部] 搜索[____] │
│ [查询] [重置] │
├──────────────────────────────────────────────────────────┤
│ [列表区] │
│ [x] | 机床名称 | device_code | 车间 | 品牌 | IP地址 | 在线 | 绑定工人 | 操作 │
│ [x] | 西-1.8 | fanake_1.8 | A栋 | FANUC| 10.1.1.8| 在线 | 张三 | [编辑][删除] │
├──────────────────────────────────────────────────────────┤
│ [分页] 共160条 每页[20▼] < 1 2 3 ... 8 >
├──────────────────────────────────────────────────────────┤
│ [批量操作栏] 已选2项 [批量停用] [批量启用] │
└──────────────────────────────────────────────────────────┘
### 3. 查询条件
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 车间 | el-select | 否 | 全部 | - | 无 |
| 在线状态 | el-select(在线/离线/全部) | 否 | 全部 | - | 无 |
| 品牌 | el-select | 否 | 全部 | - | 无 |
| 关键字 | el-input placeholder=机床名称/device_code | 否 | 空 | - | 无 |
### 4. 列表字段
| 字段名 | 列宽 | 排序 | 筛选 | 固定 | 超长处理 | 对齐 |
|--------|------|------|------|------|---------|------|
| 选择框 | 40px | - | - | left | - | center |
| 机床名称 | 120px | y | - | left | tooltip | left |
| device_code | 140px | y | - | - | tooltip | left |
| 车间 | 80px | y | 下拉 | - | - | center |
| 品牌 | 100px | y | 下拉 | - | - | center |
| IP地址 | 120px | - | - | - | - | left |
| 在线状态 | 80px | - | - | - | - | center |
| 绑定工人 | 100px | - | - | - | - | center |
| 操作 | 120px | - | - | right | - | center |
### 5. 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 新增机床 | machine:create | 页头 | 始终 | 打开新增弹窗 |
| 导入 | machine:import | 页头 | 始终 | 打开导入弹窗 |
| 导出 | machine:export | 页头 | 始终 | 调API下载Excel |
| 编辑 | machine:update | 行操作 | 始终 | 打开编辑弹窗 |
| 删除 | machine:delete | 行操作 | 始终 | 确认->软删除 |
| 批量停用 | machine:disable | 底部栏 | 已选含启用项 | 确认->批量 |
| 批量启用 | machine:enable | 底部栏 | 已选含停用项 | 确认->批量 |
| 机床名称链接 | - | 行内 | 始终 | 跳转详情页 |
### 6. 弹窗规格
**新增/编辑机床弹窗:**
- 宽度600px遮罩有ESC关闭是(脏数据检测),标题=新增机床/编辑机床
表单字段:
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 机床名称 | el-input maxlength=100 | 是 | - | 必填 | - |
| device_code | el-input maxlength=100 | 是 | - | 必填+唯一性(新增时) | - |
| 所属车间 | el-select | 是 | - | 必填 | - |
| 采集地址 | el-select | 是 | - | 必填 | 选定后品牌自动填充(只读) |
| 品牌(只读) | el-input disabled | - | 由采集地址联动 | - | 采集地址变化时自动填充 |
| IP地址 | el-input | 是 | - | 必填+IP格式 | - |
| 绑定工人 | el-select | 否 | 空 | - | - |
**导入弹窗:**
- 宽度500px标题=导入机床
| 字段 | 控件 | 说明 |
|------|------|------|
| 模板下载 | el-button link | 下载Excel模板 |
| 文件上传 | el-upload | accept=.xlsx, limit=1, auto-upload=false |
| 确认导入 | el-button primary | 手动触发上传 |
### 7. 状态机
机床is_enabled
- 1(启用): el-tag success -> 可编辑/删除/停用
- 0(停用): el-tag danger -> 可编辑/启用
### 8. 交互流程
- 加载请求机床列表API(含分页)->渲染表格
- 查询:点查询->重置page=1->请求列表API
- 重置:清空所有筛选条件->请求列表API
- 新增:弹窗->填写->保存->关闭弹窗->刷新列表
- 编辑:弹窗(回填数据)->修改->保存->关闭->刷新
- 删除:确认框->调API->成功->刷新列表
- 批量:勾选->底部栏显示->点操作->确认->批量API->刷新
- 导出调API->下载文件
- 导入:选文件->确认->上传->返回结果(成功N条/失败N条)->刷新列表
- 机床名称链接:跳转机床详情页
### 9. 空状态
列表无数据el-empty 暂无机床数据,点击新增机床添加
### 10. Mock数据
**GET /api/admin/machine 机床列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "name": "西-1.8", "deviceCode": "fanake_1.8", "workshopName": "A栋", "brandName": "FANUC", "ipAddress": "10.1.1.8", "isOnline": 1, "workerName": "张三", "isEnabled": 1 },
{ "id": 2, "name": "西-1.10", "deviceCode": "fanake_1.10", "workshopName": "A栋", "brandName": "FANUC", "ipAddress": "10.1.1.10", "isOnline": 1, "workerName": "李四", "isEnabled": 1 },
{ "id": 3, "name": "东-2.0", "deviceCode": "fanake_2.0", "workshopName": "B栋", "brandName": "FANUC", "ipAddress": "10.1.2.0", "isOnline": 0, "workerName": "王五", "isEnabled": 1 },
{ "id": 4, "name": "东-2.5", "deviceCode": "siemens_2.5", "workshopName": "B栋", "brandName": "SIEMENS", "ipAddress": "10.1.2.5", "isOnline": 0, "workerName": null, "isEnabled": 0 }
], "total": 160, "page": 1, "pageSize": 20 }}
```
**POST /api/admin/machine 新增机床成功:**
```json
{ "code": 0, "message": "success", "data": { "id": 161, "name": "新机床" }}
```
**GET /api/admin/machine/export 导出(返回文件流):**
二进制Excel文件Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
**POST /api/admin/machine/import 导入结果:**
```json
{ "code": 0, "data": { "successCount": 15, "failCount": 2, "failDetails": ["第3行device_code重复", "第8行车间不存在"] }}
```
### 10. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 机床列表(含分页) | cnc_machine | 主表需JOIN车间/品牌/工人 |
| 车间下拉 | cnc_workshop | 查询条件+表单 |
| 品牌下拉 | cnc_brand | 查询条件 |
| 采集地址下拉 | cnc_collect_address | 表单联动(选地址→填充品牌) |
| 工人下拉 | cnc_worker | 表单绑定工人 |
| 机床唯一性校验 | cnc_machine.device_code | 新增时实时校验 |
| 设备code唯一性 | cnc_machine.uk_device_code | 新增时校验 |

@ -0,0 +1,132 @@
# 设备详情页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /machine/:id |
| 权限 | admin |
| 入口 | 设备管理点击机床名称 / 仪表盘点击机床名称 |
| 面包屑 | 首页 / 设备管理 / {机床名称} |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 设备管理 / 西-1.8 │
├──────────────────────────────────────────────────────────┤
│ [基本信息区] │
< 返回 机床详情:西-1.8 │
│ 机床名称:西-1.8 device_codefanake_1.8 │
│ 车间A栋 品牌FANUC │
│ 采集地址FANUC-A栋 IP10.1.1.8 │
│ 绑定工人:张三 在线状态:在线 │
├──────────────────────────────────────────────────────────┤
│ [实时状态区](自动刷新) │
│ 当前程序1566.NC 零件数580 │
│ 运行状态:运行中 操作模式:自动 │
│ 主轴转速300 rpm 进给速度0 │
│ 主轴负载0% 加工状态G01 │
│ 最后采集3秒前 │
├──────────────────────────────────────────────────────────┤
│ [今日产量区] │
│ 程序名 | 产量 | 运行时间 | 切削时间 │
│ 1566.NC | 580 | 4h20m | 3h50m │
├──────────────────────────────────────────────────────────┤
│ [近7天产量趋势折线图] │
│ [============图表区域============] │
├──────────────────────────────────────────────────────────┤
│ [最近采集记录] [查看更多] │
│ 时间 | 程序名 | 零件数 | 运行状态 │
│ 17:36:35 | 1566 | 580 | 运行中 │
│ 17:36:05 | 1566 | 579 | 运行中 │
└──────────────────────────────────────────────────────────┘
### 3. 数据区块
| 区块 | 展示字段 | 控件类型 | 刷新策略 |
|------|---------|---------|---------|
| 基本信息 | 机床名称、device_code、车间、品牌、采集地址、IP、绑定工人、在线状态 | 文本展示 | 页面加载时请求一次 |
| 实时状态 | 当前程序、零件数、运行状态、操作模式、主轴转速、进给速度、主轴负载、加工状态、最后采集时间 | 文本展示 | setInterval每10秒刷新 |
| 今日产量 | 程序名、产量、运行时间、切削时间 | el-table | 页面加载时请求一次 |
| 近7天趋势 | 日期、产量 | 折线图 | 页面加载时请求一次 |
| 最近采集记录 | 时间、程序名、零件数、运行状态 | el-table | 页面加载时请求一次 |
### 4. 操作按钮
| 名称 | 位置 | 显示条件 | 点击行为 |
|------|------|---------|---------|
| 返回 | 页头左侧 | 始终 | router.back() |
| 查看更多 | 采集记录表头 | 始终 | 跳转产量报表(预填该机床) |
### 5. 交互流程
- 加载请求机床详情API+今日产量API+采集记录API+7天趋势API->渲染
- 自动刷新setInterval每10秒刷新实时状态部分
- 返回router.back()
### 6. 空状态
- 今日产量无数据el-empty 今日尚无产量数据
- 采集记录无数据el-empty 暂无采集记录
### 7. Mock数据
**GET /api/admin/machine/1 机床详情:**
```json
{ "code": 0, "data": {
"id": 1, "name": "西-1.8", "deviceCode": "fanake_1.8", "workshopName": "A栋", "brandName": "FANUC",
"collectAddressName": "FANUC-A栋", "ipAddress": "10.1.1.8", "workerName": "张三", "isOnline": 1, "isEnabled": 1
}}
```
**GET /api/admin/machine/1/status 实时状态:**
```json
{ "code": 0, "data": {
"programName": "1566.NC", "partCount": 580, "runStatus": "运行中", "operateMode": "自动",
"spindleSpeedSet": 3000, "feedSpeedSet": 500, "spindleSpeedActual": 2980, "feedSpeedActual": 480,
"spindleLoad": 65, "machiningStatus": "G01", "lastCollectTime": "2026-04-25T17:36:38"
}}
```
**GET /api/admin/machine/1/production/today 今日产量:**
```json
{ "code": 0, "data": { "items": [
{ "programName": "1566.NC", "quantity": 580, "runTime": "4h20m", "cuttingTime": "3h50m" },
{ "programName": "O123.NC", "quantity": 120, "runTime": "2h10m", "cuttingTime": "1h45m" }
]}}
```
**GET /api/admin/machine/1/production/trend 7天趋势**
```json
{ "code": 0, "data": { "items": [
{ "date": "2026-04-19", "quantity": 820 }, { "date": "2026-04-20", "quantity": 760 },
{ "date": "2026-04-21", "quantity": 910 }, { "date": "2026-04-22", "quantity": 850 },
{ "date": "2026-04-23", "quantity": 780 }, { "date": "2026-04-24", "quantity": 900 },
{ "date": "2026-04-25", "quantity": 700 }
]}}
```
**GET /api/admin/machine/1/collect-records 最近采集记录:**
```json
{ "code": 0, "data": { "items": [
{ "collectTime": "2026-04-25T17:36:35", "programName": "1566.NC", "partCount": 580, "runStatus": "运行中" },
{ "collectTime": "2026-04-25T17:36:05", "programName": "1566.NC", "partCount": 579, "runStatus": "运行中" },
{ "collectTime": "2026-04-25T17:35:35", "programName": "1566.NC", "partCount": 578, "runStatus": "运行中" }
]}}
### 7. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 机床基本信息 | cnc_machine | 主表,含车间/品牌/地址/工人关联 |
| 实时状态10秒刷新 | cnc_machine 冗余字段 | last_program_name/last_part_count/last_run_status等 |
| 今日产量(按程序) | cnc_daily_production | 按machine_id+当天查询 |
| 近7天趋势 | cnc_daily_production | 按machine_id+近7天聚合 |
| 最近采集记录 | cnc_collect_record | 按machine_id+时间倒序取最近N条 |

@ -0,0 +1,64 @@
# 品牌模板 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
管理CNC品牌模板及其字段映射配置。品牌数量少列表无分页无筛选。编辑使用独立页面非弹窗支持字段映射行内编辑。修改映射不影响历史数据。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 04-01 | 品牌列表页面 | /brand | 品牌列表+新增/编辑/启停/复制 |
| 04-02 | 品牌编辑页面 | /brand/create 或 /brand/{id}/edit | 品牌基本信息+字段映射配置 |
## 页面功能详情
### 04-01 品牌列表页面
**路由**`/brand`
**功能概述**:品牌模板列表,新增/编辑/启停/复制操作
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 加载品牌列表 | 页面挂载 | 请求列表API | GET /api/admin/brand |
| F02 | 新增品牌 | 点击新增 | 跳转新增编辑页 | - |
| F03 | 编辑品牌 | 点击编辑 | 跳转编辑页 | - |
| F04 | 启停品牌 | 点击启用/禁用 | 确认->切换状态 | PUT /api/admin/brand/{id}/toggle |
| F05 | 复制品牌 | 点击复制 | 复制模板到新增页 | GET /api/admin/brand/{id} |
**状态机**品牌is_enabled1(启用)/0(停用)
**路由跳转**
- 新增/编辑 -> 品牌编辑页(/brand/create 或 /brand/{id}/edit)
### 04-02 品牌编辑页面
**路由**`/brand/create` 或 `/brand/{id}/edit`
**功能概述**:编辑品牌基本信息(名称/device字段/tags路径)及字段映射配置(行内表格编辑)
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 加载品牌详情(编辑) | 页面挂载(编辑模式) | 请求品牌详情+映射列表 | GET /api/admin/brand/{id} |
| F02 | 添加映射行 | 点击添加映射 | 表格新增空行 | - |
| F03 | 删除映射行 | 点击删除 | 移除该行 | - |
| F04 | 保存品牌 | 点击保存 | 校验->调API->返回列表 | POST/PUT /api/admin/brand |
| F05 | 取消编辑 | 点击取消 | 脏数据检测->返回列表 | - |
**路由跳转**
- 保存/取消 -> 返回品牌列表页(/brand)
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 04-01 | 品牌列表页面 | 页面文件 | [04-01-品牌列表页面.md](./04-01-品牌列表页面.md) |
| 04-02 | 品牌编辑页面 | 页面文件 | [04-02-品牌编辑页面.md](./04-02-品牌编辑页面.md) |
---

@ -0,0 +1,38 @@
# 品牌模板 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---
## 品牌标准字段枚举
品牌编辑页"标准字段"下拉的完整可选项共16个
| standard_field | 含义 | data_type | 说明 |
|----------------|------|-----------|------|
| program_name | NC程序名 | string | 零件唯一识别Tag5 |
| part_count | 当前加工零件数 | number | 零件计数Tag8 |
| device_status | 设备状态 | number | _io_status |
| run_status | 运行状态 | number | Tag9 |
| operate_mode | 操作模式 | number | Tag10 |
| spindle_speed_set | 主轴设定速度 | number | Tag11 |
| feed_speed_set | 进给设定速度 | number | Tag12 |
| spindle_speed_actual | 主轴实际速度 | number | Tag13 |
| feed_speed_actual | 进给实际转速 | number | Tag14 |
| spindle_load | 主轴负载 | number | Tag15 |
| spindle_override | 主轴倍率 | number | Tag16 |
| power_on_time | 开机时间 | number | Tag17 |
| run_time | 运行时间 | number | Tag18 |
| cutting_time | 切削时间 | number | Tag19 |
| cycle_time | 循环时间 | number | Tag20 |
| machining_status | 加工状态 | string | Tag21 |
**必填标准字段**program_name、part_count、device_status标记isRequired=1
**可选标准字段**其余13个标记isRequired=0
---

@ -0,0 +1,92 @@
# 品牌列表页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /brand |
| 权限 | admin |
| 入口 | 侧边栏品牌模板 |
| 面包屑 | 首页 / 品牌模板管理 |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 品牌模板管理 │
├──────────────────────────────────────────────────────────┤
│ [操作栏] [+ 新增品牌] │
├──────────────────────────────────────────────────────────┤
│ [列表区] │
│ 品牌名称 | 状态 | 映射字段数 | 操作 │
│ FANUC | 启用 | 16 | [编辑][禁用][复制] │
│ SIEMENS | 启用 | 12 | [编辑][禁用][复制] │
│ MITSUBISHI | 停用 | 8 | [编辑][启用][复制] │
└──────────────────────────────────────────────────────────┘
### 3. 查询条件
无(品牌数量少,无需筛选)。
### 4. 列表字段
| 字段名 | 列宽 | 排序 | 超长处理 | 对齐 |
|--------|------|------|---------|------|
| 品牌名称 | 150px | y | tooltip | left |
| 状态 | 80px | - | - | center |
| 映射字段数 | 100px | - | - | center |
| 操作 | 180px | - | - | center |
### 5. 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 新增品牌 | brand:create | 页头 | 始终 | 打开新增页 |
| 编辑 | brand:update | 行操作 | 始终 | 跳转编辑页 |
| 启用/禁用 | brand:toggle | 行操作 | 始终 | 确认->切换状态 |
| 复制 | brand:copy | 行操作 | 始终 | 复制模板到新增页 |
### 6. 弹窗规格
无弹窗,使用独立编辑页。
### 7. 状态机
品牌is_enabled
- 1(启用): el-tag success -> 可编辑/禁用/复制
- 0(停用): el-tag danger -> 可编辑/启用/复制
### 8. 交互流程
- 加载:请求品牌列表->渲染表格
- 新增:跳转新增编辑页(/brand/create)
- 编辑:跳转编辑页(/brand/:id/edit)
- 启用/禁用:确认框->调API->刷新列表
- 复制:复制品牌模板数据到新增页
### 9. 空状态
列表无数据el-empty 暂无品牌数据,点击新增品牌添加
### 10. Mock数据
**GET /api/admin/brand 品牌列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "brandName": "FANUC", "deviceField": "device", "tagsPath": "tags", "isEnabled": 1, "fieldCount": 16 },
{ "id": 2, "brandName": "SIEMENS", "deviceField": "device", "tagsPath": "tags", "isEnabled": 1, "fieldCount": 12 },
{ "id": 3, "brandName": "MITSUBISHI", "deviceField": "device", "tagsPath": "tags", "isEnabled": 0, "fieldCount": 8 }
]}}
### 10. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 品牌列表 | cnc_brand | 主表 |
| 映射字段数 | cnc_brand_field_mapping | 按brand_id计数 |

@ -0,0 +1,109 @@
# 品牌编辑页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /brand/create 或 /brand/{id}/edit |
| 权限 | admin |
| 入口 | 品牌列表页点击"新增品牌"或"编辑" |
| 面包屑 | 首页 / 品牌模板管理 / 新增品牌 或 编辑FANUC |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 品牌模板管理 / 编辑FANUC │
├──────────────────────────────────────────────────────────┤
│ [基本信息区] │
< 返回 编辑品牌模板FANUC │
│ 品牌名称:[FANUC] │
│ device字段名[device] │
│ tags路径[tags] │
├──────────────────────────────────────────────────────────┤
│ [字段映射配置区] [+ 添加映射] │
│ 标准字段 | 匹配方式 | 匹配值 | 类型 | 必须 | 操作 │
│ program_name | 按id | Tag5 | string | 是 | [删除] │
│ part_count | 按id | Tag8 | number | 是 | [删除] │
│ device_status | 按id | _io_status| number | 是 | [删除] │
│ ... │
├──────────────────────────────────────────────────────────┤
│ ⚠ 修改映射配置仅影响后续新采集数据,历史数据不受影响 │
│ [取消] [保存] │
└──────────────────────────────────────────────────────────┘
### 3. 查询条件
无。
### 4. 操作按钮
| 名称 | 位置 | 显示条件 | 点击行为 |
|------|------|---------|---------|
| 添加映射 | 映射表头上方 | 始终 | 新增一行空映射 |
| 删除 | 映射行操作 | 始终 | 移除该行(不弹确认) |
| 保存 | 页脚 | 始终 | 校验->保存->返回列表 |
| 取消 | 页脚 | 始终 | 脏数据检测->返回列表 |
### 5. 弹窗规格
添加映射行使用el-select选标准字段+输入匹配值+选择类型,直接在表格行内编辑,不弹窗。
### 6. 状态机
品牌is_enabled
- 1(启用): el-tag success
- 0(停用): el-tag danger
### 7. 交互流程
- 加载(编辑):请求品牌详情+映射列表->渲染
- 加载(新增):空表单
- 添加映射:表格新增一行空行(标准字段下拉+匹配值输入+类型选择+必填勾选)
- 删除映射:直接移除该行
- 保存:确认弹窗"修改映射配置仅影响后续新采集数据,历史数据不受影响,确定保存?"->调API->成功返回列表
- 取消:脏数据检测->返回
### 8. 脏数据检测(本模块特殊规则)
品牌名称/device字段/tags路径/映射列表任一变更则isDirty=true。
### 9. Mock数据
**GET /api/admin/brand/1 品牌详情+映射列表:**
```json
{ "code": 0, "data": {
"id": 1, "brandName": "FANUC", "deviceField": "device", "tagsPath": "tags",
"mappings": [
{ "id": 1, "standardField": "program_name", "fieldName": "Tag5", "matchBy": "id", "dataType": "string", "isRequired": 1 },
{ "id": 2, "standardField": "part_count", "fieldName": "Tag8", "matchBy": "id", "dataType": "number", "isRequired": 1 },
{ "id": 3, "standardField": "device_status", "fieldName": "_io_status", "matchBy": "id", "dataType": "number", "isRequired": 1 },
{ "id": 4, "standardField": "run_status", "fieldName": "Tag9", "matchBy": "id", "dataType": "number", "isRequired": 1 },
{ "id": 5, "standardField": "operate_mode", "fieldName": "Tag10", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 6, "standardField": "spindle_speed_set", "fieldName": "Tag11", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 7, "standardField": "feed_speed_set", "fieldName": "Tag12", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 8, "standardField": "spindle_speed_actual", "fieldName": "Tag13", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 9, "standardField": "feed_speed_actual", "fieldName": "Tag14", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 10, "standardField": "spindle_load", "fieldName": "Tag15", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 11, "standardField": "spindle_override", "fieldName": "Tag16", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 12, "standardField": "power_on_time", "fieldName": "Tag17", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 13, "standardField": "run_time", "fieldName": "Tag18", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 14, "standardField": "cutting_time", "fieldName": "Tag19", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 15, "standardField": "cycle_time", "fieldName": "Tag20", "matchBy": "id", "dataType": "number", "isRequired": 0 },
{ "id": 16, "standardField": "machining_status", "fieldName": "Tag21", "matchBy": "id", "dataType": "string", "isRequired": 0 }
]
}}
### 9. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 品牌基本信息 | cnc_brand | brand_name/device_field/tags_path |
| 字段映射列表 | cnc_brand_field_mapping | 按brand_id查询含standard_field/field_name/match_by/data_type/is_required |
| 标准字段枚举 | 代码层面约定(不建表) | program_name/part_count等16个标准字段 |

@ -0,0 +1,53 @@
# 采集地址 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
管理HTTP采集地址每个地址关联品牌和机床列表。地址数量少列表无分页无筛选。新增/编辑通过弹窗完成弹窗内含品牌联动加载机床的checkbox选择区域。支持查看采集地址详情关联机床+采集历史+原始JSON
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 05-01 | 采集地址页面 | /collect-address | 采集地址列表+新增/编辑弹窗+启停 |
| 05-02 | 采集地址详情页面 | /collect-address/:id | 基本信息+关联机床+采集记录+原始JSON查看 |
## 页面功能详情
### 05-01 采集地址页面
**路由**`/collect-address`
**功能概述**采集地址列表显示URL/品牌/间隔/状态/上次采集/连续失败,新增/编辑/启停操作
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 加载地址列表 | 页面挂载 | 请求列表API | GET /api/admin/collect-address |
| F02 | 新增地址 | 点击新增 | 弹窗->选品牌(加载机床)->勾选机床->保存 | POST /api/admin/collect-address |
| F03 | 编辑地址 | 点击编辑 | 弹窗(回填+已选机床)->修改->保存 | PUT /api/admin/collect-address/{id} |
| F04 | 启停地址 | 点击启用/停用 | 确认->切换 | PUT /api/admin/collect-address/{id}/toggle |
**状态机**采集地址is_enabled1(启用)/0(停用)
**路由跳转**
- 地址名称链接 -> 采集地址详情页(/collect-address/:id)
### 05-02 采集地址详情页面
**路由**`/collect-address/:id`
**功能概述**:查看采集地址基本信息、关联机床列表、最近采集记录(含成功/失败/耗时、查看原始JSON入口、采集失败趋势图
**路由跳转**
- 机床名称 -> 设备详情页(/machine/:id)
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 05-01 | 采集地址页面 | 页面文件 | [05-01-采集地址页面.md](./05-01-采集地址页面.md) |
| 05-02 | 采集地址详情页面 | 页面文件 | [05-02-采集地址详情页面.md](./05-02-采集地址详情页面.md) |
---

@ -0,0 +1,10 @@
# 采集地址 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,126 @@
# 采集地址页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /collect-address |
| 权限 | admin |
| 入口 | 侧边栏采集地址 |
| 面包屑 | 首页 / 采集地址管理 |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 采集地址管理 │
├──────────────────────────────────────────────────────────┤
│ [操作栏] [+ 新增地址] │
├──────────────────────────────────────────────────────────┤
│ [列表区] │
│ 名称 | URL | 品牌 | 间隔 | 状态 | 上次采集 | 连续失败 | 操作 │
│ FANUC-A栋 | http://10.1.1.1/ | FANUC| 30s | 启用 | 3秒前 | 0 | [编辑][停用]│
│ FANUC-B栋 | http://10.1.2.1/ | FANUC| 60s | 启用 | 58秒前 | 0 | [编辑][停用]│
└──────────────────────────────────────────────────────────┘
### 3. 查询条件
无(地址数量少)。
### 4. 列表字段
| 字段名 | 列宽 | 排序 | 超长处理 | 对齐 |
|--------|------|------|---------|------|
| 名称 | 120px | y | tooltip | left |
| URL | 250px | - | tooltip | left |
| 品牌 | 100px | - | - | center |
| 采集间隔 | 80px | - | - | center |
| 状态 | 80px | - | - | center |
| 上次采集 | 120px | - | - | center |
| 连续失败 | 80px | - | - | center |
| 操作 | 120px | - | - | center |
### 5. 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 新增地址 | address:create | 页头 | 始终 | 打开新增弹窗 |
| 编辑 | address:update | 行操作 | 始终 | 打开编辑弹窗 |
| 启用/停用 | address:toggle | 行操作 | 始终 | 确认->切换 |
### 6. 弹窗规格
**新增/编辑采集地址弹窗:**
- 宽度600px遮罩有ESC关闭是(脏数据检测)
表单字段:
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 地址名称 | el-input maxlength=100 | 是 | - | 必填 | - |
| HTTP地址 | el-input maxlength=500 | 是 | - | 必填+URL格式 | - |
| 关联品牌 | el-select | 是 | - | 必填 | 选定后下方加载该品牌机床 |
| 采集间隔 | el-input-number min=5 max=300 | 是 | 30 | 必填+正整数 | - |
| 选择机床 | el-checkbox-group | 否 | 空 | - | 品牌变化时重新加载机床列表 |
机床选择区域说明:
- 允许不选机床(先创建地址,后续在机床管理中关联)
- 只显示属于该品牌且未分配到其他地址的机床(编辑时含当前已分配的)
- 每个checkbox显示device_code (机床名称) 车间 IP
### 7. 状态机
采集地址is_enabled
- 1(启用): el-tag success -> 可编辑/停用
- 0(停用): el-tag danger -> 可编辑/启用
### 8. 交互流程
- 加载:请求采集地址列表->渲染
- 新增:弹窗->选品牌(加载机床)->勾选机床->保存->关闭->刷新
- 编辑:弹窗(回填数据+已选机床)->修改->保存->关闭->刷新
- 启停:确认->调API->刷新
### 9. 空状态
列表无数据el-empty 暂无采集地址数据,点击新增地址添加
### 10. Mock数据
**GET /api/admin/collect-address 采集地址列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "name": "FANUC-A栋", "url": "http://10.1.1.1/", "brandName": "FANUC", "collectInterval": 30, "isEnabled": 1, "lastCollectTime": "2026-04-25T17:36:38", "failCount": 0, "machineCount": 32 },
{ "id": 2, "name": "FANUC-B栋", "url": "http://10.1.2.1/", "brandName": "FANUC", "collectInterval": 60, "isEnabled": 1, "lastCollectTime": "2026-04-25T17:35:38", "failCount": 0, "machineCount": 28 }
]}}
```
**POST /api/admin/collect-address 新增采集地址成功:**
```json
{ "code": 0, "message": "success", "data": { "id": 3, "name": "SIEMENS-C栋" }}
```
**GET /api/admin/collect-address/1/machines 地址下可选机床(弹窗联动):**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "deviceCode": "fanake_1.8", "name": "西-1.8", "workshopName": "A栋", "ipAddress": "10.1.1.8", "isAssigned": false },
{ "id": 2, "deviceCode": "fanake_1.10", "name": "西-1.10", "workshopName": "A栋", "ipAddress": "10.1.1.10", "isAssigned": true }
]}}
### 10. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 采集地址列表 | cnc_collect_address | 主表需JOIN品牌名 |
| 品牌下拉 | cnc_brand | 弹窗表单 |
| 可选机床列表 | cnc_machine | 按brand_id筛选+排除已分配其他地址的机床 |
| 机床-地址关联 | cnc_machine.collect_address_id | 机床归属地址关系 |

@ -0,0 +1,129 @@
# 采集地址详情页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /collect-address/:id |
| 权限 | admin |
| 入口 | 采集地址列表点击名称链接 / 仪表盘采集服务状态区点击地址名称 |
| 面包屑 | 首页 / 采集地址管理 / {地址名称} |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 采集地址管理 / FANUC-A栋 │
├──────────────────────────────────────────────────────────┤
│ [基本信息区] │
< 返回 采集地址详情FANUC-A栋 │
│ 名称FANUC-A栋 HTTP地址http://10.1.1.1/ │
│ 品牌FANUC 采集间隔30秒 │
│ 状态:启用 上次采集3秒前 │
│ 连续失败0次 总机床数32台 │
├──────────────────────────────────────────────────────────┤
│ [关联机床区] │
│ 机床名称 | device_code | 车间 | 在线 | 当前程序 | 零件数 │
│ 西-1.8 | fanake_1.8 | A栋 | 在线 | 1566.NC | 580 │
│ 西-1.10 | fanake_1.10 | A栋 | 在线 | O123.NC | 120 │
│ ... │
├──────────────────────────────────────────────────────────┤
│ [最近采集记录] [查看原始JSON] │
│ 采集时间 | 耗时 | 状态 | 机床数 | 失败数 │
│ 17:36:38 | 1.2s | 成功 | 32 | 0 │
│ 17:36:08 | 1.1s | 成功 | 32 | 0 │
│ 17:35:38 | 3.5s | 成功 | 31 | 1 │
│ 17:35:08 | - | 失败 | - | - │
├──────────────────────────────────────────────────────────┤
│ [采集失败趋势近7天折线图] │
│ [============图表区域============] │
└──────────────────────────────────────────────────────────┘
### 3. 数据区块
| 区块 | 展示字段 | 控件类型 | 刷新策略 |
|------|---------|---------|---------|
| 基本信息 | 名称、URL、品牌、间隔、状态、上次采集、连续失败、机床数 | 文本展示 | 页面加载时请求一次 |
| 关联机床 | 机床名称、device_code、车间、在线、当前程序、零件数 | el-table | 页面加载时请求一次 |
| 最近采集记录 | 采集时间、耗时、状态、机床数、失败数 | el-table | 页面加载时请求一次 |
| 采集失败趋势 | 日期、失败次数 | 折线图 | 页面加载时请求一次 |
### 4. 操作按钮
| 名称 | 位置 | 显示条件 | 点击行为 |
|------|------|---------|---------|
| 返回 | 页头左侧 | 始终 | router.back() |
| 机床名称 | 行内链接 | 始终 | 跳转机床详情页(/machine/:id) |
| 查看原始JSON | 采集记录表头 | 始终 | 弹窗显示选中采集记录的原始JSON |
### 5. 弹窗规格
**原始JSON查看弹窗**
- 宽度800px标题=原始采集JSON
- 内容代码高亮显示JSON只读不可编辑
- 支持:复制到剪贴板
### 6. 交互流程
- 加载请求地址详情API+关联机床API+最近采集记录API+失败趋势API->渲染
- 点击机床名称router.push到机床详情页
- 查看原始JSON点击"查看原始JSON"->弹窗显示最近一次成功采集的原始JSON或选择某条记录的JSON
- 返回router.back()
### 7. 空状态
- 关联机床无数据el-empty 该地址暂无关联机床
- 采集记录无数据el-empty 暂无采集记录
### 8. Mock数据
**GET /api/admin/collect-address/1 地址详情:**
```json
{ "code": 0, "data": {
"id": 1, "name": "FANUC-A栋", "url": "http://10.1.1.1/", "brandName": "FANUC",
"collectInterval": 30, "isEnabled": 1, "lastCollectTime": "2026-04-25T17:36:38",
"failCount": 0, "machineCount": 32
}}
```
**GET /api/admin/collect-address/1/machines 关联机床:**
```json
{ "code": 0, "data": { "items": [
{ "machineId": 1, "machineName": "西-1.8", "deviceCode": "fanake_1.8", "workshopName": "A栋", "isOnline": 1, "programName": "1566.NC", "partCount": 580 },
{ "machineId": 2, "machineName": "西-1.10", "deviceCode": "fanake_1.10", "workshopName": "A栋", "isOnline": 1, "programName": "O123.NC", "partCount": 120 }
]}}
```
**GET /api/admin/collect-address/1/collect-records 最近采集记录(日志库):**
```json
{ "code": 0, "data": { "items": [
{ "requestTime": "2026-04-25T17:36:38", "duration": 1200, "isSuccess": 1, "machineCount": 32, "failMachineCount": 0 },
{ "requestTime": "2026-04-25T17:36:08", "duration": 1100, "isSuccess": 1, "machineCount": 32, "failMachineCount": 0 },
{ "requestTime": "2026-04-25T17:35:38", "duration": 3500, "isSuccess": 1, "machineCount": 31, "failMachineCount": 1 },
{ "requestTime": "2026-04-25T17:35:08", "duration": null, "isSuccess": 0, "machineCount": null, "failMachineCount": null }
]}}
```
**GET /api/admin/collect-address/1/raw-json/123 原始JSON弹窗**
```json
{ "code": 0, "data": { "rawJson": "[{\"device\":\"fanake_1.8\",\"desc\":\"西-1.8\",\"tags\":[{\"id\":\"_io_status\",\"desc\":\"设备状态\",\"value\":\"1.00000\"},{\"id\":\"Tag5\",\"desc\":\"执行的NC主程序名\",\"value\":\"1566.NC\"},{\"id\":\"Tag8\",\"desc\":\"当前加工零件数\",\"value\":\"580.00000\"}]}]" }}
### 8. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 采集地址基本信息 | cnc_collect_address | 主表 |
| 关联机床列表 | cnc_machine | 按collect_address_id查询 |
| 最近采集记录 | log_collect_raw (日志库) | 按collect_address_id+时间倒序,跨库查询 |
| 原始JSON查看 | log_collect_raw.raw_json | 弹窗展示MEDIUMTEXT字段 |
| 采集失败趋势 | log_collect_raw聚合 | 按天统计is_success=0的次数 |

@ -0,0 +1,59 @@
# 员工管理 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
管理工人信息及工人-机床绑定关系(一对一绑定)。支持查看工人详情(绑定机床+历史产量)。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 06-01 | 员工管理页面 | /worker | 工人CRUD列表 |
| 06-02 | 员工详情页面 | /worker/:id | 基本信息+绑定机床+今日产量+7天趋势 |
## 页面功能详情
### 06-01 员工管理页面
**路由**`/worker`
**功能概述**工人CRUD列表支持新增/编辑/删除/批量启停,绑定机床管理
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 查询工人 | 点击查询/切换状态 | 重置page=1请求列表 | GET /api/admin/worker |
| F02 | 新增工人 | 点击新增 | 弹窗填写工号+姓名+绑定机床 | POST /api/admin/worker |
| F03 | 编辑工人 | 点击编辑 | 弹窗回填数据,修改后保存 | PUT /api/admin/worker/:id |
| F04 | 删除工人 | 点击删除(无绑定机床时) | 确认框->软删除 | DELETE /api/admin/worker/:id |
| F05 | 批量启停 | 勾选+底部栏操作 | 确认->批量API | PUT /api/admin/worker/batch-status |
| F06 | 查看详情 | 点击姓名链接 | 跳转详情页 | - |
**路由跳转**:点击姓名→/worker/:id员工详情页
### 06-02 员工详情页面
**路由**`/worker/:id`
**功能概述**:工人基本信息+绑定机床+今日产量+7天趋势只读
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 加载详情 | 页面进入 | 并行请求4个API | GET /api/admin/worker/:id + machines + production/today + production/trend |
| F02 | 跳转机床详情 | 点击机床名称 | router.push | - |
| F03 | 返回 | 点击返回 | router.back() | - |
**路由跳转**:点击机床名称→/machine/:id设备详情页
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 06-01 | 员工管理页面 | 页面文件 | [06-01-员工管理页面.md](./06-01-员工管理页面.md) |
| 06-02 | 员工详情页面 | 页面文件 | [06-02-员工详情页面.md](./06-02-员工详情页面.md) |
---

@ -0,0 +1,10 @@
# 员工管理 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,146 @@
# 员工管理页面
> 最后更新2026-04-26
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /worker |
| 权限 | admin |
| 入口 | 侧边栏员工管理 |
| 面包屑 | 首页 / 员工管理 |
### 2. 界面布局
```
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 员工管理 │
├──────────────────────────────────────────────────────────┤
│ [操作栏] [+ 新增工人] │
├──────────────────────────────────────────────────────────┤
│ [查询条件区] │
│ 状态[▼全部] 搜索[__________] [查询] [重置] │
├──────────────────────────────────────────────────────────┤
│ [列表区] │
│ [x] | 工号 | 姓名 | 状态 | 绑定机床数 | 绑定机床 | 操作 │
│ [x] | W001 | 张三 | 启用 | 2 | 西-1.8,西-2.0 | [编辑][删除] │
│ [x] | W002 | 李四 | 启用 | 1 | 西-1.10 | [编辑][删除] │
│ [x] | W003 | 王五 | 停用 | 0 | - | [编辑][启用] │
├──────────────────────────────────────────────────────────┤
│ [分页] 共50条 每页[20▼] < 1 2 3 >
├──────────────────────────────────────────────────────────┤
│ [批量操作栏] 已选2项 [批量停用] [批量启用] │
└──────────────────────────────────────────────────────────┘
```
### 3. 查询条件
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 状态 | el-select(启用/停用/全部) | 否 | 全部 | - | 无 |
| 关键字 | el-input placeholder=工号/姓名 | 否 | 空 | - | 无 |
### 4. 列表字段
| 字段名 | 列宽 | 排序 | 筛选 | 固定 | 超长处理 | 对齐 |
|--------|------|------|------|------|---------|------|
| 选择框 | 40px | - | - | left | - | center |
| 工号 | 120px | y | - | - | tooltip | left |
| 姓名 | 120px | y | - | - | tooltip | left |
| 状态 | 80px | - | - | - | - | center |
| 绑定机床数 | 100px | y | - | - | - | center |
| 绑定机床 | auto | - | - | - | tooltip(逗号分隔) | left |
| 操作 | 120px | - | - | right | - | center |
### 5. 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 新增工人 | worker:create | 页头 | 始终 | 打开新增弹窗 |
| 编辑 | worker:update | 行操作 | 始终 | 打开编辑弹窗 |
| 删除 | worker:delete | 行操作 | 启用状态且无绑定机床 | 确认->软删除 |
| 批量停用 | worker:disable | 底部栏 | 已选含启用项 | 确认->批量 |
| 批量启用 | worker:enable | 底部栏 | 已选含停用项 | 确认->批量 |
| 姓名链接 | - | 行内 | 始终 | 跳转工人详情页(/worker/:id) |
### 6. 弹窗规格
**新增/编辑工人弹窗:**
- 宽度500px遮罩有ESC关闭是(脏数据检测),标题=新增工人/编辑工人
表单字段:
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 工号 | el-input maxlength=50 | 是 | - | 必填+唯一性(新增时) | - |
| 姓名 | el-input maxlength=50 | 是 | - | 必填 | - |
| 绑定机床 | el-select multiple filterable | 否 | 空 | - | 仅显示未绑定其他工人的机床 |
说明:
- 弹窗中不设"状态"字段,新增默认启用
- 绑定机床下拉查询cnc_machine中未绑定其他工人的机床uk_machine约束确保一对一
- 编辑时回填当前已绑定机床+可选未绑定机床
### 7. 状态机
工人is_enabled
- 1(启用): el-tag success -> 可编辑/删除(无绑定机床时)/停用
- 0(停用): el-tag danger -> 可编辑/启用
删除前提:绑定机床数=0有绑定机床的工人不可删除需先解绑
### 8. 交互流程
- 加载请求工人列表API(含分页)->渲染表格
- 查询:点查询->重置page=1->请求列表API
- 重置:清空所有筛选条件->请求列表API
- 新增:弹窗->填写工号+姓名+选择绑定机床->保存->关闭弹窗->刷新列表
- 编辑:弹窗(回填数据)->修改->保存->关闭->刷新
- 删除:确认框"确定删除工人【{姓名}】?此操作不可恢复。 "->调API->成功->刷新列表
- 批量启停:勾选->底部栏显示->点操作->确认->批量API->刷新
- 姓名链接:跳转工人详情页
### 9. 空状态
列表无数据el-empty 暂无工人数据,点击新增工人添加
### 10. Mock数据
**GET /api/admin/worker 工人列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "code": "W001", "name": "张三", "isEnabled": 1, "machineCount": 2, "machineNames": "西-1.8,西-2.0" },
{ "id": 2, "code": "W002", "name": "李四", "isEnabled": 1, "machineCount": 1, "machineNames": "西-1.10" },
{ "id": 3, "code": "W003", "name": "王五", "isEnabled": 0, "machineCount": 0, "machineNames": "-" }
], "total": 50, "page": 1, "pageSize": 20 }}
```
**POST /api/admin/worker 新增工人成功:**
```json
{ "code": 0, "message": "success", "data": { "id": 4, "name": "赵六" }}
```
**GET /api/admin/worker/available-machines 可绑定机床下拉:**
```json
{ "code": 0, "data": { "items": [
{ "id": 5, "name": "东-2.5", "deviceCode": "siemens_2.5", "workshopName": "B栋" },
{ "id": 8, "name": "北-4.1", "deviceCode": "fanake_4.1", "workshopName": "C栋" }
]}}
```
### 11. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 工人列表(含分页) | cnc_worker | 主表需JOIN绑定机床数+机床名称 |
| 工号唯一性校验 | cnc_worker.uk_code | 新增时实时校验 |
| 可绑定机床下拉 | cnc_machine LEFT JOIN cnc_worker_machine | 查未绑定工人(not exists in cnc_worker_machine)的机床 |

@ -0,0 +1,113 @@
# 员工详情页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /worker/:id |
| 权限 | admin |
| 入口 | 员工管理列表点击工人姓名 / 仪表盘工人排行点击工人姓名 |
| 面包屑 | 首页 / 员工管理 / {工人姓名} |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 员工管理 / 张三 │
├──────────────────────────────────────────────────────────┤
│ [基本信息区] │
< 返回 工人详情:张三 │
│ 工号W001 姓名:张三 │
│ 状态:启用 绑定机床数2 │
├──────────────────────────────────────────────────────────┤
│ [绑定机床区] │
│ 机床名称 | device_code | 车间 | 品牌 | 在线状态 | 当前程序 │
│ 西-1.8 | fanake_1.8 | A栋 | FANUC| 在线 | 1566.NC │
│ 西-2.0 | fanake_2.0 | A栋 | FANUC| 离线 | - │
├──────────────────────────────────────────────────────────┤
│ [今日产量区] │
│ 机床名称 | 程序名 | 产量 | 运行时间 | 切削时间 │
│ 西-1.8 | 1566.NC | 580 | 4h20m | 3h50m │
│ 西-2.0 | - | - | - | - │
├──────────────────────────────────────────────────────────┤
│ [近7天产量趋势折线图] │
│ [============图表区域============] │
└──────────────────────────────────────────────────────────┘
### 3. 数据区块
| 区块 | 展示字段 | 控件类型 | 刷新策略 |
|------|---------|---------|---------|
| 基本信息 | 工号、姓名、状态、绑定机床数 | 文本展示 | 页面加载时请求一次 |
| 绑定机床 | 机床名称、device_code、车间、品牌、在线状态、当前程序 | el-table | 页面加载时请求一次 |
| 今日产量 | 机床名称、程序名、产量、运行时间、切削时间 | el-table | 页面加载时请求一次 |
| 近7天趋势 | 日期、产量 | 折线图 | 页面加载时请求一次 |
### 4. 操作按钮
| 名称 | 位置 | 显示条件 | 点击行为 |
|------|------|---------|---------|
| 返回 | 页头左侧 | 始终 | router.back() |
| 机床名称 | 行内链接 | 始终 | 跳转机床详情页(/machine/:id) |
### 5. 交互流程
- 加载请求工人详情API+绑定机床API+今日产量API+7天趋势API->渲染
- 点击机床名称router.push到机床详情页
- 返回router.back()
### 6. 空状态
- 绑定机床无数据el-empty 该工人暂无绑定机床
- 今日产量无数据el-empty 今日尚无产量数据
### 8. Mock数据
**GET /api/admin/worker/1 工人详情:**
```json
{ "code": 0, "data": { "id": 1, "code": "W001", "name": "张三", "isEnabled": 1, "machineCount": 2 }}
```
**GET /api/admin/worker/1/machines 绑定机床:**
```json
{ "code": 0, "data": { "items": [
{ "machineId": 1, "machineName": "西-1.8", "deviceCode": "fanake_1.8", "workshopName": "A栋", "brandName": "FANUC", "isOnline": 1, "programName": "1566.NC" },
{ "machineId": 2, "machineName": "西-2.0", "deviceCode": "fanake_2.0", "workshopName": "A栋", "brandName": "FANUC", "isOnline": 0, "programName": null }
]}}
```
**GET /api/admin/worker/1/production/today 今日产量:**
```json
{ "code": 0, "data": { "items": [
{ "machineName": "西-1.8", "programName": "1566.NC", "quantity": 580, "runTime": "4h20m", "cuttingTime": "3h50m" },
{ "machineName": "西-2.0", "programName": "-", "quantity": null, "runTime": "-", "cuttingTime": "-" }
]}}
```
**GET /api/admin/worker/1/production/trend 7天趋势**
```json
{ "code": 0, "data": { "items": [
{ "date": "2026-04-19", "quantity": 980 }, { "date": "2026-04-20", "quantity": 920 },
{ "date": "2026-04-21", "quantity": 1100 }, { "date": "2026-04-22", "quantity": 1050 },
{ "date": "2026-04-23", "quantity": 990 }, { "date": "2026-04-24", "quantity": 1080 },
{ "date": "2026-04-25", "quantity": 580 }
]}}
### 7. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 工人基本信息 | cnc_worker | 主表 |
| 绑定机床列表 | cnc_worker_machine + cnc_machine | 按worker_id查关联机床 |
| 今日产量(按机床+程序) | cnc_daily_production + cnc_machine | 按worker绑定的machine_id查询 |
| 近7天趋势 | cnc_worker_daily_summary | 按worker_id+近7天查询 |

@ -0,0 +1,45 @@
# 产量报表 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
按日期/车间/机床/工人维度查询产量汇总支持产量修正及审计支持导出Excel。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 07-01 | 产量报表页面 | /production | 待设计 |
## 页面功能详情
### 07-01 产量报表页面
**路由**`/production`
**功能概述**:按日期/车间/机床/工人维度查询日产量汇总支持产量修正含审计、导出Excel、数据缺失标记
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 查询产量 | 点击查询/切换条件 | 重置page=1请求列表+汇总 | GET /api/admin/production/daily + daily-summary |
| F02 | 重置条件 | 点击重置 | 恢复默认近7天请求 | 同上 |
| F03 | 导出Excel | 点击导出 | 按当前查询条件下载 | GET /api/admin/production/export |
| F04 | 修正产量 | 点击修正产量 | 弹窗输入修正值+原因,确认 | POST /api/admin/production/adjust |
| F05 | 查看修正记录 | 点击修正记录(已修正行) | 弹窗展示修正历史(只读) | GET /api/admin/production/adjustment-history |
**业务规则**
- 日状态data_missing时产量显示"-"而非0区分真0和缺数据
- 修正后is_adjusted=1修正记录写入cnc_production_adjustment审计表
- 导出按当前筛选条件(含日期范围+车间+机床+工人)
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 07-01 | 产量报表页面 | 页面文件 | [07-01-产量报表页面.md](./07-01-产量报表页面.md) |
---

@ -0,0 +1,10 @@
# 产量报表 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,173 @@
# 产量报表页面
> 最后更新2026-04-26
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /production |
| 权限 | admin |
| 入口 | 侧边栏产量报表 |
| 面包屑 | 首页 / 产量报表 |
### 2. 界面布局
```
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 产量报表 │
├──────────────────────────────────────────────────────────┤
│ [查询条件区] │
│ 日期范围[2026-04-19 ~ 2026-04-25] 车间[▼全部] │
│ 机床[▼全部] 工人[▼全部] 程序名[_______] │
│ [查询] [重置] [导出] │
├──────────────────────────────────────────────────────────┤
│ [汇总统计区] │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │总产量 │ │运行机床│ │切削总时│ │平均产量│ │
│ │8,520 │ │ 142 │ │580h │ │ 60 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
├──────────────────────────────────────────────────────────┤
│ [列表区] │
│ 日期 | 机床 | 程序名 | 产量 | 运行时间 | 切削时间 | 日状态 | 修正 | 操作 │
│ 2026-04-25| 西-1.8 | 1566.NC | 580 | 4h20m | 3h50m | 正常 | - | [修正产量] │
│ 2026-04-25| 东-2.5 | A456.NC | - | - | - | 缺失 | - | [修正产量] │
│ 2026-04-25| 北-4.1 | B789.NC | 310 | 2h10m | 1h50m | 正常 | ✓ | [修正记录] │
├──────────────────────────────────────────────────────────┤
│ [分页] 共1200条 每页[20▼] < 1 2 3 ... 60 >
└──────────────────────────────────────────────────────────┘
```
### 3. 查询条件
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 日期范围 | el-date-picker type=daterange | 是 | 近7天(含今日) | 必填+结束日期≥开始日期 | 无 |
| 车间 | el-select | 否 | 全部 | - | 联动机床下拉(按车间筛选) |
| 机床 | el-select filterable | 否 | 全部 | - | 受车间联动 |
| 工人 | el-select filterable | 否 | 全部 | - | 无 |
| 程序名 | el-input | 否 | 空 | - | 无 |
### 4. 列表字段
| 字段名 | 列宽 | 排序 | 筛选 | 固定 | 超长处理 | 对齐 |
|--------|------|------|------|------|---------|------|
| 日期 | 110px | y | - | left | - | center |
| 机床名称 | 120px | y | - | - | tooltip | left |
| 程序名 | 140px | y | - | - | tooltip | left |
| 产量 | 80px | y | - | - | - | center |
| 运行时间 | 100px | - | - | - | - | center |
| 切削时间 | 100px | - | - | - | - | center |
| 日状态 | 80px | - | 下拉 | - | - | center |
| 修正标记 | 80px | - | - | - | - | center |
| 操作 | 120px | - | - | right | - | center |
### 5. 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 查询 | - | 查询区 | 始终 | 重置page=1->请求列表 |
| 重置 | - | 查询区 | 始终 | 清空条件->请求列表 |
| 导出 | production:export | 查询区 | 始终 | 按当前查询条件导出Excel |
| 修正产量 | production:adjust | 行操作 | 始终 | 打开修正弹窗 |
| 修正记录 | - | 行操作 | is_adjusted=1 | 打开修正历史弹窗(只读) |
### 6. 弹窗规格
**产量修正弹窗:**
- 宽度500px遮罩有ESC关闭是(脏数据检测),标题=修正产量
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 当前产量 | el-input disabled | - | 原始产量 | - | - |
| 修正后产量 | el-input-number min=0 | 是 | 原始产量 | 必填+非负整数 | - |
| 修正原因 | el-input type=textarea maxlength=500 | 是 | - | 必填 | - |
**修正历史弹窗(只读):**
- 宽度600px标题=修正记录
| 展示字段 | 说明 |
|---------|------|
| 修正时间 | created_at |
| 修正前 | old_value |
| 修正后 | new_value |
| 修正原因 | reason |
### 7. 状态机
日状态(data_status)
- normal(正常): 文本"正常" 灰色 -> 产量正常显示
- offline(离线): 文本"离线" el-tag danger -> 产量显示0
- data_missing(数据缺失): 文本"缺失" el-tag warning -> 产量显示"-"(非0)
修正标记:
- is_adjusted=0: 显示"-"
- is_adjusted=1: 显示"✓" el-tag primary
### 8. 交互流程
- 加载默认近7天->请求列表API+汇总统计API->渲染
- 查询:选条件->查询->重置page=1->请求列表+汇总
- 重置:清空条件(恢复默认近7天)->请求
- 导出调API下载Excel(按当前查询条件导出)
- 修正产量:弹窗->输入修正后产量+原因->确认"确定修正产量?修正后将记录审计日志。 "->调API->关闭->刷新列表
- 修正记录:弹窗(只读)->展示修正历史->关闭
### 9. 空状态
列表无数据el-empty 未找到匹配的产量数据,请调整查询条件
汇总统计:无数据时各卡片显示"-"
### 10. Mock数据
**GET /api/admin/production/daily-summary 汇总统计:**
```json
{ "code": 0, "data": { "totalQuantity": 8520, "activeMachineCount": 142, "totalCuttingTime": "580h", "avgQuantityPerMachine": 60 }}
```
**GET /api/admin/production/daily 产量列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "date": "2026-04-25", "machineName": "西-1.8", "programName": "1566.NC", "quantity": 580, "runTime": "4h20m", "cuttingTime": "3h50m", "dataStatus": "normal", "isAdjusted": 0, "adjustedQuantity": null },
{ "id": 2, "date": "2026-04-25", "machineName": "东-2.5", "programName": "A456.NC", "quantity": null, "runTime": null, "cuttingTime": null, "dataStatus": "data_missing", "isAdjusted": 0, "adjustedQuantity": null },
{ "id": 3, "date": "2026-04-25", "machineName": "北-4.1", "programName": "B789.NC", "quantity": 310, "runTime": "2h10m", "cuttingTime": "1h50m", "dataStatus": "normal", "isAdjusted": 1, "adjustedQuantity": 320 }
], "total": 1200, "page": 1, "pageSize": 20 }}
```
**POST /api/admin/production/adjust 修正产量:**
```json
{ "code": 0, "message": "success", "data": null }
```
**GET /api/admin/production/adjustment-history?target_id=3 修正历史:**
```json
{ "code": 0, "data": { "items": [
{ "createdAt": "2026-04-25 15:30:00", "oldValue": 310, "newValue": 320, "reason": "传感器计数偏差,手工校准" }
]}}
```
**GET /api/admin/production/export 导出(返回文件流):**
二进制Excel文件Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
### 11. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 日产量列表(含分页) | cnc_daily_production + cnc_machine | 主表需JOIN机床名+车间名 |
| 日状态 | cnc_machine_daily_status | 按machine_id+date关联 |
| 汇总统计 | cnc_daily_production | 按日期范围聚合SUM/COUNT/AVG |
| 车间下拉 | cnc_workshop | 查询条件 |
| 机床下拉 | cnc_machine | 查询条件,受车间联动 |
| 工人下拉 | cnc_worker | 查询条件 |
| 产量修正写入 | cnc_daily_production.adjusted_quantity | 更新修正后产量+is_adjusted=1 |
| 修正审计记录 | cnc_production_adjustment | 写入修正前/后值+原因 |
| 修正历史查询 | cnc_production_adjustment | 按target_table+target_id查询 |

@ -0,0 +1,41 @@
# 告警中心 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
查看系统告警(采集失败/设备离线/产量异常/未知设备/服务错误),支持标记已处理。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 08-01 | 告警中心页面 | /alert | 待设计 |
## 页面功能详情
### 08-01 告警中心页面
**路由**`/alert`
**功能概述**:查看系统告警(采集失败/设备离线/产量异常/未知设备/服务错误),支持单个/批量标记已处理
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 查询告警 | 点击查询/切换条件 | 重置page=1请求列表+统计 | GET /api/admin/alert + statistics |
| F02 | 标记已处理 | 点击行操作 | 确认框->标记 | PUT /api/admin/alert/:id/resolve |
| F03 | 批量标记 | 勾选+批量操作 | 确认框->批量标记 | PUT /api/admin/alert/batch-resolve |
| F04 | 查看详情 | 点击查看(已处理行) | 弹窗展示完整告警详情 | - (行数据已含) |
**告警类型**collect_fail(采集失败) / device_offline(设备离线) / production_anomaly(产量异常) / unknown_device(未知设备) / service_error(服务错误)
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 08-01 | 告警中心页面 | 页面文件 | [08-01-告警中心页面.md](./08-01-告警中心页面.md) |
---

@ -0,0 +1,10 @@
# 告警中心 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,153 @@
# 告警中心页面
> 最后更新2026-04-26
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /alert |
| 权限 | admin |
| 入口 | 侧边栏告警中心 |
| 面包屑 | 首页 / 告警中心 |
### 2. 界面布局
```
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 告警中心 │
├──────────────────────────────────────────────────────────┤
│ [查询条件区] │
│ 告警类型[▼全部] 处理状态[▼未处理] 时间范围[__________] │
│ 机床[▼全部] 关键字[___________] [查询] [重置] │
├──────────────────────────────────────────────────────────┤
│ [统计区] │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │未处理 │ │采集失败│ │设备离线│ │产量异常│ │未知设备│ │
│ │ 15 │ │ 5 │ │ 6 │ │ 2 │ │ 2 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
├──────────────────────────────────────────────────────────┤
│ [操作栏] [批量标记已处理] │
├──────────────────────────────────────────────────────────┤
│ [列表区] │
│ [x] | 时间 | 类型 | 标题 | 机床 | 详情 | 状态 | 操作 │
│ [x] | 2026-04-25 17:30 | 采集失败 | 采集请求失败 | 西-1.8 | HTTP超时(30s) | 未处理 | [标记已处理] │
│ [x] | 2026-04-25 17:00 | 设备离线 | 设备离线 | 东-2.5 | 连续3次Ping失败 | 未处理 | [标记已处理] │
│ [x] | 2026-04-25 16:00 | 产量异常 | 产量骤降 | 南-3.1 | 产量下降>50% | 已处理 | [查看] │
├──────────────────────────────────────────────────────────┤
│ [分页] 共320条 每页[20▼] < 1 2 3 ... 16 >
└──────────────────────────────────────────────────────────┘
```
### 3. 查询条件
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 告警类型 | el-select(采集失败/设备离线/产量异常/未知设备/服务错误/全部) | 否 | 全部 | - | 无 |
| 处理状态 | el-select(未处理/已处理/全部) | 否 | 未处理 | - | 无 |
| 时间范围 | el-date-picker type=daterange | 否 | 空 | - | 无 |
| 机床 | el-select filterable | 否 | 全部 | - | 无 |
| 关键字 | el-input placeholder=标题/详情 | 否 | 空 | - | 无 |
### 4. 列表字段
| 字段名 | 列宽 | 排序 | 筛选 | 固定 | 超长处理 | 对齐 |
|--------|------|------|------|------|---------|------|
| 选择框 | 40px | - | - | left | - | center |
| 告警时间 | 170px | y | - | - | - | center |
| 告警类型 | 100px | - | - | - | - | center |
| 标题 | 160px | - | - | - | tooltip | left |
| 机床 | 100px | - | - | - | tooltip | center |
| 详情 | auto | - | - | - | tooltip | left |
| 处理状态 | 80px | - | - | - | - | center |
| 操作 | 120px | - | - | right | - | center |
### 5. 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 批量标记已处理 | alert:resolve | 页头 | 已选含未处理项 | 确认->批量标记 |
| 标记已处理 | alert:resolve | 行操作 | is_resolved=0 | 确认->标记已处理 |
| 查看 | - | 行操作 | is_resolved=1 | 弹窗展示详情(只读) |
### 6. 弹窗规格
**告警详情弹窗(只读):**
- 宽度600px标题=告警详情
| 展示字段 | 说明 |
|---------|------|
| 告警时间 | created_at |
| 告警类型 | alert_type |
| 标题 | title |
| 机床 | 关联机床名 |
| 采集地址 | 关联采集地址名 |
| 详情 | detail完整文本 |
| 处理状态 | is_resolved |
| 处理时间 | resolved_at |
### 7. 状态机
告警类型(alert_type)
- collect_fail(采集失败): el-tag warning
- device_offline(设备离线): el-tag danger
- production_anomaly(产量异常): el-tag warning
- unknown_device(未知设备): el-tag info
- service_error(服务错误): el-tag danger
处理状态(is_resolved)
- 0(未处理): el-tag danger -> 可标记已处理
- 1(已处理): el-tag success -> 只读查看
### 8. 交互流程
- 加载:默认查未处理告警->请求列表API+统计API->渲染
- 查询:选条件->查询->重置page=1->请求列表+统计
- 重置:清空条件(恢复默认"未处理")->请求
- 标记已处理:确认"确定标记为已处理? "->调API->刷新列表+统计
- 批量标记:勾选未处理告警->点批量标记->确认"确定对选中的{N}项标记为已处理? "->调API->刷新
- 查看详情:弹窗(只读)->关闭
### 9. 空状态
列表无数据el-empty 暂无告警数据
统计区各类型计数为0时显示0
### 10. Mock数据
**GET /api/admin/alert/statistics 告警统计:**
```json
{ "code": 0, "data": { "unresolved": 15, "collectFail": 5, "deviceOffline": 6, "productionAnomaly": 2, "unknownDevice": 2, "serviceError": 0 }}
```
**GET /api/admin/alert 告警列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "createdAt": "2026-04-25T17:30:00", "alertType": "collect_fail", "title": "采集请求失败", "machineName": "西-1.8", "detail": "HTTP超时(30s)连续失败3次", "isResolved": 0, "resolvedAt": null },
{ "id": 2, "createdAt": "2026-04-25T17:00:00", "alertType": "device_offline", "title": "设备离线", "machineName": "东-2.5", "detail": "连续3次Ping失败IP:10.1.2.5", "isResolved": 0, "resolvedAt": null },
{ "id": 3, "createdAt": "2026-04-25T16:00:00", "alertType": "production_anomaly", "title": "产量骤降", "machineName": "南-3.1", "detail": "近1小时产量较前1小时下降>50%", "isResolved": 1, "resolvedAt": "2026-04-25T16:30:00" },
{ "id": 4, "createdAt": "2026-04-25T15:00:00", "alertType": "unknown_device", "title": "未知设备接入", "machineName": null, "detail": "采集地址FANUC-A栋返回未注册设备: fanake_9.9", "isResolved": 0, "resolvedAt": null }
], "total": 320, "page": 1, "pageSize": 20 }}
```
**POST /api/admin/alert/resolve 标记已处理:**
```json
{ "code": 0, "message": "success", "data": null }
```
### 11. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 告警列表(含分页) | cnc_alert | 主表需JOIN机床名 |
| 告警统计(按类型) | cnc_alert | GROUP BY alert_type, is_resolved |
| 标记已处理 | cnc_alert.is_resolved/resolved_at | 批量更新 |
| 机床下拉 | cnc_machine | 查询条件 |

@ -0,0 +1,47 @@
# 系统设置 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
系统配置项管理+车间管理。使用Tab页切换系统配置Tabkey-value配置项+编辑+修改密码和车间管理Tab车间CRUD数据量极小
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 09-01 | 系统设置页面 | /settings | 配置项管理+修改密码+车间管理Tab切换 |
## 页面功能详情
### 09-01 系统设置页面
**路由**`/settings`
**功能概述**三Tab切换——系统配置(key-value编辑)、车间管理(CRUD)、修改密码
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 编辑配置项 | Tab1点击编辑 | 弹窗修改值,保存 | PUT /api/admin/sys-config/:id |
| F02 | 重置Token | Tab1点击重置(api_token/collector_api_key) | 确认框,含警告文案 | POST /api/admin/sys-config/reset-token |
| F03 | 新增车间 | Tab2点击新增 | 弹窗填写名称+排序 | POST /api/admin/workshop |
| F04 | 编辑车间 | Tab2点击编辑 | 弹窗回填,修改后保存 | PUT /api/admin/workshop/:id |
| F05 | 删除车间 | Tab2点击删除(无关联机床) | 确认框->删除 | DELETE /api/admin/workshop/:id |
| F06 | 启停车间 | Tab2点击启停 | 确认框->切换状态 | PUT /api/admin/workshop/:id/toggle |
| F07 | 修改密码 | Tab3填写+确认 | 校验->调API->成功->清Token->跳登录 | POST /api/admin/change-password |
**业务规则**
- 车间删除前置条件该车间下无机床cnc_machine.workshop_id约束
- 修改密码成功后立即清除Token跳转登录页重新认证
- 敏感配置项(api_token/collector_api_key)显示"********",编辑时眼睛图标切换可见
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 09-01 | 系统设置页面 | 页面文件 | [09-01-系统设置页面.md](./09-01-系统设置页面.md) |
---

@ -0,0 +1,10 @@
# 系统设置 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,245 @@
# 系统设置页面
> 最后更新2026-04-26
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /settings |
| 权限 | admin |
| 入口 | 侧边栏系统设置 |
| 面包屑 | 首页 / 系统设置 |
### 2. 界面布局
```
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 系统设置 │
├──────────────────────────────────────────────────────────┤
│ [Tab切换] [系统配置] [车间管理] [修改密码] │
├──────────────────────────────────────────────────────────┤
│ │
│ ====== Tab1: 系统配置 ====== │
│ │
│ [查询条件区] │
│ 关键字[___________] [查询] [重置] │
│ │
│ [列表区] │
│ 配置项 | 值 | 类型 | 说明 | 操作 │
│ ping_interval | 60 | number| Ping间隔| [编辑] │
│ collect_retry | 3 | number| 重试次数| [编辑] │
│ daily_summary | 01:00 | string| 汇总时间| [编辑] │
│ log_retention | 90 | number| 日志保留| [编辑] │
│ api_token | ******** | string| API Token| [编辑][重置] │
│ │
│ ====== Tab2: 车间管理 ====== │
│ │
│ [+ 新增车间] │
│ [列表区] │
│ 车间名称 | 排序 | 状态 | 操作 │
│ A栋 | 1 | 启用 | [编辑][删除] │
│ B栋 | 2 | 启用 | [编辑][删除] │
│ C栋 | 3 | 停用 | [编辑][启用] │
│ │
│ ====== Tab3: 修改密码 ====== │
│ │
│ ┌──────────────────────────┐ │
│ │ 当前密码 [__________] │ │
│ │ 新密码 [__________] │ │
│ │ 确认密码 [__________] │ │
│ │ [确认修改] │ │
│ └──────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
### 3. Tab1-系统配置
#### 查询条件
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 关键字 | el-input placeholder=配置项/说明 | 否 | 空 | - | 无 |
#### 列表字段
| 字段名 | 列宽 | 排序 | 超长处理 | 对齐 |
|--------|------|------|---------|------|
| 配置项(config_key) | 200px | - | tooltip | left |
| 配置值(config_value) | auto | - | tooltip | left |
| 值类型(value_type) | 80px | - | - | center |
| 说明(description) | 200px | - | tooltip | left |
| 操作 | 160px | - | - | center |
#### 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 编辑 | settings:update | 行操作 | 始终 | 打开编辑弹窗 |
| 重置Token | settings:reset-token | 行操作 | config_key=api_token或collector_api_key | 确认"确定重置{配置项}?重置后需同步更新相关服务配置。 "->调API |
#### 弹窗规格
**编辑配置项弹窗:**
- 宽度500px标题=编辑配置项
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 配置项 | el-input disabled | - | config_key | - | - |
| 配置值 | el-input(根据value_type切换number/string) | 是 | 当前值 | 必填 | value_type=number时控件为el-input-number |
| 说明 | el-input disabled | - | description | - | - |
说明:敏感字段(api_token/collector_api_key)显示为"********",编辑弹窗中也默认遮蔽,点击眼睛图标切换可见。
### 4. Tab2-车间管理
#### 列表字段
| 字段名 | 列宽 | 排序 | 超长处理 | 对齐 |
|--------|------|------|---------|------|
| 车间名称 | 200px | - | tooltip | left |
| 排序 | 80px | y | - | center |
| 状态 | 80px | - | - | center |
| 操作 | 160px | - | - | center |
#### 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 新增车间 | workshop:create | 页头 | 始终 | 打开新增弹窗 |
| 编辑 | workshop:update | 行操作 | 始终 | 打开编辑弹窗 |
| 删除 | workshop:delete | 行操作 | 启用状态且无关联机床 | 确认->删除 |
| 启用/停用 | workshop:toggle | 行操作 | 始终 | 确认->切换状态 |
#### 弹窗规格
**新增/编辑车间弹窗:**
- 宽度400px标题=新增车间/编辑车间
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 车间名称 | el-input maxlength=100 | 是 | - | 必填+唯一性 | - |
| 排序号 | el-input-number min=0 max=99 | 是 | 末尾 | 必填+正整数 | - |
### 5. Tab3-修改密码
#### 表单字段
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 当前密码 | el-input type=password show-password | 是 | - | 必填 | - |
| 新密码 | el-input type=password show-password | 是 | - | 必填+长度8-32位 | - |
| 确认密码 | el-input type=password show-password | 是 | - | 必填+与新密码一致 | 新密码变化时重新校验 |
#### 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 确认修改 | - | 表单底部 | 始终 | 校验通过->调API->成功提示+清空表单 |
### 6. 状态机
车间is_enabled
- 1(启用): el-tag success -> 可编辑/停用/删除(无机床关联时)
- 0(停用): el-tag danger -> 可编辑/启用
删除前提:该车间下无机床(有关联机床的不可删除)
### 7. 交互流程
**Tab1-系统配置:**
- 加载:请求配置项列表->渲染
- 查询:关键字搜索->重置page=1->请求列表
- 编辑:弹窗->修改值->保存->关闭->刷新列表
- 重置Token确认->调API重置->显示新值->提示"请同步更新相关服务配置"
**Tab2-车间管理:**
- 加载:请求车间列表->渲染(数据量极小,无需分页)
- 新增:弹窗->填写->保存->关闭->刷新
- 编辑:弹窗(回填)->修改->保存->关闭->刷新
- 删除:确认"确定删除车间【{名称}】?此操作不可恢复。 "->调API->刷新
- 启停:确认->调API->刷新
**Tab3-修改密码:**
- 填写表单->确认修改->校验->调API->成功提示"密码修改成功,请重新登录"->清除Token->跳转/login
### 8. 空状态
系统配置列表无数据el-empty 暂无配置项
车间列表无数据el-empty 暂无车间数据,点击新增车间添加
### 9. Mock数据
**GET /api/admin/sys-config 系统配置列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "configKey": "ping_interval", "configValue": "60", "valueType": "number", "description": "Ping检测间隔(秒)" },
{ "id": 2, "configKey": "collect_retry_count", "configValue": "3", "valueType": "number", "description": "采集失败重试次数" },
{ "id": 3, "configKey": "collect_retry_interval", "configValue": "30", "valueType": "number", "description": "采集重试间隔(秒)" },
{ "id": 4, "configKey": "collect_fail_alert_threshold", "configValue": "5", "valueType": "number", "description": "连续失败N次触发告警" },
{ "id": 5, "configKey": "daily_summary_time", "configValue": "01:00", "valueType": "string", "description": "日终汇总执行时间" },
{ "id": 6, "configKey": "log_retention_days", "configValue": "90", "valueType": "number", "description": "原始采集日志保留天数" },
{ "id": 7, "configKey": "bigscreen_refresh_interval", "configValue": "10", "valueType": "number", "description": "大屏刷新间隔(秒)" },
{ "id": 8, "configKey": "api_token", "configValue": "********", "valueType": "string", "description": "前端API Token" },
{ "id": 9, "configKey": "collector_api_port", "configValue": "5800", "valueType": "number", "description": "采集服务管理API端口" },
{ "id": 10, "configKey": "collector_api_key", "configValue": "********", "valueType": "string", "description": "采集服务间通信API Key" }
]}}
```
**PUT /api/admin/sys-config/1 编辑配置项:**
```json
{ "code": 0, "message": "success", "data": null }
```
**POST /api/admin/sys-config/reset-token 重置Token**
```json
{ "code": 0, "data": { "configKey": "api_token", "newValue": "eyJhbGciOiJIUzI1NiJ9.new.random.token" }}
```
**GET /api/admin/workshop 车间列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "name": "A栋", "sortOrder": 1, "isEnabled": 1, "machineCount": 32 },
{ "id": 2, "name": "B栋", "sortOrder": 2, "isEnabled": 1, "machineCount": 28 },
{ "id": 3, "name": "C栋", "sortOrder": 3, "isEnabled": 0, "machineCount": 0 }
]}}
```
**POST /api/admin/workshop 新增车间:**
```json
{ "code": 0, "message": "success", "data": { "id": 4, "name": "D栋" }}
```
**POST /api/admin/change-password 修改密码:**
```json
{ "code": 0, "message": "success", "data": null }
```
**POST /api/admin/change-password 修改密码失败(旧密码错误):**
```json
{ "code": 40001, "message": "当前密码不正确", "data": null }
```
### 10. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 系统配置列表 | cnc_sys_config | 主表 |
| 编辑配置项 | cnc_sys_config.config_value | 按config_key更新 |
| 重置Token | cnc_sys_config | 生成新随机Token写入 |
| 车间列表 | cnc_workshop | 主表+关联机床数 |
| 车间名称唯一性 | cnc_workshop.name UNIQUE | 新增/编辑时校验 |
| 车间删除约束 | cnc_machine.workshop_id | 有关联机床时禁止删除 |
| 修改密码 | admin密码校验 | 验证旧密码+写入新密码哈希 |

@ -0,0 +1,10 @@
# 车间管理 索引
> 版本v1.0
> 最后更新2026-04-25
---
⚠️ 本模块已合并至 **09-系统设置**作为系统设置页面的一个Tab页。车间数据量极小约3条不单独占一级侧边栏。
---

@ -0,0 +1,10 @@
# 车间管理 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,4 @@
<!-- 待设计 -->
> 页面类型:列表页(数据量极小,无分页)
> 必填项参照:`02-前端全局规范.md` → 列表页必填项

@ -0,0 +1,44 @@
# 操作日志 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
查看产量修正审计日志和系统运行日志,只读不可编辑。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 11-01 | 操作日志页面 | /log | 待设计 |
## 页面功能详情
### 11-01 操作日志页面
**路由**`/log`
**功能概述**双Tab只读查看——产量修正审计日志可导出+系统运行日志(含堆栈详情)
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 查询修正日志 | Tab1查询 | 重置page=1请求列表 | GET /api/admin/log/adjustment |
| F02 | 导出修正日志 | Tab1导出 | 下载Excel | GET /api/admin/log/adjustment/export |
| F03 | 查询系统日志 | Tab2查询 | 重置page=1请求列表 | GET /api/admin/log/system |
| F04 | 查看日志详情 | Tab2点击行 | 弹窗展示完整消息+堆栈+附加数据 | - (行数据已含) |
**业务规则**
- 全部只读,无编辑/删除操作
- 产量修正日志来源于cnc_production_adjustment审计表
- 系统运行日志来源于日志库log_system表按月分区
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 11-01 | 操作日志页面 | 页面文件 | [11-01-操作日志页面.md](./11-01-操作日志页面.md) |
---

@ -0,0 +1,10 @@
# 操作日志 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,181 @@
# 操作日志页面
> 最后更新2026-04-26
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /log |
| 权限 | admin |
| 入口 | 侧边栏操作日志 |
| 面包屑 | 首页 / 操作日志 |
### 2. 界面布局
```
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 操作日志 │
├──────────────────────────────────────────────────────────┤
│ [Tab切换] [产量修正日志] [系统运行日志] │
├──────────────────────────────────────────────────────────┤
│ │
│ ====== Tab1: 产量修正日志 ====== │
│ │
│ [查询条件区] │
│ 时间范围[__________] 目标[▼全部] 关键字[________] │
│ [查询] [重置] [导出] │
│ │
│ [列表区] │
│ 修正时间 | 目标表 | 目标ID | 修正前 | 修正后 | 原因 | 操作IP │
│ 2026-04-25 15:30 | daily_production | 3 | 310 | 320 | 传感器计数偏差 | 192.168.1.5│
│ 2026-04-24 10:15 | worker_summary | 12 | 850 | 900 | 漏计补录 | 192.168.1.5│
│ │
│ [分页] 共80条 每页[20▼] < 1 2 3 4 >
│ │
│ ====== Tab2: 系统运行日志 ====== │
│ │
│ [查询条件区] │
│ 日志级别[▼全部] 来源[▼全部] 时间范围[__________] │
│ 关键字[___________] [查询] [重置] │
│ │
│ [列表区] │
│ 时间 | 级别 | 来源 | 消息 │
│ 2026-04-25 17:36 | INFO | CncCollector | 采集完成:32台成功 │
│ 2026-04-25 17:35 | WARN | CncCollector | 采集失败:1台超时 │
│ 2026-04-25 17:00 | ERROR | CncCollector | 连接拒绝:10.1.2.5 │
│ │
│ [分页] 共5600条 每页[20▼] < 1 2 3 ... 280 >
└──────────────────────────────────────────────────────────┘
```
### 3. Tab1-产量修正日志
#### 查询条件
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 时间范围 | el-date-picker type=daterange | 否 | 空 | - | 无 |
| 目标表 | el-select(daily_production/worker_daily_summary/全部) | 否 | 全部 | - | 无 |
| 关键字 | el-input placeholder=原因/操作IP | 否 | 空 | - | 无 |
#### 列表字段
| 字段名 | 列宽 | 排序 | 超长处理 | 对齐 |
|--------|------|------|---------|------|
| 修正时间 | 170px | y(默认倒序) | - | center |
| 目标表 | 150px | - | tooltip | left |
| 目标ID | 80px | - | - | center |
| 修正前 | 80px | - | - | center |
| 修正后 | 80px | - | - | center |
| 修正原因 | auto | - | tooltip | left |
| 操作IP | 130px | - | - | center |
### 4. Tab2-系统运行日志
#### 查询条件
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 日志级别 | el-select(ERROR/WARN/INFO/DEBUG/全部) | 否 | 全部 | - | 无 |
| 来源 | el-select(CncCollector/WebApi/Scheduler/全部) | 否 | 全部 | - | 无 |
| 时间范围 | el-date-picker type=daterange | 否 | 空 | - | 无 |
| 关键字 | el-input placeholder=消息内容 | 否 | 空 | - | 无 |
#### 列表字段
| 字段名 | 列宽 | 排序 | 超长处理 | 对齐 |
|--------|------|------|---------|------|
| 时间 | 170px | y(默认倒序) | - | center |
| 级别 | 80px | - | - | center |
| 来源 | 130px | - | tooltip | left |
| 消息 | auto | - | tooltip+点击展开详情 | left |
### 5. 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 查询 | - | 查询区 | 始终 | 重置page=1->请求列表 |
| 重置 | - | 查询区 | 始终 | 清空条件->请求列表 |
| 导出 | log:export | 查询区 | Tab1产量修正日志 | 按当前查询条件导出Excel |
| 查看详情 | - | 行操作 | Tab2系统运行日志 | 弹窗展示完整消息+堆栈 |
### 6. 弹窗规格
**系统日志详情弹窗(只读):**
- 宽度700px标题=日志详情
| 展示字段 | 说明 |
|---------|------|
| 时间 | created_at |
| 级别 | log_level |
| 来源 | source |
| 消息 | message完整文本支持换行 |
| 堆栈信息 | stack_trace代码格式化展示无则为空 |
| 附加数据 | extra_dataJSON格式化展示 |
### 7. 状态机
日志级别(log_level)
- ERROR: el-tag danger
- WARN: el-tag warning
- INFO: el-tag success
- DEBUG: el-tag info
### 8. 交互流程
**Tab1-产量修正日志:**
- 加载:请求修正日志列表->渲染
- 查询:选条件->查询->重置page=1->请求列表
- 重置:清空条件->请求
- 导出调API下载Excel
**Tab2-系统运行日志:**
- 加载:请求系统日志列表->渲染
- 查询:选条件->查询->重置page=1->请求列表
- 重置:清空条件->请求
- 查看详情:弹窗(只读)->展示完整消息+堆栈+附加数据->关闭
### 9. 空状态
修正日志无数据el-empty 暂无产量修正记录
系统日志无数据el-empty 暂无系统日志
查询无结果el-empty 未找到匹配的日志,请调整查询条件
### 10. Mock数据
**GET /api/admin/log/adjustment 产量修正日志:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "createdAt": "2026-04-25T15:30:00", "targetTable": "daily_production", "targetId": 3, "oldValue": 310, "newValue": 320, "reason": "传感器计数偏差,手工校准", "operatorIp": "192.168.1.5" },
{ "id": 2, "createdAt": "2026-04-24T10:15:00", "targetTable": "worker_daily_summary", "targetId": 12, "oldValue": 850, "newValue": 900, "reason": "漏计补录,夜班产量未计入", "operatorIp": "192.168.1.5" }
], "total": 80, "page": 1, "pageSize": 20 }}
```
**GET /api/admin/log/system 系统运行日志:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "createdAt": "2026-04-25T17:36:38", "logLevel": "INFO", "source": "CncCollector", "message": "采集完成: 32台成功, 0台失败", "stackTrace": null, "extraData": null },
{ "id": 2, "createdAt": "2026-04-25T17:35:38", "logLevel": "WARN", "source": "CncCollector", "message": "采集失败: 1台超时(fanake_2.5)", "stackTrace": null, "extraData": "{\"machineId\":4,\"addressId\":2,\"error\":\"timeout\"}" },
{ "id": 3, "createdAt": "2026-04-25T17:00:00", "logLevel": "ERROR", "source": "CncCollector", "message": "连接拒绝: 10.1.2.5", "stackTrace": "System.Net.Http.HttpRequestException: Connection refused\n at CncCollector.HttpClientWrapper.SendAsync()", "extraData": null },
{ "id": 4, "createdAt": "2026-04-25T01:00:00", "logLevel": "INFO", "source": "Scheduler", "message": "日终汇总完成: 160台, 耗时12秒", "stackTrace": null, "extraData": null }
], "total": 5600, "page": 1, "pageSize": 20 }}
```
**GET /api/admin/log/adjustment/export 导出修正日志(返回文件流):**
二进制Excel文件Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
### 11. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 产量修正日志 | cnc_production_adjustment | 主表(业务库) |
| 系统运行日志 | log_system | 主表(日志库),按月分区 |
| 导出修正日志 | cnc_production_adjustment | 导出Excel |

@ -0,0 +1,49 @@
# 大屏配置 索引
> 版本v1.0
> 最后更新2026-04-25
---
## 模块概述
管理大屏看板的卡片配置和筛选配置。配置大屏显示哪些卡片、卡片类型(统计数字/柱状图/折线图/饼图/状态网格/排行榜)、指标、排序,以及大屏的默认筛选条件。
## 页面清单
| 页面编号 | 页面名称 | 路由 | 功能概述 |
|---------|---------|------|---------|
| 12-01 | 大屏配置页面 | /screen-config | 卡片配置列表+编辑+筛选配置 |
## 页面功能详情
### 12-01 大屏配置页面
**路由**`/screen-config`
**功能概述**:管理大屏卡片(增删改排序+启用禁用)和筛选条件配置
**功能列表**
| 功能编号 | 功能名称 | 触发条件 | 交互行为 | 涉及API |
|---------|---------|---------|---------|---------|
| F01 | 加载卡片配置列表 | 页面挂载 | 请求列表API | GET /api/admin/screen-config |
| F02 | 加载筛选配置列表 | 页面挂载 | 请求筛选列表API | GET /api/admin/screen-filter |
| F03 | 新增卡片 | 点击新增 | 弹窗填写->保存 | POST /api/admin/screen-config |
| F04 | 编辑卡片 | 点击编辑 | 弹窗回填->修改->保存 | PUT /api/admin/screen-config/{id} |
| F05 | 删除卡片 | 点击删除 | 确认->删除 | DELETE /api/admin/screen-config/{id} |
| F06 | 启停卡片 | 点击启用/禁用 | 确认->切换 | PUT /api/admin/screen-config/{id}/toggle |
| F07 | 调整卡片排序 | 拖拽或输入排序号 | 保存排序 | PUT /api/admin/screen-config/sort |
| F08 | 编辑图表配置 | 弹窗内选择图表类型+配置 | 保存 | PUT /api/admin/screen-config/{id} |
| F09 | 新增筛选条件 | 点击新增筛选 | 弹窗填写->保存 | POST /api/admin/screen-filter |
| F10 | 删除筛选条件 | 点击删除 | 确认->删除 | DELETE /api/admin/screen-filter/{id} |
**状态机**卡片is_enabled1(启用)/0(停用)
**路由跳转**:无(本模块无详情页)
## 子目录/文件
| 编号 | 名称 | 类型 | 索引 |
|------|------|------|------|
| 12-01 | 大屏配置页面 | 页面文件 | [12-01-大屏配置页面.md](./12-01-大屏配置页面.md) |
---

@ -0,0 +1,10 @@
# 大屏配置 规范
> 版本v1.0
> 最后更新2026-04-25
---
继承上级规范,如有冲突按本目录规范执行。
---

@ -0,0 +1,165 @@
# 大屏配置页面
> 最后更新2026-04-25
> 状态:已设计
---
### 1. 基本信息
| 项 | 值 |
|----|-----|
| 路由 | /screen-config |
| 权限 | admin |
| 入口 | 侧边栏大屏配置 |
| 面包屑 | 首页 / 大屏配置 |
### 2. 界面布局
┌──────────────────────────────────────────────────────────┐
│ [面包屑] 首页 / 大屏配置 │
├──────────────────────────────────────────────────────────┤
│ [卡片配置区] [+ 新增卡片] │
│ 卡片名称 | 类型 | 指标 | 排序 | 状态 | 操作 │
│ 在线机床数 | stat_number| online | 1 | 启用 | [编辑][禁用][删除] │
│ 各车间产量 | bar_chart | part_count| 3 | 启用 | [编辑][禁用][删除] │
│ 产量趋势 | line_chart | part_count| 7 | 启用 | [编辑][禁用][删除] │
│ 机床状态总览| status_grid| - | 5 | 启用 | [编辑][禁用][删除] │
│ 工人产量排行| rank_list | part_count| 4 | 停用 | [编辑][启用][删除] │
├──────────────────────────────────────────────────────────┤
│ [筛选配置区] [+ 新增筛选] │
│ 筛选标识 | 筛选类型 | 筛选值 | 默认 | 排序 | 操作 │
│ screen_main | workshop | A栋 | 是 | 1 | [编辑][删除] │
│ screen_main | workshop | B栋 | 否 | 2 | [编辑][删除] │
│ screen_main | brand | FANUC | 否 | 3 | [编辑][删除] │
└──────────────────────────────────────────────────────────┘
### 3. 查询条件
无(配置项数量少)。
### 4. 列表字段
**卡片配置表:**
| 字段名 | 列宽 | 排序 | 超长处理 | 对齐 |
|--------|------|------|---------|------|
| 卡片名称 | 150px | - | tooltip | left |
| 卡片类型 | 120px | - | - | center |
| 指标 | 120px | - | tooltip | left |
| 排序 | 80px | y | - | center |
| 状态 | 80px | - | - | center |
| 操作 | 200px | - | - | center |
**筛选配置表:**
| 字段名 | 列宽 | 排序 | 超长处理 | 对齐 |
|--------|------|------|---------|------|
| 筛选标识 | 120px | - | tooltip | left |
| 筛选类型 | 120px | - | - | center |
| 筛选值 | 150px | - | tooltip | left |
| 默认 | 60px | - | - | center |
| 排序 | 80px | y | - | center |
| 操作 | 120px | - | - | center |
### 5. 操作按钮
| 名称 | 权限编码 | 位置 | 显示条件 | 点击行为 |
|------|---------|------|---------|---------|
| 新增卡片 | screen-config:create | 卡片区页头 | 始终 | 打开新增卡片弹窗 |
| 编辑 | screen-config:update | 行操作 | 始终 | 打开编辑弹窗 |
| 启用/禁用 | screen-config:toggle | 行操作 | 始终 | 确认->切换状态 |
| 删除 | screen-config:delete | 行操作 | 始终 | 确认->删除 |
| 新增筛选 | screen-filter:create | 筛选区页头 | 始终 | 打开新增筛选弹窗 |
### 6. 弹窗规格
**新增/编辑卡片弹窗:**
- 宽度600px遮罩有ESC关闭是(脏数据检测)
表单字段:
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 卡片名称 | el-input maxlength=100 | 是 | - | 必填 | - |
| 卡片标识 | el-input maxlength=50 | 是 | - | 必填+唯一性(新增时) | - |
| 卡片类型 | el-select(stat_number/bar_chart/line_chart/pie_chart/status_grid/rank_list) | 是 | - | 必填 | 类型变化时图表配置区域联动 |
| 指标 | el-select(online_count/part_count等) | 是 | - | 必填 | - |
| 维度 | el-select(workshop/worker/machine等) | 否 | - | - | 选择rank_list或bar_chart时必填 |
| 排序号 | el-input-number min=1 max=99 | 是 | 末尾 | 必填+正整数 | - |
| 图表配置 | JSON编辑器(el-input textarea) | 否 | - | JSON格式校验 | 选择图表类型时显示 |
卡片类型说明:
- stat_number统计数字卡片如在线机床数
- bar_chart柱状图如各车间产量
- line_chart折线图如产量趋势
- pie_chart饼图
- status_grid状态网格如机床状态总览
- rank_list排行榜如工人产量排行
**新增/编辑筛选弹窗:**
- 宽度500px
| 字段 | 控件 | 必填 | 默认值 | 校验 | 联动 |
|------|------|------|--------|------|------|
| 筛选标识 | el-input maxlength=50 | 是 | - | 必填 | - |
| 筛选类型 | el-select(workshop/brand等) | 是 | - | 必填 | - |
| 筛选值 | el-input maxlength=100 | 是 | - | 必填 | - |
| 默认选中 | el-switch | 否 | 否 | - | - |
| 排序号 | el-input-number min=1 max=99 | 是 | 末尾 | 必填+正整数 | - |
### 7. 状态机
卡片is_enabled
- 1(启用): el-tag success -> 可编辑/禁用/删除
- 0(停用): el-tag danger -> 可编辑/启用/删除
### 8. 交互流程
- 加载:请求卡片配置列表+筛选配置列表->渲染两个区域
- 新增卡片:弹窗->选卡片类型(联动图表配置)->填写->保存->关闭->刷新
- 编辑卡片:弹窗(回填)->修改->保存->关闭->刷新
- 启停卡片:确认->调API->刷新
- 删除卡片:确认"确定删除卡片【{名称}】?此操作不可恢复。 "->调API->刷新
- 新增筛选:弹窗->填写->保存->关闭->刷新
- 修改排序:修改排序号->自动保存或手动保存
### 9. 空状态
卡片列表无数据el-empty 暂无卡片配置,点击新增卡片添加
筛选列表无数据el-empty 暂无筛选配置
### 10. 数据需求
> 以下为本页面需要的数据,数据库设计定稿时需覆盖。参考 `01-数据库设计.md` 草案。
| 数据需求 | 草案对应 | 说明 |
|---------|---------|------|
| 卡片配置列表 | cnc_screen_config | 主表含card_key/card_type/title/metric/dimension/sort_order/is_enabled/chart_config |
| 筛选配置列表 | cnc_screen_filter | 主表含screen_key/filter_type/filter_value/is_default/sort_order |
### 11. Mock数据
**GET /api/admin/screen-config 卡片配置列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "cardKey": "total_online", "cardType": "stat_number", "title": "在线机床数", "metric": "online_count", "dimension": null, "sortOrder": 1, "isEnabled": 1, "chartConfig": null },
{ "id": 2, "cardKey": "total_production_today", "cardType": "stat_number", "title": "今日总产量", "metric": "part_count", "dimension": null, "sortOrder": 2, "isEnabled": 1, "chartConfig": null },
{ "id": 3, "cardKey": "workshop_production", "cardType": "bar_chart", "title": "各车间产量", "metric": "part_count", "dimension": "workshop", "sortOrder": 3, "isEnabled": 1, "chartConfig": "{\"xAxis\":\"workshop\",\"yAxis\":\"part_count\"}" },
{ "id": 4, "cardKey": "worker_rank", "cardType": "rank_list", "title": "工人产量排行", "metric": "part_count", "dimension": "worker", "sortOrder": 4, "isEnabled": 0, "chartConfig": null },
{ "id": 5, "cardKey": "machine_status", "cardType": "status_grid", "title": "机床状态总览", "metric": null, "dimension": null, "sortOrder": 5, "isEnabled": 1, "chartConfig": null },
{ "id": 6, "cardKey": "collector_status", "cardType": "stat_number", "title": "采集服务状态", "metric": null, "dimension": null, "sortOrder": 6, "isEnabled": 1, "chartConfig": null },
{ "id": 7, "cardKey": "production_trend", "cardType": "line_chart", "title": "产量趋势(7天)", "metric": "part_count", "dimension": null, "sortOrder": 7, "isEnabled": 1, "chartConfig": "{\"xAxis\":\"date\",\"yAxis\":\"part_count\"}" },
{ "id": 8, "cardKey": "machine_rank", "cardType": "rank_list", "title": "机床产量排行", "metric": "part_count", "dimension": "machine", "sortOrder": 8, "isEnabled": 1, "chartConfig": null }
]}}
```
**GET /api/admin/screen-filter 筛选配置列表:**
```json
{ "code": 0, "data": { "items": [
{ "id": 1, "screenKey": "screen_main", "filterType": "workshop", "filterValue": "A栋", "isDefault": 1, "sortOrder": 1 },
{ "id": 2, "screenKey": "screen_main", "filterType": "workshop", "filterValue": "B栋", "isDefault": 0, "sortOrder": 2 },
{ "id": 3, "screenKey": "screen_main", "filterType": "brand", "filterValue": "FANUC", "isDefault": 0, "sortOrder": 3 }
]}}

@ -0,0 +1,152 @@
# 前端检查规范
**版本**: 1.0
**更新时间**: 2026-04-27
**适用范围**: CNC机床数据采集系统前端Vue 3 + Vite + Element Plus + ECharts
---
## 一、核心验收标准
### 1. Mock路由访问
- **要求**: 通过URL中添加 `/mock` 前缀,可访问所有前端界面
- **验证方式**: 访问 `http://localhost:5173/mock/login`登录后可正常浏览所有16个页面
- **验收条件**:
- `/mock/login` 可正常显示登录页
- 登录后跳转至 `/mock/dashboard`
- 侧边栏所有菜单项点击后正确跳转到 `/mock/*` 路径下对应页面
- 页面刷新后仍保持在 `/mock/*` 路径下
### 2. Mock数据贯穿
- **要求**: 通过 `/mock/login` 登录后整个后台所有功能均使用Mock数据
- **验证方式**: 所有API请求应走 `/mock-api/` 前缀
- **验收条件**:
- 登录验证使用Mock凭据admin / admin123
- 所有列表页数据来自Mock API
- 新增/编辑/删除操作调用Mock API并刷新页面数据
- 不出现真实API调用`/api/` 前缀请求)
### 3. 控制台零错误零警告
- **要求**: 后台所有功能交互正常浏览器控制台不能有错误Error和警告Warning
- **验证方式**: 逐页访问检查浏览器DevTools Console面板
- **验收条件**:
- `console.error` 数量 = 0
- `console.warn` 数量 = 0
- 无未捕获的JS异常
- 无Vue组件渲染警告
- 无网络请求失败HTTP 4xx/5xx
### 4. UI元素正常显示
- **要求**: 所有UI元素可正常显示和交互
- **验收条件**:
- Select下拉框宽度足够显示完整文字
- 表格列宽合理,文字不被截断
- 弹窗/对话框正常弹出和关闭
- 分页组件正常工作
- 表单验证提示正常显示
---
## 二、检查范围16个页面 × 13个模块
### 管理后台页面12个模块
| # | 模块 | 页面文件 | 路由路径 |
|---|------|---------|---------|
| 01 | 登录 | LoginPage.vue | /mock/login |
| 02 | 仪表盘 | DashboardPage.vue | /mock/dashboard |
| 03 | 设备管理-列表 | MachineListPage.vue | /mock/machine |
| 03 | 设备管理-详情 | MachineDetailPage.vue | /mock/machine/:id |
| 04 | 品牌模板-列表 | BrandListPage.vue | /mock/brand |
| 04 | 品牌模板-编辑 | BrandEditPage.vue | /mock/brand/:id/edit |
| 05 | 采集地址-列表 | CollectAddressListPage.vue | /mock/collect-address |
| 05 | 采集地址-详情 | CollectAddressDetailPage.vue | /mock/collect-address/:id |
| 06 | 员工管理-列表 | WorkerListPage.vue | /mock/worker |
| 06 | 员工管理-详情 | WorkerDetailPage.vue | /mock/worker/:id |
| 07 | 产量报表 | ProductionPage.vue | /mock/production |
| 08 | 告警中心 | AlertPage.vue | /mock/alert |
| 09 | 系统设置 | SettingsPage.vue | /mock/settings |
| 10 | 车间管理 | 合并至系统设置Tab | /mock/settings |
| 11 | 操作日志 | LogPage.vue | /mock/log |
| 12 | 大屏配置 | ScreenConfigPage.vue | /mock/screen-config |
### 大屏看板1个模块
| # | 模块 | 页面文件 | 路由路径 |
|---|------|---------|---------|
| 13 | 大屏看板 | ScreenPage.vue | /mock/screen |
---
## 三、逐页检查清单
每页需检查以下项目:
### 通用检查项(所有页面)
- [ ] 页面正常加载,无白屏
- [ ] 控制台无 Error
- [ ] 控制台无 Warning
- [ ] Mock API请求路径正确`/mock-api/` 前缀)
- [ ] 无网络请求失败
### 列表页额外检查项
- [ ] 表格数据正常渲染
- [ ] 分页组件显示和切换正常
- [ ] 搜索/筛选功能正常
- [ ] 新增按钮弹出弹窗正常
- [ ] 编辑按钮弹出弹窗并填充数据
- [ ] 删除按钮弹出确认框
- [ ] Select下拉框宽度正常
### 详情页额外检查项
- [ ] 从列表页点击可正确跳转
- [ ] 基本信息区域数据展示正常
- [ ] 返回按钮可正确返回列表页
- [ ] 面包屑导航正确显示
### 表单/弹窗检查项
- [ ] 必填字段校验提示正常
- [ ] 表单提交后数据刷新
- [ ] 弹窗关闭后表单重置
- [ ] Loading状态正常显示
---
## 四、构建验证
### Vite Build
- **命令**: `npx vite build`
- **验收条件**:
- 构建成功exit code 0
- 无编译错误
- 无TypeScript类型错误
### TypeScript类型
- **验收条件**: Vue文件中 `any` 类型使用 ≤ 5处合理遗留
---
## 五、执行方法
### 自动化检查Playwright
1. 启动dev server: `npx vite`
2. 使用Playwright逐页访问
3. 收集每个页面的console.error和console.warn
4. 验证路由跳转和Mock数据
### 手动检查补充
1. 逐页点击所有按钮(新增/编辑/删除/导出)
2. 验证弹窗交互
3. 检查表格排序和分页
4. 验证表单校验
---
## 六、问题等级定义
| 等级 | 定义 | 示例 |
|------|------|------|
| 🔴 阻断 | 页面无法使用 | 白屏、JS报错导致功能不可用 |
| 🟡 严重 | 核心功能异常 | 数据不显示、按钮无响应、弹窗打不开 |
| 🟢 一般 | 非核心问题 | 样式偏移、文案不符、排序不生效 |
| ⚪ 建议 | 优化建议 | 性能优化、代码风格统一 |

@ -0,0 +1,280 @@
[
{
"device": "fanake_1.8",
"desc": "西-1.8",
"tags": [
{
"id": "_io_status",
"desc": "设备状态",
"quality": "0",
"value": "1.00000",
"time": "2026-04-10 17:36:38"
},
{
"id": "Tag2",
"desc": "当前轴数",
"quality": "0",
"value": "4.00000",
"time": "2026-04-10 17:36:34"
},
{
"id": "Tag5",
"desc": "执行的NC主程序名",
"quality": "0",
"value": "1566.NC",
"time": "2026-04-10 17:36:35"
},
{
"id": "Tag6",
"desc": "执行的NC主程序号",
"quality": "0",
"value": "N0",
"time": "2026-04-10 17:36:35"
},
{
"id": "Tag7",
"desc": "当前加工程序内容",
"quality": "0",
"value": "<1566.NC>\nG40G49G80\n( NAME: Administrator )\n( M",
"time": "2026-04-10 17:36:35"
},
{
"id": "Tag8",
"desc": "当前加工零件数",
"quality": "0",
"value": "1219.00000",
"time": "2026-04-10 17:36:35"
},
{
"id": "Tag9",
"desc": "运行状态",
"quality": "0",
"value": "0.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag11",
"desc": "操作模式",
"quality": "0",
"value": "1.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag14",
"desc": "当前主轴倍率",
"quality": "0",
"value": "100.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag17",
"desc": "主轴设定速度",
"quality": "0",
"value": "300.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag18",
"desc": "进给设定速度",
"quality": "0",
"value": "0.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag19",
"desc": "主轴实际速度",
"quality": "0",
"value": "0.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag20",
"desc": "进给实际转速",
"quality": "0",
"value": "0.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag21",
"desc": "主轴负载",
"quality": "0",
"value": "0.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag22",
"desc": "开机时间",
"quality": "0",
"value": "23558160.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag23",
"desc": "运行时间",
"quality": "0",
"value": "18224.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag24",
"desc": "切削时间",
"quality": "0",
"value": "6848959.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag25",
"desc": "循环时间",
"quality": "0",
"value": "699.00000",
"time": "2026-04-10 17:36:38"
},
{
"id": "Tag26",
"desc": "加工状态",
"quality": "0",
"value": "G01",
"time": "2026-04-10 17:36:38"
}
]
},
{
"device": "fanake_1.9",
"desc": "西-1.9",
"tags": [
{
"id": "_io_status",
"desc": "设备状态",
"quality": "0",
"value": "1.00000",
"time": "2026-04-10 17:36:38"
},
{
"id": "Tag2",
"desc": "当前轴数",
"quality": "0",
"value": "4.00000",
"time": "2026-04-10 17:36:34"
},
{
"id": "Tag5",
"desc": "执行的NC主程序名",
"quality": "0",
"value": "O1",
"time": "2026-04-10 17:36:35"
},
{
"id": "Tag6",
"desc": "执行的NC主程序号",
"quality": "0",
"value": "N20",
"time": "2026-04-10 17:36:35"
},
{
"id": "Tag7",
"desc": "当前加工程序内容",
"quality": "0",
"value": "G99 G83 Z-43.000 Q3.000 R3.000 F60. \nG80 \nG00 Z",
"time": "2026-04-10 17:36:35"
},
{
"id": "Tag8",
"desc": "当前加工零件数",
"quality": "0",
"value": "62.00000",
"time": "2026-04-10 17:36:35"
},
{
"id": "Tag9",
"desc": "运行状态",
"quality": "0",
"value": "3.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag11",
"desc": "操作模式",
"quality": "0",
"value": "10.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag14",
"desc": "当前主轴倍率",
"quality": "0",
"value": "100.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag17",
"desc": "主轴设定速度",
"quality": "0",
"value": "450.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag18",
"desc": "进给设定速度",
"quality": "0",
"value": "60.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag19",
"desc": "主轴实际速度",
"quality": "0",
"value": "450.00000",
"time": "2026-04-10 17:36:36"
},
{
"id": "Tag20",
"desc": "进给实际转速",
"quality": "0",
"value": "60.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag21",
"desc": "主轴负载",
"quality": "0",
"value": "25.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag22",
"desc": "开机时间",
"quality": "0",
"value": "23784960.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag23",
"desc": "运行时间",
"quality": "0",
"value": "24253.00000",
"time": "2026-04-10 17:36:37"
},
{
"id": "Tag24",
"desc": "切削时间",
"quality": "0",
"value": "8009398.00000",
"time": "2026-04-10 17:36:38"
},
{
"id": "Tag25",
"desc": "循环时间",
"quality": "0",
"value": "82.00000",
"time": "2026-04-10 17:36:38"
},
{
"id": "Tag26",
"desc": "加工状态",
"quality": "0",
"value": "G01",
"time": "2026-04-10 17:36:38"
}
]
}
]
Loading…
Cancel
Save