更新新增板卡的抽屉页面
This commit is contained in:
parent
71095c294c
commit
269064f448
|
|
@ -4,37 +4,38 @@
|
|||
flowchart TD
|
||||
|
||||
%% ===== 入口 =====
|
||||
HOME["首页 Dashboard\n设备统计 · 待处理任务 · 快捷导航"]
|
||||
HOME["首页 Dashboard\n设备统计(8项指标) · 设备状态分布\n待处理任务(4组) · 快捷导航"]
|
||||
|
||||
%% ===== 阶段零:型号管理(核心枢纽)=====
|
||||
subgraph S0["型号管理(核心枢纽)"]
|
||||
MODEL["设备型号管理\n型号列表 · 在产/停产"]
|
||||
MODEL -->|绑定| AUTH_FILE["授权文件\n按型号绑定"]
|
||||
MODEL["设备型号管理\n型号列表 · 在产/停产\n新增型号抽屉"]
|
||||
MODEL -->|绑定| AUTH_FILE["授权文件\n按型号绑定授权项"]
|
||||
MODEL -->|绑定| CFG_FILE["配置文件\n按型号绑定"]
|
||||
MODEL -->|绑定| FW_FILE["固件文件\n主机/主协板/发射板/采集板"]
|
||||
MODEL -->|管理| CHECKLIST["装配Checklist模板\n按型号配置检查项"]
|
||||
MODEL -->|管理| CHECKLIST["装配Checklist模板\nTab切换型号 · 可编辑\n新增模版抽屉"]
|
||||
MODEL -->|管理| BOARD_MGR["板卡型号管理\n主协板/采集板/发射板/升压板\nTab筛选 · 详情抽屉"]
|
||||
end
|
||||
|
||||
%% ===== 阶段一:固件与校准 =====
|
||||
subgraph S1["阶段一:固件与校准"]
|
||||
FW_LIB["固件库\n主机固件 · 主协板固件\n发射板固件 · 采集板固件"]
|
||||
FW_LIB -->|上传zip| FW_UPLOAD["上传固件弹窗\n选择类型 · 版本号 · zip文件"]
|
||||
FW_LIB -->|烧录采集板| CALIB["采集板校准记录\n校准数据管理"]
|
||||
FW_LIB -->|上传zip| FW_UPLOAD["上传固件弹窗(Element Plus)\n版本号 · 硬件版本范围\n固件类型(5种) · 升级类型\n数字签名 · 发布说明"]
|
||||
CALIB["采集板校准管理\n校准记录列表 · 导入\n合格/不合格/待校准"]
|
||||
end
|
||||
|
||||
%% ===== 阶段二:生产装配 =====
|
||||
subgraph S2["阶段二:生产装配"]
|
||||
DEV_REG["设备登记\n装机信息 · BOM清单 · Checklist"]
|
||||
DEV_REG -->|导入BOM| IMPORT_DIALOG["Excel导入弹窗\n下载模板 · 上传文件"]
|
||||
DEV_REG -->|拍照上传| PHOTO_DIALOG["照片上传弹窗\n多张照片 · 备注"]
|
||||
DEV_REG -->|登记完成| DEV_LIST["设备列表\n筛选 · 搜索 · 状态"]
|
||||
DEV_LIST -->|点击详情| DEV_DETAIL["设备详情\n基本信息 \n授权信息 · 装配记录\n子设备列表 · 维修历史"]
|
||||
DEV_REG["设备登记\n装机信息表单 · 型号匹配提示\nBOM清单 · 装配Checklist"]
|
||||
DEV_REG -->|导入BOM| IMPORT_DIALOG["Excel导入弹窗\n下载模板 · 上传文件\n支持xlsx/xls/csv"]
|
||||
DEV_REG -->|拍照上传| PHOTO_DIALOG["照片上传弹窗\n多张照片 · 装配记录信息"]
|
||||
DEV_REG -->|登记完成| DEV_LIST["设备列表\n5项筛选 · 卡片式列表\n导出 · 分页"]
|
||||
DEV_LIST -->|点击详情| DEV_DETAIL["设备详情页\n基本信息 · 授权信息(含模块列表)\n装配记录(含Checklist摘要)\n子设备列表(5种板卡)\n固件信息 · 维修历史(时间线)"]
|
||||
end
|
||||
|
||||
%% ===== 阶段三:授权出厂 =====
|
||||
subgraph S3["阶段三:授权出厂"]
|
||||
LIC_MGR["授权管理\n授权文件列表 · 按型号管理"]
|
||||
LIC_MGR -->|选择授权项生成| LIC_DRAWER["授权项抽屉\n选择型号 · 勾选功能模块\n设置有效期 · 生成授权文件"]
|
||||
LIC_MGR["授权管理\n授权文件列表 · 按型号筛选\n已发布/草稿/已停用"]
|
||||
LIC_MGR -->|选择授权项| LIC_DRAWER["授权项抽屉(640px)\n选择型号(自动预选) · 有效期\n11项功能模块勾选\n全选/清空 · 保存"]
|
||||
end
|
||||
|
||||
%% ===== 阶段四:APP使用(非平台)=====
|
||||
|
|
@ -48,57 +49,66 @@ end
|
|||
|
||||
%% ===== 阶段五:配置管理 =====
|
||||
subgraph S5["阶段五:配置管理"]
|
||||
CFG_MGR["配置文件管理\n配置列表 · 筛选"]
|
||||
CFG_MGR -->|新建配置抽屉| CFG_NEW["新建配置抽屉\n选择型号 · 发射参数\n采集参数 · 网络参数"]
|
||||
CFG_MGR -->|编辑详情| PARAM_CFG["参数配置\n发射参数 · 采集参数\n保护参数 · 网络参数"]
|
||||
CFG_MGR["配置文件管理\n配置列表 · 筛选(型号/版本/关键字)\n生效/已停用"]
|
||||
CFG_MGR -->|新建配置抽屉| CFG_NEW["新建配置抽屉(520px)\n基本信息 · 发射参数\n采集参数 · 网络参数"]
|
||||
CFG_MGR -->|编辑详情| PARAM_CFG["参数配置页\n发射参数(电压/电流/脉宽/波形/占空比)\n采集参数(量程/采样率/通道数)\n保护参数(过压/过流/短路/高温)\n网络参数(WiFi前缀)"]
|
||||
end
|
||||
|
||||
%% ===== 阶段六:维修运维 =====
|
||||
subgraph S6["阶段六:维修运维"]
|
||||
REPAIR["维修工单列表\n筛选 · 状态 · 优先级"]
|
||||
REPAIR -->|新建工单抽屉| NEW_ORDER["新建工单抽屉\n设备信息 · 故障信息 · 工单信息"]
|
||||
REPAIR -->|处理抽屉| PROCESS["处理工单抽屉\n更换板卡 · 授权处理 · 报废申请"]
|
||||
REPAIR -->|详情抽屉| ORDER_DETAIL["工单详情抽屉\n工单/设备/故障信息\n处理记录 · 板卡更换 · 授权处理"]
|
||||
REPAIR -->|维修统计| REPAIR_STATS["维修统计\n故障分布 · 维修趋势"]
|
||||
REPAIR["维修工单列表\n6项筛选 · 卡片式列表\n状态(处理中/已处理/待处理)\n优先级(高/中/低)"]
|
||||
REPAIR -->|新建工单抽屉| NEW_ORDER["新建工单抽屉(520px)\n设备信息(SN选择+设备查找)\n故障信息(类型/描述/现象)\n工单信息(优先级/人员/时间/备注)"]
|
||||
REPAIR -->|处理抽屉| PROCESS["处理工单抽屉(520px)\n处理操作(更换板卡/固件修复/参数重置/其他)\n板卡更换(原SN→新SN)\n授权处理(重新生成/推送固件)\n报废处理(选择原因→申请报废)"]
|
||||
REPAIR -->|详情抽屉| ORDER_DRAWER["工单详情抽屉(540px)\n工单/设备/故障信息\n处理记录 · 板卡更换记录\n授权处理 · 关闭工单"]
|
||||
REPAIR -->|独立详情页| ORDER_PAGE["工单详情页(/repair/:orderId)\n工单/设备/故障信息\n处理记录 · 板卡更换记录\n授权处理\n关闭工单 · 申请报废"]
|
||||
REPAIR -->|维修统计| REPAIR_STATS["维修统计页\n时间范围筛选(5个Tab)\n4项统计指标\n故障类型分布(条形图)\n维修趋势(折线图)"]
|
||||
end
|
||||
|
||||
%% ===== 阶段七:报废回收 =====
|
||||
subgraph S7["阶段七:报废回收"]
|
||||
SCRAP["报废管理\n报废设备列表 · 审批流程"]
|
||||
SCRAP -->|关联工单| ORDER_DETAIL
|
||||
SCRAP -->|回收入库| DEV_REG
|
||||
SCRAP["报废管理\n审批流程(5步)\n4项统计 · 筛选\n报废设备列表"]
|
||||
SCRAP -->|详情抽屉| SCRAP_DETAIL["报废详情抽屉(520px)\n设备信息 · 残值评估\n审批信息 · 可回收物料\n审批记录时间线"]
|
||||
SCRAP -->|审批抽屉| SCRAP_APPROVE["报废审批抽屉(480px)\n⚠️不可逆警告\n设备摘要 · 可回收物料\n审批意见\n驳回/审批通过"]
|
||||
SCRAP -->|回收入库抽屉| SCRAP_RECYCLE["物料回收入库抽屉(480px)\n物料检测勾选\n回收备注\n确认回收入库"]
|
||||
end
|
||||
|
||||
%% ===== 首页导航 =====
|
||||
HOME -->|待校准设备| CALIB
|
||||
HOME -->|待处理工单| REPAIR
|
||||
%% ===== 首页导航(8项指标跳转) =====
|
||||
HOME -->|设备总数/装配中/已激活| DEV_LIST
|
||||
HOME -->|有新版本/可升级| FW_LIB
|
||||
HOME -->|维修中| REPAIR
|
||||
HOME -->|报废| SCRAP
|
||||
HOME -->|授权即将到期| LIC_MGR
|
||||
HOME -->|固件待升级| FW_LIB
|
||||
HOME -->|设备总数| DEV_LIST
|
||||
HOME -->|校准即将到期| CALIB
|
||||
HOME --> MODEL
|
||||
|
||||
%% ===== 型号管理跨模块关联 =====
|
||||
MODEL -->|授权按钮| LIC_MGR
|
||||
MODEL -->|配置按钮| CFG_MGR
|
||||
MODEL -->|固件按钮| FW_LIB
|
||||
MODEL -->|Checklist模板| DEV_REG
|
||||
|
||||
%% ===== 板卡管理关联 =====
|
||||
BOARD_MGR -->|固件按钮| FW_LIB
|
||||
BOARD_MGR -->|详情→服役记录| DEV_DETAIL
|
||||
BOARD_MGR -->|详情→维修记录| REPAIR
|
||||
|
||||
%% ===== 跨阶段数据流 =====
|
||||
DEV_REG -->|型号必须匹配| MODEL
|
||||
DEV_DETAIL -->|查看校准| CALIB
|
||||
DEV_DETAIL -->|查看维修历史| REPAIR
|
||||
PROCESS -->|申请报废| SCRAP
|
||||
ORDER_DETAIL -->|更换采集板需重新校准| CALIB
|
||||
FW_LIB -->|关联型号固件| MODEL
|
||||
ORDER_PAGE -->|申请报废| SCRAP
|
||||
ORDER_DRAWER -->|更换采集板需重新校准| CALIB
|
||||
SCRAP -->|关联来源工单| ORDER_PAGE
|
||||
SCRAP_RECYCLE -->|回收入库| DEV_REG
|
||||
|
||||
%% ===== 支撑模块 =====
|
||||
subgraph SUPPORT["支撑模块(Header菜单)"]
|
||||
DATA_STATS["数据统计"]
|
||||
OPS_RPT["运营报告"]
|
||||
USER_MGR["用户管理"]
|
||||
ROLE_MGR["角色权限"]
|
||||
SYS_LOG["操作日志"]
|
||||
SYS_SET["系统设置"]
|
||||
DATA_STATS["数据报表(占位)"]
|
||||
OPS_RPT["运营报告(占位)"]
|
||||
USER_MGR["用户管理(占位)"]
|
||||
ROLE_MGR["角色权限(占位)"]
|
||||
SYS_LOG["操作日志(占位)"]
|
||||
SYS_SET["系统设置(占位)"]
|
||||
end
|
||||
|
||||
%% 样式
|
||||
|
|
@ -117,20 +127,23 @@ style APP fill:#F6FFED,stroke:#52C41A,stroke-dasharray: 5 5
|
|||
|
||||
## 页面清单
|
||||
|
||||
| 模块 | 页面 | 路由 | 交互方式 |
|
||||
|------|------|------|----------|
|
||||
| 首页 | Dashboard | `/` | 卡片点击跳转 |
|
||||
| 设备 | 设备列表 | `/devices` | 筛选/详情跳转 |
|
||||
| 设备 | 设备详情 | `/devices/:id` | 页面 |
|
||||
| 设备 | 设备登记 | `/registration` | 弹窗(导入/拍照) |
|
||||
| 设备 | 型号管理 | `/models` | 抽屉(新增型号/Checklist模板) |
|
||||
| 授权 | 授权管理 | `/licenses` | 抽屉(选择授权项生成) |
|
||||
| 固件 | 固件库 | `/firmware` | 弹窗(上传固件) Tab分类 |
|
||||
| 配置 | 配置管理 | `/config-files` | 抽屉(新建配置) |
|
||||
| 配置 | 参数配置 | `/config-files/:id` | 页面 |
|
||||
| 校准 | 校准记录 | `/calibration` | 页面 |
|
||||
| 维修 | 维修工单 | `/repair` | 抽屉(新建/处理/详情) |
|
||||
| 维修 | 维修统计 | `/repair/stats` | 页面 |
|
||||
| 维修 | 工单详情 | `/repair/:orderId` | 页面 |
|
||||
| 报废 | 报废管理 | `/scrap` | 页面 |
|
||||
| 系统 | 用户/角色/日志/设置 | Header菜单 | 页面(占位) |
|
||||
| 模块 | 页面 | 路由 | 交互方式 | 组件文件 |
|
||||
|------|------|------|----------|----------|
|
||||
| 首页 | Dashboard | `/` | 卡片点击跳转 | `Dashboard.vue` |
|
||||
| 设备 | 设备列表 | `/devices` | 5项筛选 · 卡片式列表 | `DeviceList.vue` |
|
||||
| 设备 | 设备详情 | `/devices/:id` | 独立页面(6个信息卡片) | `DeviceDetail.vue` |
|
||||
| 设备 | 设备登记 | `/registration` | 弹窗(Excel导入/拍照上传) | `DeviceRegistration.vue` |
|
||||
| 设备 | 设备型号管理 | `/models` | 抽屉(新增型号/新增Checklist模板) | `DeviceModelManagement.vue` |
|
||||
| 设备 | 板卡型号管理 | `/boards` | Tab筛选 · 抽屉(板卡详情) | `BoardManagement.vue` |
|
||||
| 授权 | 授权管理 | `/licenses` | 抽屉(选择授权项 640px) | `LicenseManagement.vue` |
|
||||
| 固件 | 固件库 | `/firmware` | 弹窗(上传固件 Element Plus Dialog) | `FirmwareLibrary.vue` |
|
||||
| 配置 | 配置文件管理 | `/config-files` | 抽屉(新建配置 520px) | `ConfigFileManagement.vue` |
|
||||
| 配置 | 参数配置 | `/config-files/:configId` | 独立页面(新建/编辑两种模式) | `ParameterConfiguration.vue` |
|
||||
| 校准 | 校准管理 | `/calibration` | 表格列表 · 导入 | `CalibrationRecords.vue` |
|
||||
| 维修 | 维修工单 | `/repair` | 抽屉(新建520px/处理520px/详情540px) | `RepairOrders.vue` |
|
||||
| 维修 | 维修统计 | `/repair/stats` | 独立页面(统计+图表) | `RepairStats.vue` |
|
||||
| 维修 | 工单详情 | `/repair/:orderId` | 独立页面(含底部操作栏) | `RepairOrderDetail.vue` |
|
||||
| 报废 | 报废管理 | `/scrap` | 抽屉(详情520px/审批480px/回收480px) | `ScrapManagement.vue` |
|
||||
| 系统 | 数据报表 | `/reports` | 占位页面 | `PlaceholderPage.vue` |
|
||||
| 系统 | 操作日志 | `/logs` | 占位页面 | `PlaceholderPage.vue` |
|
||||
| 系统 | 系统设置 | `/settings` | 占位页面 | `PlaceholderPage.vue` |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,959 @@
|
|||
# 地空业务支撑平台 —— 生产管理子系统 产品原型文档
|
||||
|
||||
> 版本:v1.0
|
||||
> 更新日期:2026-04-08
|
||||
> 技术栈:Vue 3 + Vue Router + Element Plus + TailwindCSS + Lucide Icons
|
||||
> 主色调:`#4a7c59`(绿色系)
|
||||
|
||||
---
|
||||
|
||||
## 一、系统概述
|
||||
|
||||
本系统为"地空业务支撑平台"的生产管理子系统,面向地球物理仪器(高密度电法仪等)的全生命周期管理,涵盖:
|
||||
|
||||
- 设备型号管理(核心枢纽)
|
||||
- 板卡型号管理
|
||||
- 设备登记与装配
|
||||
- 授权文件管理
|
||||
- 配置文件管理
|
||||
- 固件库管理
|
||||
- 采集板校准
|
||||
- 维修工单
|
||||
- 报废回收
|
||||
|
||||
### 1.1 全局布局
|
||||
|
||||
| 区域 | 说明 |
|
||||
|------|------|
|
||||
| 左侧边栏(200px) | Logo + 分组导航菜单,固定不滚动 |
|
||||
| 顶部 Header(56px) | 系统标题 + 数据统计/运营报告入口 + 用户菜单(用户管理/角色权限/操作日志/系统设置/退出) |
|
||||
| 主内容区 | 背景色 `#F0F2F5`,内容区可滚动 |
|
||||
|
||||
### 1.2 导航菜单结构
|
||||
|
||||
| 分组 | 菜单项 | 路由 | 图标 |
|
||||
|------|--------|------|------|
|
||||
| — | 首页 | `/` | — |
|
||||
| 设备 | 设备列表 | `/devices` | Monitor |
|
||||
| 设备 | 设备型号管理 | `/models` | Settings2 |
|
||||
| 设备 | 板卡型号管理 | `/boards` | Cpu |
|
||||
| 授权 | 授权管理 | `/licenses` | Key |
|
||||
| 配置 | 配置管理 | `/config-files` | FileCode |
|
||||
| 校准 | 校准记录 | `/calibration` | Gauge |
|
||||
| 维修 | 维修工单 | `/repair` | Wrench |
|
||||
| 维修 | 报废回收 | `/scrap` | Recycle |
|
||||
|
||||
---
|
||||
|
||||
## 二、页面详细说明
|
||||
|
||||
---
|
||||
|
||||
### 2.1 首页 Dashboard
|
||||
|
||||
**路由**:`/`
|
||||
|
||||
#### 功能描述
|
||||
系统首页,展示全局数据概览和待处理任务快捷入口。
|
||||
|
||||
#### 统计卡片(8个,可点击跳转)
|
||||
|
||||
| 指标 | 示例值 | 趋势 | 跳转 |
|
||||
|------|--------|------|------|
|
||||
| 设备总数 | 5,234 | +5.2% | `/devices` |
|
||||
| 装配中 | 4,856 | +2.8% | `/devices` |
|
||||
| 已激活 | 4,912 | +1.5% | `/devices` |
|
||||
| 有新版本 | 156 | — | `/firmware` |
|
||||
| 维修中 | 23 | -12.3% | `/repair` |
|
||||
| 报废 | 56 | — | `/scrap` |
|
||||
| 授权即将到期 | 45 | — | `/licenses` |
|
||||
| 可升级 | 8 | — | `/firmware` |
|
||||
|
||||
#### 设备状态分布(横向条形图)
|
||||
|
||||
| 状态 | 颜色 |
|
||||
|------|------|
|
||||
| 已装配 | `#52C41A` |
|
||||
| 已出厂 | `#FF4D4F` |
|
||||
| 已激活 | `#FAAD14` |
|
||||
| 报废 | `#8C8C8C` |
|
||||
|
||||
#### 待处理任务(2列布局,每组显示2条+查看全部链接)
|
||||
|
||||
| 任务组 | 跳转 |
|
||||
|--------|------|
|
||||
| 校准即将到期 | `/calibration` |
|
||||
| 维修工单 | `/repair` |
|
||||
| 固件升级通知 | `/firmware` |
|
||||
| 授权即将到期 | `/licenses` |
|
||||
|
||||
---
|
||||
|
||||
### 2.2 设备型号管理
|
||||
|
||||
**路由**:`/models`
|
||||
|
||||
#### 功能描述
|
||||
管理设备型号(GD-30/GD-20/GD-10 Supreme),是平台核心枢纽,每个型号关联授权项、配置文件。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 信息提示横幅**
|
||||
- 绿色背景提示:型号管理是平台核心枢纽
|
||||
|
||||
**2. 型号列表(表格)**
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 型号名称 | 如 GD-30 Supreme |
|
||||
| 编码 | 如 GD30-2024 |
|
||||
| 状态 | 在产(绿色标签)/ 停产(黄色标签) |
|
||||
| 操作 | 编辑 / 授权(跳转`/licenses`)/ 配置(跳转`/config-files`) |
|
||||
|
||||
- 右上角按钮:「新增设备型号」
|
||||
|
||||
**3. 装配 Checklist 模板**
|
||||
- Tab 切换不同型号(GD30 / GD20 / GD10)
|
||||
- 表格列:序号(可拖拽排序)、项目名称(点击可编辑)
|
||||
- GD30 示例有 22 项检查项(主板SN扫码绑定、采集板SN录入、GPS/北斗检测、电池安装、IP66防护等)
|
||||
- 右上角按钮:「新增模版」
|
||||
|
||||
#### 抽屉:新增设备型号(480px宽)
|
||||
|
||||
| 字段 | 类型 | 必填 |
|
||||
|------|------|------|
|
||||
| 型号名称 | 文本输入 | 是 |
|
||||
| 型号编码 | 文本输入 | 是 |
|
||||
| 状态 | 单选(在产/停产) | — |
|
||||
|
||||
#### 抽屉:新增 Checklist 模版(480px宽)
|
||||
|
||||
| 字段 | 类型 | 必填 |
|
||||
|------|------|------|
|
||||
| 设备型号 | 下拉选择 | 是 |
|
||||
| 检查项列表 | 动态列表(可增删) | — |
|
||||
|
||||
---
|
||||
|
||||
### 2.3 板卡型号管理
|
||||
|
||||
**路由**:`/boards`
|
||||
|
||||
#### 功能描述
|
||||
管理板卡型号信息,包括主协板、采集板、发射板、升压板。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. Tab 筛选**:全部 / 主协板 / 采集板 / 发射板 / 升压板
|
||||
|
||||
**2. 板卡列表(表格)**
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 类型 | 主协板/采集板/发射板/升压板 |
|
||||
| 型号 | 如 MB-V2.3、RX-V2.2 |
|
||||
| 最新固件版本 | 如 v2.3.5 |
|
||||
| 操作 | 详情 / 固件(跳转`/firmware`) |
|
||||
|
||||
- 右上角按钮:「导出」「新增板卡」
|
||||
|
||||
#### 抽屉:板卡详情(560px宽)
|
||||
|
||||
包含以下信息区块:
|
||||
- 基本信息:板卡类型、型号、当前固件、生产日期
|
||||
- 固件升级记录:时间线(日期、版本变更、升级方式、操作人)
|
||||
- 校准历史:日期、结果、到期日、校准人
|
||||
- 服役记录:关联设备SN(可点击跳转)、服役时间段、状态(在役/已拆卸)
|
||||
- 维修记录:关联工单号(可点击跳转)、日期、操作、操作人
|
||||
|
||||
---
|
||||
|
||||
### 2.4 设备列表
|
||||
|
||||
**路由**:`/devices`
|
||||
|
||||
#### 功能描述
|
||||
展示所有设备,支持筛选和搜索。
|
||||
|
||||
#### 筛选条件
|
||||
|
||||
| 筛选项 | 类型 |
|
||||
|--------|------|
|
||||
| 设备型号 | 下拉(全部/GD30/GT20/GM10) |
|
||||
| 设备状态 | 下拉(全部/已激活/已出厂/装配中) |
|
||||
| 生产日期 | 日期选择器 |
|
||||
| 产品型号 | 下拉 |
|
||||
| 搜索 | 按钮 |
|
||||
|
||||
#### 设备卡片列表(非表格,卡片式)
|
||||
|
||||
每张卡片展示:
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| 设备SN号 | 如 GD30-20240308-001 |
|
||||
| 型号 | 如 GD30 高密度电法仪 |
|
||||
| 状态 | 已激活(绿)/ 已出厂(橙)/ 装配中(绿底) |
|
||||
| 主机版本 | 如 v2.3.5 |
|
||||
| 生产日期 | 如 2024-03-08 14:30 |
|
||||
|
||||
卡片底部操作:
|
||||
- 详情(跳转 `/devices/:sn`)
|
||||
- 下线(仅已激活设备显示,红色)
|
||||
|
||||
- 右上角按钮:「导出」「登记设备」(跳转`/registration`)
|
||||
- 分页:显示 X-Y / 共 N 台
|
||||
|
||||
---
|
||||
|
||||
### 2.5 设备详情
|
||||
|
||||
**路由**:`/devices/:id`
|
||||
|
||||
#### 功能描述
|
||||
展示单台设备的完整信息,包含基本信息、授权、装配记录、子设备、固件、维修历史。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 页面头部**
|
||||
- 返回按钮 + 设备SN号 + 状态标签
|
||||
|
||||
**2. 基本信息卡片**
|
||||
|
||||
| 字段 | 示例 |
|
||||
|------|------|
|
||||
| 设备型号 | GD30 高密度电法仪 |
|
||||
| 主机SN号 | GD30-2025-000001 |
|
||||
| 设备状态 | 已激活 |
|
||||
| 生产日期 | 2025-01-15 |
|
||||
| 出厂日期 | 2025-02-01 |
|
||||
| 激活日期 | 2025-02-10 |
|
||||
| 装配人员 | 张工程师 |
|
||||
| 测试人员 | 李工程师 |
|
||||
| 客户名称 | 北京地质研究院 |
|
||||
|
||||
**3. 授权信息卡片**
|
||||
|
||||
| 字段 | 示例 |
|
||||
|------|------|
|
||||
| 授权ID | LIC-2025-0001 |
|
||||
| 授权状态 | 已激活 |
|
||||
| 授权类型 | 正式授权 |
|
||||
| 生效日期 | 2025-02-10 |
|
||||
| 到期日期 | 2026-02-10 |
|
||||
| 剩余天数 | 317天 |
|
||||
|
||||
- 授权功能模块标签列表:1D SP, 2D SP, 3D SP, 1D VES, 2D ERT, 3D ERT, 1D IP, 2D IP, 3D IP
|
||||
- 授权文件下载链接
|
||||
|
||||
**4. 装配记录卡片**
|
||||
|
||||
| 字段 | 示例 |
|
||||
|------|------|
|
||||
| 装配工单 | ASM-2025-000001 |
|
||||
| 装配人员 | 张工程师 |
|
||||
| 装配日期 | 2025-01-15 |
|
||||
| 测试人员 | 李工程师 |
|
||||
| 测试结果 | 通过 |
|
||||
| Checklist完成 | 22/22 项 |
|
||||
|
||||
- Checklist 摘要(2列网格,勾选图标 + 项目名称)
|
||||
|
||||
**5. 子设备列表(表格)**
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 板卡类型 | 主板/采集板/发射板/测控板/升压板 |
|
||||
| SN号 | 绿色可点击 |
|
||||
| 硬件版本 | 如 A1 |
|
||||
| 固件版本 | 如 v2.3.5 |
|
||||
| 校准状态 | 已校准/无需校准 |
|
||||
| 状态 | 正常 |
|
||||
|
||||
**6. 固件信息卡片**
|
||||
|
||||
| 字段 | 示例 |
|
||||
|------|------|
|
||||
| 当前固件版本 | v2.3.5 |
|
||||
| 最后更新时间 | 2024-03-01 10:30 |
|
||||
| 更新方式 | 远程OTA |
|
||||
| 配置文件版本 | v1.2.0 |
|
||||
| 配置同步时间 | 2024-03-01 10:35 |
|
||||
|
||||
**7. 维修历史(时间线)**
|
||||
- 每条记录:日期、类型(固件升级/主板更换/常规保养)、操作人、描述
|
||||
- 右上角「查看全部」链接跳转 `/repair`
|
||||
|
||||
---
|
||||
|
||||
|
||||
### 2.6 设备登记
|
||||
|
||||
**路由**:`/registration`
|
||||
|
||||
#### 功能描述
|
||||
登记新设备信息,包含装机信息填写、BOM清单管理、装配Checklist执行。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 装机信息卡片(表单)**
|
||||
|
||||
| 字段 | 类型 | 必填 | 示例 |
|
||||
|------|------|------|------|
|
||||
| 设备型号 | 下拉选择(GD-30/GD-20/GD-10 Supreme) | 是 | GD-30 Supreme |
|
||||
| 主机SN号 | 文本输入 | 是 | GD30-20240308-001 |
|
||||
| 主板SN号 | 文本输入 | 是 | MB20240308001 |
|
||||
| 装机测试状态 | 下拉(测试通过/测试不通过) | — | 测试通过 |
|
||||
| 生产日期 | 日期选择器 | — | 2024-03-08 |
|
||||
| 登记人 | 文本输入(只读) | — | 张工 |
|
||||
|
||||
**2. 型号匹配提示横幅**
|
||||
- 成功(绿色):显示匹配到的授权文件、配置文件、固件版本
|
||||
- 警告(黄色):未匹配到型号关联信息,提示先在型号管理中配置
|
||||
|
||||
**3. 装机清单 BOM(表格)**
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 物料编码 | 如 MB-2024-001 |
|
||||
| 物料名称 | 主协板/采集板/测控板/发射板/升压板/外壳机箱 |
|
||||
| SN号 | 板卡SN号 |
|
||||
| 型号 | 如 MB-V2.3 |
|
||||
| 校准状态 | 已校准/无需校准 |
|
||||
| 数量 | 数字 |
|
||||
| 操作 | 编辑 / 删除 |
|
||||
|
||||
- 右上角按钮:「导入」(打开Excel导入弹窗)
|
||||
|
||||
**4. 装配 Checklist(列表)**
|
||||
- 进度显示:完成 X/Y
|
||||
- 每项包含:勾选框、序号圆圈、项目名称、版本校验提示(红色警告)、拍照上传按钮
|
||||
- 已完成项:绿色背景 + 已上传照片数量
|
||||
- 未完成项:灰色背景 + 拍照上传按钮
|
||||
|
||||
**5. 底部操作栏(sticky)**
|
||||
- 取消 / 更新 / 提交
|
||||
|
||||
#### 弹窗:导入BOM清单
|
||||
|
||||
| 区域 | 说明 |
|
||||
|------|------|
|
||||
| 第一步 | 下载导入模板(BOM导入模板.xlsx) |
|
||||
| 第二步 | 上传Excel文件(支持 .xlsx/.xls/.csv,拖拽或点击上传) |
|
||||
| 提示 | 黄色提示:确保格式与模板一致,物料编码和SN号为必填 |
|
||||
|
||||
#### 弹窗:上传照片
|
||||
|
||||
| 区域 | 说明 |
|
||||
|------|------|
|
||||
| 照片网格 | 已上传照片缩略图(可删除)+ 添加照片按钮 |
|
||||
| 装配记录信息 | 文本域,输入装配记录 |
|
||||
| 操作 | 取消 / 确认上传(显示照片数量) |
|
||||
|
||||
---
|
||||
|
||||
### 2.7 授权管理
|
||||
|
||||
**路由**:`/licenses`
|
||||
|
||||
#### 功能描述
|
||||
管理设备授权文件,按设备型号管理授权模块配置。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 信息提示横幅(青色)**
|
||||
- 说明授权文件按设备型号管理,设备在APP激活时自动下载对应型号的授权文件
|
||||
|
||||
**2. 筛选条件**
|
||||
|
||||
| 筛选项 | 类型 |
|
||||
|--------|------|
|
||||
| 设备型号 | 下拉(全部/GD-10/GD-20/GD-30) |
|
||||
| 状态 | 下拉(全部/已发布/草稿/已停用) |
|
||||
| 查询 | 按钮 |
|
||||
|
||||
**3. 授权列表(表格)**
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 适配型号 | 如 GD-10 Supreme |
|
||||
| 授权模块 | 如 1D SP, 2D SP, 1D VES... |
|
||||
| 有效期 | 永久 / 1年 / 2年 |
|
||||
| 创建日期 | 日期 |
|
||||
| 状态 | 已发布(绿)/ 草稿(黄)/ 已停用(灰) |
|
||||
| 操作 | 详情 / 下载 / 发布(草稿时)/ 停用(已发布时) |
|
||||
|
||||
- 右上角按钮:「导出」「选择授权项」
|
||||
- 分页
|
||||
|
||||
#### 抽屉:选择授权项(640px宽)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| 设备型号 | 下拉选择 | 必填,切换型号自动预选对应授权项 |
|
||||
| 授权有效期 | 下拉(永久/1年/2年/自定义) | — |
|
||||
| 到期日期 | 日期选择器 | 仅"自定义"时显示 |
|
||||
|
||||
**功能授权项列表(表格+勾选)**
|
||||
|
||||
| 授权项名称 | GD-10 | GD-20 | GD-30 |
|
||||
|------------|-------|-------|-------|
|
||||
| 1D SP | ✓ | ✓ | ✓ |
|
||||
| 2D SP | ✓ | ✓ | ✓ |
|
||||
| 3D SP | ✗ | ✓ | ✓ |
|
||||
| 1D VES | ✓ | ✓ | ✓ |
|
||||
| 2D ERT | ✓ | ✓ | ✓ |
|
||||
| 3D ERT | ✗ | ✓ | ✓ |
|
||||
| 1D IP | ✓ | ✓ | ✓ |
|
||||
| 2D IP | ✓ | ✓ | ✓ |
|
||||
| 3D IP | ✗ | ✓ | ✓ |
|
||||
| 跨孔(Cross-Hole) | ✗ | ✓ | ✓ |
|
||||
| 水上(Marine) | ✗ | ✓ | ✓ |
|
||||
|
||||
- 顶部显示:已选 X / Y 项
|
||||
- 操作:全选 / 清空
|
||||
- 底部:取消 / 保存
|
||||
|
||||
---
|
||||
|
||||
### 2.8 配置文件管理
|
||||
|
||||
**路由**:`/config-files`
|
||||
|
||||
#### 功能描述
|
||||
管理设备型号配置文件,包含发射参数、采集参数、网络参数等。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 信息提示横幅(绿色)**
|
||||
- 说明配置文件按设备型号绑定适配
|
||||
|
||||
**2. 筛选条件**
|
||||
|
||||
| 筛选项 | 类型 |
|
||||
|--------|------|
|
||||
| 适配型号 | 下拉 |
|
||||
| 配置版本 | 下拉 |
|
||||
| 关键字 | 文本输入 |
|
||||
| 查询 | 按钮 |
|
||||
|
||||
**3. 配置文件列表(表格)**
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 配置文件 | 如 CFG-GD30-v1.2.0(绿色) |
|
||||
| 适配型号 | 如 GD-30 Supreme |
|
||||
| 版本 | 如 v1.2.0 |
|
||||
| 创建时间 | 日期时间 |
|
||||
| 状态 | 生效(绿)/ 已停用(灰) |
|
||||
| 操作 | 详情 / 编辑 / 下载 / 删除 |
|
||||
|
||||
- 右上角按钮:「新建配置」
|
||||
- 分页
|
||||
|
||||
#### 抽屉:新建配置文件(520px宽)
|
||||
|
||||
分为以下区块:
|
||||
|
||||
**基本信息**
|
||||
| 字段 | 类型 | 必填 |
|
||||
|------|------|------|
|
||||
| 适配型号 | 下拉选择 (GD-10 Supreme/GD-20 Supreme/GD-30 Supreme) | 是 |
|
||||
| 配置版本 | 文本输入 | 是 |
|
||||
|
||||
**发射参数**
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 最大发射电压 | 下拉(500V/800V/1000V/1200V/1500V) |
|
||||
| 最大发射电流 | 下拉(2A/5A/8A/10A/15A) |
|
||||
| 占空比 | 下拉 (50%)、(50%、100%)|
|
||||
| 脉宽宽度 | 下拉(0.25s/0.5s/1s/2s/4s/8s/16s/32s/64s) /(0.25s/0.5s/1s/2s/4s/8s)|
|
||||
| 迭代次数 | 下拉(1~256) |
|
||||
|
||||
**采集参数**
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 支持通道数 | 数字输入(1/6/12) |
|
||||
| 采样率 | 下拉(50Hz/60Hz)/(50Hz/60Hz/100Hz/1000Hz) |
|
||||
| 电压测量量程 | 下拉(±2.5V)/(±2.5V/±80V) /(±80V/±600V) |
|
||||
| 全波形采集 | 下拉(支持/不支持) |
|
||||
|
||||
**网络参数**
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| WiFi SSID 前缀 | 文本输入 |
|
||||
|
||||
---
|
||||
|
||||
### 2.9 参数配置(配置详情)
|
||||
|
||||
**路由**:`/config-files/:configId`
|
||||
|
||||
#### 功能描述
|
||||
配置设备型号的详细参数,支持新建和编辑两种模式。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 型号信息卡片**
|
||||
- 新建模式:适配型号(下拉)、配置文件版本(输入)、状态(待生成)
|
||||
- 编辑模式:适配型号(只读)、版本(只读)、最后更新时间
|
||||
|
||||
**2. 发射参数卡片**
|
||||
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 最大发射电压 | 下拉(500V~1500V) |
|
||||
| 最大发射电流 | 下拉(2A~10A) |
|
||||
| 发射脉宽 | 多选标签(0.25s~64s,共9项) |
|
||||
| 发射波形 | 多选标签(0+0-、+0-0、+-) |
|
||||
| 支持全波形测量 | 复选框 |
|
||||
| 占空比支持 | 复选框(50%/100%) |
|
||||
|
||||
**3. 采集参数卡片**
|
||||
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 电压测量范围 | 多选标签(±2.5V/±80V/±600V) |
|
||||
| 采样率 | 多选标签(50Hz/60Hz/100Hz/1000Hz) |
|
||||
| 支持通道数 | 数字输入 |
|
||||
| 迭代次数范围 | 范围输入(最小~最大) |
|
||||
|
||||
**4. 保护参数卡片**
|
||||
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 过压保护 | 复选框 + 阈值输入(V) |
|
||||
| 过流保护 | 复选框 + 阈值输入(A) |
|
||||
| 短路保护 | 复选框 |
|
||||
| 高温保护 | 复选框 + 阈值输入(°C) |
|
||||
|
||||
**5. 网络参数卡片**
|
||||
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| WiFi SSID | 文本输入 |
|
||||
|
||||
**6. 底部操作栏(sticky)**
|
||||
- 新建模式:取消 / 预览配置 / 确认生成配置文件
|
||||
- 编辑模式:取消 / 重置默认 / 预览配置 / 下发配置
|
||||
|
||||
---
|
||||
|
||||
### 2.10 固件库
|
||||
|
||||
**路由**:`/firmware`
|
||||
|
||||
#### 功能描述
|
||||
管理固件版本,支持上传、查看详情、下载。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**固件版本列表(卡片式)**
|
||||
|
||||
每个版本卡片展示:
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| 版本号 | 如 v2.3.0 |
|
||||
| 发布日期 | 日期 |
|
||||
| 状态 | 已发布 / 草稿 |
|
||||
| 文件大小 | 如 12.5MB |
|
||||
| 下载次数 | 如 1,234次 |
|
||||
|
||||
展开详情后额外显示:
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| MD5 / SHA256 | 校验值 |
|
||||
| 升级类型 | 可选 / 强制 |
|
||||
| 数字签名 | 已签名 |
|
||||
| 发布说明 | 列表形式 |
|
||||
|
||||
操作按钮:下载 / 编辑 / 撤回发布 / 查看详情
|
||||
|
||||
- 右上角按钮:「上传固件」
|
||||
|
||||
#### 弹窗:上传固件(Element Plus Dialog,550px宽)
|
||||
|
||||
| 字段 | 类型 | 必填 |
|
||||
|------|------|------|
|
||||
| 固件版本 | 文本输入 | 是 |
|
||||
| 硬件版本范围 | 文本输入 | 是 |
|
||||
| 升级类型 | 下拉(可选/强制) | 是 |
|
||||
| 固件类型 | 下拉(主协板/采集板/发射板/主机固件/计算单元固件) | 是 |
|
||||
| 数字签名 | 复选框 | — |
|
||||
| 固件包 | ZIP文件上传(拖拽) | 是 |
|
||||
| 发布说明 | 多行文本(每行一条) | — |
|
||||
|
||||
---
|
||||
|
||||
### 2.11 校准管理
|
||||
|
||||
**路由**:`/calibration`
|
||||
|
||||
#### 功能描述
|
||||
管理采集板校准数据。仅针对采集板,其他板卡无需校准。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 信息提示横幅(紫色)**
|
||||
- 说明校准仅针对采集板
|
||||
|
||||
**2. 筛选条件**
|
||||
|
||||
| 筛选项 | 类型 |
|
||||
|--------|------|
|
||||
| 采集板SN号 | 文本输入 |
|
||||
| 校准状态 | 下拉(全部/合格/不合格/待校准) |
|
||||
| 校准人员 | 下拉 |
|
||||
| 查询 | 按钮 |
|
||||
|
||||
**3. 校准记录列表(表格)**
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 采集板SN号 | 如 RX20240308001 |
|
||||
| 校准日期 | 日期 |
|
||||
| 到期日期 | 日期 |
|
||||
| 校准人员 | 如 王工程师 |
|
||||
| 状态 | 合格(绿)/ 不合格(红)/ 待校准(黄) |
|
||||
| 操作 | 详情 / 校准文件 |
|
||||
|
||||
- 右上角按钮:「导入」
|
||||
- 分页
|
||||
|
||||
---
|
||||
|
||||
|
||||
### 2.12 维修工单
|
||||
|
||||
**路由**:`/repair`
|
||||
|
||||
#### 功能描述
|
||||
管理维修工单的全生命周期,包括新建、处理、查看详情。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 筛选条件**
|
||||
|
||||
| 筛选项 | 类型 |
|
||||
|--------|------|
|
||||
| 状态 | 下拉(全部/处理中/已处理/待处理) |
|
||||
| 优先级 | 下拉(全部/高/中/低) |
|
||||
| 维修人员 | 下拉 |
|
||||
| 创建日期 | 日期范围(开始~结束) |
|
||||
| SN | 文本输入 |
|
||||
| 搜索/重置 | 按钮 |
|
||||
|
||||
**2. 维修工单列表(卡片式)**
|
||||
|
||||
每条工单展示:
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| 工单号 | 如 WO-2024-0001 |
|
||||
| 设备SN | 如 GD30-xxxx |
|
||||
| 故障类型 | 板卡故障/固件异常/通信异常 |
|
||||
| 状态 | 处理中(绿底)/ 已处理(绿标签)/ 待处理(灰标签),带emoji图标 |
|
||||
| 优先级 | 高(红)/ 中(橙)/ 低(蓝) |
|
||||
|
||||
操作按钮:详情 / 处理(处理中和待处理时显示)
|
||||
|
||||
- 右上角按钮:「新建工单」「维修统计」(跳转`/repair/stats`)
|
||||
- 分页
|
||||
|
||||
#### 抽屉:新建维修工单(520px宽)
|
||||
|
||||
分为三个区块:
|
||||
|
||||
**设备信息**
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 设备SN | 下拉选择 + 查找设备按钮 |
|
||||
| 设备信息展示 | 只读(型号、固件、硬件版本、客户) |
|
||||
|
||||
**故障信息**
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 故障类型 | 单选(板卡故障/固件异常/通信故障/其他问题) |
|
||||
| 故障描述 | 多行文本 |
|
||||
| 故障现象 | 多行文本 |
|
||||
|
||||
**工单信息**
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 优先级 | 单选(低/中/高,带颜色) |
|
||||
| 维修人员 | 下拉选择 |
|
||||
| 预计修复时间 | 日期选择器 |
|
||||
| 备注 | 多行文本 |
|
||||
|
||||
底部:取消 / 创建工单
|
||||
|
||||
#### 抽屉:处理工单(520px宽)
|
||||
|
||||
分为以下区块:
|
||||
|
||||
**处理操作**
|
||||
- 单选:更换板卡 / 固件修复 / 参数重置 / 其他处理
|
||||
|
||||
**板卡更换(条件显示,选择"更换板卡"时)**
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 原板卡SN | 文本输入 |
|
||||
| 新板卡SN | 文本输入 |
|
||||
|
||||
**授权处理**
|
||||
| 字段 | 类型 |
|
||||
|------|------|
|
||||
| 重新生成授权文件 | 复选框(默认勾选) |
|
||||
| 推送适配固件 | 复选框 |
|
||||
|
||||
**处理备注**
|
||||
- 多行文本
|
||||
|
||||
**报废处理(红色警告区域)**
|
||||
- 警告文字:报废操作不可逆
|
||||
- 报废原因:下拉选择(主板损坏无法修复/多个核心部件损坏/维修成本超过设备价值/设备老化严重)
|
||||
- 申请报废按钮(跳转`/scrap`)
|
||||
|
||||
底部:取消 / 提交处理
|
||||
|
||||
#### 抽屉:工单详情(540px宽)
|
||||
|
||||
包含以下信息区块:
|
||||
- 工单信息:工单号、状态、优先级、创建时间、维修人员、预计修复
|
||||
- 设备信息:设备SN、型号、固件、硬件版本、客户
|
||||
- 故障信息:故障类型、描述、现象
|
||||
- 处理记录:时间线列表 + 添加记录按钮
|
||||
- 板卡更换记录:原板卡/新板卡信息、更换时间、更换人员
|
||||
- 授权处理:复选框(重新生成授权文件/推送适配固件)+ 处理授权按钮
|
||||
|
||||
底部:取消 / 关闭工单
|
||||
|
||||
---
|
||||
|
||||
### 2.13 维修工单详情(独立页面)
|
||||
|
||||
**路由**:`/repair/:orderId`
|
||||
|
||||
#### 功能描述
|
||||
维修工单的独立详情页面,与抽屉详情内容一致但以独立页面形式展示。
|
||||
|
||||
#### 页面区块(白色卡片堆叠)
|
||||
|
||||
1. 工单信息卡片
|
||||
2. 设备信息卡片
|
||||
3. 故障信息卡片
|
||||
4. 处理记录卡片(时间线 + 添加记录按钮)
|
||||
5. 板卡更换记录卡片
|
||||
6. 授权处理卡片(复选框 + 处理授权按钮)
|
||||
|
||||
**底部操作栏(sticky)**
|
||||
- 取消 / 关闭工单 / 申请报废(红色,跳转`/scrap`)
|
||||
|
||||
---
|
||||
|
||||
### 2.14 维修统计
|
||||
|
||||
**路由**:`/repair/stats`
|
||||
|
||||
#### 功能描述
|
||||
展示维修数据统计和趋势分析。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 时间范围筛选**
|
||||
- 下拉选择 + Tab 切换(本月/上月/本季度/本年度/自定义)
|
||||
|
||||
**2. 统计概览(4列卡片)**
|
||||
|
||||
| 指标 | 颜色 |
|
||||
|------|------|
|
||||
| 总工单数 | 黑色 |
|
||||
| 处理中 | 绿色 `#4a7c59` |
|
||||
| 已完成 | 绿色 `#52C41A` |
|
||||
| 待处理 | 红色 `#FF4D4F` |
|
||||
|
||||
**3. 图表区域(2列)**
|
||||
|
||||
| 图表 | 说明 |
|
||||
|------|------|
|
||||
| 故障类型分布 | 横向进度条(板卡故障65.5%、固件异常22.3%、通信故障6.3%、其他5.9%) |
|
||||
| 维修趋势 | 占位图表(1月-6月趋势) |
|
||||
|
||||
- 右上角按钮:「导出报告」
|
||||
|
||||
---
|
||||
|
||||
### 2.15 报废管理
|
||||
|
||||
**路由**:`/scrap`
|
||||
|
||||
#### 功能描述
|
||||
管理报废设备审批与物料回收,包含完整的审批流程。
|
||||
|
||||
#### 页面区块
|
||||
|
||||
**1. 报废审批流程(步骤条)**
|
||||
|
||||
| 步骤 | 描述 |
|
||||
|------|------|
|
||||
| 1. 申请报废 | 维修工单发起 |
|
||||
| 2. 主管审批 | 审核报废原因 |
|
||||
| 3. 物料检测 | 检测可回收物料 |
|
||||
| 4. 回收入库 | 物料回收登记 |
|
||||
| 5. 报废完成 | 设备注销 |
|
||||
|
||||
**2. 统计概览(4列卡片)**
|
||||
|
||||
| 指标 | 颜色 |
|
||||
|------|------|
|
||||
| 报废总数 | 黑色 |
|
||||
| 待审批 | 黄色 |
|
||||
| 已审批待回收 | 绿色 |
|
||||
| 已回收 | 绿色 |
|
||||
|
||||
**3. 筛选条件**
|
||||
|
||||
| 筛选项 | 类型 |
|
||||
|--------|------|
|
||||
| 设备SN号 | 文本输入 |
|
||||
| 状态 | 下拉(全部/待审批/审批中/已审批/已驳回/回收中/已回收) |
|
||||
| 报废日期 | 日期选择器 |
|
||||
| 查询 | 按钮 |
|
||||
|
||||
**4. 报废设备列表(表格)**
|
||||
|
||||
| 列名 | 说明 |
|
||||
|------|------|
|
||||
| 设备SN | 如 GD30-2023-001234 |
|
||||
| 型号 | 如 GD-30 Supreme |
|
||||
| 报废原因 | 如 主板损坏无法修复 |
|
||||
| 申请人 | 如 李工 |
|
||||
| 状态 | 待审批(黄)/审批中(绿底)/已审批(绿)/已驳回(红)/回收中/已回收 |
|
||||
| 来源工单 | 可点击跳转到维修工单详情 |
|
||||
| 操作 | 详情 / 审批(待审批时)/ 回收入库(已审批时)/ 重新申请(已驳回时) |
|
||||
|
||||
- 右上角按钮:「导出」
|
||||
|
||||
#### 抽屉:报废详情(520px宽)
|
||||
|
||||
包含以下信息区块:
|
||||
- 设备信息:SN、型号、报废日期、报废原因、残值评估(元)
|
||||
- 审批信息:申请人、审批人、来源工单
|
||||
- 可回收物料:标签列表(如 采集板 AC20240308002、测控板 CT20240308003)
|
||||
- 审批记录:时间线(提交申请 → 审批通过/驳回 → 物料回收完成)
|
||||
|
||||
底部:关闭 / 去审批(待审批时)/ 回收入库(已审批时)
|
||||
|
||||
#### 抽屉:报废审批(480px宽)
|
||||
|
||||
- 红色警告横幅:报废操作不可逆
|
||||
- 报废设备摘要:SN、型号、报废原因、残值评估、申请人
|
||||
- 可回收物料列表
|
||||
- 审批意见:多行文本
|
||||
|
||||
底部:取消 / 驳回(红色)/ 审批通过
|
||||
|
||||
#### 抽屉:物料回收入库(480px宽)
|
||||
|
||||
- 报废设备摘要
|
||||
- 物料检测与回收:勾选列表(每项可勾选标记"已检测",绿色高亮)
|
||||
- 回收备注:多行文本
|
||||
|
||||
底部:取消 / 确认回收入库(绿色,跳转`/registration`)
|
||||
|
||||
---
|
||||
|
||||
## 三、占位页面
|
||||
|
||||
以下页面目前为占位状态,显示"此页面正在开发中...":
|
||||
|
||||
| 页面 | 路由 | 入口 |
|
||||
|------|------|------|
|
||||
| 数据报表 | `/reports` | Header 图标 |
|
||||
| 操作日志 | `/logs` | Header 用户菜单 |
|
||||
| 系统设置 | `/settings` | Header 用户菜单 |
|
||||
| 用户管理 | `/users` | Header 用户菜单 |
|
||||
| 角色权限 | `/roles` | Header 用户菜单 |
|
||||
|
||||
---
|
||||
|
||||
## 四、通用交互规范
|
||||
|
||||
### 4.1 状态标签颜色规范
|
||||
|
||||
| 状态类型 | 背景色 | 文字色 | 边框色 |
|
||||
|----------|--------|--------|--------|
|
||||
| 成功/已激活/已发布/合格/已审批/已回收 | `#F6FFED` | `#52C41A` | `#B7EB8F` |
|
||||
| 进行中/在产/处理中 | `#eef5f0` | `#4a7c59` | `#a3c4ad` |
|
||||
| 警告/草稿/待审批/待校准 | `#FFFBE6` | `#FAAD14` | `#FFE58F` |
|
||||
| 错误/已驳回/高优先级 | `#FFF1F0` | `#FF4D4F` | `#FFCCC7` |
|
||||
| 已出厂/中优先级 | `#FFF7E6` | `#FA8C16` | `#FFD591` |
|
||||
| 低优先级 | `#F0F5FF` | `#597EF7` | `#ADC6FF` |
|
||||
| 停用/灰色 | `#FAFAFA` | `rgba(0,0,0,0.45)` | `#D9D9D9` |
|
||||
|
||||
### 4.2 交互模式
|
||||
|
||||
| 模式 | 宽度 | 使用场景 |
|
||||
|------|------|----------|
|
||||
| 抽屉(Drawer) | 480px~640px | 新建/编辑/详情(从右侧滑入,背景遮罩) |
|
||||
| 弹窗(Dialog) | 520px~560px | 导入文件/上传照片 |
|
||||
| 独立页面 | 全宽 | 设备详情/参数配置/维修工单详情/维修统计 |
|
||||
|
||||
### 4.3 表格/列表规范
|
||||
|
||||
- 表头背景:`#FAFAFA`
|
||||
- 行分隔线:`#F0F0F0`
|
||||
- 分页组件:左侧显示"显示 X-Y / 共 N 条",右侧页码按钮
|
||||
- 操作按钮:绿色文字链接 `#4a7c59`,危险操作红色 `#FF4D4F`
|
||||
|
||||
### 4.4 表单规范
|
||||
|
||||
- 必填标记:红色星号 `*`
|
||||
- 输入框边框:`#D9D9D9`
|
||||
- 主按钮:`#4a7c59` 绿色背景白色文字
|
||||
- 次按钮:`#D9D9D9` 边框灰色文字
|
||||
- 危险按钮:`#FF4D4F` 边框红色文字
|
||||
- 禁用状态:`#D9D9D9` 背景
|
||||
|
||||
---
|
||||
|
||||
## 五、页面路由总览
|
||||
|
||||
| 路由 | 页面 | 交互方式 | 文件 |
|
||||
|------|------|----------|------|
|
||||
| `/` | 首页 Dashboard | 卡片点击跳转 | `Dashboard.vue` |
|
||||
| `/models` | 设备型号管理 | 抽屉(新增型号/Checklist模板) | `DeviceModelManagement.vue` |
|
||||
| `/boards` | 板卡型号管理 | Tab筛选 + 抽屉(详情) | `BoardManagement.vue` |
|
||||
| `/devices` | 设备列表 | 筛选 + 卡片列表 | `DeviceList.vue` |
|
||||
| `/devices/:id` | 设备详情 | 独立页面 | `DeviceDetail.vue` |
|
||||
| `/registration` | 设备登记 | 弹窗(导入/拍照) | `DeviceRegistration.vue` |
|
||||
| `/licenses` | 授权管理 | 抽屉(选择授权项) | `LicenseManagement.vue` |
|
||||
| `/firmware` | 固件库 | 弹窗(上传固件) | `FirmwareLibrary.vue` |
|
||||
| `/config-files` | 配置文件管理 | 抽屉(新建配置) | `ConfigFileManagement.vue` |
|
||||
| `/config-files/:configId` | 参数配置 | 独立页面 | `ParameterConfiguration.vue` |
|
||||
| `/calibration` | 校准管理 | 表格列表 | `CalibrationRecords.vue` |
|
||||
| `/repair` | 维修工单 | 抽屉(新建/处理/详情) | `RepairOrders.vue` |
|
||||
| `/repair/stats` | 维修统计 | 独立页面 | `RepairStats.vue` |
|
||||
| `/repair/:orderId` | 工单详情 | 独立页面 | `RepairOrderDetail.vue` |
|
||||
| `/scrap` | 报废管理 | 抽屉(详情/审批/回收) | `ScrapManagement.vue` |
|
||||
|
||||
---
|
||||
|
||||
## 六、跨模块数据流关系
|
||||
|
||||
```
|
||||
设备型号管理 ──→ 授权管理(按设备型号绑定授权项)
|
||||
设备型号管理 ──→ 配置管理(按设备型号绑定配置文件)
|
||||
板卡型号管理 ──→ 固件库(按板卡型号关联固件)
|
||||
设备型号管理 ──→ 设备登记(Checklist模板按型号配置)
|
||||
|
||||
设备登记 ──→ 设备列表(登记完成后出现在列表中)
|
||||
设备列表 ──→ 设备详情(点击查看)
|
||||
|
||||
设备详情 ──→ 校准记录(查看校准信息)
|
||||
设备详情 ──→ 维修工单(查看维修历史)
|
||||
|
||||
维修工单 ──→ 报废管理(申请报废)
|
||||
维修工单 ──→ 校准记录(更换采集板需重新校准)
|
||||
|
||||
报废管理 ──→ 维修工单(关联来源工单)
|
||||
报废管理 ──→ 设备登记(回收入库后物料重新登记)
|
||||
```
|
||||
|
|
@ -44,7 +44,8 @@ const isActive = (path: string) =>
|
|||
const menuGroups = [
|
||||
{ title: '设备', items: [
|
||||
{ path: '/devices', label: '设备列表', icon: Monitor },
|
||||
{ path: '/models', label: '型号管理', icon: Settings2 },
|
||||
{ path: '/models', label: '设备型号管理', icon: Settings2 },
|
||||
{ path: '/boards', label: '板卡型号管理', icon: Cpu },
|
||||
]},
|
||||
{ title: '授权', items: [
|
||||
{ path: '/licenses', label: '授权管理', icon: Key },
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import {ArrowLeft, X} from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const goToFirmware = () => {
|
||||
router.push('/firmware')
|
||||
}
|
||||
|
||||
const activeType = ref('全部')
|
||||
const boardTypes = ['全部', '主协板', '采集板', '发射板', '升压板']
|
||||
|
||||
interface Board {type: string; hwVersion: string; fwVersion: string
|
||||
productionDate: string
|
||||
}
|
||||
|
||||
const allBoards = ref<Board[]>([
|
||||
{ type: '主协板', hwVersion: 'MB-V2.3', fwVersion: 'v2.3.5', productionDate: '2024-01-10' },
|
||||
{ type: '主协板', hwVersion: 'MB-V2.2', fwVersion: 'v2.3.5', productionDate: '2024-02-15' },
|
||||
{ type: '主协板', hwVersion: 'MB-V2.1', fwVersion: 'v1.5.0', productionDate: '2024-01-12' },
|
||||
{ type: '采集板', hwVersion: 'RX-V2.2', fwVersion: 'v1.8.2', productionDate: '2024-01-15' },
|
||||
{ type: '采集板', hwVersion: 'RX-V2.3', fwVersion: 'v1.8.0', productionDate: '2024-03-09' },
|
||||
{ type: '发射板', hwVersion: 'TX-V2.1', fwVersion: 'v1.5.0', productionDate: '2024-01-18' },
|
||||
{ type: '发射板', hwVersion: 'TX-V2.2', fwVersion: 'v1.4.2', productionDate: '2023-06-01' },
|
||||
{ type: '升压板', hwVersion: 'BO-V2.1', fwVersion: 'v1.0.0', productionDate: '2024-01-20' },
|
||||
{ type: '采集板', hwVersion: 'RX-V2.3', fwVersion: 'v1.7.0',productionDate: '2023-08-10' },
|
||||
])
|
||||
|
||||
const filteredBoards = ref(allBoards.value)
|
||||
const filterBoards = () => {
|
||||
filteredBoards.value = activeType.value === '全部'
|
||||
? allBoards.value
|
||||
: allBoards.value.filter(b => b.type === activeType.value)
|
||||
}
|
||||
filterBoards()
|
||||
const switchType = (t: string) => { activeType.value = t; filterBoards() }
|
||||
|
||||
|
||||
// Detail drawer
|
||||
const showDetail = ref(false)
|
||||
const currentBoard = ref<Board | null>(null)
|
||||
const openDetail = (b: Board) => { currentBoard.value = b; showDetail.value = true }
|
||||
|
||||
// Add board drawer
|
||||
const showAddDrawer = ref(false)
|
||||
const addForm = ref({
|
||||
type: '主协板' as string,
|
||||
hwVersion: '',
|
||||
fwVersion: '',
|
||||
productionDate: '',
|
||||
})
|
||||
const openAddDrawer = () => {
|
||||
addForm.value = { type: '主协板', hwVersion: '', fwVersion: '', productionDate: '' }
|
||||
showAddDrawer.value = true
|
||||
}
|
||||
const submitAddBoard = () => {
|
||||
const { type, hwVersion, fwVersion, productionDate } = addForm.value
|
||||
if (!hwVersion || !fwVersion || !productionDate) return
|
||||
allBoards.value.push({ type, hwVersion, fwVersion, productionDate })
|
||||
filterBoards()
|
||||
showAddDrawer.value = false
|
||||
}
|
||||
|
||||
const upgradeHistory = [
|
||||
{ date: '2024-03-01', from: 'v2.3.0', to: 'v2.3.5', operator: '王工程师', method: '远程OTA' },
|
||||
{ date: '2024-01-20', from: 'v2.2.0', to: 'v2.3.0', operator: '李工程师', method: '本地烧录' },
|
||||
]
|
||||
const calibHistory = [
|
||||
{ date: '2024-03-05', result: '合格', calibrator: '张工程师', expiry: '2025-03-05' },
|
||||
{ date: '2023-03-10', result: '合格', calibrator: '王工程师', expiry: '2024-03-10' },
|
||||
]
|
||||
const serviceHistory = [
|
||||
{ deviceSn: 'GD30-2025-000001', from: '2025-01-15', to: '至今', role: '在役' },
|
||||
{ deviceSn: 'GD30-2024-000890', from: '2024-03-08', to: '2024-12-31', role: '已拆卸' },
|
||||
]
|
||||
const repairHistory = [
|
||||
{ orderId: 'WO-2024-0001', date: '2024-02-26', action: '更换(旧板换下)', operator: '李工' },
|
||||
]
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-6">
|
||||
<!-- Header -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<h2 class="text-2xl font-semibold">板卡型号管理</h2>
|
||||
<div class="flex items-center gap-3">
|
||||
<button
|
||||
class="px-4 py-2 rounded flex items-center gap-2"
|
||||
style="border: 1px solid #D9D9D9; color: rgba(0, 0, 0, 0.85)"
|
||||
>
|
||||
<Download :size="16" />
|
||||
导出
|
||||
</button>
|
||||
<button
|
||||
class="px-4 py-2 rounded text-white flex items-center gap-2"
|
||||
style="background-color: #4a7c59"
|
||||
@click="openAddDrawer"
|
||||
>
|
||||
<Plus :size="16" />
|
||||
新增板卡
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Board Type Tabs + Table -->
|
||||
<div class="bg-white rounded-lg mb-6" style="box-shadow: 0 1px 2px rgba(0,0,0,0.05)">
|
||||
<div class="flex border-b" style="border-color: #F0F0F0">
|
||||
<button v-for="t in boardTypes" :key="t" @click="switchType(t)"
|
||||
class="px-5 py-3 text-sm font-medium transition-colors"
|
||||
:style="{ color: activeType === t ? '#4a7c59' : 'rgba(0,0,0,0.65)', borderBottom: activeType === t ? '2px solid #4a7c59' : '2px solid transparent', marginBottom: '-1px' }">
|
||||
{{ t }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead style="background-color: #FAFAFA">
|
||||
<tr>
|
||||
<th class="px-5 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">类型</th>
|
||||
<th class="px-5 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">型号</th>
|
||||
<th class="px-5 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">最新固件版本</th>
|
||||
<th class="px-5 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="b in filteredBoards" class="border-b" style="border-color: #F0F0F0">
|
||||
<td class="px-5 py-4 text-sm" style="color: rgba(0,0,0,0.65)">{{ b.type }}</td>
|
||||
<td class="px-5 py-4 text-sm">{{ b.hwVersion }}</td>
|
||||
<td class="px-5 py-4 text-sm" style="color: rgba(0,0,0,0.65)">{{ b.fwVersion }}</td>
|
||||
<td class="px-5 py-4">
|
||||
<div class="flex items-center gap-3">
|
||||
|
||||
<button class="text-sm" style="color: #4a7c59" @click="openDetail(b)">详情</button>
|
||||
|
||||
<button class="text-sm" style="color: #4a7c59" @click="goToFirmware">固件</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detail Drawer -->
|
||||
<div v-if="showDetail && currentBoard" class="fixed inset-0 z-50 flex justify-end" style="background-color: rgba(0,0,0,0.45)" @click.self="showDetail = false">
|
||||
<div class="bg-white w-[560px] h-full flex flex-col" style="box-shadow: -4px 0 12px rgba(0,0,0,0.1)">
|
||||
<div class="flex items-center gap-3 p-5 border-b" style="border-color: #F0F0F0">
|
||||
<button @click="showDetail = false" class="p-1 rounded hover:bg-gray-100" style="color: rgba(0,0,0,0.65)"><ArrowLeft :size="18" /></button>
|
||||
<h3 class="text-lg font-semibold">板卡详情</h3>
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto p-6 space-y-5">
|
||||
<!-- Basic Info -->
|
||||
<div class="p-5 rounded-lg" style="background-color: #FAFAFA; border: 1px solid #F0F0F0">
|
||||
<h4 class="text-base font-semibold mb-3">基本信息</h4>
|
||||
<div class="grid grid-cols-2 gap-3 text-sm" style="color: rgba(0,0,0,0.65)">
|
||||
<div>板卡类型:{{ currentBoard.type }}</div>
|
||||
<div>型号:{{ currentBoard.hwVersion }}</div>
|
||||
<div>当前固件:{{ currentBoard.fwVersion }}</div>
|
||||
<div>生产日期:{{ currentBoard.productionDate }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Upgrade History -->
|
||||
<div class="p-5 rounded-lg" style="background-color: #FAFAFA; border: 1px solid #F0F0F0">
|
||||
<h4 class="text-base font-semibold mb-3">固件升级记录</h4>
|
||||
<div v-if="upgradeHistory.length === 0" class="text-sm" style="color: rgba(0,0,0,0.25)">暂无升级记录</div>
|
||||
<div v-else class="space-y-2">
|
||||
<div v-for="(u, i) in upgradeHistory" :key="i" class="flex items-center gap-3 text-sm" style="color: rgba(0,0,0,0.65)">
|
||||
<span style="color: rgba(0,0,0,0.35)">{{ u.date }}</span>
|
||||
<span>{{ u.from }} → {{ u.to }}</span>
|
||||
<span class="px-1.5 py-0.5 rounded text-xs" style="background-color: #eef5f0; color: #4a7c59">{{ u.method }}</span>
|
||||
<span style="color: rgba(0,0,0,0.35)">{{ u.operator }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Calibration History -->
|
||||
<div class="p-5 rounded-lg" style="background-color: #FAFAFA; border: 1px solid #F0F0F0">
|
||||
<h4 class="text-base font-semibold mb-3">校准历史</h4>
|
||||
<div v-if="calibHistory.length === 0" class="text-sm" style="color: rgba(0,0,0,0.25)">暂无校准记录</div>
|
||||
<div v-else class="space-y-2">
|
||||
<div v-for="(c, i) in calibHistory" :key="i" class="flex items-center gap-3 text-sm" style="color: rgba(0,0,0,0.65)">
|
||||
<span style="color: rgba(0,0,0,0.35)">{{ c.date }}</span>
|
||||
<span class="px-1.5 py-0.5 rounded text-xs" style="background-color: #F6FFED; color: #52C41A; border: 1px solid #B7EB8F">{{ c.result }}</span>
|
||||
<span>到期:{{ c.expiry }}</span>
|
||||
<span style="color: rgba(0,0,0,0.35)">{{ c.calibrator }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service History -->
|
||||
<div class="p-5 rounded-lg" style="background-color: #FAFAFA; border: 1px solid #F0F0F0">
|
||||
<h4 class="text-base font-semibold mb-3">服役记录</h4>
|
||||
<div v-if="serviceHistory.length === 0" class="text-sm" style="color: rgba(0,0,0,0.25)">暂无服役记录</div>
|
||||
<div v-else class="space-y-2">
|
||||
<div v-for="(s, i) in serviceHistory" :key="i" class="flex items-center gap-3 text-sm" style="color: rgba(0,0,0,0.65)">
|
||||
<router-link :to="'/devices/' + s.deviceSn" style="color: #4a7c59">{{ s.deviceSn }}</router-link>
|
||||
<span>{{ s.from }} ~ {{ s.to }}</span>
|
||||
<span class="px-1.5 py-0.5 rounded text-xs" :style="s.role === '在役' ? { backgroundColor: '#F6FFED', color: '#52C41A', border: '1px solid #B7EB8F' } : { backgroundColor: '#FAFAFA', color: 'rgba(0,0,0,0.45)', border: '1px solid #D9D9D9' }">{{ s.role }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Repair History -->
|
||||
<div class="p-5 rounded-lg" style="background-color: #FAFAFA; border: 1px solid #F0F0F0">
|
||||
<h4 class="text-base font-semibold mb-3">维修记录</h4>
|
||||
<div v-if="repairHistory.length === 0" class="text-sm" style="color: rgba(0,0,0,0.25)">暂无维修记录</div>
|
||||
<div v-else class="space-y-2">
|
||||
<div v-for="(r, i) in repairHistory" :key="i" class="flex items-center gap-3 text-sm" style="color: rgba(0,0,0,0.65)">
|
||||
<span style="color: rgba(0,0,0,0.35)">{{ r.date }}</span>
|
||||
<router-link :to="'/repair/' + r.orderId" style="color: #4a7c59">{{ r.orderId }}</router-link>
|
||||
<span>{{ r.action }}</span>
|
||||
<span style="color: rgba(0,0,0,0.35)">{{ r.operator }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-center gap-3 p-5 border-t" style="border-color: #F0F0F0">
|
||||
<button class="px-6 py-2 rounded text-sm" style="border: 1px solid #D9D9D9; color: rgba(0,0,0,0.85)" @click="showDetail = false">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Add Board Drawer -->
|
||||
<div v-if="showAddDrawer" class="fixed inset-0 z-50 flex justify-end" style="background-color: rgba(0,0,0,0.45)" @click.self="showAddDrawer = false">
|
||||
<div class="bg-white w-[480px] h-full flex flex-col" style="box-shadow: -4px 0 12px rgba(0,0,0,0.1)">
|
||||
<div class="flex items-center justify-between p-5 border-b" style="border-color: #F0F0F0">
|
||||
<h3 class="text-lg font-semibold">新增板卡</h3>
|
||||
<button @click="showAddDrawer = false" class="p-1 rounded hover:bg-gray-100" style="color: rgba(0,0,0,0.45)"><X :size="18" /></button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto p-6 space-y-5">
|
||||
<!-- 板卡类型 -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1.5" style="color: rgba(0,0,0,0.85)"><span class="text-red-500 mr-0.5">*</span>板卡类型</label>
|
||||
<select v-model="addForm.type" class="w-full px-3 py-2 rounded text-sm" style="border: 1px solid #D9D9D9; color: rgba(0,0,0,0.85); outline: none">
|
||||
<option v-for="t in boardTypes.filter(x => x !== '全部')" :key="t" :value="t">{{ t }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- 型号 -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1.5" style="color: rgba(0,0,0,0.85)"><span class="text-red-500 mr-0.5">*</span>板卡型号</label>
|
||||
<input v-model="addForm.hwVersion" type="text" placeholder="如 MB-V2.3" class="w-full px-3 py-2 rounded text-sm" style="border: 1px solid #D9D9D9; outline: none" />
|
||||
</div>
|
||||
<!-- 固件版本 -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1.5" style="color: rgba(0,0,0,0.85)"><span class="text-red-500 mr-0.5">*</span>固件版本</label>
|
||||
<input v-model="addForm.fwVersion" type="text" placeholder="如 v1.0.0" class="w-full px-3 py-2 rounded text-sm" style="border: 1px solid #D9D9D9; outline: none" />
|
||||
</div>
|
||||
<!-- 生产日期 -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-1.5" style="color: rgba(0,0,0,0.85)"><span class="text-red-500 mr-0.5">*</span>生产日期</label>
|
||||
<input v-model="addForm.productionDate" type="date" class="w-full px-3 py-2 rounded text-sm" style="border: 1px solid #D9D9D9; outline: none" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-end gap-3 p-5 border-t" style="border-color: #F0F0F0">
|
||||
<button class="px-6 py-2 rounded text-sm" style="border: 1px solid #D9D9D9; color: rgba(0,0,0,0.85)" @click="showAddDrawer = false">取消</button>
|
||||
<button class="px-6 py-2 rounded text-sm text-white" style="background-color: #4a7c59" @click="submitAddBoard">确认新增</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { Info } from 'lucide-vue-next'
|
||||
import { Download, Info } from 'lucide-vue-next'
|
||||
|
||||
interface CalibrationRecord {
|
||||
boardSn: string
|
||||
deviceSn: string
|
||||
calibrationDate: string
|
||||
calibrator: string
|
||||
expiryDate: string
|
||||
|
|
@ -13,7 +12,6 @@ interface CalibrationRecord {
|
|||
const calibrationRecords: CalibrationRecord[] = [
|
||||
{
|
||||
boardSn: 'RX20240308001',
|
||||
deviceSn: 'GD30-2025-000001',
|
||||
calibrationDate: '2024-03-01',
|
||||
calibrator: '王工程师',
|
||||
expiryDate: '2025-03-01',
|
||||
|
|
@ -21,7 +19,6 @@ const calibrationRecords: CalibrationRecord[] = [
|
|||
},
|
||||
{
|
||||
boardSn: 'RX20240308002',
|
||||
deviceSn: 'GD20-2025-000045',
|
||||
calibrationDate: '2024-03-05',
|
||||
calibrator: '李工程师',
|
||||
expiryDate: '2025-03-05',
|
||||
|
|
@ -29,7 +26,6 @@ const calibrationRecords: CalibrationRecord[] = [
|
|||
},
|
||||
{
|
||||
boardSn: 'RX20240308003',
|
||||
deviceSn: 'GD10-2025-000023',
|
||||
calibrationDate: '2024-03-08',
|
||||
calibrator: '张工程师',
|
||||
expiryDate: '2025-03-08',
|
||||
|
|
@ -65,7 +61,16 @@ const getStatusStyle = (status: CalibrationRecord['status']) => {
|
|||
<div class="p-6">
|
||||
<!-- Page Header -->
|
||||
<div class="mb-6">
|
||||
<h2 class="text-2xl font-semibold mb-1">校准管理</h2>
|
||||
|
||||
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<h2 class="text-2xl font-semibold">校准管理</h2>
|
||||
<div class="flex items-center gap-3">
|
||||
<button class="px-4 py-2 rounded flex items-center gap-2" style="border: 1px solid #D9D9D9; color: rgba(0,0,0,0.85)">
|
||||
<Download :size="16" /> 导入
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm" style="color: rgba(0, 0, 0, 0.45)">管理采集板校准数据</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -83,22 +88,6 @@ const getStatusStyle = (status: CalibrationRecord['status']) => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stat Cards -->
|
||||
<div class="grid grid-cols-4 gap-6 mb-6">
|
||||
<div class="bg-white p-6 rounded-lg" style="box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05)">
|
||||
<div class="text-sm mb-2" style="color: rgba(0, 0, 0, 0.45)">采集板校准总数</div>
|
||||
<div class="text-3xl font-semibold" style="color: #4a7c59">1,245</div>
|
||||
</div>
|
||||
<div class="bg-white p-6 rounded-lg" style="box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05)">
|
||||
<div class="text-sm mb-2" style="color: rgba(0, 0, 0, 0.45)">待校准采集板</div>
|
||||
<div class="text-3xl font-semibold" style="color: #FAAD14">23</div>
|
||||
</div>
|
||||
<div class="bg-white p-6 rounded-lg" style="box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05)">
|
||||
<div class="text-sm mb-2" style="color: rgba(0, 0, 0, 0.45)">校准即将到期</div>
|
||||
<div class="text-3xl font-semibold" style="color: #FF4D4F">15</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Card -->
|
||||
<div class="bg-white p-6 rounded-lg mb-6" style="box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05)">
|
||||
<div class="grid grid-cols-4 gap-4">
|
||||
|
|
@ -153,7 +142,6 @@ const getStatusStyle = (status: CalibrationRecord['status']) => {
|
|||
<thead style="background-color: #FAFAFA">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">采集板SN号</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">所属设备</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">校准日期</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">到期日期</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">校准人员</th>
|
||||
|
|
@ -169,7 +157,6 @@ const getStatusStyle = (status: CalibrationRecord['status']) => {
|
|||
style="border-color: #F0F0F0"
|
||||
>
|
||||
<td class="px-6 py-4">{{ record.boardSn }}</td>
|
||||
<td class="px-6 py-4" style="color: rgba(0, 0, 0, 0.65)">{{ record.deviceSn }}</td>
|
||||
<td class="px-6 py-4" style="color: rgba(0, 0, 0, 0.65)">{{ record.calibrationDate }}</td>
|
||||
<td class="px-6 py-4" style="color: rgba(0, 0, 0, 0.65)">{{ record.expiryDate }}</td>
|
||||
<td class="px-6 py-4" style="color: rgba(0, 0, 0, 0.65)">{{ record.calibrator }}</td>
|
||||
|
|
|
|||
|
|
@ -19,14 +19,14 @@ interface ConfigFile {
|
|||
const configFiles: ConfigFile[] = [
|
||||
{
|
||||
configId: 'CFG-GD30-v1.2.0',
|
||||
model: 'GD30 高密度电法仪',
|
||||
model: 'GD-30 Supreme',
|
||||
version: 'v1.2.0',
|
||||
createdTime: '2024-03-01 10:30',
|
||||
status: '生效',
|
||||
},
|
||||
{
|
||||
configId: 'CFG-GT20-v1.5.3',
|
||||
model: 'GT20 瞬变电磁仪',
|
||||
configId: 'CFG-GD20-v1.5.3',
|
||||
model: 'GD-20 Supreme',
|
||||
version: 'v1.5.3',
|
||||
createdTime: '2024-02-28 14:20',
|
||||
status: '生效',
|
||||
|
|
@ -95,9 +95,9 @@ const getStatusStyle = (status: ConfigFile['status']) => {
|
|||
style="border-color: #D9D9D9; background-color: #fff"
|
||||
>
|
||||
<option>全部型号</option>
|
||||
<option>GD30 高密度电法仪</option>
|
||||
<option>GT20 瞬变电磁仪</option>
|
||||
<option>GM10 大地电磁仪</option>
|
||||
<option>GD-30 Supreme</option>
|
||||
<option>GD-20 Supreme</option>
|
||||
<option>GD-10 Supreme</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -118,7 +118,7 @@ const getStatusStyle = (status: ConfigFile['status']) => {
|
|||
type="text"
|
||||
class="w-full px-3 py-2 border rounded"
|
||||
style="border-color: #D9D9D9"
|
||||
placeholder="搜索配置ID或描述"
|
||||
placeholder="搜索配置文件或描述"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-end">
|
||||
|
|
@ -142,7 +142,7 @@ const getStatusStyle = (status: ConfigFile['status']) => {
|
|||
<table class="w-full">
|
||||
<thead style="background-color: #FAFAFA">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">配置ID</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">配置文件</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">适配型号</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">版本</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0, 0, 0, 0.85)">创建时间</th>
|
||||
|
|
@ -218,9 +218,9 @@ const getStatusStyle = (status: ConfigFile['status']) => {
|
|||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">适配型号 <span style="color: #FF4D4F">*</span></label>
|
||||
<select v-model="newModel" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="">请选择型号</option>
|
||||
<option>GD30 高密度电法仪</option>
|
||||
<option>GT20 瞬变电磁仪</option>
|
||||
<option>GM10 大地电磁仪</option>
|
||||
<option>GD-30 Supreme</option>
|
||||
<option>GD-20 Supreme</option>
|
||||
<option>GD-10 Supreme</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -278,7 +278,7 @@ const getStatusStyle = (status: ConfigFile['status']) => {
|
|||
<div>
|
||||
<label class="block text-sm mb-1" style="color: rgba(0,0,0,0.65)">采样率</label>
|
||||
<select class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option>50Hz、60Hz、100Hz、1000Hz</option><option>50Hz、60Hz、100Hz、1000Hz</option><option>50Hz、60Hz</option>
|
||||
<option>50Hz、60Hz、100Hz、1000Hz</option><option>50Hz、60Hz</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -287,7 +287,7 @@ const getStatusStyle = (status: ConfigFile['status']) => {
|
|||
<option>±2.5V、±80V</option><option>±80V、±600V</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<label class="block text-sm mb-1" style="color: rgba(0,0,0,0.65)">全波形采集</label>
|
||||
<select class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option>支持</option><option>不支持</option>
|
||||
|
|
@ -301,12 +301,8 @@ const getStatusStyle = (status: ConfigFile['status']) => {
|
|||
<h4 class="text-base font-semibold mb-4">网络参数</h4>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm mb-1" style="color: rgba(0,0,0,0.65)">WiFi SSID</label>
|
||||
<input type="text" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9" placeholder="如 GD30_Device" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm mb-1" style="color: rgba(0,0,0,0.65)">默认IP地址</label>
|
||||
<input type="text" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9" placeholder="192.168.1.100" />
|
||||
<label class="block text-sm mb-1" style="color: rgba(0,0,0,0.65)">WiFi SSID 前缀</label>
|
||||
<input type="text" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9" placeholder="如 GD30_" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@
|
|||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xs mb-1" style="color: rgba(0, 0, 0, 0.45)">固件版本</div>
|
||||
<div>{{ device.firmwareVersion }}</div>
|
||||
<div class="text-xs mb-1" style="color: rgba(0, 0, 0, 0.45)">主机版本</div>
|
||||
<div>{{ device.version }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xs mb-1" style="color: rgba(0, 0, 0, 0.45)">生产日期</div>
|
||||
|
|
@ -172,7 +172,7 @@ interface Device {
|
|||
sn: string
|
||||
model: string
|
||||
status: '已激活' | '已出厂' | '装配中'
|
||||
firmwareVersion: string
|
||||
version: string
|
||||
registrationDate: string
|
||||
}
|
||||
|
||||
|
|
@ -185,21 +185,21 @@ const devices: Device[] = [
|
|||
sn: 'GD30-20240308-001',
|
||||
model: 'GD30 高密度电法仪',
|
||||
status: '已激活',
|
||||
firmwareVersion: 'v2.3.5',
|
||||
version: 'v2.3.5',
|
||||
registrationDate: '2024-03-08 14:30',
|
||||
},
|
||||
{
|
||||
sn: 'GT20-20240307-045',
|
||||
model: 'GT20 瞬变电磁仪',
|
||||
status: '已出厂',
|
||||
firmwareVersion: 'v1.8.2',
|
||||
version: 'v1.8.2',
|
||||
registrationDate: '2024-03-07 10:15',
|
||||
},
|
||||
{
|
||||
sn: 'GD30-20240308-002',
|
||||
model: 'GD30 高密度电法仪',
|
||||
status: '装配中',
|
||||
firmwareVersion: 'v2.3.4',
|
||||
version: 'v2.3.4',
|
||||
registrationDate: '2024-03-08 16:20',
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ const showDrawer = ref(false)
|
|||
const drawerForm = ref({
|
||||
name: '',
|
||||
code: '',
|
||||
authFile: '',
|
||||
configFile: '',
|
||||
firmwareVersion: '',
|
||||
status: '在产' as '在产' | '停产',
|
||||
})
|
||||
|
||||
|
|
@ -34,41 +31,22 @@ interface ChecklistData {
|
|||
[key: string]: ChecklistItem[]
|
||||
}
|
||||
|
||||
const activeTab = ref('GD30')
|
||||
|
||||
const stats = [
|
||||
{ label: '型号总数', value: '12', icon: Server, color: '#4a7c59' },
|
||||
{ label: '在产型号', value: '8', icon: CheckCircle2, color: '#52C41A' },
|
||||
{ label: '停产型号', value: '3', icon: AlertTriangle, color: '#FAAD14' },
|
||||
{ label: '关联设备总数', value: '5,234', icon: Layers, color: '#722ED1' },
|
||||
]
|
||||
const activeTab = ref('GD-30 Supreme')
|
||||
|
||||
const modelData = [
|
||||
{
|
||||
name: 'GD30 高密度电法仪',
|
||||
name: 'GD-30 Supreme',
|
||||
code: 'GD30-2024',
|
||||
authFile: 'auth_gd30_v2.3.lic',
|
||||
configFile: 'config_gd30_v1.5.json',
|
||||
firmwareVersion: 'v2.3.5',
|
||||
deviceCount: 2456,
|
||||
status: '在产' as const,
|
||||
},
|
||||
{
|
||||
name: 'GT20 瞬变电磁仪',
|
||||
code: 'GT20-2023',
|
||||
authFile: 'auth_gt20_v1.8.lic',
|
||||
configFile: 'config_gt20_v1.2.json',
|
||||
firmwareVersion: 'v1.8.2',
|
||||
deviceCount: 1823,
|
||||
name: 'GD-20 Supreme',
|
||||
code: 'GD20-2023',
|
||||
status: '在产' as const,
|
||||
},
|
||||
{
|
||||
name: 'GM10 大地电磁仪',
|
||||
code: 'GM10-2022',
|
||||
authFile: 'auth_gm10_v1.5.lic',
|
||||
configFile: 'config_gm10_v1.0.json',
|
||||
firmwareVersion: 'v1.5.1',
|
||||
deviceCount: 955,
|
||||
name: 'GD-10 Supreme',
|
||||
code: 'GD10-2022',
|
||||
status: '停产' as const,
|
||||
},
|
||||
]
|
||||
|
|
@ -98,14 +76,14 @@ const checklistData = ref<ChecklistData>({
|
|||
{ id: 21, text: '过流/过压/短路保护', type: 'bool', required: true, note: '' },
|
||||
{ id: 22, text: '出厂装箱核对', type: 'bool', required: true, note: '' },
|
||||
],
|
||||
GT20: [
|
||||
GD20: [
|
||||
{ id: 1, text: '主板SN扫码绑定主机', type: 'text', required: true, note: '唯一SN' },
|
||||
{ id: 2, text: '采集板SN录入', type: 'text', required: true, note: '' },
|
||||
{ id: 3, text: 'GPS/北斗检测', type: 'bool', required: true, note: '授时正常' },
|
||||
{ id: 4, text: '系统启动正常', type: 'bool', required: true, note: '' },
|
||||
{ id: 5, text: '整体功能测试', type: 'bool', required: true, note: '' },
|
||||
],
|
||||
GM10: [
|
||||
GD10: [
|
||||
{ id: 1, text: '主板SN扫码绑定主机', type: 'text', required: true, note: '唯一SN' },
|
||||
{ id: 2, text: '传感器模块连接', type: 'bool', required: true, note: '' },
|
||||
{ id: 3, text: '接口板安装', type: 'bool', required: true, note: '' },
|
||||
|
|
@ -173,11 +151,11 @@ const boardVersionData = [
|
|||
|
||||
// Checklist template drawer state
|
||||
const showChecklistDrawer = ref(false)
|
||||
const newTplModel = ref('GD30')
|
||||
const newTplModel = ref('GD-30 Supreme')
|
||||
const newTplItems = ref<{ text: string }[]>([{ text: '' }])
|
||||
|
||||
const openChecklistDrawer = () => {
|
||||
newTplModel.value = 'GD30'
|
||||
newTplModel.value = 'GD-30 Supreme'
|
||||
newTplItems.value = [{ text: '' }]
|
||||
showChecklistDrawer.value = true
|
||||
}
|
||||
|
|
@ -206,30 +184,7 @@ const removeTplItem = (index: number) => {
|
|||
>
|
||||
<Info :size="20" :style="{ color: '#4a7c59', flexShrink: 0, marginTop: '2px' }" />
|
||||
<div :style="{ color: '#2d5a3d' }">
|
||||
型号管理是平台核心枢纽,每个型号关联授权文件、配置文件和固件版本
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stat Cards -->
|
||||
<div class="grid grid-cols-4 gap-6 mb-6">
|
||||
<div
|
||||
v-for="(stat, index) in stats"
|
||||
:key="index"
|
||||
class="bg-white p-6 rounded-lg"
|
||||
:style="{ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' }"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="text-sm mb-2" :style="{ color: 'rgba(0, 0, 0, 0.65)' }">{{ stat.label }}</div>
|
||||
<div class="text-3xl font-semibold">{{ stat.value }}</div>
|
||||
</div>
|
||||
<div
|
||||
class="w-12 h-12 rounded-lg flex items-center justify-center"
|
||||
:style="{ backgroundColor: `${stat.color}15` }"
|
||||
>
|
||||
<component :is="stat.icon" :size="24" :style="{ color: stat.color }" />
|
||||
</div>
|
||||
</div>
|
||||
型号管理是平台核心枢纽,每个型号关联授权项、配置文件
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -244,7 +199,7 @@ const removeTplItem = (index: number) => {
|
|||
@click="showDrawer = true"
|
||||
>
|
||||
<Plus :size="16" />
|
||||
新增型号
|
||||
新增设备型号
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -254,10 +209,6 @@ const removeTplItem = (index: number) => {
|
|||
<tr>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">型号名称</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">编码</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">授权文件</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">配置文件</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">固件版本</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">设备数</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">状态</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">操作</th>
|
||||
</tr>
|
||||
|
|
@ -271,16 +222,6 @@ const removeTplItem = (index: number) => {
|
|||
>
|
||||
<td class="px-6 py-4">{{ model.name }}</td>
|
||||
<td class="px-6 py-4" :style="{ color: 'rgba(0, 0, 0, 0.65)' }">{{ model.code }}</td>
|
||||
<td class="px-6 py-4">
|
||||
<router-link to="/licenses" class="text-sm" style="color: #4a7c59">{{ model.authFile }}</router-link>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<router-link to="/config-files" class="text-sm" style="color: #4a7c59">{{ model.configFile }}</router-link>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<router-link to="/firmware" class="text-sm" style="color: #4a7c59">{{ model.firmwareVersion }}</router-link>
|
||||
</td>
|
||||
<td class="px-6 py-4">{{ model.deviceCount.toLocaleString() }}</td>
|
||||
<td class="px-6 py-4">
|
||||
<span
|
||||
class="px-2 py-1 rounded text-xs"
|
||||
|
|
@ -298,7 +239,6 @@ const removeTplItem = (index: number) => {
|
|||
<button class="text-sm" :style="{ color: '#4a7c59' }">编辑</button>
|
||||
<router-link to="/licenses" class="text-sm" style="color: #4a7c59">授权</router-link>
|
||||
<router-link to="/config-files" class="text-sm" style="color: #4a7c59">配置</router-link>
|
||||
<router-link to="/firmware" class="text-sm" style="color: #4a7c59">固件</router-link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -403,99 +343,14 @@ const removeTplItem = (index: number) => {
|
|||
<div class="space-y-5">
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">型号名称 <span style="color: #FF4D4F">*</span></label>
|
||||
<input v-model="drawerForm.name" type="text" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9" placeholder="如:GD30 高密度电法仪" />
|
||||
<input v-model="drawerForm.name" type="text" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9" placeholder="如:GD-30 Supreme" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">型号编码 <span style="color: #FF4D4F">*</span></label>
|
||||
<select v-model="drawerForm.code" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="">请选择编码</option>
|
||||
<option>GD10-2025</option>
|
||||
<option>GD20-2025</option>
|
||||
<option>GD30-2025</option>
|
||||
<option>GT20-2025</option>
|
||||
<option>GM10-2025</option>
|
||||
</select>
|
||||
<input class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
</input>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定授权文件</label>
|
||||
<select v-model="drawerForm.authFile" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="">请选择授权文件</option>
|
||||
<option>auth_gd10_v1.0.lic</option>
|
||||
<option>auth_gd20_v2.0.lic</option>
|
||||
<option>auth_gd30_v2.3.lic</option>
|
||||
<option>auth_gt20_v1.8.lic</option>
|
||||
<option>auth_gm10_v1.5.lic</option>
|
||||
</select>
|
||||
<div class="text-xs mt-1" style="color: rgba(0,0,0,0.45)">授权文件按型号绑定,设备激活时自动下载</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定配置文件</label>
|
||||
<select v-model="drawerForm.configFile" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="">请选择配置文件</option>
|
||||
<option>config_gd10_v1.0.json</option>
|
||||
<option>config_gd20_v1.2.json</option>
|
||||
<option>config_gd30_v1.5.json</option>
|
||||
<option>config_gt20_v1.2.json</option>
|
||||
<option>config_gm10_v1.0.json</option>
|
||||
</select>
|
||||
<div class="text-xs mt-1" style="color: rgba(0,0,0,0.45)">配置文件包含发射参数、采集参数、网络参数等</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定主机固件版本</label>
|
||||
<select v-model="drawerForm.firmwareVersion" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="">请选择主机固件版本</option>
|
||||
<option>v2.3.5</option>
|
||||
<option>v2.3.0</option>
|
||||
<option>v2.2.0</option>
|
||||
<option>v2.1.0</option>
|
||||
<option>v1.8.2</option>
|
||||
<option>v1.5.1</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定主协板固件版本</label>
|
||||
<select v-model="drawerForm.firmwareVersion" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="">请选择主协板固件版本</option>
|
||||
<option>v2.3.5</option>
|
||||
<option>v2.3.0</option>
|
||||
<option>v2.2.0</option>
|
||||
<option>v2.1.0</option>
|
||||
<option>v1.8.2</option>
|
||||
<option>v1.5.1</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定发射板固件版本</label>
|
||||
<select v-model="drawerForm.firmwareVersion" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="">请选择发射板固件版本</option>
|
||||
<option>v2.3.5</option>
|
||||
<option>v2.3.0</option>
|
||||
<option>v2.2.0</option>
|
||||
<option>v2.1.0</option>
|
||||
<option>v1.8.2</option>
|
||||
<option>v1.5.1</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">绑定采集板固件版本</label>
|
||||
<select v-model="drawerForm.firmwareVersion" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="">请选择采集板固件版本</option>
|
||||
<option>v2.3.5</option>
|
||||
<option>v2.3.0</option>
|
||||
<option>v2.2.0</option>
|
||||
<option>v2.1.0</option>
|
||||
<option>v1.8.2</option>
|
||||
<option>v1.5.1</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">状态</label>
|
||||
<div class="flex items-center gap-4">
|
||||
|
|
@ -509,25 +364,6 @@ const removeTplItem = (index: number) => {
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Preview -->
|
||||
<div class="p-4 rounded-lg" style="background-color: #FAFAFA; border: 1px solid #F0F0F0">
|
||||
<div class="text-sm font-medium mb-3">绑定预览</div>
|
||||
<div class="space-y-2 text-sm" style="color: rgba(0,0,0,0.65)">
|
||||
<div class="flex justify-between">
|
||||
<span>授权文件</span>
|
||||
<span :style="{ color: drawerForm.authFile ? '#52C41A' : '#FF4D4F' }">{{ drawerForm.authFile || '未绑定' }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>配置文件</span>
|
||||
<span :style="{ color: drawerForm.configFile ? '#52C41A' : '#FF4D4F' }">{{ drawerForm.configFile || '未绑定' }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>固件版本</span>
|
||||
<span :style="{ color: drawerForm.firmwareVersion ? '#52C41A' : '#FF4D4F' }">{{ drawerForm.firmwareVersion || '未绑定' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -561,9 +397,9 @@ const removeTplItem = (index: number) => {
|
|||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">设备型号 <span style="color: #FF4D4F">*</span></label>
|
||||
<select v-model="newTplModel" class="w-full px-3 py-2 border rounded text-sm" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option value="GD30">GD30</option>
|
||||
<option value="GT20">GT20</option>
|
||||
<option value="GM10">GM10</option>
|
||||
<option value="GD-30 Supreme">GD-30 Supreme</option>
|
||||
<option value="GT20">GD-20 Supreme</option>
|
||||
<option value="GM10">GD-10 Supreme</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ const checklistItems = ref([
|
|||
])
|
||||
|
||||
const bomData = [
|
||||
{ code: 'MB-2024-001', name: '主控板', sn: 'MB20240308001', spec: 'GD30-MB-V2.3', calibration: '无需校准', quantity: 1 },
|
||||
{ code: 'RX-2024-002', name: '采集板', sn: 'RX20240308001、RX20240308002', spec: 'GD30-RX-V1.8', calibration: '已校准', quantity: 2 },
|
||||
{ code: 'MC-2024-003', name: '测控板', sn: 'MC20240308003', spec: 'GD30-MC-V1.5', calibration: '无需校准', quantity: 1 },
|
||||
{ code: 'TX-2024-003', name: '发射板', sn: 'TX20240308003', spec: 'GD30-TX-V1.5', calibration: '无需校准', quantity: 1 },
|
||||
{ code: 'BO-2024-004', name: '升压板', sn: 'BO20240308004', spec: 'BP600', calibration: '无需校准', quantity: 1 },
|
||||
{ code: 'MB-2024-001', name: '主协板', sn: 'MB20240308001', spec: 'MB-V2.3', calibration: '无需校准', quantity: 1 },
|
||||
{ code: 'RX-2024-002', name: '采集板', sn: 'RX20240308001、RX20240308002', spec: 'RX-V1.8', calibration: '已校准', quantity: 2 },
|
||||
{ code: 'MC-2024-003', name: '测控板', sn: 'MC20240308003', spec: 'MC-V1.5', calibration: '无需校准', quantity: 1 },
|
||||
{ code: 'TX-2024-003', name: '发射板', sn: 'TX20240308003', spec: 'TX-V1.5', calibration: '无需校准', quantity: 1 },
|
||||
{ code: 'BO-2024-004', name: '升压板', sn: 'BO20240308004', spec: 'BO-V1.4', calibration: '无需校准', quantity: 1 },
|
||||
{ code: 'CS-2024-005', name: '外壳机箱', sn: '-', spec: 'AL6061-T6', calibration: '无需校准', quantity: 1 },
|
||||
]
|
||||
|
||||
|
|
@ -103,9 +103,9 @@ const toggleChecklistItem = (id: number) => {
|
|||
class="w-full px-3 py-2 border rounded"
|
||||
:style="{ borderColor: '#D9D9D9', backgroundColor: '#fff' }"
|
||||
>
|
||||
<option value="GD30">GD30 高密度电法仪</option>
|
||||
<option value="GT20">GT20 瞬变电磁仪</option>
|
||||
<option value="GTXD">GM10 大地电磁仪</option>
|
||||
<option value="GD30">GD-30 Supreme</option>
|
||||
<option value="GT20">GD-20 Supreme</option>
|
||||
<option value="GTXD">GD-10 Supreme</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -202,7 +202,7 @@ const toggleChecklistItem = (id: number) => {
|
|||
<div class="bg-white rounded-lg mb-6" :style="{ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' }">
|
||||
<div class="p-6 border-b" :style="{ borderColor: '#F0F0F0' }">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-lg font-semibold">设备BOM清单</h3>
|
||||
<h3 class="text-lg font-semibold">装机清单</h3>
|
||||
<button
|
||||
class="px-4 py-2 rounded flex items-center gap-2"
|
||||
:style="{ border: '1px solid #D9D9D9', color: 'rgba(0, 0, 0, 0.85)' }"
|
||||
|
|
@ -220,7 +220,7 @@ const toggleChecklistItem = (id: number) => {
|
|||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">物料编码</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">物料名称</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">SN号</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">规格型号</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">型号</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">校准状态</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">数量</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" :style="{ color: 'rgba(0, 0, 0, 0.85)' }">操作</th>
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ const formatFileSize = (bytes: number): string => {
|
|||
<!-- Page Header -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<h2 class="text-2xl font-semibold">GD-30 Supreme固件库</h2>
|
||||
<h2 class="text-2xl font-semibold">固件库</h2>
|
||||
<div class="flex items-center gap-3">
|
||||
<button class="px-4 py-2 rounded text-white flex items-center gap-2" style="background-color: #4a7c59" @click="uploadDialogVisible = true">
|
||||
<Upload :size="16" />
|
||||
|
|
@ -197,10 +197,6 @@ const formatFileSize = (bytes: number): string => {
|
|||
<span class="text-lg font-semibold">版本: {{ fw.version }}</span>
|
||||
<span class="text-sm" style="color: rgba(0,0,0,0.45)">发布日期: {{ fw.releaseDate }}</span>
|
||||
<span class="text-sm" style="color: #52C41A">{{ fw.status }}</span>
|
||||
<!-- 新增:固件类型标签 -->
|
||||
<span class="text-sm px-2 py-1 rounded" style="background-color: #f0f9ff; color: #4a7c59">
|
||||
类型: {{ fw.firmwareType }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Basic info -->
|
||||
|
|
@ -214,7 +210,7 @@ const formatFileSize = (bytes: number): string => {
|
|||
MD5: {{ fw.md5 }} SHA256: {{ fw.sha256 }}
|
||||
</div>
|
||||
<div class="text-sm mb-3" style="color: rgba(0,0,0,0.65)">
|
||||
适用型号: {{ fw.model }} 硬件版本范围: {{ fw.hardwareRange }} 升级类型: {{ fw.upgradeType }}
|
||||
升级类型: {{ fw.upgradeType }}
|
||||
</div>
|
||||
|
||||
<!-- Signature -->
|
||||
|
|
@ -257,13 +253,6 @@ const formatFileSize = (bytes: number): string => {
|
|||
<ElInput v-model="uploadForm.version" placeholder="例如:v2.4.0" />
|
||||
</ElFormItem>
|
||||
|
||||
<!-- 新增:固件类型选择 -->
|
||||
<ElFormItem label="固件类型" prop="firmwareType">
|
||||
<ElSelect v-model="uploadForm.firmwareType" placeholder="请选择固件类型">
|
||||
<ElOption v-for="type in firmwareTypes" :key="type" :label="type" :value="type" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
|
||||
<!-- 硬件版本范围 -->
|
||||
<ElFormItem label="硬件版本范围" prop="hardwareRange">
|
||||
<ElInput v-model="uploadForm.hardwareRange" placeholder="例如:A1-A3" />
|
||||
|
|
|
|||
|
|
@ -1,165 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ArrowLeft, Info } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const router = useRouter()
|
||||
const selectedModel = ref('GD-10 Supreme')
|
||||
const expiryType = ref('永久')
|
||||
const expiryDate = ref('')
|
||||
|
||||
interface AuthItem {
|
||||
name: string
|
||||
}
|
||||
|
||||
const authItems = ref<AuthItem[]>([
|
||||
{ name: '1D SP' },
|
||||
{ name: '2D SP' },
|
||||
{ name: '3D SP' },
|
||||
{ name: '1D VES' },
|
||||
{ name: '2D ERT' },
|
||||
{ name: '3D ERT' },
|
||||
{ name: '1D IP'},
|
||||
{ name: '2D IP' },
|
||||
{ name: '3D IP'},
|
||||
{ name: '跨孔(Cross-Hole)' },
|
||||
{ name: '水上(Marine)'},
|
||||
])
|
||||
|
||||
const availableItems = computed(() => {
|
||||
return authItems.value.map(item => {
|
||||
let available = false
|
||||
return { ...item, available }
|
||||
})
|
||||
})
|
||||
|
||||
const checkedItems = ref(new Set<string>())
|
||||
|
||||
const toggleItem = (name: string) => {
|
||||
if (checkedItems.value.has(name)) checkedItems.value.delete(name)
|
||||
else checkedItems.value.add(name)
|
||||
}
|
||||
|
||||
const selectAll = () => {
|
||||
availableItems.value.forEach(item => {
|
||||
if (item.available) checkedItems.value.add(item.name)
|
||||
})
|
||||
}
|
||||
|
||||
const clearAll = () => {
|
||||
checkedItems.value.clear()
|
||||
}
|
||||
|
||||
const selectedCount = computed(() => {
|
||||
return availableItems.value.filter(i => i.available && checkedItems.value.has(i.name)).length
|
||||
})
|
||||
|
||||
const totalAvailable = computed(() => {
|
||||
return availableItems.value.filter(i => i.available).length
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-6">
|
||||
<!-- Page Header -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center gap-4 mb-2">
|
||||
<button @click="router.go(-1)" class="p-2 rounded hover:bg-gray-100 transition-colors" style="color: rgba(0,0,0,0.65)">
|
||||
<ArrowLeft :size="20" />
|
||||
</button>
|
||||
<h2 class="text-2xl font-semibold">选择授权项生成</h2>
|
||||
</div>
|
||||
<p class="text-sm ml-12" style="color: rgba(0,0,0,0.45)">选择设备型号和授权功能模块,生成授权文件</p>
|
||||
</div>
|
||||
|
||||
<!-- Info Banner -->
|
||||
<div class="mb-6 p-4 rounded-lg flex items-start gap-3" style="background-color: #eef5f0; border: 1px solid #a3c4ad">
|
||||
<Info :size="20" style="color: #4a7c59; flex-shrink: 0; margin-top: 2px" />
|
||||
<div style="color: #2d5a3d">
|
||||
<div class="text-sm">
|
||||
不同设备型号支持不同的授权功能模块。选择型号后,下方表格会显示该型号可用的授权项。生成的授权文件将在设备APP激活时自动下载到对应设备。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Model & Expiry Selection -->
|
||||
<div class="bg-white p-6 rounded-lg mb-6" style="box-shadow: 0 1px 2px rgba(0,0,0,0.05)">
|
||||
<h3 class="text-lg font-semibold mb-6">基本信息</h3>
|
||||
<div class="grid grid-cols-3 gap-6">
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">设备型号 <span style="color: #FF4D4F">*</span></label>
|
||||
<select v-model="selectedModel" class="w-full px-3 py-2 border rounded" style="border-color: #D9D9D9; background-color: #fff" @change="clearAll()">
|
||||
<option>GD-10 Supreme</option>
|
||||
<option>GD-20 Supreme</option>
|
||||
<option>GD-30 Supreme</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">授权有效期</label>
|
||||
<select v-model="expiryType" class="w-full px-3 py-2 border rounded" style="border-color: #D9D9D9; background-color: #fff">
|
||||
<option>永久</option>
|
||||
<option>1年</option>
|
||||
<option>2年</option>
|
||||
<option>自定义</option>
|
||||
</select>
|
||||
</div>
|
||||
<div v-if="expiryType === '自定义'">
|
||||
<label class="block text-sm mb-2" style="color: rgba(0,0,0,0.85)">到期日期</label>
|
||||
<input type="date" v-model="expiryDate" class="w-full px-3 py-2 border rounded" style="border-color: #D9D9D9" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Authorization Items Table -->
|
||||
<div class="bg-white rounded-lg mb-6" style="box-shadow: 0 1px 2px rgba(0,0,0,0.05)">
|
||||
<div class="p-6 border-b flex items-center justify-between" style="border-color: #F0F0F0">
|
||||
<div class="flex items-center gap-3">
|
||||
<h3 class="text-lg font-semibold">功能授权项选择</h3>
|
||||
<span class="text-sm" style="color: rgba(0,0,0,0.45)">已选 {{ selectedCount }} / {{ totalAvailable }} 项</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<button class="text-sm" style="color: #4a7c59" @click="selectAll">全选可用项</button>
|
||||
<button class="text-sm" style="color: rgba(0,0,0,0.45)" @click="clearAll">清空</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead style="background-color: #FAFAFA">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85); width: 150px">选择</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">授权项名称</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in availableItems" :key="index" class="border-b" style="border-color: #F0F0F0">
|
||||
<td class="px-6 py-3">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="w-4 h-4"
|
||||
style="accent-color: #4a7c59"
|
||||
:checked="checkedItems.has(item.name)"
|
||||
:disabled="!item.available"
|
||||
@change="toggleItem(item.name)"
|
||||
/>
|
||||
</td>
|
||||
<td class="px-6 py-3 text-sm">{{ item.name }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Bar -->
|
||||
<div class="flex items-center justify-end gap-3 p-4 bg-white rounded-lg sticky bottom-0" style="box-shadow: 0 -2px 8px rgba(0,0,0,0.05)">
|
||||
<button class="px-6 py-2 rounded" style="border: 1px solid #D9D9D9; color: rgba(0,0,0,0.85)" @click="router.go(-1)">取消</button>
|
||||
<button
|
||||
class="px-6 py-2 rounded text-white"
|
||||
:style="{ backgroundColor: selectedCount > 0 ? '#52C41A' : '#D9D9D9' }"
|
||||
:disabled="selectedCount === 0"
|
||||
@click="router.push('/licenses')"
|
||||
>
|
||||
生成授权文件({{ selectedCount }}项)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -60,11 +60,11 @@ const onModelChange = () => {
|
|||
})
|
||||
}
|
||||
|
||||
interface License { licenseId: string; model: string; status: '已发布' | '草稿' | '已停用'; modules: string; expiry: string; createdDate: string }
|
||||
interface License {model: string; status: '已发布' | '草稿' | '已停用'; modules: string; expiry: string; createdDate: string }
|
||||
const licenses: License[] = [
|
||||
{ licenseId: 'LIC-GD10-Supreme-v1.0', model: 'GD-10 Supreme', status: '已发布', modules: '1D SP, 2D SP, 1D VES, 2D ERT, 1D IP, 2D IP', expiry: '永久', createdDate: '2025-02-01' },
|
||||
{ licenseId: 'LIC-GD20-Supreme-v1.0', model: 'GD-20 Supreme', status: '已发布', modules: '全部模块', expiry: '永久', createdDate: '2025-02-05' },
|
||||
{ licenseId: 'LIC-GD30-Supreme-v1.0', model: 'GD-30 Supreme', status: '草稿', modules: '全部模块(不含水上)', expiry: '1年', createdDate: '2025-02-08' },
|
||||
{model: 'GD-10 Supreme', status: '已发布', modules: '1D SP, 2D SP, 1D VES, 2D ERT, 1D IP, 2D IP', expiry: '永久', createdDate: '2025-02-01' },
|
||||
{model: 'GD-20 Supreme', status: '已发布', modules: '全部模块', expiry: '永久', createdDate: '2025-02-05' },
|
||||
{model: 'GD-30 Supreme', status: '草稿', modules: '全部模块(不含水上)', expiry: '1年', createdDate: '2025-02-08' },
|
||||
]
|
||||
const getStatusStyle = (s: License['status']) => {
|
||||
if (s === '已发布') return { backgroundColor: '#F6FFED', color: '#52C41A', border: '1px solid #B7EB8F' }
|
||||
|
|
@ -84,7 +84,7 @@ const getStatusStyle = (s: License['status']) => {
|
|||
<Download :size="16" /> 导出
|
||||
</button>
|
||||
<button class="px-4 py-2 rounded text-white flex items-center gap-2" style="background-color: #4a7c59" @click="openDrawer">
|
||||
<Plus :size="16" /> 选择授权项生成
|
||||
<Plus :size="16" /> 选择授权项
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -96,7 +96,7 @@ const getStatusStyle = (s: License['status']) => {
|
|||
<Info :size="20" style="color: #13C2C2; flex-shrink: 0; margin-top: 2px" />
|
||||
<div style="color: #006D75">
|
||||
<div class="font-medium mb-1">授权说明</div>
|
||||
<div class="text-sm">授权文件按设备型号管理,每个型号对应一套授权模块配置。点击"选择授权项生成"可按型号勾选功能模块并生成授权文件,设备在APP激活时自动下载对应型号的授权文件。</div>
|
||||
<div class="text-sm">授权文件按设备型号管理,每个型号对应一套授权模块配置。点击"选择授权项"可按型号勾选功能模块,设备在APP激活时自动下载对应型号的授权文件。</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -127,7 +127,6 @@ const getStatusStyle = (s: License['status']) => {
|
|||
<table class="w-full">
|
||||
<thead style="background-color: #FAFAFA">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">授权文件ID</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">适配型号</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">授权模块</th>
|
||||
<th class="px-6 py-3 text-left text-sm font-medium" style="color: rgba(0,0,0,0.85)">有效期</th>
|
||||
|
|
@ -138,7 +137,6 @@ const getStatusStyle = (s: License['status']) => {
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(lic, i) in licenses" :key="i" class="border-b" style="border-color: #F0F0F0">
|
||||
<td class="px-6 py-4" style="color: #4a7c59">{{ lic.licenseId }}</td>
|
||||
<td class="px-6 py-4">{{ lic.model }}</td>
|
||||
<td class="px-6 py-4 text-sm" style="color: rgba(0,0,0,0.65); max-width: 200px">{{ lic.modules }}</td>
|
||||
<td class="px-6 py-4" style="color: rgba(0,0,0,0.65)">{{ lic.expiry }}</td>
|
||||
|
|
@ -175,7 +173,7 @@ const getStatusStyle = (s: License['status']) => {
|
|||
<div class="bg-white w-[640px] h-full flex flex-col" style="box-shadow: -4px 0 12px rgba(0,0,0,0.1)">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between p-5 border-b" style="border-color: #F0F0F0">
|
||||
<h3 class="text-lg font-semibold">选择授权项生成</h3>
|
||||
<h3 class="text-lg font-semibold">选择授权项</h3>
|
||||
<button @click="showDrawer = false" class="p-1 rounded hover:bg-gray-100" style="color: rgba(0,0,0,0.45)">
|
||||
<X :size="18" />
|
||||
</button>
|
||||
|
|
@ -243,7 +241,7 @@ const getStatusStyle = (s: License['status']) => {
|
|||
:style="{ backgroundColor: selectedCount > 0 ? '#52C41A' : '#D9D9D9' }"
|
||||
:disabled="selectedCount === 0"
|
||||
@click="showDrawer = false"
|
||||
>生成授权文件({{ selectedCount }}项)</button>
|
||||
>保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ export const router = createRouter({
|
|||
{ path: 'devices', component: () => import('./pages/DeviceList.vue') },
|
||||
{ path: 'devices/:id', component: () => import('./pages/DeviceDetail.vue') },
|
||||
{ path: 'registration', component: () => import('./pages/DeviceRegistration.vue') },
|
||||
{ path: 'boards', component: () => import('./pages/BoardManagement.vue') },
|
||||
{ path: 'licenses', component: () => import('./pages/LicenseManagement.vue') },
|
||||
{ path: 'licenses/generate', component: () => import('./pages/LicenseGenerate.vue') },
|
||||
{ path: 'calibration', component: () => import('./pages/CalibrationRecords.vue') },
|
||||
{ path: 'repair', component: () => import('./pages/RepairOrders.vue') },
|
||||
{ path: 'repair/stats', component: () => import('./pages/RepairStats.vue') },
|
||||
|
|
|
|||
Loading…
Reference in New Issue