Merge branch '0.8.X' of https://gitee.com/hdka/klp-oa into 0.8.X
This commit is contained in:
492
docs/oee-report-design.md
Normal file
492
docs/oee-report-design.md
Normal file
@@ -0,0 +1,492 @@
|
||||
# OEE 报表页面设计(酸轧线、镀锌一线)
|
||||
|
||||
> ⚠️ **状态说明(2026-01)**:`klp-da` 中 `OeeReportServiceImpl` 的旧实现已全部移除,目前仅保留可编译运行的空骨架(接口返回空数据)。本设计文档中所有“✅ 当前实现口径/实现说明/回归实现细节”等内容已不再成立,需要以新的实现方案为准。
|
||||
|
||||
> 目标:在现阶段**不依赖班次/工单/客户维度**的前提下,完成可对比的两条产线 OEE 报表页面,包含 **OEE + 三大构成指标(时间稼动率/性能稼动率/良品率)**、**趋势**、**7 大损失**、**明细**,并在页面中**展示公式与口径**,方便统一认知与复核。
|
||||
|
||||
---
|
||||
|
||||
## 1. 范围与非范围
|
||||
|
||||
### 1.1 本期范围(V1)
|
||||
- **对象**:两条产线
|
||||
- 酸轧线
|
||||
- 镀锌一线
|
||||
- **时间粒度**:
|
||||
- 报表查询:按日(必做)
|
||||
- 趋势图:按日(必做),可扩展按小时/班次(后续)
|
||||
- **核心指标**:
|
||||
- OEE
|
||||
- 时间稼动率(Availability)
|
||||
- 性能稼动率(Performance)
|
||||
- 良品率(Quality)
|
||||
- **分析内容**:
|
||||
- 两线对比:KPI + 趋势
|
||||
- 7 大损失(分类汇总 + Top 原因)
|
||||
- 停机/损失明细列表(可筛选:产线/日期/损失类别)
|
||||
|
||||
### 1.2 非范围(V1 不做)
|
||||
- 班次维度、工单维度、客户维度
|
||||
- 设备级 OEE(仅产线级;如产线下含多设备,可在数据层聚合)
|
||||
- 复杂的理论产能模型(先以**标准节拍**/标准速度为主)
|
||||
|
||||
---
|
||||
|
||||
## 2. 页面信息架构(IA)与交互
|
||||
|
||||
### 2.1 页面入口与路由建议
|
||||
- 菜单:EMS / 报表 / **OEE 报表**
|
||||
- 路由:`/ems/oee`(建议)
|
||||
|
||||
### 2.2 查询区(页面顶部)
|
||||
- **日期范围**:开始日期、结束日期(默认最近 7 天/30 天)
|
||||
- **产线选择**:
|
||||
- 默认勾选:酸轧线、镀锌一线(两线同时展示)
|
||||
- 支持单选/多选(便于对比)
|
||||
- **统计口径选择(可选)**:
|
||||
- 负荷时间口径:是否扣除“计划停机”(默认扣除)
|
||||
- 性能口径:使用标准节拍(默认)/使用标准速度(可选)
|
||||
- 查询按钮、重置按钮
|
||||
|
||||
### 2.3 KPI 总览区(第一屏)
|
||||
以“产线”为列,指标为行(或每条产线一张卡片):
|
||||
- **OEE(%)**
|
||||
- **时间稼动率(%)**
|
||||
- **性能稼动率(%)**
|
||||
- **良品率(%)**
|
||||
- 辅助数值(建议展示,便于解释指标波动):
|
||||
- 负荷时间(min)
|
||||
- 停机时间(min)
|
||||
- 实际运转时间(min)
|
||||
- 产量(件/吨/卷,按你们产线计量单位)
|
||||
- 不良数
|
||||
|
||||
> 建议:KPI 卡片中同时显示“数值 + 分子/分母”摘要,例如:时间稼动率 87%(运转 400 / 负荷 460)。
|
||||
|
||||
### 2.4 趋势区(第二屏)
|
||||
- 折线图 1:两条产线 **OEE 日趋势**(同一图两条线)
|
||||
- 折线图 2:两条产线 **三大指标日趋势**(可 Tab 切换或分三图)
|
||||
|
||||
### 2.5 7 大损失区(第三屏)
|
||||
- 维度:产线(Tab:酸轧线 / 镀锌一线 / 合计)
|
||||
- 图表:
|
||||
- 柱状图:7 大损失分类的**时间损失(min)**
|
||||
- 帕累托:TopN 原因(来自停机原因/质量原因)占比
|
||||
- 表格:
|
||||
- 7 大损失分类:损失时间、占比、次数(可选)、平均时长(可选)
|
||||
|
||||
### 2.6 明细区(第四屏)
|
||||
- 停机/损失事件明细表
|
||||
- 日期时间、产线、损失类别、原因、开始/结束、时长、备注
|
||||
- 支持筛选:
|
||||
- 产线、日期、损失类别、关键词(原因/备注)
|
||||
|
||||
### 2.7 公式与口径说明区(页面底部或抽屉)
|
||||
> 你希望页面上展示公式:建议做成“口径说明”卡片 + 可折叠(默认折叠),避免占用首屏空间。
|
||||
|
||||
内容包括:OEE 公式、三大指标公式、字段定义、边界规则(见第 3、6 节)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 指标定义与公式(页面需展示)
|
||||
|
||||
### 3.1 总公式
|
||||
**设备综合效率(OEE)**:
|
||||
\[
|
||||
OEE = 时间稼动率 \times 性能稼动率 \times 良品率
|
||||
\]
|
||||
|
||||
### 3.2 时间稼动率(Availability)
|
||||
定义:在负荷时间内,真正处于“运转”的时间比例。
|
||||
|
||||
\[
|
||||
时间稼动率 = \frac{负荷时间 - 停机时间}{负荷时间} \times 100\%
|
||||
\]
|
||||
|
||||
字段解释:
|
||||
- **负荷时间**:计划生产时间扣除计划停机后的时间(V1 默认扣除计划停机)
|
||||
- **停机时间**:属于“停止损失”的所有停机/中断的总时长
|
||||
|
||||
### 3.3 性能稼动率(Performance)
|
||||
定义:在实际运转时间内,理论应完成的产量对应的时间占比(或等价的速度比)。
|
||||
|
||||
以“标准节拍”为口径(推荐、通用):
|
||||
\[
|
||||
性能稼动率 = \frac{理论节拍 \times 产量}{实际运转时间} \times 100\%
|
||||
\]
|
||||
|
||||
字段解释:
|
||||
- **理论节拍**:每单位产出的理论加工时间(如 min/吨、sec/卷,需统一单位)
|
||||
- **产量**:该期间内的产出总量(单位需与理论节拍匹配)
|
||||
- **实际运转时间**:负荷时间 - 停机时间
|
||||
|
||||
> 备注:如果你们更习惯“标准速度”,可替换为速度比口径:
|
||||
> \[
|
||||
> 性能稼动率 = \frac{实际产量}{理论产量} \times 100\%
|
||||
> \]
|
||||
> 其中理论产量 = 实际运转时间 / 理论节拍。
|
||||
|
||||
### 3.4 良品率(Quality)
|
||||
\[
|
||||
良品率 = \frac{良品数}{总产量} \times 100\%
|
||||
\]
|
||||
|
||||
字段解释:
|
||||
- **总产量**:产出总量(良品 + 不良/报废/返工产出,按你们定义)
|
||||
- **良品数**:合格产出数量
|
||||
|
||||
---
|
||||
|
||||
## 4. 7 大损失(分类口径)
|
||||
|
||||
> 7 大损失的目的:把 OEE 的损失拆解成可行动的改善项。V1 先做“分类汇总 + Top 原因”,不强依赖复杂的自动归因。
|
||||
|
||||
### 4.1 7 大损失分类(建议编码)
|
||||
1. **故障**(Breakdown)
|
||||
2. **换模换线/调整**(Setup & Adjustment)
|
||||
3. **刀具交换**(Tool Change)
|
||||
4. **暖机**(Warm-up)
|
||||
5. **空转/短暂停机**(Idling & Minor Stops)
|
||||
6. **速度下降**(Reduced Speed)
|
||||
7. **不良/修正**(Defects & Rework)
|
||||
|
||||
### 4.2 数据落地建议(最小可用)
|
||||
V1 推荐按“事件表 + 分类映射”实现:
|
||||
- 停机事件(1~5 类):从停机事件表按原因映射到分类
|
||||
- 速度下降(6 类):允许先不拆事件,直接以“性能损失分钟数”计算后挂到第 6 类
|
||||
- 不良/修正(7 类):从质量数据汇总;可换算成时间损失或先仅显示数量/比例(见 5.3)
|
||||
|
||||
> 关键点:**分类映射表**要可配置(原因码 -> 损失类别),便于后期持续维护与纠正。
|
||||
|
||||
---
|
||||
|
||||
## 5. 数据需求(V1 最小数据集)
|
||||
|
||||
### 5.1 维表:产线定义(必需)
|
||||
用于固定两条产线的展示与筛选。
|
||||
- `line_id`:产线 ID(建议固定,例如 `SY`、`DX1`)
|
||||
- `line_name`:产线名称(酸轧线、镀锌一线)
|
||||
|
||||
### 5.2 事实表 A:产线日汇总(推荐:可由明细聚合生成)
|
||||
用于 KPI 与趋势图(按日、按产线)。
|
||||
|
||||
字段(按日、按产线一行):
|
||||
- `stat_date`:日期(yyyy-MM-dd)
|
||||
- `line_id`
|
||||
- `planned_time_min`:计划时间(min,可选)
|
||||
- `planned_downtime_min`:计划停机(min,可选;若无则置 0)
|
||||
- `loading_time_min`:负荷时间(min)= planned_time_min - planned_downtime_min
|
||||
- `downtime_min`:停机时间(min,来自停机事件汇总)
|
||||
- `run_time_min`:实际运转时间(min)= loading_time_min - downtime_min
|
||||
- `total_output`:总产量(单位:吨/卷/件,需统一)
|
||||
- `good_output`:良品量
|
||||
- `defect_output`:不良量(= total_output - good_output,或单独提供)
|
||||
- `ideal_cycle_time_min_per_unit`:理论节拍(min/单位;若按产品不同,可取当日主产品或加权平均)
|
||||
|
||||
派生指标(后端返回也可以,前端不必重复算):
|
||||
- `availability`:时间稼动率(0~1 或 0~100)
|
||||
- `performance`:性能稼动率
|
||||
- `quality`:良品率
|
||||
- `oee`:OEE
|
||||
|
||||
### 5.3 事实表 B:停机/损失事件明细(必需)
|
||||
用于“停机明细”和 7 大损失(1~5 类)。
|
||||
|
||||
字段(每次事件一行):
|
||||
- `line_id`
|
||||
- `event_start_time`:开始时间
|
||||
- `event_end_time`:结束时间
|
||||
- `duration_min`:时长(min,可由 start/end 计算)
|
||||
- `raw_reason_code`:原始原因码(PLC/MES/人工)
|
||||
- `raw_reason_name`:原因描述
|
||||
- `loss_category_code`:损失分类(7 大损失之一;可由映射表生成)
|
||||
- `loss_category_name`
|
||||
- `remark`:备注(可选)
|
||||
|
||||
### 5.4 映射表:原因 -> 7 大损失类别(强烈建议)
|
||||
- `reason_code`
|
||||
- `reason_name`
|
||||
- `loss_category_code`(1~7 或枚举)
|
||||
- `enabled`
|
||||
- `updated_by/updated_time`
|
||||
|
||||
### 5.5 事实表 C:质量汇总(必需,至少按日/产线)
|
||||
用于良品率与第 7 类损失。
|
||||
|
||||
字段(按日、按产线一行,或更细):
|
||||
- `stat_date`
|
||||
- `line_id`
|
||||
- `total_output`
|
||||
- `good_output`
|
||||
- `defect_output`
|
||||
- `defect_reason_code`/`defect_reason_name`(如有则可做 Pareto)
|
||||
|
||||
> 若当前系统只有“总产量 + 不良量”,也可先做,Pareto 暂缺。
|
||||
|
||||
---
|
||||
|
||||
## 6. 计算规则与边界(避免口径争议)
|
||||
|
||||
### 6.1 单位与精度
|
||||
- 时间统一用 **分钟(min)**,产量统一用某一个单位(吨/卷/件三选一,不建议混用)
|
||||
- 比例类指标输出:
|
||||
- 存储:`0~1`(推荐)或 `0~100`(二选一,接口需固定)
|
||||
- 展示:百分比 `%`,保留 1~2 位小数
|
||||
|
||||
### 6.2 负荷时间缺失的处理
|
||||
若 V1 暂无计划时间/计划停机:
|
||||
- 方案 A(推荐):先把 **负荷时间**直接作为外部输入(由业务提供/班组报工)
|
||||
- 方案 B:以“日历时间(24h)”近似(不推荐,会误导)
|
||||
|
||||
### 6.3 性能稼动率上限与异常
|
||||
理论上性能稼动率可能 > 100%(标准节拍偏大、或实际速度超标)。
|
||||
建议规则:
|
||||
- **展示值**:允许 >100%,但同时给出提示“标准节拍/标准速度需校准”
|
||||
- **可选**:提供开关将 performance clamp 到 100%(不建议默认 clamp,会掩盖问题)
|
||||
|
||||
### 6.4 速度下降(第 6 类)如何得到“分钟数”
|
||||
当你们没有“速度下降事件”时,建议以性能损失折算分钟数:
|
||||
- `ideal_time_min = ideal_cycle_time_min_per_unit * total_output`
|
||||
- `performance_loss_min = max(0, run_time_min - ideal_time_min)`
|
||||
将 `performance_loss_min` 作为第 6 类“速度下降”损失时间。
|
||||
|
||||
> 注意:如果 `ideal_time_min > run_time_min`,说明当日速度优于标准(或标准过宽),此时性能损失为 0。
|
||||
|
||||
### 6.5 不良/修正(第 7 类)如何换算“分钟数”(可选)
|
||||
V1 可先只展示“不良量/不良率”;若要换算成时间损失:
|
||||
- `quality_loss_min = defect_output * ideal_cycle_time_min_per_unit`
|
||||
并作为第 7 类损失时间。
|
||||
|
||||
---
|
||||
|
||||
## 7. 接口设计(建议)
|
||||
|
||||
> 下面为接口设计说明。注意:本文不再描述“当前后端实现细节”,仅给出建议的接口形态与字段含义,具体实现以代码为准。
|
||||
|
||||
### 7.0 多服务(多 IP/端口)接入原则
|
||||
|
||||
当前两条产线来自**两个不同服务**(不同 IP/端口),需在接口设计中显式考虑:
|
||||
|
||||
- **方式 A(推荐):后端统一网关/中台**
|
||||
- 在现有 Java 服务或 API 网关中,新增一个 **OEE 聚合接口** 模块:
|
||||
- 内部分别调用「酸轧线服务」与「镀锌一线服务」的地址
|
||||
- 对外仍暴露统一的 `/api/ems/oee/...` 风格接口
|
||||
- 优点:前端无感知多服务、网络安全/鉴权可统一;后期扩展新产线也只需后端配置。
|
||||
- **方式 B:前端直连多服务(不推荐,仅在现有架构强约束时考虑)**
|
||||
- 需在 `vue.config.js` 中配置多个 `proxy`,例如 `/ems-sy` -> 酸轧线、`/ems-dx1` -> 镀锌一线
|
||||
- 前端在请求时根据 `lineId` 选择不同前缀(易产生逻辑分叉、难复用)
|
||||
|
||||
> 设计目标:**对前端暴露统一接口**,由后端负责区分产线来源服务并做数据聚合与清洗。
|
||||
|
||||
以下接口路径均以“后端统一聚合后”的 API 为准。
|
||||
|
||||
- 路由前缀:以 `klp-da` 实际 Controller 为准(本文不再假设已实现的固定前缀)。
|
||||
|
||||
### 7.1 KPI + 趋势汇总
|
||||
`GET /oee/line/summary`
|
||||
|
||||
参数:
|
||||
- `startDate`:yyyy-MM-dd
|
||||
- `endDate`:yyyy-MM-dd
|
||||
- `lineIds`:逗号分隔(例如 `SY,DX1`)
|
||||
|
||||
返回(示例结构):
|
||||
- `lines[]`
|
||||
- `lineId`
|
||||
- `lineName`
|
||||
- `total`:区间汇总
|
||||
- `loadingTimeMin`
|
||||
- `downtimeMin`
|
||||
- `runTimeMin`
|
||||
- `totalOutput`
|
||||
- `goodOutput`
|
||||
- `defectOutput`
|
||||
- `availability`
|
||||
- `performance`
|
||||
- `quality`
|
||||
- `oee`
|
||||
- `daily[]`:按日明细(用于趋势图)
|
||||
|
||||
- 指标口径:以业务定义为准(负荷时间/停机/运转/产出/良品率/理论节拍的具体取数来源与规则需在新实现中明确)。
|
||||
|
||||
### 7.2 7 大损失汇总
|
||||
`GET /oee/line/loss7`
|
||||
|
||||
参数同上,额外:
|
||||
- `topN`:默认 10
|
||||
|
||||
返回:
|
||||
- `byLine[]`
|
||||
- `lineId`
|
||||
- `lineName`
|
||||
- `losses[]`
|
||||
- `lossCategoryCode`
|
||||
- `lossCategoryName`
|
||||
- `lossTimeMin`
|
||||
- `lossTimeRate`(占比,分母为“停机损失 + 速度下降损失”)
|
||||
- `count`(次数,部分分类可能为空)
|
||||
- `avgDurationMin`(平均时长,部分分类可能为空)
|
||||
- `topReasons[]`:TopN 原因(按原因文本聚合)
|
||||
|
||||
- 速度下降(第 6 类)建议口径:可用“性能损失分钟数”折算(详见 6.4),具体落地以新实现为准。
|
||||
|
||||
### 7.3 停机/损失事件明细
|
||||
`GET /oee/line/events`
|
||||
|
||||
参数:
|
||||
- `startTime`、`endTime`(支持到分钟)
|
||||
- `lineId`(可选)
|
||||
- `lossCategoryCode`(可选)
|
||||
- `keyword`(可选)
|
||||
- `pageNum`、`pageSize`
|
||||
|
||||
返回:
|
||||
- `rows[]`:事件列表
|
||||
- `total`
|
||||
|
||||
> ✅ **当前实现说明**
|
||||
> - 事件来源:分别调用两条产线各自的停机事件接口进行聚合;并支持 `keyword/lossCategoryCode` 过滤与分页。
|
||||
|
||||
### 7.4 理论节拍回归(散点 + 拟合线,用于前端绘图)
|
||||
`GET /oee/line/theoryCycle/regression`
|
||||
|
||||
用途:
|
||||
- 前端绘制“散点 + 回归折线”的**理论节拍回归图**
|
||||
- 同时为 `summary` / `loss7` 提供 **理论节拍(分钟/吨)** 数据源(Performance 计算)
|
||||
|
||||
参数:
|
||||
- 复用 `OeeQueryBo` 的 `startTime/endTime`(可选,格式 `yyyy-MM-dd HH:mm:ss`)
|
||||
- 不传时默认近 6 个月(由 WMS 侧默认)
|
||||
|
||||
返回(结构透传 WMS 回归结果):
|
||||
- `lines[]`
|
||||
- `lineId`:`SY` / `DX1`
|
||||
- `lineName`
|
||||
- `slopeMinPerTon`:**分钟/吨(核心值,可作为理论节拍)**
|
||||
- `interceptMin`:截距(分钟)
|
||||
- `r2`:拟合优度
|
||||
- `sampleCount`:参与回归样本数
|
||||
- `startTime` / `endTime`
|
||||
- `points[]`:散点
|
||||
- `weightTon`(X)
|
||||
- `durationMin`(Y)
|
||||
- `actionId`
|
||||
- `createTime`
|
||||
- `linePoints[]`:拟合线两个端点(前端可直接画线)
|
||||
|
||||
> ✅ **当前实现的数据来源(WMS)**
|
||||
> - `SY`:`wms_coil_pending_action.action_type=11`,单卷,吨数来自该记录 `coil_id` 对应钢卷的 `netWeight/grossWeight`。
|
||||
> - `DX1`:`action_type=501`,`remark` 为钢卷 id 列表字符串(提取数字),按列表汇总吨数。
|
||||
> - 样本过滤:`action_status=2`、`create_time` 在近 6 个月、`completeTime-createTime` > 0、吨数 > 0。
|
||||
|
||||
---
|
||||
|
||||
## 8. 前端页面实现建议(klp-ui)
|
||||
|
||||
### 8.1 组件拆分建议
|
||||
- `views/ems/oee/index.vue`(主页面)
|
||||
- `OeeQueryBar`:查询区
|
||||
- `OeeKpiCards`:KPI 区
|
||||
- `OeeTrendCharts`:趋势区
|
||||
- `OeeLoss7Panel`:7 大损失区
|
||||
- `OeeEventTable`:明细区
|
||||
- `OeeFormulaCard`:公式与口径说明(可折叠)
|
||||
|
||||
### 8.2 公式展示(建议文案)
|
||||
页面“口径说明”中直接展示下列内容(与第 3 节一致):
|
||||
- \( OEE = A \times P \times Q \)
|
||||
- \( A = (负荷时间-停机时间)/负荷时间 \)
|
||||
- \( P = (理论节拍 \times 产量)/实际运转时间 \)
|
||||
- \( Q = 良品数/总产量 \)
|
||||
|
||||
并附“字段解释”与“边界规则”(第 6 节)。
|
||||
|
||||
---
|
||||
|
||||
## 9. 打印与 Word 导出设计
|
||||
|
||||
当前会议使用**打印好的纸张**,因此 OEE 报表页面必须:
|
||||
- 在浏览器中**一屏内可阅读**,同时
|
||||
- 能以固定版式打印到 A4 纸上(或多页),并且
|
||||
- 能方便地导出到 **Word 文档** 中(便于留存与二次编辑)。
|
||||
|
||||
### 9.1 页面布局对打印友好化
|
||||
|
||||
- 整体布局遵循「自上而下」结构:
|
||||
1. 标题 + 查询条件概览(日期范围、产线)
|
||||
2. KPI 总览(两产线对比表格)
|
||||
3. OEE & 三大指标趋势图
|
||||
4. 7 大损失汇总表 + 图
|
||||
5. 停机/损失明细表(可只打印 Top N,避免过多页)
|
||||
6. 公式与口径说明
|
||||
- 为打印准备专用 CSS:
|
||||
- 使用 `@media print` 隐藏页面导航、按钮等交互元素
|
||||
- 控制分页:在关键模块间加 `page-break-before/after: always;`,保证章节不要被随机拆页
|
||||
- 统一字体(建议 `SimSun` 或 `Microsoft YaHei`)与字号(正文 10–12pt)
|
||||
|
||||
### 9.2 打印实现(浏览器直接打印)
|
||||
|
||||
- 页面中提供 **“打印 OEE 报表”** 按钮:
|
||||
- 触发 `window.print()`,由浏览器生成打印预览
|
||||
- 打印模板由 `@media print` 样式控制
|
||||
- 打印前展示一个小弹窗/提示:
|
||||
- 确认当前查询条件(日期范围、产线)
|
||||
- 提示:如“明细表仅打印前 50 条记录”
|
||||
|
||||
### 9.3 Word 导出方案(前后端二选一)
|
||||
|
||||
#### 方案 A(推荐):后端生成 Word 模板
|
||||
- 在 Java 后端使用如 **Apache POI** 或 **docx4j**:
|
||||
- 准备一个固定 Word 模板(包括标题、表格样式、公司抬头等)
|
||||
- 将 OEE 汇总、趋势(可只写数据表)、7 大损失、公式说明填入模板
|
||||
- 返回 `application/vnd.openxmlformats-officedocument.wordprocessingml.document` 文件流
|
||||
- 前端仅需增加一个 **“导出 Word”** 按钮:
|
||||
- 请求 `/oee/line/exportWord?startDate=...&endDate=...&lineIds=...`
|
||||
- 将响应保存为 `.docx` 文件。
|
||||
|
||||
#### 方案 B:前端转为 Word(适合作为备选)
|
||||
- 使用 JS 库(如 `html-docx-js` / `PizZip + Docxtemplater` 等):
|
||||
- 将页面区域(或结构化数据)转换为 docx
|
||||
- 但对版式与中文支持不如后端模板稳妥
|
||||
|
||||
> 综上,建议优先采用:**后端模板 + 导出 Word 接口**,前端仅承载触发与参数传递。
|
||||
|
||||
---
|
||||
|
||||
## 10. 验收标准(V1)
|
||||
- 支持选择日期范围,展示两条产线(酸轧线、镀锌一线)的:
|
||||
- KPI:OEE、A、P、Q + 辅助数值
|
||||
- 按日趋势:OEE + A/P/Q
|
||||
- 7 大损失:分类时间损失 + 占比
|
||||
- 明细:停机事件列表可筛选/分页
|
||||
- 页面包含“口径说明/公式展示”,且与接口口径一致
|
||||
- 任一指标可追溯:KPI 卡片能够对上分子/分母(至少时间稼动率与良品率)
|
||||
- 页面支持 **直接打印为纸质报表**(版式稳定),并提供 **Word 导出** 功能
|
||||
|
||||
---
|
||||
|
||||
## 11. 需要你补充/确认的最少信息(不影响先做页面骨架)
|
||||
1. **产量计量单位**:酸轧/镀锌使用“吨/卷/件”的哪一个?能否统一?
|
||||
2. **标准节拍来源**:是否已有“产线/产品”标准节拍表?若暂时没有,V1 可先按产线固定一个标准值。
|
||||
3. **停机事件来源**:当前是否已有停机记录表(start/end/reason)?原因码是否稳定?
|
||||
|
||||
---
|
||||
|
||||
## 12. 后端实现与配置(用于前端对接与联调)
|
||||
|
||||
### 12.1 路由前缀说明
|
||||
- **DA 聚合服务**(OEE 对外统一接口):`/oee/line/*`
|
||||
- **WMS 回归服务**(内部数据源,DA 会代理调用):`/wms/coilPendingAction/theoryCycle/regression`
|
||||
|
||||
### 12.2 DA(klp-da)需要的配置项
|
||||
- `da.oee.acid-line-base-url`:酸轧线数据源服务地址(klp-pocket)
|
||||
- `da.oee.galvanize-line-base-url`:镀锌一线数据源服务地址(Fizz)
|
||||
- `da.oee.wms-base-url`:WMS 服务地址(用于代理调用理论节拍回归接口;不配默认 `http://localhost:8080`)
|
||||
- `da.oee.ideal-cycle-time-min-per-unit.sy`:理论节拍兜底值(分钟/吨)
|
||||
- `da.oee.ideal-cycle-time-min-per-unit.dx1`:理论节拍兜底值(分钟/吨)
|
||||
|
||||
### 12.3 WMS 回归与缓存说明
|
||||
- WMS 会将回归的斜率(分钟/吨)写入 Redis:
|
||||
- Key:`oee:ideal-cycle-time`,field:`SY` / `DX1`,value:`slopeMinPerTon`
|
||||
- Key:`oee:ideal-cycle-time:intercept`,field:`SY` / `DX1`,value:`interceptMin`
|
||||
- DA 在计算 `summary/loss7` 时会优先使用回归斜率(并在 DA 内做 60s 本地 TTL 缓存),回归不可用时才回退到 `da.oee.ideal-cycle-time-min-per-unit.*`。
|
||||
225
ems-cost-allocation-notes.md
Normal file
225
ems-cost-allocation-notes.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# 能源分摊(现有实现)与加入“备件/辅料分摊”的接入方案
|
||||
|
||||
## 0. 时间线(用于交接,持续更新)
|
||||
|
||||
- **2026-01-20**
|
||||
- **已改动(代码)**:
|
||||
- `klp-ems/src/main/java/com/klp/ems/domain/vo/CoilTotalCostVo.java`:新增 `auxCost/spareCost` 字段,`totalCost` 注释更新。
|
||||
- `klp-ems/src/main/java/com/klp/ems/domain/vo/CoilTotalMergedExportVo.java`:新增导出列 `auxCost/spareCost`。
|
||||
- `klp-ems/src/main/resources/mapper/WmsEnergyCoilDailyMapper.xml`:`selectCoilTotalMerged` 与 `selectCoilTotalMergedExport` 已加入 `auxCost/spareCost` 计算与 join,并更新 `totalCost` 公式。
|
||||
- `klp-ems/src/main/java/com/klp/ems/controller/EnergyCostReportController.java`:导出接口已补充 `auxCost/spareCost` 赋值。
|
||||
- `klp-ui/src/views/ems/cost/cost.vue`:列表新增列展示 `auxCost/spareCost`;顶部卡片展示 `materialSummary`(当前按列表行求和);总成本计算加入备件/辅料。
|
||||
|
||||
- **2026-01-26**
|
||||
- **新增(前端页面)**:按数据库路由方式新增两个独立页面(不在前端代码写路由)。
|
||||
- `klp-ui/src/views/ems/cost/auxAllocation.vue`:辅料成本分摊页面(按入场卷号汇总),包含“分摊明细”弹窗与导出;并新增“辅料消耗构成(分摊口径)”区域(展示用了哪些辅料、几种、数量与金额)。
|
||||
- `klp-ui/src/views/ems/cost/spareAllocation.vue`:备件成本分摊页面(按入场卷号汇总),包含“分摊明细”弹窗与导出;并新增“备件消耗构成(分摊口径)”区域(展示用了哪些备件、几种、数量与金额)。
|
||||
- **路由 component 配置建议(写入数据库)**:
|
||||
- 辅料:`ems/cost/auxAllocation`
|
||||
- 备件:`ems/cost/spareAllocation`
|
||||
- **接口复用说明**:
|
||||
- 汇总:两个页面均复用 `GET /ems/energy/report/coilTotal/merged` 与 `GET /ems/energy/report/coilTotal/merged/export`,分别取字段 `auxCost` / `spareCost`。
|
||||
- 构成:新增两个接口返回“按物料/备件聚合后的分摊构成”(数量与金额均按日分摊系数切分):
|
||||
- `GET /ems/energy/report/material/aux/breakdown`
|
||||
- `GET /ems/energy/report/material/spare/breakdown`
|
||||
- **口径(构成)**:
|
||||
- 全厂按日聚合消耗(`eqp_*_change`,`change_type='减少'`,金额取 `ABS(amount)`,数量取 `ABS(change_quantity)`)
|
||||
- 当日卷分摊系数:`coil_minutes_day / total_minutes_day`(分钟基于 `wms_coil_pending_action.create_time ~ complete_time/now`)
|
||||
- 最终按物料/备件汇总:`allocatedQty = Σ_D (day_item_qty * factor_day)`,`allocatedAmount = Σ_D (day_item_amount * factor_day)`
|
||||
- **重要说明**:
|
||||
- merged 仍不返回按日池/分钟明细;页面“分摊明细”弹窗仍为汇总占位。
|
||||
- 构成接口可在不强制 enterCoilNo 的情况下使用:不传 enterCoilNo 时可用于查看全厂消耗构成(allocated≈total)。
|
||||
|
||||
- **2026-01-20**
|
||||
- **口径确认**:备件/辅料分摊池按**全厂**聚合(不按库区/设备/产线拆分)。
|
||||
- **过滤规则确认**:
|
||||
- `wms_coil_pending_action`:按 `pa.create_time` 落在 `[startDate, endDate]` 过滤。
|
||||
- `eqp_*_change`:按 `change_time` 落在同一 `[startDate, endDate]` 过滤。
|
||||
- 仅统计 `change_type = '减少'`(消耗)。
|
||||
- **金额按天切分规则确认**:采用 **A 方案**(按 `DATE(pa.create_time)` 归属到某一天;不做跨天拆分时长)。消耗金额按天形成日池(例如 3 天形成 3 个日池、5 天形成 5 个日池),再在当日内按钢卷时长占比分摊。
|
||||
- **跨库可达性确认**:EMS/WMS 可以直接查询到 MES 的 `eqp_auxiliary_material_change`、`eqp_spare_parts_change` 两张变动表(可在 EMS 侧 SQL 直接使用)。
|
||||
- **已完成**:梳理前端 `klp-ui/src/views/ems/cost/cost.vue` 的查询/展示/接口调用。
|
||||
- **已完成**:定位后端 `EnergyCostReportController` 与 `WmsEnergyCoilDailyMapper.xml`。
|
||||
- **已修正**:早期将能源分摊概括为“库区时间窗”会误导备件/辅料接入;备件/辅料分摊以 `wms_coil_pending_action` 的待操作时间窗为中心(见本时间线确认项)。
|
||||
- **已确认(MES 成本记账规则)**:
|
||||
- 台账表(`eqp_spare_part`、`eqp_auxiliary_material`)补充 `unit_price/total_amount`。
|
||||
- 入库单价来源:**前端必传**(老接口与前端一并改造)。
|
||||
- 入库/增加时采用移动加权平均价:`new_unit_price = (old_unit_price*old_qty + in_unit_price*in_qty) / (old_qty+in_qty)`。
|
||||
- 消耗/减少时在变动表写入 `unit_price_snapshot` 并计算 `amount`(**有符号**;减少为负:`-unit_price_snapshot * change_quantity`)。
|
||||
- 分摊侧聚合消耗金额使用 `ABS(amount)`。
|
||||
|
||||
> 范围:
|
||||
> - 前端页面:`klp-ui/src/views/ems/cost/cost.vue`
|
||||
> - 后端接口:`klp-ems/src/main/java/com/klp/ems/controller/EnergyCostReportController.java`
|
||||
> - 主要 SQL:`klp-ems/src/main/resources/mapper/WmsEnergyCoilDailyMapper.xml`
|
||||
> - MES 表结构:`script/sql/mysql/eqp_auxiliary_material.sql`
|
||||
|
||||
## 1. 现有页面做了什么(前端)
|
||||
|
||||
页面名称:`CoilTotalCost`(钢卷成本汇总)
|
||||
|
||||
### 1.1 查询条件
|
||||
|
||||
`queryParams`:
|
||||
|
||||
- `enterCoilNo`:入场卷号(页面标记 required,支持模糊)
|
||||
- `currentCoilNo`:当前卷号(支持模糊)
|
||||
- `startDate`:开始日期(yyyy-MM-dd)
|
||||
- `endDate`:结束日期(yyyy-MM-dd)
|
||||
|
||||
点击“查询”会同时触发三块数据加载:
|
||||
|
||||
- **能源成本汇总 + 明细**(EMS)
|
||||
- **囤积成本明细/汇总**(WMS)
|
||||
- **能源+囤积 合并汇总**(EMS 聚合接口)
|
||||
|
||||
### 1.2 页面展示结构
|
||||
|
||||
- **顶部 4 个卡片**
|
||||
- **能源成本**:来自 `energySummary.totalEnergyCost`,并展示耗能、时长
|
||||
- **本日囤积成本**:来自 `stockSummary.todayCost`,并展示净重/毛重
|
||||
- **辅料成本**:当前写死 `0.00`(`暂不计`)
|
||||
- **总成本**:`能源 + 囤积 + 辅料(当前为 0)`
|
||||
|
||||
- **表格:成本汇总(按入场卷号)**
|
||||
- 数据源:`mergedRows`
|
||||
- 列:入场卷号、当前卷号、能源成本、囤积成本(当日)、总成本、净重、毛重
|
||||
- 操作:查看详情
|
||||
|
||||
- **详情弹窗**
|
||||
- 能源分摊明细(按待操作时间跨度分摊)
|
||||
- 囤积成本(单行汇总)
|
||||
|
||||
### 1.3 前端调用的接口
|
||||
|
||||
能源相关(同一模块 `@/api/ems/energyCostReport`):
|
||||
|
||||
- `fetchCoilTotalEnergySummary(params)`
|
||||
- 对应后端:`GET /ems/energy/report/coilTotal/summary`
|
||||
|
||||
- `fetchCoilTotalEnergyDetail(params)`
|
||||
- 对应后端:`GET /ems/energy/report/coilTotal/detail`
|
||||
|
||||
- `fetchCoilTotalMerged(params)`
|
||||
- 对应后端:`GET /ems/energy/report/coilTotal/merged`
|
||||
|
||||
- `exportCoilTotalMerged(params)`
|
||||
- 对应后端:`GET /ems/energy/report/coilTotal/merged/export`
|
||||
|
||||
囤积成本(WMS 模块 `@/api/wms/cost`):
|
||||
|
||||
- `getStockpileCostList(params)`
|
||||
|
||||
## 2. 现有“能源分摊”后端是怎么做的(与备件/辅料接入相关的部分)
|
||||
|
||||
核心 Controller:`EnergyCostReportController`
|
||||
|
||||
- `GET /ems/energy/report/coilTotal/summary`
|
||||
- `GET /ems/energy/report/coilTotal/detail`
|
||||
- `GET /ems/energy/report/coilTotal/merged`
|
||||
- `GET /ems/energy/report/coilTotal/merged/export`
|
||||
|
||||
入参对象:`CoilTotalCostBo`:`enterCoilNo/currentCoilNo/startDate/endDate`
|
||||
|
||||
当前实现中,`coilTotal/*` 相关 SQL 主要围绕 `wms_coil_pending_action` 的时间跨度计算(分钟/小时),并将能耗/成本按占比分配到卷。
|
||||
|
||||
## 3. 备件/辅料分摊:最新确认的正确口径(可直接实现)
|
||||
|
||||
### 3.1 总体思路
|
||||
|
||||
- 备件/辅料成本池:按**全厂**聚合。
|
||||
- 成本池按**日**切分:以 `DATE(change_time)` 形成每日消耗金额池。
|
||||
- 分摊权重按**日**切分:以 `DATE(pa.create_time)` 形成每日钢卷“待操作时长”池。
|
||||
- 当天内按“入场卷号的总时长 / 全厂总时长”占比,将当日消耗金额分摊到各入场卷号。
|
||||
|
||||
### 3.2 关键定义(A 方案:不拆跨天时长)
|
||||
|
||||
#### (1) 当日消耗金额池(仅减少)
|
||||
|
||||
- `aux_pool_day(D) = SUM(eqp_auxiliary_material_change.amount)`
|
||||
- `spare_pool_day(D) = SUM(eqp_spare_parts_change.amount)`
|
||||
|
||||
过滤:
|
||||
|
||||
- `change_type = '减少'`
|
||||
- `DATE(change_time) = D`
|
||||
- 且 `change_time` 在 `[startDate, endDate]` 范围内(与查询一致)
|
||||
|
||||
#### (2) 当日全厂总时长池
|
||||
|
||||
- `minutes(pa) = TIMESTAMPDIFF(MINUTE, pa.create_time, COALESCE(pa.complete_time, NOW()))`
|
||||
- `total_minutes_day(D) = SUM(minutes(pa))`
|
||||
|
||||
过滤:
|
||||
|
||||
- `pa.create_time` 在 `[startDate, endDate]`
|
||||
- `DATE(pa.create_time) = D`
|
||||
|
||||
#### (3) 当日按入场卷号的时长
|
||||
|
||||
- `coil_minutes_day(D, enter_coil_no) = SUM(minutes(pa))`
|
||||
|
||||
其中 `enter_coil_no` 通过:
|
||||
|
||||
- `wms_coil_pending_action.pa.coil_id -> wms_material_coil.coil_id -> wms_material_coil.enter_coil_no`
|
||||
|
||||
#### (4) 当日分摊与汇总
|
||||
|
||||
- `aux_cost_day = aux_pool_day(D) * coil_minutes_day / total_minutes_day`
|
||||
- `spare_cost_day = spare_pool_day(D) * coil_minutes_day / total_minutes_day`
|
||||
|
||||
最终:
|
||||
|
||||
- `auxCost = Σ_D aux_cost_day`
|
||||
- `spareCost = Σ_D spare_cost_day`
|
||||
|
||||
### 3.3 SQL 接入点(在 EMS merged 中 join)
|
||||
|
||||
建议在 `WmsEnergyCoilDailyMapper.xml`:
|
||||
|
||||
- `selectCoilTotalMerged`
|
||||
- `selectCoilTotalMergedExport`
|
||||
|
||||
新增 join 结构:
|
||||
|
||||
1. 先构造“按入场卷号的每日分钟数”子查询:`coil_day_minutes`
|
||||
2. 再构造“全厂每日总分钟数”子查询:`total_day_minutes`
|
||||
3. 再构造“全厂每日消耗金额池(备件/辅料)”子查询:`aux_day_amount` / `spare_day_amount`
|
||||
4. 通过 `day` 将以上子查询 join 起来,得到 `Σ( day_amount * coil_day_minutes / total_day_minutes )`
|
||||
5. 最终在 `merged` 的 select 列表中补充:
|
||||
- `IFNULL(x.aux_cost, 0) AS auxCost`
|
||||
- `IFNULL(x.spare_cost, 0) AS spareCost`
|
||||
- `totalCost = energy_cost + stock_cost + aux_cost + spare_cost`
|
||||
|
||||
> 注意:实现时需要防止分母为 0:`CASE WHEN total_day_minutes > 0 THEN ... ELSE 0 END`。
|
||||
|
||||
## 4. 需要改动的后端/前端文件清单(待实现)
|
||||
|
||||
### 4.1 EMS 后端(klp-ems)
|
||||
|
||||
- `klp-ems/src/main/java/com/klp/ems/domain/vo/CoilTotalCostVo.java`
|
||||
- 增加字段:`auxCost`、`spareCost`(以及 `totalCost` 公式更新)
|
||||
|
||||
- `klp-ems/src/main/resources/mapper/WmsEnergyCoilDailyMapper.xml`
|
||||
- 修改:`selectCoilTotalMerged`、`selectCoilTotalMergedExport`
|
||||
|
||||
- `klp-ems/src/main/java/com/klp/ems/controller/EnergyCostReportController.java`
|
||||
- 导出映射:`coilTotalMergedExport` 增加导出字段赋值
|
||||
|
||||
- `klp-ems/src/main/java/com/klp/ems/domain/vo/CoilTotalMergedExportVo.java`
|
||||
- 增加列:备件成本、辅料成本(以及总成本)
|
||||
|
||||
### 4.2 前端(klp-ui)
|
||||
|
||||
- `klp-ui/src/views/ems/cost/cost.vue`
|
||||
- 顶部卡片:“辅料成本”从 0 改为接口返回(或新增 summary 聚合)
|
||||
- 表格增加两列:`auxCost`、`spareCost`
|
||||
- 总成本公式更新:能源 + 囤积 + 备件 + 辅料
|
||||
|
||||
---
|
||||
|
||||
## 5. 当前状态(给新 agent 的交接结论)
|
||||
|
||||
- 分摊口径已最终确认并记录:**全厂池 + 按天切分 + A 方案(按 `DATE(pa.create_time)` 归属)**。
|
||||
- EMS/WMS 可直接查询 MES 的 change 表,允许在 `WmsEnergyCoilDailyMapper.xml` 内直接 join 实现。
|
||||
- 尚未开始实际代码改造;下一步按第 4 节清单逐项实现,并在每次提交后回写本文件时间线(记录修改了哪些文件/字段/SQL)。
|
||||
0
galvanize1.sql
Normal file
0
galvanize1.sql
Normal file
@@ -69,14 +69,23 @@ spring:
|
||||
url: jdbc:mysql://140.143.206.120:13306/klp-oa?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: klp
|
||||
password: KeLunPu@123
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从库数据源(酸轧库)
|
||||
acid:
|
||||
lazy: true
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://140.143.206.120:13306/klp_pocketfactory?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: klp
|
||||
password: KeLunPu@123
|
||||
|
||||
# 从库数据源(镀锌一库)
|
||||
galvanize1:
|
||||
lazy: true
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://140.143.206.120:3306/cgldb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: klp
|
||||
password: KeLunPu123@
|
||||
# oracle:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: oracle.jdbc.OracleDriver
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
<groupId>com.klp</groupId>
|
||||
<artifactId>klp-framework</artifactId>
|
||||
</dependency>
|
||||
<!-- OEE 聚合依赖 pocket 原子能力(酸轧/镀锌一线) -->
|
||||
<dependency>
|
||||
<groupId>com.klp</groupId>
|
||||
<artifactId>klp-pocket</artifactId>
|
||||
<version>0.8.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
||||
@@ -1,37 +1,43 @@
|
||||
package com.klp.da.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.da.domain.bo.OeeQueryBo;
|
||||
import com.klp.da.domain.vo.OeeLineSummaryVo;
|
||||
import com.klp.da.domain.vo.OeeEventVo;
|
||||
import com.klp.da.service.IOeeReportService;
|
||||
import com.klp.da.service.OeeSummaryJobService;
|
||||
import com.klp.da.service.OeeTheoryCycleJobService;
|
||||
import com.klp.common.utils.StringUtils;
|
||||
import com.klp.da.service.OeeReportJobService;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeRegressionVo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.acid.service.IAcidOeeService;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* OEE 报表聚合 Controller(方式 A:后端统一聚合多服务)
|
||||
* OEE 报表对外接口(聚合层)
|
||||
*
|
||||
* 当前仅提供接口“架子”,具体聚合逻辑在 {@link IOeeReportService} 中实现。
|
||||
*
|
||||
* 路由前缀与 docs/oee-report-design.md 设计文档保持一致:
|
||||
* - /api/ems/oee/line/summary
|
||||
* - /api/ems/oee/line/loss7
|
||||
* - /api/ems/oee/line/events
|
||||
* - /api/ems/oee/line/exportWord
|
||||
* 当前阶段:主要暴露酸轧线相关接口,通过 `klp-pocket` 的 {@link IAcidOeeService} 取数。
|
||||
* - 当月 summary / loss7 优先走 Redis 预计算缓存;
|
||||
* - 任意日期范围通过异步任务接口实现。
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@@ -39,92 +45,304 @@ import java.util.Map;
|
||||
@RequestMapping("/oee/line")
|
||||
public class OeeReportController extends BaseController {
|
||||
|
||||
private final IOeeReportService oeeReportService;
|
||||
private final OeeTheoryCycleJobService oeeTheoryCycleJobService;
|
||||
private final OeeSummaryJobService oeeSummaryJobService;
|
||||
private final IAcidOeeService acidOeeService;
|
||||
private final StringRedisTemplate stringRedisTemplate;
|
||||
private final OeeReportJobService oeeReportJobService;
|
||||
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||
|
||||
private static final String JOB_META_KEY_PATTERN = "oee:report:job:meta:%s";
|
||||
private static final String JOB_RESULT_KEY_PATTERN = "oee:report:job:result:%s";
|
||||
|
||||
/**
|
||||
* KPI + 趋势汇总
|
||||
*/
|
||||
@Log(title = "OEE 报表-汇总", businessType = BusinessType.OTHER)
|
||||
@GetMapping("/summary")
|
||||
public R<List<OeeLineSummaryVo>> summary(OeeQueryBo queryBo) {
|
||||
return R.ok(oeeReportService.summary(queryBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* KPI + 趋势汇总(异步任务):立即返回 jobId,通过 WebSocket 推送进度与结果。
|
||||
* 酸轧线 OEE 日汇总(含趋势)
|
||||
*
|
||||
* 前端订阅:
|
||||
* ws://{host}/websocket?type={wsType}
|
||||
* 路由:GET /oee/line/acid/summary
|
||||
* 说明:
|
||||
* - 不接受 start/end 参数,固定返回“当前月份(1号~今天)”的当月预计算结果;
|
||||
* - 优先从 Redis 当月缓存读取;若缓存缺失则实时计算一次当前月。
|
||||
*/
|
||||
@Log(title = "OEE 报表-汇总(异步)", businessType = BusinessType.OTHER)
|
||||
@GetMapping("/summary/job")
|
||||
public R<Map<String, Object>> summaryJob(OeeQueryBo queryBo) {
|
||||
System.out.println("[OEE][summary][job][controller] request received, thread=" + Thread.currentThread().getName()
|
||||
+ ", startDate=" + (queryBo == null ? null : queryBo.getStartDate())
|
||||
+ ", endDate=" + (queryBo == null ? null : queryBo.getEndDate())
|
||||
+ ", lineIds=" + (queryBo == null ? null : queryBo.getLineIds()));
|
||||
Map<String, Object> resp = oeeSummaryJobService.createAndStart(queryBo);
|
||||
System.out.println("[OEE][summary][job][controller] job created, resp=" + resp);
|
||||
return R.ok(resp);
|
||||
@GetMapping("/acid/summary")
|
||||
public R<List<AcidOeeDailySummaryVo>> getAcidSummary() {
|
||||
String yyyyMM = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
|
||||
String summaryKey = String.format("oee:report:month:summary:%s:SY", yyyyMM);
|
||||
|
||||
// 1. 优先从 Redis 读取当月预计算结果
|
||||
String json = stringRedisTemplate.opsForValue().get(summaryKey);
|
||||
if (StringUtils.isNotBlank(json)) {
|
||||
List<AcidOeeDailySummaryVo> cached =
|
||||
JSON.parseArray(json, AcidOeeDailySummaryVo.class);
|
||||
return R.ok(cached);
|
||||
}
|
||||
|
||||
// 2. 缓存缺失时,回退为实时计算当前月
|
||||
String[] range = resolveDateRange(null, null);
|
||||
List<AcidOeeDailySummaryVo> dailyList =
|
||||
acidOeeService.getDailySummary(range[0], range[1]);
|
||||
return R.ok(dailyList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 7 大损失汇总
|
||||
* 酸轧线 7 大损失汇总
|
||||
*
|
||||
* 路由:GET /oee/line/acid/loss7
|
||||
* 说明:
|
||||
* - 不接受 start/end 参数,固定返回“当前月份(1号~今天)”的当月预计算结果;
|
||||
* - {@code topN} 用于限制返回的损失类别条数(按损失时间降序截取)。
|
||||
*/
|
||||
@Log(title = "OEE 报表-7大损失", businessType = BusinessType.OTHER)
|
||||
@GetMapping("/loss7")
|
||||
public R<Map<String, Object>> lossSummary(OeeQueryBo queryBo) {
|
||||
Map<String, Object> result = oeeReportService.lossSummary(queryBo);
|
||||
@GetMapping("/acid/loss7")
|
||||
public R<List<AcidOeeLoss7Vo>> getAcidLoss7(
|
||||
@RequestParam(required = false, defaultValue = "50") Integer topN
|
||||
) {
|
||||
String yyyyMM = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
|
||||
String loss7Key = String.format("oee:report:month:loss7:%s:SY", yyyyMM);
|
||||
|
||||
// 1. 优先从 Redis 读取当月 7 大损失预计算结果
|
||||
String json = stringRedisTemplate.opsForValue().get(loss7Key);
|
||||
List<AcidOeeLoss7Vo> lossList;
|
||||
if (StringUtils.isNotBlank(json)) {
|
||||
lossList = JSON.parseArray(json, AcidOeeLoss7Vo.class);
|
||||
} else {
|
||||
// 2. 缓存缺失时,回退为实时计算当前月
|
||||
String[] range = resolveDateRange(null, null);
|
||||
lossList = acidOeeService.getLoss7Summary(range[0], range[1]);
|
||||
}
|
||||
|
||||
if (topN != null && topN > 0 && lossList.size() > topN) {
|
||||
lossList = new ArrayList<>(lossList.subList(0, topN));
|
||||
}
|
||||
|
||||
return R.ok(lossList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 酸轧线停机/损失事件明细(分页)
|
||||
*
|
||||
* 路由:GET /oee/line/acid/events
|
||||
* 说明:
|
||||
* - 若未传入开始/结束时间,则默认查询当月。
|
||||
* - 当前实现为在内存中进行简单过滤与分页,后续可按需下沉到 pocket 或 Mapper。
|
||||
*/
|
||||
@GetMapping("/acid/events")
|
||||
public TableDataInfo<Klptcm1ProStoppageVo> getAcidEvents(
|
||||
@RequestParam(required = false) String startTime,
|
||||
@RequestParam(required = false) String endTime,
|
||||
@RequestParam(required = false) String stopType,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(required = false, defaultValue = "10") Integer pageSize
|
||||
) {
|
||||
// 事件明细底层按「日期」查询,这里从时间字符串中截取日期部分
|
||||
String startDate = extractDateOrDefault(startTime, true);
|
||||
String endDate = extractDateOrDefault(endTime, false);
|
||||
|
||||
List<Klptcm1ProStoppageVo> events =
|
||||
acidOeeService.getStoppageEvents(startDate, endDate);
|
||||
|
||||
// 业务筛选:stopType、关键字(目前对 stopType / remark 做 contains 匹配)
|
||||
List<Klptcm1ProStoppageVo> filtered = events.stream()
|
||||
.filter(e -> {
|
||||
if (StringUtils.isNotBlank(stopType) &&
|
||||
!StringUtils.equals(stopType, e.getStopType())) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtils.isBlank(keyword)) {
|
||||
return true;
|
||||
}
|
||||
String remark = e.getRemark();
|
||||
String type = e.getStopType();
|
||||
return (StringUtils.isNotBlank(remark) && remark.contains(keyword))
|
||||
|| (StringUtils.isNotBlank(type) && type.contains(keyword));
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
long total = filtered.size();
|
||||
int page = (pageNum == null || pageNum < 1) ? 1 : pageNum;
|
||||
int size = (pageSize == null || pageSize < 1) ? 10 : pageSize;
|
||||
int fromIndex = (page - 1) * size;
|
||||
int toIndex = Math.min(fromIndex + size, filtered.size());
|
||||
|
||||
List<Klptcm1ProStoppageVo> pageList;
|
||||
if (fromIndex >= filtered.size()) {
|
||||
pageList = new ArrayList<>();
|
||||
} else {
|
||||
pageList = filtered.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
TableDataInfo<Klptcm1ProStoppageVo> rsp = TableDataInfo.build();
|
||||
rsp.setRows(pageList);
|
||||
rsp.setTotal(total);
|
||||
return rsp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 酸轧线理论节拍回归数据
|
||||
*
|
||||
* 路由:GET /oee/line/acid/regression
|
||||
* 说明:
|
||||
* - {@code startDate} / {@code endDate} 可选,若为空则由 pocket 按“近6个月”默认处理。
|
||||
*/
|
||||
@GetMapping("/acid/regression")
|
||||
public R<AcidOeeRegressionVo> getAcidRegression(
|
||||
@RequestParam(required = false) String startDate,
|
||||
@RequestParam(required = false) String endDate
|
||||
) {
|
||||
AcidOeeRegressionVo data = acidOeeService.getRegressionData(startDate, endDate);
|
||||
return R.ok(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 若未显式传入日期范围,则默认当前月 [1号, 今天]。
|
||||
*/
|
||||
private String[] resolveDateRange(String startDate, String endDate) {
|
||||
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
|
||||
return new String[]{startDate, endDate};
|
||||
}
|
||||
LocalDate today = LocalDate.now();
|
||||
LocalDate firstDay = today.withDayOfMonth(1);
|
||||
return new String[]{firstDay.format(DATE_FORMATTER), today.format(DATE_FORMATTER)};
|
||||
}
|
||||
|
||||
/**
|
||||
* 从完整时间字符串中截取 yyyy-MM-dd;若为空则回退到当月默认范围。
|
||||
*/
|
||||
private String extractDateOrDefault(String dateTime, boolean isStart) {
|
||||
if (StringUtils.isNotBlank(dateTime)) {
|
||||
// 期望格式 yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss,统一截前 10 位
|
||||
if (dateTime.length() >= 10) {
|
||||
return dateTime.substring(0, 10);
|
||||
}
|
||||
}
|
||||
LocalDate today = LocalDate.now();
|
||||
LocalDate firstDay = today.withDayOfMonth(1);
|
||||
return isStart ? firstDay.format(DATE_FORMATTER) : today.format(DATE_FORMATTER);
|
||||
}
|
||||
|
||||
// ======================== 任意日期范围异步任务(酸轧线) ========================
|
||||
|
||||
/**
|
||||
* 提交酸轧线 OEE 报表异步任务(任意日期范围)。
|
||||
*
|
||||
* 路由:POST /oee/line/acid/report-jobs
|
||||
*/
|
||||
@PostMapping("/acid/report-jobs")
|
||||
public R<OeeReportJobMeta> submitAcidReportJob(@RequestBody OeeReportJobSubmitBo body) {
|
||||
if (body == null || StringUtils.isBlank(body.getStartDate()) || StringUtils.isBlank(body.getEndDate())) {
|
||||
return R.fail("startDate/endDate 不能为空");
|
||||
}
|
||||
|
||||
String jobId = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
OeeReportJobMeta meta = new OeeReportJobMeta();
|
||||
meta.setJobId(jobId);
|
||||
meta.setStatus("PENDING");
|
||||
meta.setSubmittedAt(now.format(DATE_TIME_FORMATTER));
|
||||
meta.setStartDate(body.getStartDate());
|
||||
meta.setEndDate(body.getEndDate());
|
||||
|
||||
// 先写入 PENDING 状态
|
||||
String metaKey = String.format(JOB_META_KEY_PATTERN, jobId);
|
||||
stringRedisTemplate.opsForValue().set(metaKey, JSON.toJSONString(meta), 1, TimeUnit.DAYS);
|
||||
|
||||
boolean includeSummary = body.getIncludeSummary() == null || Boolean.TRUE.equals(body.getIncludeSummary());
|
||||
boolean includeLoss7 = body.getIncludeLoss7() == null || Boolean.TRUE.equals(body.getIncludeLoss7());
|
||||
String resultKey = String.format(JOB_RESULT_KEY_PATTERN, jobId);
|
||||
|
||||
// 异步执行实际计算
|
||||
oeeReportJobService.executeAcidReportJob(
|
||||
jobId,
|
||||
metaKey,
|
||||
resultKey,
|
||||
body.getStartDate(),
|
||||
body.getEndDate(),
|
||||
includeSummary,
|
||||
includeLoss7
|
||||
);
|
||||
|
||||
return R.ok(meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询酸轧线 OEE 报表任务状态。
|
||||
*
|
||||
* 路由:GET /oee/line/acid/report-jobs/{jobId}
|
||||
*/
|
||||
@GetMapping("/acid/report-jobs/{jobId}")
|
||||
public R<OeeReportJobMeta> getAcidReportJob(@PathVariable String jobId) {
|
||||
String metaKey = String.format(JOB_META_KEY_PATTERN, jobId);
|
||||
String json = stringRedisTemplate.opsForValue().get(metaKey);
|
||||
if (StringUtils.isBlank(json)) {
|
||||
return R.fail("任务不存在或已过期");
|
||||
}
|
||||
OeeReportJobMeta meta = JSON.parseObject(json, OeeReportJobMeta.class);
|
||||
return R.ok(meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取酸轧线 OEE 报表任务结果。
|
||||
*
|
||||
* 路由:GET /oee/line/acid/report-jobs/{jobId}/result
|
||||
*/
|
||||
@GetMapping("/acid/report-jobs/{jobId}/result")
|
||||
public R<OeeReportJobResult> getAcidReportJobResult(@PathVariable String jobId) {
|
||||
String metaKey = String.format(JOB_META_KEY_PATTERN, jobId);
|
||||
String metaJson = stringRedisTemplate.opsForValue().get(metaKey);
|
||||
if (StringUtils.isBlank(metaJson)) {
|
||||
return R.fail("任务不存在或已过期");
|
||||
}
|
||||
OeeReportJobMeta meta = JSON.parseObject(metaJson, OeeReportJobMeta.class);
|
||||
if (!"COMPLETED".equals(meta.getStatus())) {
|
||||
return R.fail("结果未就绪,当前状态:" + meta.getStatus());
|
||||
}
|
||||
|
||||
String resultKey = String.format(JOB_RESULT_KEY_PATTERN, jobId);
|
||||
String resultJson = stringRedisTemplate.opsForValue().get(resultKey);
|
||||
if (StringUtils.isBlank(resultJson)) {
|
||||
return R.fail("任务结果不存在或已过期");
|
||||
}
|
||||
|
||||
OeeReportJobResult result = JSON.parseObject(resultJson, OeeReportJobResult.class);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停机/损失事件明细
|
||||
*/
|
||||
@Log(title = "OEE 报表-事件明细", businessType = BusinessType.OTHER)
|
||||
@GetMapping("/events")
|
||||
public TableDataInfo<OeeEventVo> events(OeeQueryBo queryBo, PageQuery pageQuery) {
|
||||
return oeeReportService.events(queryBo, pageQuery);
|
||||
// ======================== 内部 DTO ========================
|
||||
|
||||
@Data
|
||||
private static class OeeReportJobSubmitBo {
|
||||
/** 开始日期(yyyy-MM-dd) */
|
||||
private String startDate;
|
||||
/** 结束日期(yyyy-MM-dd) */
|
||||
private String endDate;
|
||||
/** 是否计算 summary(默认 true) */
|
||||
private Boolean includeSummary;
|
||||
/** 是否计算 loss7(默认 true) */
|
||||
private Boolean includeLoss7;
|
||||
/**
|
||||
* 口径开关等扩展选项(JSON 文本或键值对),当前实现暂不解析,仅作为预留字段。
|
||||
*/
|
||||
private String options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出 Word 报表(整体版式由后端模板控制)
|
||||
*/
|
||||
@Log(title = "OEE 报表-导出Word", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/exportWord")
|
||||
public void exportWord(OeeQueryBo queryBo, HttpServletResponse response) {
|
||||
oeeReportService.exportWord(queryBo, response);
|
||||
@Data
|
||||
private static class OeeReportJobMeta {
|
||||
private String jobId;
|
||||
/** PENDING / RUNNING / COMPLETED / FAILED / EXPIRED */
|
||||
private String status;
|
||||
private String submittedAt;
|
||||
private String startedAt;
|
||||
private String completedAt;
|
||||
private String startDate;
|
||||
private String endDate;
|
||||
private String errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 理论节拍回归(散点+拟合线)
|
||||
*
|
||||
* 说明:该接口用于前端绘制“散点+回归折线”的图形,节拍数据来源于 WMS 回归结果。
|
||||
*/
|
||||
@Log(title = "OEE 报表-理论节拍回归", businessType = BusinessType.OTHER)
|
||||
@GetMapping("/theoryCycle/regression")
|
||||
public R<Map<String, Object>> theoryCycleRegression(OeeQueryBo queryBo) {
|
||||
return R.ok(oeeReportService.theoryCycleRegression(queryBo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 理论节拍回归(异步任务):立即返回 jobId,通过 WebSocket 推送进度与结果。
|
||||
*
|
||||
* 前端订阅:
|
||||
* ws://{host}/websocket?type={wsType}
|
||||
*/
|
||||
@Log(title = "OEE 报表-理论节拍回归(异步)", businessType = BusinessType.OTHER)
|
||||
@GetMapping("/theoryCycle/regression/job")
|
||||
public R<Map<String, Object>> theoryCycleRegressionJob(OeeQueryBo queryBo) {
|
||||
System.out.println("[OEE][theoryCycle][job][controller] request received, thread=" + Thread.currentThread().getName()
|
||||
+ ", startTime=" + (queryBo == null ? null : queryBo.getStartTime())
|
||||
+ ", endTime=" + (queryBo == null ? null : queryBo.getEndTime())
|
||||
+ ", lineIds=" + (queryBo == null ? null : queryBo.getLineIds()));
|
||||
Map<String, Object> resp = oeeTheoryCycleJobService.createAndStart(queryBo);
|
||||
System.out.println("[OEE][theoryCycle][job][controller] job created, resp=" + resp);
|
||||
return R.ok(resp);
|
||||
@Data
|
||||
private static class OeeReportJobResult {
|
||||
/** 日汇总结果(用于 KPI + 趋势) */
|
||||
private List<AcidOeeDailySummaryVo> summary;
|
||||
/** 7 大损失结果 */
|
||||
private List<AcidOeeLoss7Vo> loss7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
占位文件,无需使用。
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.klp.da.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* OEE 事件(停机/损失)明细 VO
|
||||
*/
|
||||
@Data
|
||||
public class OeeEventVo {
|
||||
|
||||
private String lineId;
|
||||
|
||||
private String lineName;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime eventStartTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime eventEndTime;
|
||||
|
||||
/**
|
||||
* 时长(分钟)
|
||||
*/
|
||||
private Integer durationMin;
|
||||
|
||||
private String rawReasonCode;
|
||||
|
||||
private String rawReasonName;
|
||||
|
||||
private String lossCategoryCode;
|
||||
|
||||
private String lossCategoryName;
|
||||
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.klp.da.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 产线 OEE 汇总 + 日趋势 VO
|
||||
*
|
||||
* 对应设计文档 7.1 返回结构中的一条 line 记录。
|
||||
*/
|
||||
@Data
|
||||
public class OeeLineSummaryVo {
|
||||
|
||||
/**
|
||||
* 产线 ID
|
||||
*/
|
||||
private String lineId;
|
||||
|
||||
/**
|
||||
* 产线名称
|
||||
*/
|
||||
private String lineName;
|
||||
|
||||
/**
|
||||
* 区间汇总
|
||||
*/
|
||||
private Summary total;
|
||||
|
||||
/**
|
||||
* 日粒度数据(用于趋势图)
|
||||
*/
|
||||
private List<Daily> daily;
|
||||
|
||||
@Data
|
||||
public static class Summary {
|
||||
private Integer loadingTimeMin;
|
||||
private Integer downtimeMin;
|
||||
private Integer runTimeMin;
|
||||
private BigDecimal totalOutput;
|
||||
private BigDecimal goodOutput;
|
||||
private BigDecimal defectOutput;
|
||||
|
||||
private BigDecimal availability;
|
||||
private BigDecimal performance;
|
||||
private BigDecimal quality;
|
||||
private BigDecimal oee;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Daily {
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate statDate;
|
||||
|
||||
private Integer loadingTimeMin;
|
||||
private Integer downtimeMin;
|
||||
private Integer runTimeMin;
|
||||
private BigDecimal totalOutput;
|
||||
private BigDecimal goodOutput;
|
||||
private BigDecimal defectOutput;
|
||||
|
||||
private BigDecimal availability;
|
||||
private BigDecimal performance;
|
||||
private BigDecimal quality;
|
||||
private BigDecimal oee;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.klp.da.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 7 大损失分类汇总 VO
|
||||
*/
|
||||
@Data
|
||||
public class OeeLossCategorySummaryVo {
|
||||
|
||||
/**
|
||||
* 损失类别编码(1~7 或枚举)
|
||||
*/
|
||||
private String lossCategoryCode;
|
||||
|
||||
/**
|
||||
* 损失类别名称
|
||||
*/
|
||||
private String lossCategoryName;
|
||||
|
||||
/**
|
||||
* 损失时间(分钟)
|
||||
*/
|
||||
private Integer lossTimeMin;
|
||||
|
||||
/**
|
||||
* 损失占比(0~1 或 0~100,随整体口径配置)
|
||||
*/
|
||||
private BigDecimal lossTimeRate;
|
||||
|
||||
/**
|
||||
* 事件次数(可选)
|
||||
*/
|
||||
private Integer count;
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.klp.da.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 损失原因 TopN VO
|
||||
*/
|
||||
@Data
|
||||
public class OeeLossReasonVo {
|
||||
|
||||
private String lineId;
|
||||
|
||||
/**
|
||||
* 原因编码
|
||||
*/
|
||||
private String reasonCode;
|
||||
|
||||
/**
|
||||
* 原因名称
|
||||
*/
|
||||
private String reasonName;
|
||||
|
||||
/**
|
||||
* 所属损失类别编码
|
||||
*/
|
||||
private String lossCategoryCode;
|
||||
|
||||
/**
|
||||
* 损失时间(分钟)
|
||||
*/
|
||||
private Integer lossTimeMin;
|
||||
|
||||
/**
|
||||
* 时间占比
|
||||
*/
|
||||
private BigDecimal lossTimeRate;
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.klp.da.service;
|
||||
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.da.domain.bo.OeeQueryBo;
|
||||
import com.klp.da.domain.vo.OeeEventVo;
|
||||
import com.klp.da.domain.vo.OeeLineSummaryVo;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* OEE 报表聚合 Service 接口(方式 A:后端统一聚合多服务)
|
||||
*
|
||||
* 实现类负责:
|
||||
* - 调用酸轧线、镀锌一线等外部服务
|
||||
* - 做数据汇总、口径统一和格式转换
|
||||
*/
|
||||
public interface IOeeReportService {
|
||||
|
||||
/**
|
||||
* KPI + 趋势汇总
|
||||
*/
|
||||
List<OeeLineSummaryVo> summary(OeeQueryBo queryBo);
|
||||
|
||||
/**
|
||||
* 7 大损失汇总
|
||||
*
|
||||
* 返回 Map 以便后续扩展:
|
||||
* - byLine: List<LineLossSummary>
|
||||
* - topReasons: List<OeeLossReasonVo>
|
||||
* 等
|
||||
*/
|
||||
Map<String, Object> lossSummary(OeeQueryBo queryBo);
|
||||
|
||||
/**
|
||||
* 事件明细
|
||||
*/
|
||||
TableDataInfo<OeeEventVo> events(OeeQueryBo queryBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 导出 Word 报表
|
||||
*/
|
||||
void exportWord(OeeQueryBo queryBo, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 理论节拍线性回归(散点+拟合线),用于前端绘图。
|
||||
*/
|
||||
Map<String, Object> theoryCycleRegression(OeeQueryBo queryBo);
|
||||
}
|
||||
|
||||
137
klp-da/src/main/java/com/klp/da/service/OeeReportJobService.java
Normal file
137
klp-da/src/main/java/com/klp/da/service/OeeReportJobService.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package com.klp.da.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
|
||||
import com.klp.pocket.acid.service.IAcidOeeService;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* OEE 报表异步任务执行 Service(酸轧线)。
|
||||
*
|
||||
* 负责在后台线程中执行任意日期范围的 summary/loss7 计算,
|
||||
* 并将任务状态与结果写入 Redis。
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OeeReportJobService {
|
||||
|
||||
private final IAcidOeeService acidOeeService;
|
||||
private final StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||
|
||||
/**
|
||||
* 异步执行酸轧线报表任务。
|
||||
*
|
||||
* @param jobId 任务 ID
|
||||
* @param metaKey 任务元信息 Redis key
|
||||
* @param resultKey 任务结果 Redis key
|
||||
* @param startDate 开始日期(yyyy-MM-dd)
|
||||
* @param endDate 结束日期(yyyy-MM-dd)
|
||||
* @param includeSummary 是否计算 summary
|
||||
* @param includeLoss7 是否计算 loss7
|
||||
*/
|
||||
@Async
|
||||
public void executeAcidReportJob(
|
||||
String jobId,
|
||||
String metaKey,
|
||||
String resultKey,
|
||||
String startDate,
|
||||
String endDate,
|
||||
boolean includeSummary,
|
||||
boolean includeLoss7
|
||||
) {
|
||||
try {
|
||||
// 更新状态为 RUNNING
|
||||
OeeReportJobMeta meta = readMeta(metaKey);
|
||||
if (meta == null) {
|
||||
meta = new OeeReportJobMeta();
|
||||
meta.setJobId(jobId);
|
||||
meta.setStartDate(startDate);
|
||||
meta.setEndDate(endDate);
|
||||
}
|
||||
meta.setStatus("RUNNING");
|
||||
meta.setStartedAt(LocalDateTime.now().format(DATE_TIME_FORMATTER));
|
||||
writeMeta(metaKey, meta);
|
||||
|
||||
// 实际计算
|
||||
OeeReportJobResult result = new OeeReportJobResult();
|
||||
if (includeSummary) {
|
||||
List<AcidOeeDailySummaryVo> summary =
|
||||
acidOeeService.getDailySummary(startDate, endDate);
|
||||
result.setSummary(summary);
|
||||
}
|
||||
if (includeLoss7) {
|
||||
List<AcidOeeLoss7Vo> loss7 =
|
||||
acidOeeService.getLoss7Summary(startDate, endDate);
|
||||
result.setLoss7(loss7);
|
||||
}
|
||||
|
||||
stringRedisTemplate.opsForValue()
|
||||
.set(resultKey, JSON.toJSONString(result), 1, TimeUnit.DAYS);
|
||||
|
||||
// 标记为 COMPLETED
|
||||
meta.setStatus("COMPLETED");
|
||||
meta.setCompletedAt(LocalDateTime.now().format(DATE_TIME_FORMATTER));
|
||||
writeMeta(metaKey, meta);
|
||||
} catch (Exception e) {
|
||||
log.error("[OeeReportJobService] executeAcidReportJob error, jobId={}", jobId, e);
|
||||
OeeReportJobMeta meta = readMeta(metaKey);
|
||||
if (meta == null) {
|
||||
meta = new OeeReportJobMeta();
|
||||
meta.setJobId(jobId);
|
||||
meta.setStartDate(startDate);
|
||||
meta.setEndDate(endDate);
|
||||
}
|
||||
meta.setStatus("FAILED");
|
||||
meta.setCompletedAt(LocalDateTime.now().format(DATE_TIME_FORMATTER));
|
||||
meta.setErrorMessage(e.getMessage());
|
||||
writeMeta(metaKey, meta);
|
||||
}
|
||||
}
|
||||
|
||||
private OeeReportJobMeta readMeta(String metaKey) {
|
||||
String json = stringRedisTemplate.opsForValue().get(metaKey);
|
||||
if (json == null || json.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parseObject(json, OeeReportJobMeta.class);
|
||||
}
|
||||
|
||||
private void writeMeta(String metaKey, OeeReportJobMeta meta) {
|
||||
stringRedisTemplate.opsForValue()
|
||||
.set(metaKey, JSON.toJSONString(meta), 1, TimeUnit.DAYS);
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class OeeReportJobMeta {
|
||||
private String jobId;
|
||||
private String status;
|
||||
private String submittedAt;
|
||||
private String startedAt;
|
||||
private String completedAt;
|
||||
private String startDate;
|
||||
private String endDate;
|
||||
private String errorMessage;
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class OeeReportJobResult {
|
||||
private List<AcidOeeDailySummaryVo> summary;
|
||||
private List<AcidOeeLoss7Vo> loss7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.klp.da.service;
|
||||
|
||||
import com.klp.da.domain.bo.OeeQueryBo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* OEE summary 异步任务(WebSocket 推送)
|
||||
*/
|
||||
public interface OeeSummaryJobService {
|
||||
|
||||
/**
|
||||
* 创建任务并异步执行,立即返回 job 信息。
|
||||
*
|
||||
* @return Map: { jobId, wsType }
|
||||
*/
|
||||
Map<String, Object> createAndStart(OeeQueryBo queryBo);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.klp.da.service;
|
||||
|
||||
import com.klp.da.domain.bo.OeeQueryBo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 理论节拍回归异步任务(WebSocket 推送)
|
||||
*/
|
||||
public interface OeeTheoryCycleJobService {
|
||||
|
||||
/**
|
||||
* 创建任务并异步执行,立即返回 job 信息。
|
||||
*
|
||||
* @return Map: { jobId, wsType }
|
||||
*/
|
||||
Map<String, Object> createAndStart(OeeQueryBo queryBo);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,155 +0,0 @@
|
||||
package com.klp.da.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.klp.da.domain.bo.OeeQueryBo;
|
||||
import com.klp.da.domain.vo.OeeLineSummaryVo;
|
||||
import com.klp.da.service.IOeeReportService;
|
||||
import com.klp.da.service.OeeSummaryJobService;
|
||||
import com.klp.framework.websocket.TypeWebSocketUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OeeSummaryJobServiceImpl implements OeeSummaryJobService {
|
||||
|
||||
public static final String WS_TYPE_PREFIX = "oee_summary:";
|
||||
|
||||
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(2, r -> {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("oee-summary-job");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
|
||||
private final IOeeReportService oeeReportService;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public Map<String, Object> createAndStart(OeeQueryBo queryBo) {
|
||||
String jobId = UUID.randomUUID().toString().replace("-", "");
|
||||
String wsType = WS_TYPE_PREFIX + jobId;
|
||||
|
||||
String auth = captureAuthorization();
|
||||
log.info("[OEE][summary][job] created jobId={}, wsType={}, window={}~{}, lines={}, authPresent={}",
|
||||
jobId,
|
||||
wsType,
|
||||
queryBo == null ? null : queryBo.getStartDate(),
|
||||
queryBo == null ? null : queryBo.getEndDate(),
|
||||
queryBo == null ? null : queryBo.getLineIds(),
|
||||
auth != null && !auth.trim().isEmpty());
|
||||
|
||||
push(jobId, wsType, "running", 5, "任务已创建,准备生成汇总…", null, null);
|
||||
|
||||
OeeQueryBo qb = copyQueryBo(queryBo);
|
||||
EXECUTOR.submit(() -> run(jobId, wsType, qb, auth));
|
||||
|
||||
Map<String, Object> resp = new HashMap<>();
|
||||
resp.put("jobId", jobId);
|
||||
resp.put("wsType", wsType);
|
||||
return resp;
|
||||
}
|
||||
|
||||
private void run(String jobId, String wsType, OeeQueryBo queryBo, String authorization) {
|
||||
long t0 = System.currentTimeMillis();
|
||||
try {
|
||||
System.out.println("[OEE][summary][job] start jobId=" + jobId + ", wsType=" + wsType
|
||||
+ ", thread=" + Thread.currentThread().getName()
|
||||
+ ", authPresent=" + (authorization != null && !authorization.trim().isEmpty()));
|
||||
log.info("[OEE][summary][job] start jobId={}, wsType={}, thread={}, authPresent={}",
|
||||
jobId, wsType, Thread.currentThread().getName(), authorization != null && !authorization.trim().isEmpty());
|
||||
push(jobId, wsType, "running", 20, "正在聚合 KPI 与趋势…", null, null);
|
||||
OeeReportServiceImpl.setAuthOverride(authorization);
|
||||
List<OeeLineSummaryVo> lines = oeeReportService.summary(queryBo);
|
||||
push(jobId, wsType, "running", 90, "正在整理汇总结果…", null, null);
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("lines", lines);
|
||||
|
||||
push(jobId, wsType, "success", 100, "汇总生成完成", data, null);
|
||||
System.out.println("[OEE][summary][job] success jobId=" + jobId + ", costMs=" + (System.currentTimeMillis() - t0)
|
||||
+ ", lineCount=" + (lines == null ? 0 : lines.size()));
|
||||
log.info("[OEE][summary][job] success jobId={}, costMs={}, lineCount={}",
|
||||
jobId, (System.currentTimeMillis() - t0), lines == null ? 0 : lines.size());
|
||||
} catch (Exception e) {
|
||||
log.warn("summary job failed, jobId={}", jobId, e);
|
||||
push(jobId, wsType, "failed", 100, "汇总生成失败", null, e.getMessage());
|
||||
System.out.println("[OEE][summary][job] failed jobId=" + jobId + ", costMs=" + (System.currentTimeMillis() - t0)
|
||||
+ ", msg=" + e.getMessage());
|
||||
log.warn("[OEE][summary][job] failed jobId={}, costMs={}, msg={}",
|
||||
jobId, (System.currentTimeMillis() - t0), e.getMessage());
|
||||
} finally {
|
||||
OeeReportServiceImpl.clearAuthOverride();
|
||||
System.out.println("[OEE][summary][job] end jobId=" + jobId + ", costMs=" + (System.currentTimeMillis() - t0));
|
||||
log.info("[OEE][summary][job] end jobId={}, costMs={}", jobId, (System.currentTimeMillis() - t0));
|
||||
}
|
||||
}
|
||||
|
||||
private void push(String jobId, String wsType, String status, int progress, String text,
|
||||
Map<String, Object> data, String errorMsg) {
|
||||
try {
|
||||
Map<String, Object> msg = new HashMap<>();
|
||||
msg.put("jobId", jobId);
|
||||
msg.put("status", status);
|
||||
msg.put("progress", progress);
|
||||
msg.put("text", text);
|
||||
if (data != null) {
|
||||
msg.put("data", data);
|
||||
}
|
||||
if (errorMsg != null && !errorMsg.trim().isEmpty()) {
|
||||
msg.put("errorMsg", errorMsg);
|
||||
}
|
||||
TypeWebSocketUtil.sendToType(wsType, objectMapper.writeValueAsString(msg));
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
private OeeQueryBo copyQueryBo(OeeQueryBo queryBo) {
|
||||
OeeQueryBo qb = new OeeQueryBo();
|
||||
if (queryBo == null) {
|
||||
return qb;
|
||||
}
|
||||
qb.setStartDate(queryBo.getStartDate());
|
||||
qb.setEndDate(queryBo.getEndDate());
|
||||
qb.setLineIds(queryBo.getLineIds());
|
||||
qb.setStartTime(queryBo.getStartTime());
|
||||
qb.setEndTime(queryBo.getEndTime());
|
||||
qb.setTopN(queryBo.getTopN());
|
||||
qb.setLossCategoryCode(queryBo.getLossCategoryCode());
|
||||
qb.setKeyword(queryBo.getKeyword());
|
||||
return qb;
|
||||
}
|
||||
|
||||
private String captureAuthorization() {
|
||||
try {
|
||||
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attrs == null || attrs.getRequest() == null) {
|
||||
return null;
|
||||
}
|
||||
HttpServletRequest req = attrs.getRequest();
|
||||
String auth = req.getHeader("Authorization");
|
||||
if (auth != null && !auth.trim().isEmpty()) {
|
||||
return auth.trim();
|
||||
}
|
||||
String token = req.getHeader("token");
|
||||
if (token != null && !token.trim().isEmpty()) {
|
||||
return "Bearer " + token.trim();
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
package com.klp.da.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.klp.da.domain.bo.OeeQueryBo;
|
||||
import com.klp.da.service.IOeeReportService;
|
||||
import com.klp.da.service.OeeTheoryCycleJobService;
|
||||
import com.klp.framework.websocket.TypeWebSocketUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OeeTheoryCycleJobServiceImpl implements OeeTheoryCycleJobService {
|
||||
|
||||
/**
|
||||
* 推送 type 前缀:前端用 ws://host/websocket?type=oee_theory_cycle_regression:{jobId} 订阅。
|
||||
*/
|
||||
public static final String WS_TYPE_PREFIX = "oee_theory_cycle_regression:";
|
||||
|
||||
private static final long TTL_MS = 10 * 60_000L;
|
||||
private static final ConcurrentHashMap<String, JobState> JOBS = new ConcurrentHashMap<>();
|
||||
|
||||
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(2, r -> {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("oee-theory-cycle-job");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
|
||||
private final IOeeReportService oeeReportService;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public Map<String, Object> createAndStart(OeeQueryBo queryBo) {
|
||||
String jobId = UUID.randomUUID().toString().replace("-", "");
|
||||
String wsType = WS_TYPE_PREFIX + jobId;
|
||||
|
||||
JobState st = new JobState();
|
||||
st.updatedAt = System.currentTimeMillis();
|
||||
JOBS.put(jobId, st);
|
||||
|
||||
String auth = captureAuthorization();
|
||||
log.info("[OEE][theoryCycle][job] created jobId={}, wsType={}, window={}~{}, lines={}, authPresent={}",
|
||||
jobId,
|
||||
wsType,
|
||||
queryBo == null ? null : queryBo.getStartTime(),
|
||||
queryBo == null ? null : queryBo.getEndTime(),
|
||||
queryBo == null ? null : queryBo.getLineIds(),
|
||||
auth != null && !auth.trim().isEmpty());
|
||||
|
||||
// 立即推送“已创建”
|
||||
push(jobId, wsType, "running", 5, "任务已创建,准备计算…", null, null);
|
||||
|
||||
// 异步执行
|
||||
OeeQueryBo qb = copyQueryBo(queryBo);
|
||||
EXECUTOR.submit(() -> run(jobId, wsType, qb, auth));
|
||||
|
||||
Map<String, Object> resp = new HashMap<>();
|
||||
resp.put("jobId", jobId);
|
||||
resp.put("wsType", wsType);
|
||||
return resp;
|
||||
}
|
||||
|
||||
private void run(String jobId, String wsType, OeeQueryBo queryBo, String authorization) {
|
||||
long t0 = System.currentTimeMillis();
|
||||
try {
|
||||
cleanupExpired();
|
||||
System.out.println("[OEE][theoryCycle][job] start jobId=" + jobId + ", wsType=" + wsType
|
||||
+ ", thread=" + Thread.currentThread().getName()
|
||||
+ ", authPresent=" + (authorization != null && !authorization.trim().isEmpty()));
|
||||
log.info("[OEE][theoryCycle][job] start jobId={}, wsType={}, thread={}, authPresent={}",
|
||||
jobId, wsType, Thread.currentThread().getName(), authorization != null && !authorization.trim().isEmpty());
|
||||
push(jobId, wsType, "running", 20, "开始计算理论节拍回归…", null, null);
|
||||
|
||||
// 这里复用现有 WMS 同步回归聚合逻辑(内部会走 WMS 接口)
|
||||
push(jobId, wsType, "running", 50, "正在拉取样本并拟合回归…", null, null);
|
||||
OeeReportServiceImpl.setAuthOverride(authorization);
|
||||
Map<String, Object> data = oeeReportService.theoryCycleRegression(queryBo);
|
||||
|
||||
push(jobId, wsType, "running", 90, "正在整理回归结果…", null, null);
|
||||
JobState st = JOBS.get(jobId);
|
||||
if (st != null) {
|
||||
st.updatedAt = System.currentTimeMillis();
|
||||
}
|
||||
push(jobId, wsType, "success", 100, "回归计算完成", data, null);
|
||||
System.out.println("[OEE][theoryCycle][job] success jobId=" + jobId + ", costMs=" + (System.currentTimeMillis() - t0));
|
||||
log.info("[OEE][theoryCycle][job] success jobId={}, costMs={}", jobId, (System.currentTimeMillis() - t0));
|
||||
} catch (Exception e) {
|
||||
log.warn("theoryCycle job failed, jobId={}", jobId, e);
|
||||
JobState st = JOBS.get(jobId);
|
||||
if (st != null) {
|
||||
st.updatedAt = System.currentTimeMillis();
|
||||
}
|
||||
push(jobId, wsType, "failed", 100, "回归计算失败", null, e.getMessage());
|
||||
System.out.println("[OEE][theoryCycle][job] failed jobId=" + jobId + ", costMs=" + (System.currentTimeMillis() - t0)
|
||||
+ ", msg=" + e.getMessage());
|
||||
log.warn("[OEE][theoryCycle][job] failed jobId={}, costMs={}, msg={}",
|
||||
jobId, (System.currentTimeMillis() - t0), e.getMessage());
|
||||
} finally {
|
||||
OeeReportServiceImpl.clearAuthOverride();
|
||||
System.out.println("[OEE][theoryCycle][job] end jobId=" + jobId + ", costMs=" + (System.currentTimeMillis() - t0));
|
||||
log.info("[OEE][theoryCycle][job] end jobId={}, costMs={}", jobId, (System.currentTimeMillis() - t0));
|
||||
}
|
||||
}
|
||||
|
||||
private void push(String jobId, String wsType, String status, int progress, String text,
|
||||
Map<String, Object> data, String errorMsg) {
|
||||
try {
|
||||
Map<String, Object> msg = new HashMap<>();
|
||||
msg.put("jobId", jobId);
|
||||
msg.put("status", status);
|
||||
msg.put("progress", progress);
|
||||
msg.put("text", text);
|
||||
if (data != null) {
|
||||
msg.put("data", data);
|
||||
}
|
||||
if (errorMsg != null && !errorMsg.trim().isEmpty()) {
|
||||
msg.put("errorMsg", errorMsg);
|
||||
}
|
||||
TypeWebSocketUtil.sendToType(wsType, objectMapper.writeValueAsString(msg));
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupExpired() {
|
||||
long now = System.currentTimeMillis();
|
||||
JOBS.entrySet().removeIf(e -> e.getValue() == null || (now - e.getValue().updatedAt) > TTL_MS);
|
||||
}
|
||||
|
||||
private OeeQueryBo copyQueryBo(OeeQueryBo queryBo) {
|
||||
OeeQueryBo qb = new OeeQueryBo();
|
||||
if (queryBo == null) {
|
||||
return qb;
|
||||
}
|
||||
qb.setStartDate(queryBo.getStartDate());
|
||||
qb.setEndDate(queryBo.getEndDate());
|
||||
qb.setLineIds(queryBo.getLineIds());
|
||||
qb.setStartTime(queryBo.getStartTime());
|
||||
qb.setEndTime(queryBo.getEndTime());
|
||||
qb.setTopN(queryBo.getTopN());
|
||||
qb.setLossCategoryCode(queryBo.getLossCategoryCode());
|
||||
qb.setKeyword(queryBo.getKeyword());
|
||||
return qb;
|
||||
}
|
||||
|
||||
private String captureAuthorization() {
|
||||
try {
|
||||
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attrs == null || attrs.getRequest() == null) {
|
||||
return null;
|
||||
}
|
||||
HttpServletRequest req = attrs.getRequest();
|
||||
String auth = req.getHeader("Authorization");
|
||||
if (auth != null && !auth.trim().isEmpty()) {
|
||||
return auth.trim();
|
||||
}
|
||||
String token = req.getHeader("token");
|
||||
if (token != null && !token.trim().isEmpty()) {
|
||||
return "Bearer " + token.trim();
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class JobState {
|
||||
long updatedAt;
|
||||
}
|
||||
}
|
||||
|
||||
148
klp-da/src/main/java/com/klp/da/task/AcidOeeMonthTask.java
Normal file
148
klp-da/src/main/java/com/klp/da/task/AcidOeeMonthTask.java
Normal file
@@ -0,0 +1,148 @@
|
||||
package com.klp.da.task;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
|
||||
import com.klp.pocket.acid.service.IAcidOeeService;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 酸轧线 OEE 当月预计算任务
|
||||
*
|
||||
* 需求对应 docs/oee-report-design.md 第 12.2 节:
|
||||
* - 项目启动完成后即计算当月 OEE 聚合结果并写入 Redis;
|
||||
* - 每天凌晨 04:00 重新计算当月数据并覆盖缓存。
|
||||
*
|
||||
* 当前仅实现酸轧线(SY)的当月日汇总 & 7 大损失预计算;
|
||||
* key 约定:
|
||||
* - 汇总结果:oee:report:month:summary:{yyyyMM}:SY
|
||||
* - 7 大损失:oee:report:month:loss7:{yyyyMM}:SY
|
||||
* - 元信息: oee:report:month:meta:{yyyyMM}:SY
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class AcidOeeMonthTask {
|
||||
|
||||
/** Redis 缓存 key 模板:当月 OEE 汇总(酸轧线) */
|
||||
private static final String SUMMARY_KEY_PATTERN = "oee:report:month:summary:%s:SY";
|
||||
|
||||
/** Redis 缓存 key 模板:当月 7 大损失(酸轧线) */
|
||||
private static final String LOSS7_KEY_PATTERN = "oee:report:month:loss7:%s:SY";
|
||||
|
||||
/** Redis 缓存 key 模板:当月元信息(酸轧线) */
|
||||
private static final String META_KEY_PATTERN = "oee:report:month:meta:%s:SY";
|
||||
|
||||
private static final DateTimeFormatter YEAR_MONTH_FMT = DateTimeFormatter.ofPattern("yyyyMM");
|
||||
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ISO_DATE;
|
||||
private static final DateTimeFormatter DATE_TIME_FMT = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||
|
||||
private final IAcidOeeService acidOeeService;
|
||||
private final StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
/**
|
||||
* 项目启动完成后立即计算一次当月酸轧 OEE 汇总并写入 Redis。
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
try {
|
||||
computeCurrentMonth("startup");
|
||||
} catch (Exception e) {
|
||||
log.error("[AcidOeeMonthTask] startup compute failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天凌晨 04:00 重新计算当月酸轧 OEE 汇总并覆盖 Redis 缓存。
|
||||
*/
|
||||
@Scheduled(cron = "0 0 4 * * ?")
|
||||
public void scheduleDaily() {
|
||||
try {
|
||||
computeCurrentMonth("schedule-04");
|
||||
} catch (Exception e) {
|
||||
log.error("[AcidOeeMonthTask] 4am compute failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算当前月份(从当月1号到今天)的酸轧 OEE 日汇总,并写入 Redis。
|
||||
*
|
||||
* @param trigger 触发来源标记(startup / schedule-04 等)
|
||||
*/
|
||||
private void computeCurrentMonth(String trigger) {
|
||||
long startNs = System.nanoTime();
|
||||
|
||||
LocalDate now = LocalDate.now();
|
||||
String yyyyMM = now.format(YEAR_MONTH_FMT);
|
||||
|
||||
LocalDate startDate = now.withDayOfMonth(1);
|
||||
LocalDate endDate = now;
|
||||
|
||||
String startStr = startDate.format(DATE_FMT);
|
||||
String endStr = endDate.format(DATE_FMT);
|
||||
|
||||
log.info("[AcidOeeMonthTask] trigger={}, computing acid OEE month summary for {} ({} ~ {})",
|
||||
trigger, yyyyMM, startStr, endStr);
|
||||
|
||||
// 1. 调用 pocket 的 AcidOeeService 获取当月日汇总 & 7 大损失
|
||||
List<AcidOeeDailySummaryVo> dailySummaryList = acidOeeService.getDailySummary(startStr, endStr);
|
||||
List<AcidOeeLoss7Vo> loss7List = acidOeeService.getLoss7Summary(startStr, endStr);
|
||||
|
||||
// 2. 写入 Redis(summary)
|
||||
String summaryKey = String.format(SUMMARY_KEY_PATTERN, yyyyMM);
|
||||
String summaryJson = JSON.toJSONString(dailySummaryList);
|
||||
stringRedisTemplate.opsForValue().set(summaryKey, summaryJson, 1, TimeUnit.DAYS);
|
||||
|
||||
// 2.1 写入 Redis(loss7)
|
||||
String loss7Key = String.format(LOSS7_KEY_PATTERN, yyyyMM);
|
||||
String loss7Json = JSON.toJSONString(loss7List);
|
||||
stringRedisTemplate.opsForValue().set(loss7Key, loss7Json, 1, TimeUnit.DAYS);
|
||||
|
||||
long durationMs = (System.nanoTime() - startNs) / 1_000_000L;
|
||||
|
||||
// 3. 写入 Redis(meta)
|
||||
Meta meta = new Meta();
|
||||
meta.setComputedAt(LocalDateTime.now().format(DATE_TIME_FMT));
|
||||
meta.setDurationMs(durationMs);
|
||||
meta.setStartDate(startStr);
|
||||
meta.setEndDate(endStr);
|
||||
meta.setTrigger(trigger);
|
||||
|
||||
String metaKey = String.format(META_KEY_PATTERN, yyyyMM);
|
||||
stringRedisTemplate.opsForValue().set(metaKey, JSON.toJSONString(meta), 1, TimeUnit.DAYS);
|
||||
|
||||
log.info("[AcidOeeMonthTask] compute finish for {} dailySize={}, loss7Size={}, durationMs={}ms, summaryKey={}",
|
||||
yyyyMM, dailySummaryList.size(), loss7List.size(), durationMs, summaryKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当月预计算元信息
|
||||
*/
|
||||
@Data
|
||||
private static class Meta {
|
||||
/** 计算完成时间(ISO-8601 字符串) */
|
||||
private String computedAt;
|
||||
/** 计算耗时(毫秒) */
|
||||
private long durationMs;
|
||||
/** 统计起始日期(yyyy-MM-dd) */
|
||||
private String startDate;
|
||||
/** 统计结束日期(yyyy-MM-dd) */
|
||||
private String endDate;
|
||||
/** 触发来源(startup / schedule-04 等) */
|
||||
private String trigger;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,5 +24,11 @@
|
||||
<artifactId>klp-system</artifactId>
|
||||
<version>0.8.3</version>
|
||||
</dependency>
|
||||
<!-- 用于 OEE 口径:按“当前钢卷号 + 成品库库区ID”获取 quality_status 以区分良品/次品 -->
|
||||
<dependency>
|
||||
<groupId>com.klp</groupId>
|
||||
<artifactId>klp-wms</artifactId>
|
||||
<version>0.8.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package com.klp.pocket.controller;
|
||||
package com.klp.pocket.acid.controller;
|
||||
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateCurrent;
|
||||
import com.klp.pocket.service.IKlptcm1ProPlantStateCurrentService;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateCurrent;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProPlantStateCurrentService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.klp.pocket.controller;
|
||||
package com.klp.pocket.acid.controller;
|
||||
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateDefine;
|
||||
import com.klp.pocket.domain.vo.PlantStateWithValueVo;
|
||||
import com.klp.pocket.service.IKlptcm1ProPlantStateDefineService;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateDefine;
|
||||
import com.klp.pocket.acid.domain.vo.PlantStateWithValueVo;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProPlantStateDefineService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.controller;
|
||||
package com.klp.pocket.acid.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
@@ -11,9 +11,9 @@ import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ProPlantStateHistoryVo;
|
||||
import com.klp.pocket.domain.bo.Klptcm1ProPlantStateHistoryBo;
|
||||
import com.klp.pocket.service.IKlptcm1ProPlantStateHistoryService;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProPlantStateHistoryVo;
|
||||
import com.klp.pocket.acid.domain.bo.Klptcm1ProPlantStateHistoryBo;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProPlantStateHistoryService;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.controller;
|
||||
package com.klp.pocket.acid.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
@@ -11,9 +11,9 @@ import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.domain.bo.Klptcm1ProStoppageBo;
|
||||
import com.klp.pocket.service.IKlptcm1ProStoppageService;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.acid.domain.bo.Klptcm1ProStoppageBo;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProStoppageService;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.klp.pocket.controller;
|
||||
package com.klp.pocket.acid.controller;
|
||||
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.pocket.domain.vo.ProductionStatisticsVo;
|
||||
import com.klp.pocket.domain.vo.CrewProductionVo;
|
||||
import com.klp.pocket.domain.vo.SpecDistributionVo;
|
||||
import com.klp.pocket.domain.vo.TeamPerformanceVo;
|
||||
import com.klp.pocket.service.IKlptcm1PdoExcoilService;
|
||||
import com.klp.pocket.acid.domain.vo.ProductionStatisticsVo;
|
||||
import com.klp.pocket.acid.domain.vo.CrewProductionVo;
|
||||
import com.klp.pocket.acid.domain.vo.SpecDistributionVo;
|
||||
import com.klp.pocket.acid.domain.vo.TeamPerformanceVo;
|
||||
import com.klp.pocket.acid.service.IKlptcm1PdoExcoilService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.klp.pocket.controller;
|
||||
package com.klp.pocket.acid.controller;
|
||||
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ShiftCurrentVo;
|
||||
import com.klp.pocket.service.IKlptcm1ShiftCurrentService;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ShiftCurrentVo;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ShiftCurrentService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain;
|
||||
package com.klp.pocket.acid.domain;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain;
|
||||
package com.klp.pocket.acid.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain;
|
||||
package com.klp.pocket.acid.domain;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain;
|
||||
package com.klp.pocket.acid.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain;
|
||||
package com.klp.pocket.acid.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain;
|
||||
package com.klp.pocket.acid.domain;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.bo;
|
||||
package com.klp.pocket.acid.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.bo;
|
||||
package com.klp.pocket.acid.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.bo;
|
||||
package com.klp.pocket.acid.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 酸轧线OEE日汇总视图对象
|
||||
* 用于按日、按产线聚合的KPI与趋势数据
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-01-30
|
||||
*/
|
||||
@Data
|
||||
public class AcidOeeDailySummaryVo {
|
||||
|
||||
/** 统计日期(yyyy-MM-dd) */
|
||||
private String statDate;
|
||||
|
||||
/** 产线ID(固定为 SY) */
|
||||
private String lineId;
|
||||
|
||||
/** 产线名称(酸轧线) */
|
||||
private String lineName;
|
||||
|
||||
/** 计划时间(min,可选) */
|
||||
private Long plannedTimeMin;
|
||||
|
||||
/** 计划停机(min,可选;若无则置 0) */
|
||||
private Long plannedDowntimeMin;
|
||||
|
||||
/** 负荷时间(min)= planned_time_min - planned_downtime_min */
|
||||
private Long loadingTimeMin;
|
||||
|
||||
/** 停机时间(min,来自停机事件汇总) */
|
||||
private Long downtimeMin;
|
||||
|
||||
/** 实际运转时间(min)= loading_time_min - downtime_min */
|
||||
private Long runTimeMin;
|
||||
|
||||
/** 总产量(吨) */
|
||||
private BigDecimal totalOutputTon;
|
||||
|
||||
/** 总产量(卷) */
|
||||
private Long totalOutputCoil;
|
||||
|
||||
/** 良品量(吨) */
|
||||
private BigDecimal goodOutputTon;
|
||||
|
||||
/** 良品量(卷) */
|
||||
private Long goodOutputCoil;
|
||||
|
||||
/** 不良量(吨)= total_output_ton - good_output_ton */
|
||||
private BigDecimal defectOutputTon;
|
||||
|
||||
/** 不良量(卷)= total_output_coil - good_output_coil */
|
||||
private Long defectOutputCoil;
|
||||
|
||||
/** 理论节拍(min/吨;回归斜率) */
|
||||
private BigDecimal idealCycleTimeMinPerTon;
|
||||
|
||||
/** 理论节拍(min/卷;回归斜率) */
|
||||
private BigDecimal idealCycleTimeMinPerCoil;
|
||||
|
||||
/** 派生指标:时间稼动率(0~1 或 0~100) */
|
||||
private BigDecimal availability;
|
||||
|
||||
/** 派生指标:性能稼动率(吨维度) */
|
||||
private BigDecimal performanceTon;
|
||||
|
||||
/** 派生指标:性能稼动率(卷维度) */
|
||||
private BigDecimal performanceCoil;
|
||||
|
||||
/** 派生指标:良品率 */
|
||||
private BigDecimal quality;
|
||||
|
||||
/** 派生指标:OEE(建议以吨维度为主) */
|
||||
private BigDecimal oee;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 酸轧线OEE 7大损失汇总视图对象
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-01-30
|
||||
*/
|
||||
@Data
|
||||
public class AcidOeeLoss7Vo {
|
||||
|
||||
/** 损失类别编码(1-7,或直接使用 stop_type 名称) */
|
||||
private String lossCategoryCode;
|
||||
|
||||
/** 损失类别名称 */
|
||||
private String lossCategoryName;
|
||||
|
||||
/** 损失时间(分钟) */
|
||||
private Long lossTimeMin;
|
||||
|
||||
/** 损失时间占比(%) */
|
||||
private BigDecimal lossTimeRate;
|
||||
|
||||
/** 发生次数(部分分类可能为空) */
|
||||
private Integer count;
|
||||
|
||||
/** 平均时长(分钟,部分分类可能为空) */
|
||||
private BigDecimal avgDurationMin;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 酸轧线OEE回归数据视图对象
|
||||
* 用于理论节拍计算和前端散点图展示
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-01-30
|
||||
*/
|
||||
@Data
|
||||
public class AcidOeeRegressionVo {
|
||||
|
||||
/** 产线ID(固定为 SY) */
|
||||
private String lineId;
|
||||
|
||||
/** 产线名称(酸轧线) */
|
||||
private String lineName;
|
||||
|
||||
/** 回归斜率:分钟/吨(核心值,可作为理论节拍) */
|
||||
private BigDecimal slopeMinPerTon;
|
||||
|
||||
/** 回归斜率:分钟/卷(核心值,可作为理论节拍) */
|
||||
private BigDecimal slopeMinPerCoil;
|
||||
|
||||
/** 截距(分钟) */
|
||||
private BigDecimal interceptMin;
|
||||
|
||||
/** 拟合优度(R²) */
|
||||
private BigDecimal r2;
|
||||
|
||||
/** 参与回归样本数 */
|
||||
private Integer sampleCount;
|
||||
|
||||
/** 回归数据开始时间 */
|
||||
private String startTime;
|
||||
|
||||
/** 回归数据结束时间 */
|
||||
private String endTime;
|
||||
|
||||
/** 散点列表 */
|
||||
private List<RegressionPointVo> points;
|
||||
|
||||
/** 拟合线两个端点(前端可直接画线) */
|
||||
private List<RegressionLinePointVo> linePoints;
|
||||
|
||||
/**
|
||||
* 散点数据
|
||||
*/
|
||||
@Data
|
||||
public static class RegressionPointVo {
|
||||
/** 重量(吨,X轴) */
|
||||
private BigDecimal weightTon;
|
||||
/** 卷数(X轴) */
|
||||
private Long coilCount;
|
||||
/** 时长(分钟,Y轴) */
|
||||
private Long durationMin;
|
||||
/** 关联的actionId(可选) */
|
||||
private String actionId;
|
||||
/** 创建时间 */
|
||||
private String createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拟合线端点
|
||||
*/
|
||||
@Data
|
||||
public static class RegressionLinePointVo {
|
||||
/** 重量(吨,X轴) */
|
||||
private BigDecimal weightTon;
|
||||
/** 卷数(X轴) */
|
||||
private Long coilCount;
|
||||
/** 时长(分钟,Y轴) */
|
||||
private BigDecimal durationMin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import java.util.Date;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.domain.vo;
|
||||
package com.klp.pocket.acid.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.klp.pocket.acid.mapper;
|
||||
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeRegressionVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 酸轧线OEE Mapper接口
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-01-30
|
||||
*/
|
||||
@Mapper
|
||||
public interface AcidOeeMapper {
|
||||
|
||||
/**
|
||||
* 查询OEE日汇总(按日期范围)
|
||||
* 聚合产量(吨/卷)、停机时间等
|
||||
*
|
||||
* @param startDate 开始日期(yyyy-MM-dd)
|
||||
* @param endDate 结束日期(yyyy-MM-dd)
|
||||
* @return 日汇总列表
|
||||
*/
|
||||
List<AcidOeeDailySummaryVo> selectDailySummary(@Param("startDate") String startDate,
|
||||
@Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 查询回归数据散点(用于理论节拍计算)
|
||||
* 返回:重量(吨)、卷数、时长(分钟)等
|
||||
*
|
||||
* @param startDate 开始日期(yyyy-MM-dd,可选)
|
||||
* @param endDate 结束日期(yyyy-MM-dd,可选)
|
||||
* @return 散点列表
|
||||
*/
|
||||
List<AcidOeeRegressionVo.RegressionPointVo> selectRegressionPoints(@Param("startDate") String startDate,
|
||||
@Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 查询每日的钢卷号和重量(用于良品/次品判定)
|
||||
*
|
||||
* @param startDate 开始日期(yyyy-MM-dd)
|
||||
* @param endDate 结束日期(yyyy-MM-dd)
|
||||
* @return Map列表,key为日期,value为卷号和重量信息
|
||||
*/
|
||||
List<CoilInfoByDate> selectCoilInfoByDate(@Param("startDate") String startDate,
|
||||
@Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 卷号信息内部类(用于Mapper返回)
|
||||
*/
|
||||
class CoilInfoByDate {
|
||||
private String statDate;
|
||||
private String coilNo;
|
||||
private java.math.BigDecimal weight;
|
||||
|
||||
public String getStatDate() { return statDate; }
|
||||
public void setStatDate(String statDate) { this.statDate = statDate; }
|
||||
public String getCoilNo() { return coilNo; }
|
||||
public void setCoilNo(String coilNo) { this.coilNo = coilNo; }
|
||||
public java.math.BigDecimal getWeight() { return weight; }
|
||||
public void setWeight(java.math.BigDecimal weight) { this.weight = weight; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.klp.pocket.mapper;
|
||||
package com.klp.pocket.acid.mapper;
|
||||
|
||||
import com.klp.pocket.domain.vo.ProductionStatisticsVo;
|
||||
import com.klp.pocket.domain.vo.CrewProductionVo;
|
||||
import com.klp.pocket.domain.vo.SpecDistributionVo;
|
||||
import com.klp.pocket.domain.vo.TeamPerformanceVo;
|
||||
import com.klp.pocket.acid.domain.vo.ProductionStatisticsVo;
|
||||
import com.klp.pocket.acid.domain.vo.CrewProductionVo;
|
||||
import com.klp.pocket.acid.domain.vo.SpecDistributionVo;
|
||||
import com.klp.pocket.acid.domain.vo.TeamPerformanceVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package com.klp.pocket.mapper;
|
||||
package com.klp.pocket.acid.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateCurrent;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateCurrent;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.klp.pocket.mapper;
|
||||
package com.klp.pocket.acid.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateDefine;
|
||||
import com.klp.pocket.domain.vo.PlantStateWithValueVo;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateDefine;
|
||||
import com.klp.pocket.acid.domain.vo.PlantStateWithValueVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.klp.pocket.mapper;
|
||||
package com.klp.pocket.acid.mapper;
|
||||
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateHistory;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ProPlantStateHistoryVo;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateHistory;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProPlantStateHistoryVo;
|
||||
import com.klp.common.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.klp.pocket.mapper;
|
||||
package com.klp.pocket.acid.mapper;
|
||||
|
||||
import com.klp.pocket.domain.Klptcm1ProStoppage;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProStoppage;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.common.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.klp.pocket.mapper;
|
||||
package com.klp.pocket.acid.mapper;
|
||||
|
||||
import com.klp.pocket.domain.Klptcm1ShiftCurrent;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ShiftCurrentVo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ShiftCurrentVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.klp.pocket.acid.service;
|
||||
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeRegressionVo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 酸轧线OEE Service接口
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-01-30
|
||||
*/
|
||||
public interface IAcidOeeService {
|
||||
|
||||
/**
|
||||
* 查询OEE日汇总(按日期范围)
|
||||
* 包含:产量(吨/卷)、停机时间、良品/次品、派生指标等
|
||||
*
|
||||
* @param startDate 开始日期(yyyy-MM-dd)
|
||||
* @param endDate 结束日期(yyyy-MM-dd)
|
||||
* @return 日汇总列表(按日期排序)
|
||||
*/
|
||||
List<AcidOeeDailySummaryVo> getDailySummary(String startDate, String endDate);
|
||||
|
||||
/**
|
||||
* 查询停机事件列表(用于OEE明细和7大损失)
|
||||
*
|
||||
* @param startDate 开始日期(yyyy-MM-dd)
|
||||
* @param endDate 结束日期(yyyy-MM-dd)
|
||||
* @return 停机事件列表
|
||||
*/
|
||||
List<Klptcm1ProStoppageVo> getStoppageEvents(String startDate, String endDate);
|
||||
|
||||
/**
|
||||
* 查询理论节拍回归数据(吨和卷两个维度)
|
||||
* 用于性能稼动率计算和前端散点图展示
|
||||
*
|
||||
* @param startDate 开始日期(yyyy-MM-dd,可选,默认近6个月)
|
||||
* @param endDate 结束日期(yyyy-MM-dd,可选)
|
||||
* @return 回归数据(包含斜率、截距、散点等)
|
||||
*/
|
||||
AcidOeeRegressionVo getRegressionData(String startDate, String endDate);
|
||||
|
||||
/**
|
||||
* 查询7大损失汇总(按日期范围)
|
||||
*
|
||||
* @param startDate 开始日期(yyyy-MM-dd)
|
||||
* @param endDate 结束日期(yyyy-MM-dd)
|
||||
* @return 7大损失汇总列表
|
||||
*/
|
||||
List<AcidOeeLoss7Vo> getLoss7Summary(String startDate, String endDate);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.klp.pocket.service;
|
||||
package com.klp.pocket.acid.service;
|
||||
|
||||
import com.klp.pocket.domain.vo.ProductionStatisticsVo;
|
||||
import com.klp.pocket.domain.vo.CrewProductionVo;
|
||||
import com.klp.pocket.domain.vo.SpecDistributionVo;
|
||||
import com.klp.pocket.domain.vo.TeamPerformanceVo;
|
||||
import com.klp.pocket.acid.domain.vo.ProductionStatisticsVo;
|
||||
import com.klp.pocket.acid.domain.vo.CrewProductionVo;
|
||||
import com.klp.pocket.acid.domain.vo.SpecDistributionVo;
|
||||
import com.klp.pocket.acid.domain.vo.TeamPerformanceVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.klp.pocket.service;
|
||||
package com.klp.pocket.acid.service;
|
||||
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateCurrent;
|
||||
import java.util.List;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateCurrent;
|
||||
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.klp.pocket.service;
|
||||
package com.klp.pocket.acid.service;
|
||||
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateDefine;
|
||||
import com.klp.pocket.domain.vo.PlantStateWithValueVo;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateDefine;
|
||||
import com.klp.pocket.acid.domain.vo.PlantStateWithValueVo;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.klp.pocket.service;
|
||||
package com.klp.pocket.acid.service;
|
||||
|
||||
import com.klp.pocket.domain.vo.Klptcm1ProPlantStateHistoryVo;
|
||||
import com.klp.pocket.domain.bo.Klptcm1ProPlantStateHistoryBo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProPlantStateHistoryVo;
|
||||
import com.klp.pocket.acid.domain.bo.Klptcm1ProPlantStateHistoryBo;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.klp.pocket.service;
|
||||
package com.klp.pocket.acid.service;
|
||||
|
||||
import com.klp.pocket.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.domain.bo.Klptcm1ProStoppageBo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.acid.domain.bo.Klptcm1ProStoppageBo;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.klp.pocket.service;
|
||||
package com.klp.pocket.acid.service;
|
||||
|
||||
import com.klp.pocket.domain.vo.Klptcm1ShiftCurrentVo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ShiftCurrentVo;
|
||||
|
||||
/**
|
||||
* 当前班组Service接口
|
||||
@@ -0,0 +1,503 @@
|
||||
package com.klp.pocket.acid.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.klp.common.utils.StringUtils;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
|
||||
import com.klp.pocket.acid.domain.vo.AcidOeeRegressionVo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.acid.domain.bo.Klptcm1ProStoppageBo;
|
||||
import com.klp.pocket.acid.mapper.AcidOeeMapper;
|
||||
import com.klp.pocket.acid.service.IAcidOeeService;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProStoppageService;
|
||||
import com.klp.pocket.common.service.ICoilQualityJudgeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 酸轧线OEE Service实现类
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-01-30
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@DS("acid")
|
||||
@Service
|
||||
public class AcidOeeServiceImpl implements IAcidOeeService {
|
||||
|
||||
/** 酸轧成品库库区ID */
|
||||
private static final Long ACID_FINISHED_WAREHOUSE_ID = 1988150099140866050L;
|
||||
|
||||
private final AcidOeeMapper acidOeeMapper;
|
||||
private final IKlptcm1ProStoppageService stoppageService;
|
||||
private final ICoilQualityJudgeService coilQualityJudgeService;
|
||||
|
||||
@Override
|
||||
public List<AcidOeeDailySummaryVo> getDailySummary(String startDate, String endDate) {
|
||||
// 1. 查询基础日汇总(产量、停机时间等)
|
||||
List<AcidOeeDailySummaryVo> summaries = acidOeeMapper.selectDailySummary(startDate, endDate);
|
||||
|
||||
if (summaries == null || summaries.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 2. 查询停机事件,按日期聚合停机时间
|
||||
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate);
|
||||
|
||||
// 3. 查询产量明细,用于良品/次品判定
|
||||
Map<String, List<CoilInfo>> coilInfoByDate = getCoilNosByDate(startDate, endDate);
|
||||
|
||||
// 4. 填充每个日汇总的完整数据
|
||||
for (AcidOeeDailySummaryVo summary : summaries) {
|
||||
String statDate = summary.getStatDate();
|
||||
summary.setLineId("SY");
|
||||
summary.setLineName("酸轧线");
|
||||
|
||||
// 填充停机时间
|
||||
Long downtime = downtimeByDate.getOrDefault(statDate, 0L);
|
||||
summary.setDowntimeMin(downtime);
|
||||
|
||||
// 计算运转时间
|
||||
Long loadingTime = summary.getLoadingTimeMin() != null ? summary.getLoadingTimeMin() : 0L;
|
||||
Long runTime = Math.max(0, loadingTime - downtime);
|
||||
summary.setRunTimeMin(runTime);
|
||||
|
||||
// 良品/次品判定(通过WMS)
|
||||
if (coilInfoByDate.containsKey(statDate)) {
|
||||
List<CoilInfo> coilInfos = coilInfoByDate.get(statDate);
|
||||
calculateQualityOutput(summary, coilInfos);
|
||||
} else {
|
||||
// 如果没有卷号,默认全部为良品(或根据业务规则处理)
|
||||
summary.setGoodOutputTon(summary.getTotalOutputTon());
|
||||
summary.setGoodOutputCoil(summary.getTotalOutputCoil());
|
||||
summary.setDefectOutputTon(BigDecimal.ZERO);
|
||||
summary.setDefectOutputCoil(0L);
|
||||
}
|
||||
|
||||
// 填充理论节拍(从回归数据或缓存获取,这里暂时留空,由调用方填充)
|
||||
// summary.setIdealCycleTimeMinPerTon(...);
|
||||
// summary.setIdealCycleTimeMinPerCoil(...);
|
||||
|
||||
// 计算派生指标
|
||||
calculateDerivedMetrics(summary);
|
||||
}
|
||||
|
||||
return summaries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Klptcm1ProStoppageVo> getStoppageEvents(String startDate, String endDate) {
|
||||
Klptcm1ProStoppageBo bo = new Klptcm1ProStoppageBo();
|
||||
bo.setStartDate(parseDate(startDate));
|
||||
bo.setEndDate(parseDate(endDate));
|
||||
return stoppageService.queryList(bo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AcidOeeRegressionVo getRegressionData(String startDate, String endDate) {
|
||||
// 1. 查询散点数据
|
||||
List<AcidOeeRegressionVo.RegressionPointVo> points = acidOeeMapper.selectRegressionPoints(startDate, endDate);
|
||||
|
||||
AcidOeeRegressionVo result = new AcidOeeRegressionVo();
|
||||
result.setLineId("SY");
|
||||
result.setLineName("酸轧线");
|
||||
result.setStartTime(startDate);
|
||||
result.setEndTime(endDate);
|
||||
result.setPoints(points);
|
||||
result.setSampleCount(points != null ? points.size() : 0);
|
||||
|
||||
if (points == null || points.isEmpty()) {
|
||||
// 没有数据时返回空结果
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 计算回归(吨维度)
|
||||
RegressionResult tonResult = calculateRegression(
|
||||
points.stream().map(AcidOeeRegressionVo.RegressionPointVo::getWeightTon).filter(Objects::nonNull).collect(Collectors.toList()),
|
||||
points.stream().map(AcidOeeRegressionVo.RegressionPointVo::getDurationMin).filter(Objects::nonNull).collect(Collectors.toList())
|
||||
);
|
||||
if (tonResult != null) {
|
||||
result.setSlopeMinPerTon(tonResult.slope);
|
||||
result.setInterceptMin(tonResult.intercept);
|
||||
result.setR2(tonResult.r2);
|
||||
}
|
||||
|
||||
// 3. 计算回归(卷维度)
|
||||
RegressionResult coilResult = calculateRegression(
|
||||
points.stream().map(p -> p.getCoilCount() != null ? BigDecimal.valueOf(p.getCoilCount()) : null).filter(Objects::nonNull).collect(Collectors.toList()),
|
||||
points.stream().map(AcidOeeRegressionVo.RegressionPointVo::getDurationMin).filter(Objects::nonNull).collect(Collectors.toList())
|
||||
);
|
||||
if (coilResult != null) {
|
||||
result.setSlopeMinPerCoil(coilResult.slope);
|
||||
}
|
||||
|
||||
// 4. 生成拟合线端点(用于前端画线)
|
||||
if (tonResult != null && !points.isEmpty()) {
|
||||
List<AcidOeeRegressionVo.RegressionLinePointVo> linePoints = generateLinePoints(points, tonResult);
|
||||
result.setLinePoints(linePoints);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AcidOeeLoss7Vo> getLoss7Summary(String startDate, String endDate) {
|
||||
// 1. 查询停机事件(含 stopType、duration 等)
|
||||
List<Klptcm1ProStoppageVo> events = getStoppageEvents(startDate, endDate);
|
||||
if (events == null || events.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 2. 按 stopType 分组汇总
|
||||
Map<String, LossStats> statsByType = new HashMap<>();
|
||||
long totalLossMin = 0L;
|
||||
|
||||
for (Klptcm1ProStoppageVo event : events) {
|
||||
String stopType = event.getStopType();
|
||||
if (StringUtils.isBlank(stopType)) {
|
||||
// 没有类型的记录暂时忽略
|
||||
continue;
|
||||
}
|
||||
Long durationSec = event.getDuration();
|
||||
if (durationSec == null || durationSec <= 0) {
|
||||
continue;
|
||||
}
|
||||
long durationMin = durationSec / 60;
|
||||
if (durationMin <= 0) {
|
||||
durationMin = 1; // 最小记 1 分钟,避免全为 0
|
||||
}
|
||||
|
||||
LossStats stats = statsByType.computeIfAbsent(stopType, k -> new LossStats());
|
||||
stats.totalMin += durationMin;
|
||||
stats.count++;
|
||||
totalLossMin += durationMin;
|
||||
}
|
||||
|
||||
if (statsByType.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 3. 组装 VO 列表
|
||||
List<AcidOeeLoss7Vo> result = new ArrayList<>();
|
||||
for (Map.Entry<String, LossStats> entry : statsByType.entrySet()) {
|
||||
String stopType = entry.getKey();
|
||||
LossStats stats = entry.getValue();
|
||||
|
||||
AcidOeeLoss7Vo vo = new AcidOeeLoss7Vo();
|
||||
vo.setLossCategoryCode(stopType);
|
||||
vo.setLossCategoryName(stopType);
|
||||
vo.setLossTimeMin(stats.totalMin);
|
||||
|
||||
if (totalLossMin > 0) {
|
||||
BigDecimal rate = BigDecimal.valueOf(stats.totalMin)
|
||||
.divide(BigDecimal.valueOf(totalLossMin), 4, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
vo.setLossTimeRate(rate);
|
||||
} else {
|
||||
vo.setLossTimeRate(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
vo.setCount(stats.count);
|
||||
if (stats.count > 0) {
|
||||
BigDecimal avg = BigDecimal.valueOf(stats.totalMin)
|
||||
.divide(BigDecimal.valueOf(stats.count), 2, RoundingMode.HALF_UP);
|
||||
vo.setAvgDurationMin(avg);
|
||||
} else {
|
||||
vo.setAvgDurationMin(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
result.add(vo);
|
||||
}
|
||||
|
||||
// 4. 按损失时间从大到小排序
|
||||
result.sort(Comparator.comparingLong(AcidOeeLoss7Vo::getLossTimeMin).reversed());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按日期聚合停机时间
|
||||
*/
|
||||
private Map<String, Long> aggregateDowntimeByDate(String startDate, String endDate) {
|
||||
List<Klptcm1ProStoppageVo> events = getStoppageEvents(startDate, endDate);
|
||||
Map<String, Long> downtimeMap = new HashMap<>();
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
for (Klptcm1ProStoppageVo event : events) {
|
||||
if (event.getStartDate() != null && event.getDuration() != null) {
|
||||
String date = dateFormat.format(event.getStartDate());
|
||||
// duration单位是秒,转换为分钟
|
||||
Long minutes = event.getDuration() / 60;
|
||||
downtimeMap.merge(date, minutes, Long::sum);
|
||||
}
|
||||
}
|
||||
|
||||
return downtimeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取每日的钢卷号和重量(用于良品/次品判定)
|
||||
*/
|
||||
private Map<String, List<CoilInfo>> getCoilNosByDate(String startDate, String endDate) {
|
||||
List<AcidOeeMapper.CoilInfoByDate> coilInfoList = acidOeeMapper.selectCoilInfoByDate(startDate, endDate);
|
||||
Map<String, List<CoilInfo>> result = new HashMap<>();
|
||||
|
||||
for (AcidOeeMapper.CoilInfoByDate info : coilInfoList) {
|
||||
String date = info.getStatDate();
|
||||
result.computeIfAbsent(date, k -> new ArrayList<>())
|
||||
.add(new CoilInfo(info.getCoilNo(), info.getWeight()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 卷号信息内部类
|
||||
*/
|
||||
private static class CoilInfo {
|
||||
final String coilNo;
|
||||
final BigDecimal weight;
|
||||
|
||||
CoilInfo(String coilNo, BigDecimal weight) {
|
||||
this.coilNo = coilNo;
|
||||
this.weight = weight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算良品/次品产量
|
||||
*/
|
||||
private void calculateQualityOutput(AcidOeeDailySummaryVo summary, List<CoilInfo> coilInfos) {
|
||||
BigDecimal goodTon = BigDecimal.ZERO;
|
||||
long goodCoil = 0L;
|
||||
BigDecimal defectTon = BigDecimal.ZERO;
|
||||
long defectCoil = 0L;
|
||||
|
||||
for (CoilInfo coilInfo : coilInfos) {
|
||||
String coilNo = coilInfo.coilNo;
|
||||
BigDecimal coilWeight = coilInfo.weight != null ? coilInfo.weight : BigDecimal.ZERO;
|
||||
|
||||
// 通过WMS判定良品/次品
|
||||
Boolean isScrap = coilQualityJudgeService.isScrap(ACID_FINISHED_WAREHOUSE_ID, coilNo);
|
||||
if (isScrap == null) {
|
||||
// 匹配不到,忽略不计
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(isScrap)) {
|
||||
// 次品
|
||||
defectTon = defectTon.add(coilWeight);
|
||||
defectCoil++;
|
||||
} else {
|
||||
// 良品
|
||||
goodTon = goodTon.add(coilWeight);
|
||||
goodCoil++;
|
||||
}
|
||||
}
|
||||
|
||||
summary.setGoodOutputTon(goodTon);
|
||||
summary.setGoodOutputCoil(goodCoil);
|
||||
summary.setDefectOutputTon(defectTon);
|
||||
summary.setDefectOutputCoil(defectCoil);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算派生指标(时间稼动率、性能稼动率、良品率、OEE)
|
||||
*/
|
||||
private void calculateDerivedMetrics(AcidOeeDailySummaryVo summary) {
|
||||
// 时间稼动率
|
||||
Long loadingTime = summary.getLoadingTimeMin() != null ? summary.getLoadingTimeMin() : 0L;
|
||||
Long downtime = summary.getDowntimeMin() != null ? summary.getDowntimeMin() : 0L;
|
||||
if (loadingTime > 0) {
|
||||
BigDecimal availability = BigDecimal.valueOf(loadingTime - downtime)
|
||||
.divide(BigDecimal.valueOf(loadingTime), 4, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
summary.setAvailability(availability);
|
||||
}
|
||||
|
||||
// 性能稼动率(吨维度)
|
||||
Long runTime = summary.getRunTimeMin() != null ? summary.getRunTimeMin() : 0L;
|
||||
BigDecimal idealCycleTon = summary.getIdealCycleTimeMinPerTon();
|
||||
BigDecimal totalOutputTon = summary.getTotalOutputTon();
|
||||
if (runTime > 0 && idealCycleTon != null && totalOutputTon != null && totalOutputTon.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal idealTime = idealCycleTon.multiply(totalOutputTon);
|
||||
BigDecimal performanceTon = idealTime.divide(BigDecimal.valueOf(runTime), 4, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
summary.setPerformanceTon(performanceTon);
|
||||
}
|
||||
|
||||
// 性能稼动率(卷维度)
|
||||
Long totalOutputCoil = summary.getTotalOutputCoil() != null ? summary.getTotalOutputCoil() : 0L;
|
||||
BigDecimal idealCycleCoil = summary.getIdealCycleTimeMinPerCoil();
|
||||
if (runTime > 0 && idealCycleCoil != null && totalOutputCoil > 0) {
|
||||
BigDecimal idealTime = idealCycleCoil.multiply(BigDecimal.valueOf(totalOutputCoil));
|
||||
BigDecimal performanceCoil = idealTime.divide(BigDecimal.valueOf(runTime), 4, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
summary.setPerformanceCoil(performanceCoil);
|
||||
}
|
||||
|
||||
// 良品率
|
||||
if (totalOutputTon != null && totalOutputTon.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal goodOutputTon = summary.getGoodOutputTon() != null ? summary.getGoodOutputTon() : BigDecimal.ZERO;
|
||||
BigDecimal quality = goodOutputTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
summary.setQuality(quality);
|
||||
}
|
||||
|
||||
// OEE(以吨维度为主)
|
||||
BigDecimal availability = summary.getAvailability();
|
||||
BigDecimal performanceTon = summary.getPerformanceTon();
|
||||
BigDecimal quality = summary.getQuality();
|
||||
if (availability != null && performanceTon != null && quality != null) {
|
||||
BigDecimal oee = availability.multiply(performanceTon).multiply(quality)
|
||||
.divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP);
|
||||
summary.setOee(oee);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算线性回归(最小二乘法)
|
||||
*/
|
||||
private RegressionResult calculateRegression(List<BigDecimal> xValues, List<Long> yValues) {
|
||||
if (xValues.size() != yValues.size() || xValues.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int n = xValues.size();
|
||||
BigDecimal sumX = BigDecimal.ZERO;
|
||||
BigDecimal sumY = BigDecimal.ZERO;
|
||||
BigDecimal sumXY = BigDecimal.ZERO;
|
||||
BigDecimal sumX2 = BigDecimal.ZERO;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
BigDecimal x = xValues.get(i);
|
||||
BigDecimal y = BigDecimal.valueOf(yValues.get(i));
|
||||
sumX = sumX.add(x);
|
||||
sumY = sumY.add(y);
|
||||
sumXY = sumXY.add(x.multiply(y));
|
||||
sumX2 = sumX2.add(x.multiply(x));
|
||||
}
|
||||
|
||||
BigDecimal nDecimal = BigDecimal.valueOf(n);
|
||||
BigDecimal denominator = nDecimal.multiply(sumX2).subtract(sumX.multiply(sumX));
|
||||
if (denominator.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// slope = (n*ΣXY - ΣX*ΣY) / (n*ΣX² - (ΣX)²)
|
||||
BigDecimal slope = nDecimal.multiply(sumXY).subtract(sumX.multiply(sumY))
|
||||
.divide(denominator, 6, RoundingMode.HALF_UP);
|
||||
|
||||
// intercept = (ΣY - slope*ΣX) / n
|
||||
BigDecimal intercept = sumY.subtract(slope.multiply(sumX))
|
||||
.divide(nDecimal, 6, RoundingMode.HALF_UP);
|
||||
|
||||
// 计算R²
|
||||
BigDecimal meanY = sumY.divide(nDecimal, 6, RoundingMode.HALF_UP);
|
||||
BigDecimal ssTotal = BigDecimal.ZERO;
|
||||
BigDecimal ssResidual = BigDecimal.ZERO;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
BigDecimal x = xValues.get(i);
|
||||
BigDecimal y = BigDecimal.valueOf(yValues.get(i));
|
||||
BigDecimal predictedY = slope.multiply(x).add(intercept);
|
||||
BigDecimal diff = y.subtract(meanY);
|
||||
ssTotal = ssTotal.add(diff.multiply(diff));
|
||||
BigDecimal residual = y.subtract(predictedY);
|
||||
ssResidual = ssResidual.add(residual.multiply(residual));
|
||||
}
|
||||
|
||||
BigDecimal r2 = BigDecimal.ONE;
|
||||
if (ssTotal.compareTo(BigDecimal.ZERO) > 0) {
|
||||
r2 = BigDecimal.ONE.subtract(ssResidual.divide(ssTotal, 6, RoundingMode.HALF_UP));
|
||||
}
|
||||
|
||||
return new RegressionResult(slope, intercept, r2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成拟合线端点
|
||||
*/
|
||||
private List<AcidOeeRegressionVo.RegressionLinePointVo> generateLinePoints(
|
||||
List<AcidOeeRegressionVo.RegressionPointVo> points,
|
||||
RegressionResult result) {
|
||||
if (points.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 找到X轴的最小值和最大值
|
||||
BigDecimal minX = points.stream()
|
||||
.map(AcidOeeRegressionVo.RegressionPointVo::getWeightTon)
|
||||
.filter(Objects::nonNull)
|
||||
.min(BigDecimal::compareTo)
|
||||
.orElse(BigDecimal.ZERO);
|
||||
|
||||
BigDecimal maxX = points.stream()
|
||||
.map(AcidOeeRegressionVo.RegressionPointVo::getWeightTon)
|
||||
.filter(Objects::nonNull)
|
||||
.max(BigDecimal::compareTo)
|
||||
.orElse(BigDecimal.ZERO);
|
||||
|
||||
// 计算对应的Y值
|
||||
BigDecimal y1 = result.slope.multiply(minX).add(result.intercept);
|
||||
BigDecimal y2 = result.slope.multiply(maxX).add(result.intercept);
|
||||
|
||||
AcidOeeRegressionVo.RegressionLinePointVo p1 = new AcidOeeRegressionVo.RegressionLinePointVo();
|
||||
p1.setWeightTon(minX);
|
||||
p1.setDurationMin(y1);
|
||||
|
||||
AcidOeeRegressionVo.RegressionLinePointVo p2 = new AcidOeeRegressionVo.RegressionLinePointVo();
|
||||
p2.setWeightTon(maxX);
|
||||
p2.setDurationMin(y2);
|
||||
|
||||
return Arrays.asList(p1, p2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期字符串为Date对象
|
||||
*/
|
||||
private Date parseDate(String dateStr) {
|
||||
if (StringUtils.isBlank(dateStr)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
return sdf.parse(dateStr);
|
||||
} catch (Exception e) {
|
||||
log.warn("解析日期失败: {}", dateStr, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 回归结果内部类
|
||||
*/
|
||||
private static class RegressionResult {
|
||||
final BigDecimal slope;
|
||||
final BigDecimal intercept;
|
||||
final BigDecimal r2;
|
||||
|
||||
RegressionResult(BigDecimal slope, BigDecimal intercept, BigDecimal r2) {
|
||||
this.slope = slope;
|
||||
this.intercept = intercept;
|
||||
this.r2 = r2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部统计类:某一 stopType 的总损失时间与次数
|
||||
*/
|
||||
private static class LossStats {
|
||||
long totalMin = 0L;
|
||||
int count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.klp.pocket.service.impl;
|
||||
package com.klp.pocket.acid.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.klp.pocket.domain.vo.ProductionStatisticsVo;
|
||||
import com.klp.pocket.domain.vo.CrewProductionVo;
|
||||
import com.klp.pocket.domain.vo.SpecDistributionVo;
|
||||
import com.klp.pocket.domain.vo.TeamPerformanceVo;
|
||||
import com.klp.pocket.mapper.Klptcm1PdoExcoilMapper;
|
||||
import com.klp.pocket.service.IKlptcm1PdoExcoilService;
|
||||
import com.klp.pocket.acid.domain.vo.ProductionStatisticsVo;
|
||||
import com.klp.pocket.acid.domain.vo.CrewProductionVo;
|
||||
import com.klp.pocket.acid.domain.vo.SpecDistributionVo;
|
||||
import com.klp.pocket.acid.domain.vo.TeamPerformanceVo;
|
||||
import com.klp.pocket.acid.mapper.Klptcm1PdoExcoilMapper;
|
||||
import com.klp.pocket.acid.service.IKlptcm1PdoExcoilService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.List;
|
||||
* 生产统计Service实现类
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@DS("slave")
|
||||
@DS("acid")
|
||||
@Service
|
||||
public class Klptcm1PdoExcoilServiceImpl implements IKlptcm1PdoExcoilService {
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
package com.klp.pocket.service.impl;
|
||||
package com.klp.pocket.acid.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateCurrent;
|
||||
import com.klp.pocket.mapper.Klptcm1ProPlantStateCurrentMapper;
|
||||
import com.klp.pocket.service.IKlptcm1ProPlantStateCurrentService;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateCurrent;
|
||||
import com.klp.pocket.acid.mapper.Klptcm1ProPlantStateCurrentMapper;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProPlantStateCurrentService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@DS("slave")
|
||||
@DS("acid")
|
||||
@Service
|
||||
public class Klptcm1ProPlantStateCurrentServiceImpl implements IKlptcm1ProPlantStateCurrentService {
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
package com.klp.pocket.service.impl;
|
||||
package com.klp.pocket.acid.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateCurrent;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateDefine;
|
||||
import com.klp.pocket.domain.vo.PlantStateWithValueVo;
|
||||
import com.klp.pocket.mapper.Klptcm1ProPlantStateDefineMapper;
|
||||
import com.klp.pocket.service.IKlptcm1ProPlantStateDefineService;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateDefine;
|
||||
import com.klp.pocket.acid.domain.vo.PlantStateWithValueVo;
|
||||
import com.klp.pocket.acid.mapper.Klptcm1ProPlantStateDefineMapper;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProPlantStateDefineService;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 工厂状态定义表Service实现类
|
||||
* 具体业务逻辑实现,依赖Mapper操作数据库
|
||||
*/
|
||||
@DS("slave")
|
||||
@DS("acid")
|
||||
@Service
|
||||
public class Klptcm1ProPlantStateDefineServiceImpl implements IKlptcm1ProPlantStateDefineService {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.service.impl;
|
||||
package com.klp.pocket.acid.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
@@ -9,11 +9,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.klp.pocket.domain.bo.Klptcm1ProPlantStateHistoryBo;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ProPlantStateHistoryVo;
|
||||
import com.klp.pocket.domain.Klptcm1ProPlantStateHistory;
|
||||
import com.klp.pocket.mapper.Klptcm1ProPlantStateHistoryMapper;
|
||||
import com.klp.pocket.service.IKlptcm1ProPlantStateHistoryService;
|
||||
import com.klp.pocket.acid.domain.bo.Klptcm1ProPlantStateHistoryBo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProPlantStateHistoryVo;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProPlantStateHistory;
|
||||
import com.klp.pocket.acid.mapper.Klptcm1ProPlantStateHistoryMapper;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProPlantStateHistoryService;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
@@ -27,7 +27,7 @@ import java.util.Map;
|
||||
* @date 2025-10-27
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@DS("slave")
|
||||
@DS("acid")
|
||||
@Service
|
||||
public class Klptcm1ProPlantStateHistoryServiceImpl implements IKlptcm1ProPlantStateHistoryService {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.klp.pocket.service.impl;
|
||||
package com.klp.pocket.acid.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
@@ -10,11 +10,11 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.klp.common.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.klp.pocket.domain.bo.Klptcm1ProStoppageBo;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.domain.Klptcm1ProStoppage;
|
||||
import com.klp.pocket.mapper.Klptcm1ProStoppageMapper;
|
||||
import com.klp.pocket.service.IKlptcm1ProStoppageService;
|
||||
import com.klp.pocket.acid.domain.bo.Klptcm1ProStoppageBo;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
|
||||
import com.klp.pocket.acid.domain.Klptcm1ProStoppage;
|
||||
import com.klp.pocket.acid.mapper.Klptcm1ProStoppageMapper;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ProStoppageService;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -32,7 +32,7 @@ import java.util.Map;
|
||||
* @date 2025-10-27
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@DS("slave")
|
||||
@DS("acid")
|
||||
@Service
|
||||
public class Klptcm1ProStoppageServiceImpl implements IKlptcm1ProStoppageService {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.klp.pocket.service.impl;
|
||||
package com.klp.pocket.acid.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.klp.pocket.domain.vo.Klptcm1ShiftCurrentVo;
|
||||
import com.klp.pocket.mapper.Klptcm1ShiftCurrentMapper;
|
||||
import com.klp.pocket.service.IKlptcm1ShiftCurrentService;
|
||||
import com.klp.pocket.acid.domain.vo.Klptcm1ShiftCurrentVo;
|
||||
import com.klp.pocket.acid.mapper.Klptcm1ShiftCurrentMapper;
|
||||
import com.klp.pocket.acid.service.IKlptcm1ShiftCurrentService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
|
||||
* 当前班组Service实现类
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@DS("slave")
|
||||
@DS("acid")
|
||||
@Service
|
||||
public class Klptcm1ShiftCurrentServiceImpl implements IKlptcm1ShiftCurrentService {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.klp.pocket.common.service;
|
||||
|
||||
/**
|
||||
* 钢卷良品/次品判定(OEE 口径用)。
|
||||
*
|
||||
* 规则:
|
||||
* - 以 WMS 的 wms_material_coil 为准
|
||||
* - 按“当前钢卷号(current_coil_no) + 所在库区ID(warehouse_id)”精确匹配
|
||||
* - quality_status 命中 {"C+","C","C-","D+","D","D-"} => 次品;否则 => 良品
|
||||
* - 若匹配不到(WMS 无记录),返回 null,调用方按“忽略不计”处理
|
||||
*/
|
||||
public interface ICoilQualityJudgeService {
|
||||
|
||||
/**
|
||||
* @param warehouseId 所在库区ID(成品库库区ID)
|
||||
* @param currentCoilNo 当前钢卷号(注意:pocket 侧查询到的“钢卷id/卷号”口径等同于该字段)
|
||||
* @return Boolean:true=次品,false=良品,null=匹配不到(忽略不计)
|
||||
*/
|
||||
Boolean isScrap(Long warehouseId, String currentCoilNo);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.klp.pocket.common.service.impl;
|
||||
|
||||
import com.klp.common.utils.StringUtils;
|
||||
import com.klp.pocket.common.service.ICoilQualityJudgeService;
|
||||
import com.klp.service.IWmsMaterialCoilService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class CoilQualityJudgeServiceImpl implements ICoilQualityJudgeService {
|
||||
|
||||
/**
|
||||
* 次品状态枚举:命中这些 quality_status 则判定为次品,否则判定为良品。
|
||||
*/
|
||||
private static final Set<String> SCRAP_QUALITY_STATUS = new HashSet<>(
|
||||
Arrays.asList("C+", "C", "C-", "D+", "D", "D-")
|
||||
);
|
||||
|
||||
private final IWmsMaterialCoilService wmsMaterialCoilService;
|
||||
|
||||
@Override
|
||||
public Boolean isScrap(Long warehouseId, String currentCoilNo) {
|
||||
if (warehouseId == null || StringUtils.isBlank(currentCoilNo)) {
|
||||
return null;
|
||||
}
|
||||
String qualityStatus = wmsMaterialCoilService
|
||||
.queryQualityStatusByWarehouseIdAndCurrentCoilNo(warehouseId, currentCoilNo);
|
||||
if (StringUtils.isBlank(qualityStatus)) {
|
||||
// WMS 匹配不到或字段为空:按“忽略不计”
|
||||
return null;
|
||||
}
|
||||
return SCRAP_QUALITY_STATUS.contains(qualityStatus.trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.CplSegmentTotalBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.CplSegmentTotalVo;
|
||||
import com.klp.pocket.galvanize1.service.ICplSegmentTotalService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/cplSegmentTotal")
|
||||
public class CplSegmentTotalController extends BaseController {
|
||||
|
||||
private final ICplSegmentTotalService iCplSegmentTotalService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<CplSegmentTotalVo> list(CplSegmentTotalBo bo, PageQuery pageQuery) {
|
||||
return iCplSegmentTotalService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R<CplSegmentTotalVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
|
||||
return R.ok(iCplSegmentTotalService.queryById(id));
|
||||
}
|
||||
|
||||
@Log(title = "带钢段工艺参数汇总", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody CplSegmentTotalBo bo) {
|
||||
return toAjax(iCplSegmentTotalService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "带钢段工艺参数汇总", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CplSegmentTotalBo bo) {
|
||||
return toAjax(iCplSegmentTotalService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "带钢段工艺参数汇总", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
|
||||
return toAjax(iCplSegmentTotalService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.CrmPdiPlanBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.CrmPdiPlanVo;
|
||||
import com.klp.pocket.galvanize1.service.ICrmPdiPlanService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/crmPdiPlan")
|
||||
public class CrmPdiPlanController extends BaseController {
|
||||
|
||||
private final ICrmPdiPlanService iCrmPdiPlanService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<CrmPdiPlanVo> list(CrmPdiPlanBo bo, PageQuery pageQuery) {
|
||||
return iCrmPdiPlanService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R<CrmPdiPlanVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
|
||||
return R.ok(iCrmPdiPlanService.queryById(id));
|
||||
}
|
||||
|
||||
@Log(title = "钢卷计划信息", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody CrmPdiPlanBo bo) {
|
||||
return toAjax(iCrmPdiPlanService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "钢卷计划信息", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CrmPdiPlanBo bo) {
|
||||
return toAjax(iCrmPdiPlanService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "钢卷计划信息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
|
||||
return toAjax(iCrmPdiPlanService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.CrmPdoExcoilBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.CrmPdoExcoilVo;
|
||||
import com.klp.pocket.galvanize1.service.ICrmPdoExcoilService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/crmPdoExcoil")
|
||||
public class CrmPdoExcoilController extends BaseController {
|
||||
|
||||
private final ICrmPdoExcoilService iCrmPdoExcoilService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<CrmPdoExcoilVo> list(CrmPdoExcoilBo bo, PageQuery pageQuery) {
|
||||
return iCrmPdoExcoilService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R<CrmPdoExcoilVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
|
||||
return R.ok(iCrmPdoExcoilService.queryById(id));
|
||||
}
|
||||
|
||||
@Log(title = "钢卷生产数据", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody CrmPdoExcoilBo bo) {
|
||||
return toAjax(iCrmPdoExcoilService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "钢卷生产数据", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CrmPdoExcoilBo bo) {
|
||||
return toAjax(iCrmPdoExcoilService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "钢卷生产数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
|
||||
return toAjax(iCrmPdoExcoilService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.PdiSetupBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.PdiSetupVo;
|
||||
import com.klp.pocket.galvanize1.service.IPdiSetupService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/pdiSetup")
|
||||
public class PdiSetupController extends BaseController {
|
||||
|
||||
private final IPdiSetupService iPdiSetupService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<PdiSetupVo> list(PdiSetupBo bo, PageQuery pageQuery) {
|
||||
return iPdiSetupService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R<PdiSetupVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
|
||||
return R.ok(iPdiSetupService.queryById(id));
|
||||
}
|
||||
|
||||
@Log(title = "张力参数", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody PdiSetupBo bo) {
|
||||
return toAjax(iPdiSetupService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "张力参数", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody PdiSetupBo bo) {
|
||||
return toAjax(iPdiSetupService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "张力参数", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
|
||||
return toAjax(iPdiSetupService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.ProStoppageBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.ProStoppageVo;
|
||||
import com.klp.pocket.galvanize1.service.IProStoppageService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/proStoppage")
|
||||
public class ProStoppageController extends BaseController {
|
||||
|
||||
private final IProStoppageService iProStoppageService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ProStoppageVo> list(ProStoppageBo bo, PageQuery pageQuery) {
|
||||
return iProStoppageService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/{stopid}")
|
||||
public R<ProStoppageVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long stopid) {
|
||||
return R.ok(iProStoppageService.queryById(stopid));
|
||||
}
|
||||
|
||||
@Log(title = "停机", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody ProStoppageBo bo) {
|
||||
return toAjax(iProStoppageService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "停机", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProStoppageBo bo) {
|
||||
return toAjax(iProStoppageService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "停机", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{stopids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] stopids) {
|
||||
return toAjax(iProStoppageService.deleteWithValidByIds(Arrays.asList(stopids), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.ProStoppageTypeBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.ProStoppageTypeVo;
|
||||
import com.klp.pocket.galvanize1.service.IProStoppageTypeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/proStoppageType")
|
||||
public class ProStoppageTypeController extends BaseController {
|
||||
|
||||
private final IProStoppageTypeService iProStoppageTypeService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ProStoppageTypeVo> list(ProStoppageTypeBo bo, PageQuery pageQuery) {
|
||||
return iProStoppageTypeService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/{stopType}")
|
||||
public R<ProStoppageTypeVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Integer stopType) {
|
||||
return R.ok(iProStoppageTypeService.queryById(stopType));
|
||||
}
|
||||
|
||||
@Log(title = "停机类型", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody ProStoppageTypeBo bo) {
|
||||
return toAjax(iProStoppageTypeService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "停机类型", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProStoppageTypeBo bo) {
|
||||
return toAjax(iProStoppageTypeService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "停机类型", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{stopTypes}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Integer[] stopTypes) {
|
||||
return toAjax(iProStoppageTypeService.deleteWithValidByIds(Arrays.asList(stopTypes), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.ShiftConfigBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.ShiftConfigVo;
|
||||
import com.klp.pocket.galvanize1.service.IShiftConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/shiftConfig")
|
||||
public class ShiftConfigController extends BaseController {
|
||||
|
||||
private final IShiftConfigService iShiftConfigService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ShiftConfigVo> list(ShiftConfigBo bo, PageQuery pageQuery) {
|
||||
return iShiftConfigService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R<ShiftConfigVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Integer id) {
|
||||
return R.ok(iShiftConfigService.queryById(id));
|
||||
}
|
||||
|
||||
@Log(title = "班次配置", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody ShiftConfigBo bo) {
|
||||
return toAjax(iShiftConfigService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "班次配置", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ShiftConfigBo bo) {
|
||||
return toAjax(iShiftConfigService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "班次配置", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Integer[] ids) {
|
||||
return toAjax(iShiftConfigService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.ShiftCrewBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.ShiftCrewVo;
|
||||
import com.klp.pocket.galvanize1.service.IShiftCrewService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/shiftCrew")
|
||||
public class ShiftCrewController extends BaseController {
|
||||
|
||||
private final IShiftCrewService iShiftCrewService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ShiftCrewVo> list(ShiftCrewBo bo, PageQuery pageQuery) {
|
||||
return iShiftCrewService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public R<ShiftCrewVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Integer id) {
|
||||
return R.ok(iShiftCrewService.queryById(id));
|
||||
}
|
||||
|
||||
@Log(title = "班次班组", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody ShiftCrewBo bo) {
|
||||
return toAjax(iShiftCrewService.insertByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "班次班组", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ShiftCrewBo bo) {
|
||||
return toAjax(iShiftCrewService.updateByBo(bo));
|
||||
}
|
||||
|
||||
@Log(title = "班次班组", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Integer[] ids) {
|
||||
return toAjax(iShiftCrewService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.klp.pocket.galvanize1.controller;
|
||||
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.pocket.galvanize1.domain.bo.ShiftHistoryBo;
|
||||
import com.klp.pocket.galvanize1.domain.vo.ShiftHistoryVo;
|
||||
import com.klp.pocket.galvanize1.service.IShiftHistoryService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pocket/galvanize1/shiftHistory")
|
||||
public class ShiftHistoryController extends BaseController {
|
||||
|
||||
private final IShiftHistoryService iShiftHistoryService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<ShiftHistoryVo> list(ShiftHistoryBo bo, PageQuery pageQuery) {
|
||||
return iShiftHistoryService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@Log(title = "班次履历", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody ShiftHistoryBo bo) {
|
||||
return toAjax(iShiftHistoryService.insertByBo(bo));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("cpl_segment_total")
|
||||
public class CplSegmentTotal {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String enCoilId;
|
||||
|
||||
private Integer picklingCount;
|
||||
|
||||
private Integer segNo;
|
||||
|
||||
private Double startPos;
|
||||
|
||||
private Double endPos;
|
||||
|
||||
private Double segLen;
|
||||
|
||||
private String totalValuesJson;
|
||||
|
||||
private Date createTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("crm_pdi_plan")
|
||||
public class CrmPdiPlan {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Integer seqid;
|
||||
private String coilid;
|
||||
private Integer dummyCoilFlag;
|
||||
private String status;
|
||||
private String planid;
|
||||
private String planType;
|
||||
|
||||
private java.math.BigDecimal yieldPoint;
|
||||
private java.math.BigDecimal entryWeight;
|
||||
private java.math.BigDecimal entryThick;
|
||||
private java.math.BigDecimal entryWidth;
|
||||
private java.math.BigDecimal entryLength;
|
||||
private java.math.BigDecimal entryOuterDiameter;
|
||||
private java.math.BigDecimal entryInnerDiameter;
|
||||
private java.math.BigDecimal exitInnerDiameter;
|
||||
|
||||
private String steelGrade;
|
||||
private String exitCoilid;
|
||||
private Integer tlvFlag;
|
||||
private String orderNo;
|
||||
private String custommerCode;
|
||||
|
||||
private java.math.BigDecimal orderThick;
|
||||
private java.math.BigDecimal orderWidth;
|
||||
private java.math.BigDecimal orderLenLow;
|
||||
private java.math.BigDecimal orderLenUp;
|
||||
private java.math.BigDecimal orderWt;
|
||||
private java.math.BigDecimal orderWtLow;
|
||||
private java.math.BigDecimal orderWtUp;
|
||||
private java.math.BigDecimal orderMetCoatTop;
|
||||
private java.math.BigDecimal orderMetCoatBot;
|
||||
|
||||
private String finalUse;
|
||||
private String hotCoilCode;
|
||||
|
||||
private java.math.BigDecimal exitLengthTar;
|
||||
private java.math.BigDecimal exitLengthTolMax;
|
||||
private java.math.BigDecimal exitLengthTolMin;
|
||||
private java.math.BigDecimal exitThickTar;
|
||||
private java.math.BigDecimal exitThickTolMax;
|
||||
private java.math.BigDecimal exitThickTolMin;
|
||||
private java.math.BigDecimal exitWidthTar;
|
||||
private java.math.BigDecimal exitWidthTolMax;
|
||||
private java.math.BigDecimal exitWidthTolMin;
|
||||
|
||||
private String nextWholeBacklogCode;
|
||||
private String prevWholeBacklogCode;
|
||||
private String exitWtMode;
|
||||
private Integer splitNum;
|
||||
|
||||
private java.math.BigDecimal exitWeight1;
|
||||
private java.math.BigDecimal exitWeight2;
|
||||
private java.math.BigDecimal exitWeight3;
|
||||
private java.math.BigDecimal exitWeight4;
|
||||
private java.math.BigDecimal exitWeight5;
|
||||
private java.math.BigDecimal exitWeight6;
|
||||
|
||||
private String headSampleMode;
|
||||
private String headSamplePosition;
|
||||
private java.math.BigDecimal headSampleLength;
|
||||
private String headSamplePlace;
|
||||
private Integer headSampleNum;
|
||||
|
||||
private String tailSampleMode;
|
||||
private String tailSamplePosition;
|
||||
private java.math.BigDecimal tailSampleLength;
|
||||
private String tailSamplePlace;
|
||||
private Integer tailSampleNum;
|
||||
|
||||
private Date timestamp;
|
||||
private Date onlineDate;
|
||||
private Date startDate;
|
||||
private Date endDate;
|
||||
private Date furInDate;
|
||||
private Date furOutDate;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
|
||||
private String surfaceVice;
|
||||
private String weldCode;
|
||||
|
||||
private Integer spmFlag;
|
||||
private java.math.BigDecimal spmElongation;
|
||||
private java.math.BigDecimal spmRollforce;
|
||||
private String spmProcessType;
|
||||
private String spmControlMode;
|
||||
private java.math.BigDecimal spmBendingForce;
|
||||
private java.math.BigDecimal spmCrimpingRollMesh;
|
||||
private java.math.BigDecimal spmBillyRollMesh;
|
||||
|
||||
private Integer trimFlag;
|
||||
private String tlvMode;
|
||||
private java.math.BigDecimal tlvElongation;
|
||||
private Integer chromating;
|
||||
private String coatingCode;
|
||||
private Integer oilingFlag;
|
||||
private String oilingType;
|
||||
private java.math.BigDecimal oilingTop;
|
||||
private java.math.BigDecimal oilingBottom;
|
||||
|
||||
private String heatCycle;
|
||||
private String coatingSelection;
|
||||
private String coatingType;
|
||||
private java.math.BigDecimal zincCoatingThickness;
|
||||
private String chemTreatMode;
|
||||
|
||||
private java.math.BigDecimal aimWeightTop;
|
||||
private java.math.BigDecimal aimWeightBottom;
|
||||
private java.math.BigDecimal maxTolWeightTop;
|
||||
private java.math.BigDecimal maxTolWeightBottom;
|
||||
private java.math.BigDecimal headendGaugeLength;
|
||||
private java.math.BigDecimal tailendGaugeLength;
|
||||
|
||||
private String unitCode;
|
||||
private String originCoilid;
|
||||
private Date onlineTime;
|
||||
private Date producingTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("crm_pdo_excoil")
|
||||
public class CrmPdoExcoil {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String exitMatId;
|
||||
private String entryMatId;
|
||||
private Integer subId;
|
||||
private Double startPosition;
|
||||
private Double endPosition;
|
||||
private Long planId;
|
||||
private String planNo;
|
||||
private String prodCode;
|
||||
private String groupNo;
|
||||
private String shiftNo;
|
||||
private String status;
|
||||
private String steelGrade;
|
||||
|
||||
private Double entryThick;
|
||||
private Double entryWidth;
|
||||
private Double entryLength;
|
||||
private Double entryWeight;
|
||||
|
||||
private Double weightTop;
|
||||
private Double weightBottom;
|
||||
|
||||
private Double exitLength;
|
||||
private Double exitNetWeight;
|
||||
private Double theoryWeight;
|
||||
private Double actualWeight;
|
||||
|
||||
private Double exitOuterDiameter;
|
||||
private Double exitThickness;
|
||||
private Double exitWidth;
|
||||
|
||||
private String customer;
|
||||
|
||||
private Date onlineTime;
|
||||
private Date startTime;
|
||||
private Date endTime;
|
||||
|
||||
private Long delFlag;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
|
||||
private String unitCode;
|
||||
private String processCode;
|
||||
|
||||
private Boolean lastFlag;
|
||||
private Boolean separateFlag;
|
||||
|
||||
private String planOrigin;
|
||||
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("pdi_setup")
|
||||
public class PdiSetup {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String coilid;
|
||||
private String planid;
|
||||
private String steelGrade;
|
||||
private Float thick;
|
||||
private Float yieldStren;
|
||||
|
||||
private Float porTension;
|
||||
private Float celTension;
|
||||
private Float cleanTension;
|
||||
private Float passivationTension;
|
||||
private Float cxlTension;
|
||||
private Float trTension;
|
||||
private Float levelerEntryTension;
|
||||
private Float levelerExitTension;
|
||||
private Float straightenerExitTension;
|
||||
private Float furTension;
|
||||
private Float towerTension;
|
||||
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("pro_stoppage")
|
||||
public class ProStoppage {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "STOPID", type = IdType.AUTO)
|
||||
private Long stopid;
|
||||
|
||||
private String coilid;
|
||||
private String shift;
|
||||
private String crew;
|
||||
private String area;
|
||||
private String unit;
|
||||
private String seton;
|
||||
|
||||
private Date startDate;
|
||||
private Date endDate;
|
||||
|
||||
private Float duration;
|
||||
private Date insdate;
|
||||
private String stopType;
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("pro_stoppage_type")
|
||||
public class ProStoppageType {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "STOP_TYPE")
|
||||
private Integer stopType;
|
||||
|
||||
private String remark;
|
||||
|
||||
private Date insdate;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("shift_config")
|
||||
public class ShiftConfig {
|
||||
|
||||
@TableId(value = "configid", type = IdType.INPUT)
|
||||
private Integer configid;
|
||||
|
||||
@TableField("START_DATE")
|
||||
private Date startDate;
|
||||
|
||||
@TableField("SHIFT1")
|
||||
private Float shift1;
|
||||
|
||||
@TableField("SHIFT2")
|
||||
private Float shift2;
|
||||
|
||||
@TableField("SHIFT3")
|
||||
private Float shift3;
|
||||
|
||||
@TableField("SHIFT4")
|
||||
private Float shift4;
|
||||
|
||||
@TableField("SHIFT5")
|
||||
private Float shift5;
|
||||
|
||||
@TableField("SHIFT_NUM")
|
||||
private Integer shiftNum;
|
||||
|
||||
@TableField("FLAG")
|
||||
private Integer flag;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@TableName("shift_crew")
|
||||
public class ShiftCrew {
|
||||
|
||||
@TableId(value = "seqno", type = IdType.INPUT)
|
||||
private Integer seqno;
|
||||
|
||||
@TableField("shift")
|
||||
private String shift;
|
||||
|
||||
@TableField("crew")
|
||||
private String crew;
|
||||
|
||||
@TableField("flag")
|
||||
private Integer flag;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.klp.pocket.galvanize1.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("shift_history")
|
||||
public class ShiftHistory {
|
||||
|
||||
@TableField("SHIFT")
|
||||
private String shift;
|
||||
|
||||
@TableField("CREW")
|
||||
private String crew;
|
||||
|
||||
@TableField("insdate")
|
||||
private Date insdate;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CplSegmentTotalBo extends BaseEntity {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String enCoilId;
|
||||
|
||||
private Integer picklingCount;
|
||||
|
||||
private Integer segNo;
|
||||
|
||||
private Double startPos;
|
||||
|
||||
private Double endPos;
|
||||
|
||||
private Double segLen;
|
||||
|
||||
private String totalValuesJson;
|
||||
|
||||
private Date createTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CrmPdiPlanBo extends BaseEntity {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Integer seqid;
|
||||
private String coilid;
|
||||
private Integer dummyCoilFlag;
|
||||
private String status;
|
||||
private String planid;
|
||||
private String planType;
|
||||
|
||||
private BigDecimal yieldPoint;
|
||||
private BigDecimal entryWeight;
|
||||
private BigDecimal entryThick;
|
||||
private BigDecimal entryWidth;
|
||||
private BigDecimal entryLength;
|
||||
private BigDecimal entryOuterDiameter;
|
||||
private BigDecimal entryInnerDiameter;
|
||||
private BigDecimal exitInnerDiameter;
|
||||
|
||||
private String steelGrade;
|
||||
private String exitCoilid;
|
||||
private Integer tlvFlag;
|
||||
private String orderNo;
|
||||
private String custommerCode;
|
||||
|
||||
private BigDecimal orderThick;
|
||||
private BigDecimal orderWidth;
|
||||
private BigDecimal orderLenLow;
|
||||
private BigDecimal orderLenUp;
|
||||
private BigDecimal orderWt;
|
||||
private BigDecimal orderWtLow;
|
||||
private BigDecimal orderWtUp;
|
||||
private BigDecimal orderMetCoatTop;
|
||||
private BigDecimal orderMetCoatBot;
|
||||
|
||||
private String finalUse;
|
||||
private String hotCoilCode;
|
||||
|
||||
private BigDecimal exitLengthTar;
|
||||
private BigDecimal exitLengthTolMax;
|
||||
private BigDecimal exitLengthTolMin;
|
||||
private BigDecimal exitThickTar;
|
||||
private BigDecimal exitThickTolMax;
|
||||
private BigDecimal exitThickTolMin;
|
||||
private BigDecimal exitWidthTar;
|
||||
private BigDecimal exitWidthTolMax;
|
||||
private BigDecimal exitWidthTolMin;
|
||||
|
||||
private String nextWholeBacklogCode;
|
||||
private String prevWholeBacklogCode;
|
||||
private String exitWtMode;
|
||||
private Integer splitNum;
|
||||
|
||||
private BigDecimal exitWeight1;
|
||||
private BigDecimal exitWeight2;
|
||||
private BigDecimal exitWeight3;
|
||||
private BigDecimal exitWeight4;
|
||||
private BigDecimal exitWeight5;
|
||||
private BigDecimal exitWeight6;
|
||||
|
||||
private String headSampleMode;
|
||||
private String headSamplePosition;
|
||||
private BigDecimal headSampleLength;
|
||||
private String headSamplePlace;
|
||||
private Integer headSampleNum;
|
||||
|
||||
private String tailSampleMode;
|
||||
private String tailSamplePosition;
|
||||
private BigDecimal tailSampleLength;
|
||||
private String tailSamplePlace;
|
||||
private Integer tailSampleNum;
|
||||
|
||||
private Date timestamp;
|
||||
private Date onlineDate;
|
||||
private Date startDate;
|
||||
private Date endDate;
|
||||
private Date furInDate;
|
||||
private Date furOutDate;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
|
||||
private String surfaceVice;
|
||||
private String weldCode;
|
||||
|
||||
private Integer spmFlag;
|
||||
private BigDecimal spmElongation;
|
||||
private BigDecimal spmRollforce;
|
||||
private String spmProcessType;
|
||||
private String spmControlMode;
|
||||
private BigDecimal spmBendingForce;
|
||||
private BigDecimal spmCrimpingRollMesh;
|
||||
private BigDecimal spmBillyRollMesh;
|
||||
|
||||
private Integer trimFlag;
|
||||
private String tlvMode;
|
||||
private BigDecimal tlvElongation;
|
||||
private Integer chromating;
|
||||
private String coatingCode;
|
||||
private Integer oilingFlag;
|
||||
private String oilingType;
|
||||
private BigDecimal oilingTop;
|
||||
private BigDecimal oilingBottom;
|
||||
|
||||
private String heatCycle;
|
||||
private String coatingSelection;
|
||||
private String coatingType;
|
||||
private BigDecimal zincCoatingThickness;
|
||||
private String chemTreatMode;
|
||||
|
||||
private BigDecimal aimWeightTop;
|
||||
private BigDecimal aimWeightBottom;
|
||||
private BigDecimal maxTolWeightTop;
|
||||
private BigDecimal maxTolWeightBottom;
|
||||
private BigDecimal headendGaugeLength;
|
||||
private BigDecimal tailendGaugeLength;
|
||||
|
||||
private String unitCode;
|
||||
private String originCoilid;
|
||||
private Date onlineTime;
|
||||
private Date producingTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CrmPdoExcoilBo extends BaseEntity {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String exitMatId;
|
||||
private String entryMatId;
|
||||
private Integer subId;
|
||||
private Double startPosition;
|
||||
private Double endPosition;
|
||||
private Long planId;
|
||||
private String planNo;
|
||||
private String prodCode;
|
||||
private String groupNo;
|
||||
private String shiftNo;
|
||||
private String status;
|
||||
private String steelGrade;
|
||||
|
||||
private Double entryThick;
|
||||
private Double entryWidth;
|
||||
private Double entryLength;
|
||||
private Double entryWeight;
|
||||
|
||||
private Double weightTop;
|
||||
private Double weightBottom;
|
||||
|
||||
private Double exitLength;
|
||||
private Double exitNetWeight;
|
||||
private Double theoryWeight;
|
||||
private Double actualWeight;
|
||||
|
||||
private Double exitOuterDiameter;
|
||||
private Double exitThickness;
|
||||
private Double exitWidth;
|
||||
|
||||
private String customer;
|
||||
|
||||
private Date onlineTime;
|
||||
private Date startTime;
|
||||
private Date endTime;
|
||||
|
||||
private Long delFlag;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
|
||||
private String unitCode;
|
||||
private String processCode;
|
||||
|
||||
private Boolean lastFlag;
|
||||
private Boolean separateFlag;
|
||||
|
||||
private String planOrigin;
|
||||
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PdiSetupBo extends BaseEntity {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String coilid;
|
||||
private String planid;
|
||||
private String steelGrade;
|
||||
private Float thick;
|
||||
private Float yieldStren;
|
||||
|
||||
private Float porTension;
|
||||
private Float celTension;
|
||||
private Float cleanTension;
|
||||
private Float passivationTension;
|
||||
private Float cxlTension;
|
||||
private Float trTension;
|
||||
private Float levelerEntryTension;
|
||||
private Float levelerExitTension;
|
||||
private Float straightenerExitTension;
|
||||
private Float furTension;
|
||||
private Float towerTension;
|
||||
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ProStoppageBo extends BaseEntity {
|
||||
|
||||
private Long stopid;
|
||||
|
||||
private String coilid;
|
||||
private String shift;
|
||||
private String crew;
|
||||
private String area;
|
||||
private String unit;
|
||||
private String seton;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date startDate;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date endDate;
|
||||
|
||||
private Float duration;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date insdate;
|
||||
|
||||
private String stopType;
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ProStoppageTypeBo extends BaseEntity {
|
||||
|
||||
private Integer stopType;
|
||||
|
||||
private String remark;
|
||||
|
||||
private Date insdate;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ShiftConfigBo extends BaseEntity {
|
||||
|
||||
private Integer configid;
|
||||
|
||||
private Date startDate;
|
||||
|
||||
private Float shift1;
|
||||
|
||||
private Float shift2;
|
||||
|
||||
private Float shift3;
|
||||
|
||||
private Float shift4;
|
||||
|
||||
private Float shift5;
|
||||
|
||||
private Integer shiftNum;
|
||||
|
||||
private Integer flag;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ShiftCrewBo extends BaseEntity {
|
||||
|
||||
private Integer seqno;
|
||||
|
||||
private String shift;
|
||||
|
||||
private String crew;
|
||||
|
||||
private Integer flag;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.klp.pocket.galvanize1.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ShiftHistoryBo extends BaseEntity {
|
||||
|
||||
private String shift;
|
||||
|
||||
private String crew;
|
||||
|
||||
private Date insdate;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.klp.pocket.galvanize1.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CplSegmentTotalVo {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String enCoilId;
|
||||
|
||||
private Integer picklingCount;
|
||||
|
||||
private Integer segNo;
|
||||
|
||||
private Double startPos;
|
||||
|
||||
private Double endPos;
|
||||
|
||||
private Double segLen;
|
||||
|
||||
private String totalValuesJson;
|
||||
|
||||
private Date createTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.klp.pocket.galvanize1.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CrmPdiPlanVo {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Integer seqid;
|
||||
private String coilid;
|
||||
private Integer dummyCoilFlag;
|
||||
private String status;
|
||||
private String planid;
|
||||
private String planType;
|
||||
|
||||
private BigDecimal yieldPoint;
|
||||
private BigDecimal entryWeight;
|
||||
private BigDecimal entryThick;
|
||||
private BigDecimal entryWidth;
|
||||
private BigDecimal entryLength;
|
||||
private BigDecimal entryOuterDiameter;
|
||||
private BigDecimal entryInnerDiameter;
|
||||
private BigDecimal exitInnerDiameter;
|
||||
|
||||
private String steelGrade;
|
||||
private String exitCoilid;
|
||||
private Integer tlvFlag;
|
||||
private String orderNo;
|
||||
private String custommerCode;
|
||||
|
||||
private BigDecimal orderThick;
|
||||
private BigDecimal orderWidth;
|
||||
private BigDecimal orderLenLow;
|
||||
private BigDecimal orderLenUp;
|
||||
private BigDecimal orderWt;
|
||||
private BigDecimal orderWtLow;
|
||||
private BigDecimal orderWtUp;
|
||||
private BigDecimal orderMetCoatTop;
|
||||
private BigDecimal orderMetCoatBot;
|
||||
|
||||
private String finalUse;
|
||||
private String hotCoilCode;
|
||||
|
||||
private BigDecimal exitLengthTar;
|
||||
private BigDecimal exitLengthTolMax;
|
||||
private BigDecimal exitLengthTolMin;
|
||||
private BigDecimal exitThickTar;
|
||||
private BigDecimal exitThickTolMax;
|
||||
private BigDecimal exitThickTolMin;
|
||||
private BigDecimal exitWidthTar;
|
||||
private BigDecimal exitWidthTolMax;
|
||||
private BigDecimal exitWidthTolMin;
|
||||
|
||||
private String nextWholeBacklogCode;
|
||||
private String prevWholeBacklogCode;
|
||||
private String exitWtMode;
|
||||
private Integer splitNum;
|
||||
|
||||
private BigDecimal exitWeight1;
|
||||
private BigDecimal exitWeight2;
|
||||
private BigDecimal exitWeight3;
|
||||
private BigDecimal exitWeight4;
|
||||
private BigDecimal exitWeight5;
|
||||
private BigDecimal exitWeight6;
|
||||
|
||||
private String headSampleMode;
|
||||
private String headSamplePosition;
|
||||
private BigDecimal headSampleLength;
|
||||
private String headSamplePlace;
|
||||
private Integer headSampleNum;
|
||||
|
||||
private String tailSampleMode;
|
||||
private String tailSamplePosition;
|
||||
private BigDecimal tailSampleLength;
|
||||
private String tailSamplePlace;
|
||||
private Integer tailSampleNum;
|
||||
|
||||
private Date timestamp;
|
||||
private Date onlineDate;
|
||||
private Date startDate;
|
||||
private Date endDate;
|
||||
private Date furInDate;
|
||||
private Date furOutDate;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
|
||||
private String surfaceVice;
|
||||
private String weldCode;
|
||||
|
||||
private Integer spmFlag;
|
||||
private BigDecimal spmElongation;
|
||||
private BigDecimal spmRollforce;
|
||||
private String spmProcessType;
|
||||
private String spmControlMode;
|
||||
private BigDecimal spmBendingForce;
|
||||
private BigDecimal spmCrimpingRollMesh;
|
||||
private BigDecimal spmBillyRollMesh;
|
||||
|
||||
private Integer trimFlag;
|
||||
private String tlvMode;
|
||||
private BigDecimal tlvElongation;
|
||||
private Integer chromating;
|
||||
private String coatingCode;
|
||||
private Integer oilingFlag;
|
||||
private String oilingType;
|
||||
private BigDecimal oilingTop;
|
||||
private BigDecimal oilingBottom;
|
||||
|
||||
private String heatCycle;
|
||||
private String coatingSelection;
|
||||
private String coatingType;
|
||||
private BigDecimal zincCoatingThickness;
|
||||
private String chemTreatMode;
|
||||
|
||||
private BigDecimal aimWeightTop;
|
||||
private BigDecimal aimWeightBottom;
|
||||
private BigDecimal maxTolWeightTop;
|
||||
private BigDecimal maxTolWeightBottom;
|
||||
private BigDecimal headendGaugeLength;
|
||||
private BigDecimal tailendGaugeLength;
|
||||
|
||||
private String unitCode;
|
||||
private String originCoilid;
|
||||
private Date onlineTime;
|
||||
private Date producingTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.klp.pocket.galvanize1.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CrmPdoExcoilVo {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String exitMatId;
|
||||
private String entryMatId;
|
||||
private Integer subId;
|
||||
private Double startPosition;
|
||||
private Double endPosition;
|
||||
private Long planId;
|
||||
private String planNo;
|
||||
private String prodCode;
|
||||
private String groupNo;
|
||||
private String shiftNo;
|
||||
private String status;
|
||||
private String steelGrade;
|
||||
|
||||
private Double entryThick;
|
||||
private Double entryWidth;
|
||||
private Double entryLength;
|
||||
private Double entryWeight;
|
||||
|
||||
private Double weightTop;
|
||||
private Double weightBottom;
|
||||
|
||||
private Double exitLength;
|
||||
private Double exitNetWeight;
|
||||
private Double theoryWeight;
|
||||
private Double actualWeight;
|
||||
|
||||
private Double exitOuterDiameter;
|
||||
private Double exitThickness;
|
||||
private Double exitWidth;
|
||||
|
||||
private String customer;
|
||||
|
||||
private Date onlineTime;
|
||||
private Date startTime;
|
||||
private Date endTime;
|
||||
|
||||
private Long delFlag;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
|
||||
private String unitCode;
|
||||
private String processCode;
|
||||
|
||||
private Boolean lastFlag;
|
||||
private Boolean separateFlag;
|
||||
|
||||
private String planOrigin;
|
||||
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user