From c425a8afba0a76eb62d5650cc9c98c42d8339f06 Mon Sep 17 00:00:00 2001
From: zhuguifei <312353457@qq.com>
Date: 星期四, 12 三月 2026 13:01:23 +0800
Subject: [PATCH] perf: 1.优化储丝柜单柜卷包产量计算方式,支持未出料结束计算统计 2.新增储丝柜单柜卷包产量桑基图
---
ruoyi-plus-soybean/src/router/elegant/routes.ts | 9 +
ruoyi-plus-soybean/src/views/analy/store-silk/index.vue | 137 ++++++++++++++--
ruoyi-plus-soybean/src/hooks/common/echarts.ts | 14 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java | 102 ++++++++++++
ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-search.vue | 111 +++++++++----
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkDetailVo.java | 12 +
ruoyi-plus-soybean/src/views/analy/feed-match/modules/feed-match-search.vue | 38 +++
ruoyi-plus-soybean/src/typings/api/analy.feed-match.api.d.ts | 2
ruoyi-plus-soybean/src/router/elegant/imports.ts | 1
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkInfoVo.java | 12 +
ruoyi-plus-soybean/src/typings/elegant-router.d.ts | 2
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/FeedmatchTimeDataServiceImpl.java | 5
ruoyi-plus-soybean/src/views/analy/feed-match/index.vue | 1
RuoYi-Vue-Plus/开发日志.md | 2
ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-detail.vue | 25 +-
ruoyi-plus-soybean/src/router/elegant/transform.ts | 1
16 files changed, 393 insertions(+), 81 deletions(-)
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkDetailVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkDetailVo.java
index f08f5b8..d312ac1 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkDetailVo.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkDetailVo.java
@@ -49,7 +49,17 @@
private Date shiftEndTime;
/**
- * 璇ョ彮娆″唴璁$畻鍑虹殑浜ч噺
+ * 璇ョ彮娆″唴璁$畻鍑虹殑浜ч噺锛堜綔涓鸿褰曟椂姝f暟琛ㄧず澧炲姞锛岃礋鏁拌〃绀哄墧闄わ級
*/
private Double output;
+
+ /**
+ * 鎿嶄綔绫诲瀷鎻忚堪锛堝 "鐝绱", "鎵i櫎澶撮儴", "鎵i櫎灏鹃儴"锛�
+ */
+ private String calcType;
+
+ /**
+ * 鍛戒腑鏁版嵁鐨勬椂闂寸偣锛堢敤浜庤拷婧暟鎹潵婧愶級
+ */
+ private Date hitTime;
}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkInfoVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkInfoVo.java
index e7d9e7e..fcac65e 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkInfoVo.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/domain/vo/StoreSilkInfoVo.java
@@ -106,7 +106,17 @@
private List<StoreSilkDetailVo> rollerDetailList;
/**
- * 鍖呰鏈轰骇閲忔槑缁�
+ * 鍖呰鏈轰骇閲忔槑缁嗭紙鏈�缁堢粨鏋滐級
*/
private List<StoreSilkDetailVo> packerDetailList;
+
+ /**
+ * 鍗锋帴鏈烘搷浣滆繃绋嬭褰曪紙澧炲噺鏄庣粏锛�
+ */
+ private List<StoreSilkDetailVo> rollerRecordList;
+
+ /**
+ * 鍖呰鏈烘搷浣滆繃绋嬭褰曪紙澧炲噺鏄庣粏锛�
+ */
+ private List<StoreSilkDetailVo> packerRecordList;
}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/FeedmatchTimeDataServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/FeedmatchTimeDataServiceImpl.java
index 4095578..b9c1689 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/FeedmatchTimeDataServiceImpl.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/FeedmatchTimeDataServiceImpl.java
@@ -9,6 +9,7 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.dromara.qa.analy.domain.StoreSilkInfo;
import org.springframework.stereotype.Service;
import org.dromara.qa.analy.domain.bo.FeedmatchTimeDataBo;
import org.dromara.qa.analy.domain.vo.FeedmatchTimeDataVo;
@@ -74,7 +75,9 @@
private LambdaQueryWrapper<FeedmatchTimeData> buildQueryWrapper(FeedmatchTimeDataBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<FeedmatchTimeData> lqw = Wrappers.lambdaQuery();
- lqw.eq(bo.getTime() != null, FeedmatchTimeData::getTime, bo.getTime());
+ lqw.eq(bo.getShift() != null, FeedmatchTimeData::getShift, bo.getShift());
+ lqw.between(params.get("beginTime") != null && params.get("endTime") != null,
+ FeedmatchTimeData::getTime, params.get("beginTime"), params.get("endTime"));
lqw.eq(StringUtils.isNotBlank(bo.getKey()), FeedmatchTimeData::getKey, bo.getKey());
return lqw;
}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java
index eaf9a1c..03254ad 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java
@@ -219,9 +219,12 @@
// 鍗峰寘浜ч噺缁熻
Double rollerOutput = 0.0;
Double packerOutput = 0.0;
- // 鏄庣粏鍒楄〃
+ // 鏄庣粏鍒楄〃锛堜粎瀛樻渶缁堟鏁扮粨鏋滐級
List<StoreSilkDetailVo> rollerDetailList = new ArrayList<>();
List<StoreSilkDetailVo> packerDetailList = new ArrayList<>();
+ // 鎿嶄綔璁板綍鍒楄〃锛堝瓨鎵�鏈夊鍑忚繃绋嬶級
+ List<StoreSilkDetailVo> rollerRecordList = new ArrayList<>();
+ List<StoreSilkDetailVo> packerRecordList = new ArrayList<>();
for (int s = 0; s < distShiftList.size(); s++) {
MdShiftBo shiftBo = distShiftList.get(s);
@@ -347,6 +350,20 @@
// 鍏堟妸缁熻缁撴潫鏃跺埢绱鍊煎姞杩涙潵锛歝urrent = Qty(calcEnd)
currentRollerOutput += rData.getQty();
+ // 璁板綍杩囩▼锛氱彮娆℃埅姝㈢疮璁�
+ StoreSilkDetailVo endRecord = new StoreSilkDetailVo();
+ endRecord.setFsNum(fsNum.substring(2, 3));
+ endRecord.setSiloNum(containerNum);
+ endRecord.setPipeNum(channel);
+ endRecord.setEquNo(equNo);
+ endRecord.setShiftCode(shift);
+ endRecord.setShiftStartTime(calcStartDate);
+ endRecord.setShiftEndTime(calcEndDate);
+ endRecord.setOutput(rData.getQty());
+ endRecord.setCalcType("鐝鎴绱");
+ endRecord.setHitTime(rData.getTime());
+ rollerRecordList.add(endRecord);
+
// 2) 鎵b�滃ご鈥濓細濡傛灉缁熻寮�濮嬫椂鍒绘櫄浜庣彮娆″紑濮嬶紝鍒欏噺鍘� Qty(calcStart)
if (calcStartDate.after(stimDate)) {
LocalDateTime calcStartLdt = LocalDateTime.ofInstant(calcStartDate.toInstant(), zone);
@@ -365,6 +382,20 @@
RollerTimeData rBeginData = rollerTimeDataMapper.selectOne(beginRlqw);
if (rBeginData != null) {
currentRollerOutput -= rBeginData.getQty();
+
+ // 璁板綍杩囩▼锛氭墸闄ゅご閮ㄤ骇閲�
+ StoreSilkDetailVo beginRecord = new StoreSilkDetailVo();
+ beginRecord.setFsNum(fsNum.substring(2, 3));
+ beginRecord.setSiloNum(containerNum);
+ beginRecord.setPipeNum(channel);
+ beginRecord.setEquNo(equNo);
+ beginRecord.setShiftCode(shift);
+ beginRecord.setShiftStartTime(calcStartDate);
+ beginRecord.setShiftEndTime(calcEndDate);
+ beginRecord.setOutput(-rBeginData.getQty()); // 璐熸暟琛ㄧず鎵i櫎
+ beginRecord.setCalcType("鎵i櫎鍑烘枡鍓嶇疮璁�");
+ beginRecord.setHitTime(rBeginData.getTime());
+ rollerRecordList.add(beginRecord);
}
}
}
@@ -401,6 +432,20 @@
// 鍏堟妸缁熻缁撴潫鏃跺埢绱鍊煎姞杩涙潵锛歝urrent = Qty(calcEnd)
currentPackerOutput += pData.getTsQty();
+ // 璁板綍杩囩▼锛氱彮娆℃埅姝㈢疮璁�
+ StoreSilkDetailVo endRecord = new StoreSilkDetailVo();
+ endRecord.setFsNum(fsNum.substring(2, 3));
+ endRecord.setSiloNum(containerNum);
+ endRecord.setPipeNum(channel);
+ endRecord.setEquNo(equNo);
+ endRecord.setShiftCode(shift);
+ endRecord.setShiftStartTime(calcStartDate);
+ endRecord.setShiftEndTime(calcEndDate);
+ endRecord.setOutput(pData.getTsQty());
+ endRecord.setCalcType("鐝鎴绱");
+ endRecord.setHitTime(pData.getTime());
+ packerRecordList.add(endRecord);
+
// 2) 鎵b�滃ご鈥濓細濡傛灉缁熻寮�濮嬫椂鍒绘櫄浜庣彮娆″紑濮嬶紝鍒欏噺鍘� Qty(calcStart)
if (calcStartDate.after(stimDate)) {
LocalDateTime calcStartLdt = LocalDateTime.ofInstant(calcStartDate.toInstant(), zone);
@@ -419,6 +464,20 @@
PackerTimeData pBeginData = packerTimeDataMapper.selectOne(beginPlqw);
if (pBeginData != null) {
currentPackerOutput -= pBeginData.getTsQty();
+
+ // 璁板綍杩囩▼锛氭墸闄ゅご閮ㄤ骇閲�
+ StoreSilkDetailVo beginRecord = new StoreSilkDetailVo();
+ beginRecord.setFsNum(fsNum.substring(2, 3));
+ beginRecord.setSiloNum(containerNum);
+ beginRecord.setPipeNum(channel);
+ beginRecord.setEquNo(equNo);
+ beginRecord.setShiftCode(shift);
+ beginRecord.setShiftStartTime(calcStartDate);
+ beginRecord.setShiftEndTime(calcEndDate);
+ beginRecord.setOutput(-pBeginData.getTsQty()); // 璐熸暟琛ㄧず鎵i櫎
+ beginRecord.setCalcType("鎵i櫎鍑烘枡鍓嶇疮璁�");
+ beginRecord.setHitTime(pBeginData.getTime());
+ packerRecordList.add(beginRecord);
}
}
}
@@ -444,6 +503,8 @@
storeSilkInfoVo.setPackerOutput(packerOutput);
storeSilkInfoVo.setRollerDetailList(rollerDetailList);
storeSilkInfoVo.setPackerDetailList(packerDetailList);
+ storeSilkInfoVo.setRollerRecordList(rollerRecordList);
+ storeSilkInfoVo.setPackerRecordList(packerRecordList);
}
@@ -558,11 +619,44 @@
LambdaQueryWrapper<StoreSilkInfo> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(StoreSilkInfo::getId);
lqw.like(StringUtils.isNotBlank(bo.getMaterialname()), StoreSilkInfo::getMaterialname, bo.getMaterialname());
- lqw.eq(StringUtils.isNotBlank(bo.getBatchcode()), StoreSilkInfo::getBatchcode, bo.getBatchcode());
- lqw.eq(bo.getActualstarttime() != null, StoreSilkInfo::getActualstarttime, bo.getActualstarttime());
+ lqw.like(StringUtils.isNotBlank(bo.getBatchcode()), StoreSilkInfo::getBatchcode, bo.getBatchcode());
+ if (bo.getActualstarttime() != null) {
+ ZoneId zone = ZoneId.systemDefault();
+ LocalDate day = bo.getActualstarttime().toInstant().atZone(zone).toLocalDate();
+ Date dayStart = Date.from(day.atStartOfDay(zone).toInstant());
+ Date nextDayStart = Date.from(day.plusDays(1).atStartOfDay(zone).toInstant());
+ lqw.ge(StoreSilkInfo::getActualstarttime, dayStart);
+ lqw.lt(StoreSilkInfo::getActualstarttime, nextDayStart);
+ }
lqw.eq(bo.getDistimebegin() != null, StoreSilkInfo::getDistimebegin, bo.getDistimebegin());
lqw.eq(bo.getDistimeend() != null, StoreSilkInfo::getDistimeend, bo.getDistimeend());
- lqw.eq(StringUtils.isNotBlank(bo.getSiloid()), StoreSilkInfo::getSiloid, bo.getSiloid());
+ if (StringUtils.isNotBlank(bo.getSiloid())) {
+ // 鏀寔澶氫釜鏌滃彿鏌ヨ锛屼互閫楀彿鍒嗛殧
+ String[] siloids = bo.getSiloid().split(",");
+ lqw.and(wrapper -> {
+ for (String val : siloids) {
+ val = val.trim();
+ if (StringUtils.isBlank(val)) {
+ continue;
+ }
+ String finalVal = val;
+ // 浣跨敤 OR 杩炴帴澶氫釜鏌滃彿鏉′欢
+ wrapper.or(w -> {
+ try {
+ int num = Integer.parseInt(finalVal);
+ String padded = String.format("%02d", num);
+ // 鍖归厤 _1 鎴� _01 (鍏煎涓嶈ˉ闆跺拰琛ラ浂鐨勬儏鍐�)
+ w.likeLeft(StoreSilkInfo::getSiloid, "_" + num)
+ .or()
+ .likeLeft(StoreSilkInfo::getSiloid, "_" + padded);
+ } catch (NumberFormatException e) {
+ // 闈炴暟瀛楀垯鎸夊師鍊煎尮閰�
+ w.eq(StoreSilkInfo::getSiloid, finalVal);
+ }
+ });
+ }
+ });
+ }
lqw.between(params.get("beginTime") != null && params.get("endTime") != null,
StoreSilkInfo::getDistimeend, params.get("beginTime"), params.get("endTime"));
return lqw;
diff --git "a/RuoYi-Vue-Plus/\345\274\200\345\217\221\346\227\245\345\277\227.md" "b/RuoYi-Vue-Plus/\345\274\200\345\217\221\346\227\245\345\277\227.md"
index 2123e4c..2cd3a9a 100644
--- "a/RuoYi-Vue-Plus/\345\274\200\345\217\221\346\227\245\345\277\227.md"
+++ "b/RuoYi-Vue-Plus/\345\274\200\345\217\221\346\227\245\345\277\227.md"
@@ -13,6 +13,8 @@
#### 20260302
- 寰呭姙浜嬮」
- [ ] 鐩墠鍌ㄤ笣鏌滀俊鎭俊鎭病鏈変粠瑙嗗浘涓幏鍙栵紝浣跨敤oracle_store_silk琛ㄦā鎷�->浣跨敤鍒朵笣杞﹂棿鐪熷疄瑙嗗浘鏁版嵁婧�
+- [ ] 鍒朵笣闆嗘帶锛圤racle 瑙嗗浘锛変腑娌℃湁鍑烘枡缁撴潫鏃堕棿锛屼互鍙婂疄鏃堕噸閲忔槸濡備綍璁$畻
+- [ ] 鍠備笣鏈哄搴斿叧绯伙紝鐩墠redis鏁版嵁搴撳懡鍚嶈鑼�3.4鏈�4鍙锋満锛屽疄闄呰溅闂存病鏈�4鍙锋満锛岄渶鍒扮幇鍦烘牎楠屽搴斿叧绯�
- [ ] 鍠備笣鏈哄搴斿叧绯伙紝fs寮�澶村偍瀛樼殑鐪熷疄鍊兼槸浠�涔堬紝鐩墠娴嬭瘯鏁版嵁浣跨敤鐨勬槸 fs11 -> 鍌ㄤ笣鏌滃彿
- [ ] 纭1鍙板杺涓濇満瀵瑰簲鐨�2鍙板偍涓濇煖鏄緷娆′緵涓濊繕鏄彲浠ュ苟琛屼緵涓�(<span style="color: red;">***骞惰渚涗笣鏃犳硶鍑嗙‘璁$畻浜ч噺***</span>)
- [ ] 纭 鍠備笣鏈哄搴斿叧绯讳腑(key->pipe01 value->1#鏈虹粍瀵瑰簲鐨勫杺涓濇満鍜岀閬�)value涓嶄細閲嶅 (<span style="color: red;">***閲嶅灏嗗鑷磋绠楅�昏緫鍑虹幇閿欒***</span>)
diff --git a/ruoyi-plus-soybean/src/hooks/common/echarts.ts b/ruoyi-plus-soybean/src/hooks/common/echarts.ts
index 8e7c728..d74f93e 100755
--- a/ruoyi-plus-soybean/src/hooks/common/echarts.ts
+++ b/ruoyi-plus-soybean/src/hooks/common/echarts.ts
@@ -1,7 +1,16 @@
import { computed, effectScope, nextTick, onScopeDispose, shallowRef, watch } from 'vue';
import { useElementSize } from '@vueuse/core';
import * as echarts from 'echarts/core';
-import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts';
+import {
+ BarChart,
+ GaugeChart,
+ LineChart,
+ PictorialBarChart,
+ PieChart,
+ RadarChart,
+ SankeyChart,
+ ScatterChart
+} from 'echarts/charts';
import type {
BarSeriesOption,
GaugeSeriesOption,
@@ -9,6 +18,7 @@
PictorialBarSeriesOption,
PieSeriesOption,
RadarSeriesOption,
+ SankeySeriesOption,
ScatterSeriesOption
} from 'echarts/charts';
import {
@@ -40,6 +50,7 @@
| PictorialBarSeriesOption
| RadarSeriesOption
| GaugeSeriesOption
+ | SankeySeriesOption
| TitleComponentOption
| LegendComponentOption
| TooltipComponentOption
@@ -63,6 +74,7 @@
PictorialBarChart,
RadarChart,
GaugeChart,
+ SankeyChart,
LabelLayout,
UniversalTransition,
CanvasRenderer
diff --git a/ruoyi-plus-soybean/src/router/elegant/imports.ts b/ruoyi-plus-soybean/src/router/elegant/imports.ts
index 4751a41..4d0ffc3 100755
--- a/ruoyi-plus-soybean/src/router/elegant/imports.ts
+++ b/ruoyi-plus-soybean/src/router/elegant/imports.ts
@@ -38,6 +38,7 @@
monitor_online: () => import("@/views/monitor/online/index.vue"),
monitor_operlog: () => import("@/views/monitor/operlog/index.vue"),
qm_batch: () => import("@/views/qm/batch/index.vue"),
+ qm_std: () => import("@/views/qm/std/index.vue"),
system_client: () => import("@/views/system/client/index.vue"),
system_config: () => import("@/views/system/config/index.vue"),
system_dept: () => import("@/views/system/dept/index.vue"),
diff --git a/ruoyi-plus-soybean/src/router/elegant/routes.ts b/ruoyi-plus-soybean/src/router/elegant/routes.ts
index 274f98a..35c99c3 100755
--- a/ruoyi-plus-soybean/src/router/elegant/routes.ts
+++ b/ruoyi-plus-soybean/src/router/elegant/routes.ts
@@ -264,6 +264,15 @@
title: 'qm_batch',
i18nKey: 'route.qm_batch'
}
+ },
+ {
+ name: 'qm_std',
+ path: '/qm/std',
+ component: 'view.qm_std',
+ meta: {
+ title: 'qm_std',
+ i18nKey: 'route.qm_std'
+ }
}
]
},
diff --git a/ruoyi-plus-soybean/src/router/elegant/transform.ts b/ruoyi-plus-soybean/src/router/elegant/transform.ts
index 7459606..fac85aa 100755
--- a/ruoyi-plus-soybean/src/router/elegant/transform.ts
+++ b/ruoyi-plus-soybean/src/router/elegant/transform.ts
@@ -193,6 +193,7 @@
"monitor_operlog": "/monitor/operlog",
"qm": "/qm",
"qm_batch": "/qm/batch",
+ "qm_std": "/qm/std",
"social-callback": "/social-callback",
"system": "/system",
"system_client": "/system/client",
diff --git a/ruoyi-plus-soybean/src/typings/api/analy.feed-match.api.d.ts b/ruoyi-plus-soybean/src/typings/api/analy.feed-match.api.d.ts
index 2a695e9..eded276 100644
--- a/ruoyi-plus-soybean/src/typings/api/analy.feed-match.api.d.ts
+++ b/ruoyi-plus-soybean/src/typings/api/analy.feed-match.api.d.ts
@@ -70,7 +70,7 @@
/** feed match search params */
type FeedMatchSearchParams = CommonType.RecordNullable<
- Pick<Api.Analy.FeedMatch, 'time' | 'key'> & Api.Common.CommonSearchParams
+ Pick<Api.Analy.FeedMatch, 'time' | 'key' | 'shift'> & Api.Common.CommonSearchParams
>;
/** feed match operate params */
diff --git a/ruoyi-plus-soybean/src/typings/elegant-router.d.ts b/ruoyi-plus-soybean/src/typings/elegant-router.d.ts
index cd2f9bb..013ab97 100755
--- a/ruoyi-plus-soybean/src/typings/elegant-router.d.ts
+++ b/ruoyi-plus-soybean/src/typings/elegant-router.d.ts
@@ -47,6 +47,7 @@
"monitor_operlog": "/monitor/operlog";
"qm": "/qm";
"qm_batch": "/qm/batch";
+ "qm_std": "/qm/std";
"social-callback": "/social-callback";
"system": "/system";
"system_client": "/system/client";
@@ -156,6 +157,7 @@
| "monitor_online"
| "monitor_operlog"
| "qm_batch"
+ | "qm_std"
| "system_client"
| "system_config"
| "system_dept"
diff --git a/ruoyi-plus-soybean/src/views/analy/feed-match/index.vue b/ruoyi-plus-soybean/src/views/analy/feed-match/index.vue
index 0c59e4b..3f303be 100644
--- a/ruoyi-plus-soybean/src/views/analy/feed-match/index.vue
+++ b/ruoyi-plus-soybean/src/views/analy/feed-match/index.vue
@@ -24,6 +24,7 @@
pageSize: 10,
time: null,
key: null,
+ shift: null,
params: {}
});
diff --git a/ruoyi-plus-soybean/src/views/analy/feed-match/modules/feed-match-search.vue b/ruoyi-plus-soybean/src/views/analy/feed-match/modules/feed-match-search.vue
index 4482f5d..a88e769 100644
--- a/ruoyi-plus-soybean/src/views/analy/feed-match/modules/feed-match-search.vue
+++ b/ruoyi-plus-soybean/src/views/analy/feed-match/modules/feed-match-search.vue
@@ -1,5 +1,5 @@
<script setup lang="ts">
-import { toRaw } from 'vue';
+import { ref, toRaw } from 'vue';
import { jsonClone } from '@sa/utils';
import { useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
@@ -21,8 +21,30 @@
const defaultModel = jsonClone(toRaw(model.value));
function resetModel() {
+ timeRange.value = null;
Object.assign(model.value, defaultModel);
}
+
+const timeRange = ref<[string, string] | null>(null);
+
+function onTimeRangeUpdate(value: [string, string] | null) {
+ const params = (model.value.params ||= {});
+ const beginTime = value?.[0] ? String(value[0]).trim() : '';
+ const endTime = value?.[1] ? String(value[1]).trim() : '';
+ if (beginTime && endTime) {
+ params.beginTime = beginTime;
+ params.endTime = endTime;
+ } else {
+ delete params.beginTime;
+ delete params.endTime;
+ }
+}
+
+const shiftOptions = [
+ { label: '鏃╃彮', value: 1 },
+ { label: '涓彮', value: 2 },
+ { label: '鏅氱彮', value: 3 }
+];
async function reset() {
await restoreValidation();
@@ -42,18 +64,20 @@
<NCollapseItem :title="$t('common.search')" name="analy-feed-match-search">
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
<NGrid responsive="screen" item-responsive>
- <NFormItemGi span="24 s:12 m:6" label="鏃堕棿鎴�" label-width="auto" path="time" class="pr-24px">
+ <NFormItemGi span="24 s:12 m:8 l:8 xl:8" label="鏃堕棿鍖洪棿" label-width="auto" path="params.beginTime" class="pr-24px">
<NDatePicker
- v-model:formatted-value="model.time"
- type="datetime"
+ v-model:formatted-value="timeRange"
+ type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
clearable
+ :default-time="['00:00:00', '23:59:59']"
+ @update:formatted-value="onTimeRangeUpdate"
/>
</NFormItemGi>
- <NFormItemGi span="24 s:12 m:6" label="鐝+鏈哄彴" label-width="auto" path="key" class="pr-24px">
- <NInput v-model:value="model.key" placeholder="璇疯緭鍏ョ彮娆�+鏈哄彴" />
+ <NFormItemGi span="24 s:12 m:8 l:8 xl:8" label="鐝" label-width="auto" path="shift" class="pr-24px">
+ <NSelect v-model:value="model.shift" placeholder="璇烽�夋嫨鐝" :options="shiftOptions" clearable />
</NFormItemGi>
- <NFormItemGi :show-feedback="false" span="24" class="pr-24px">
+ <NFormItemGi :show-feedback="false" span="24 s:12 m:8 l:8 xl:8" class="pr-24px">
<NSpace class="w-full" justify="end">
<NButton @click="reset">
<template #icon>
diff --git a/ruoyi-plus-soybean/src/views/analy/store-silk/index.vue b/ruoyi-plus-soybean/src/views/analy/store-silk/index.vue
index 89f96b8..141fbeb 100644
--- a/ruoyi-plus-soybean/src/views/analy/store-silk/index.vue
+++ b/ruoyi-plus-soybean/src/views/analy/store-silk/index.vue
@@ -1,5 +1,5 @@
<script setup lang="tsx">
-import { ref } from 'vue';
+import { computed, ref } from 'vue';
import { NDivider } from 'naive-ui';
import { fetchBatchDeleteStoreSilk, fetchGetStoreSilkList } from '@/service/api/analy/store-silk';
import { useAppStore } from '@/store/modules/app';
@@ -11,6 +11,7 @@
import StoreSilkOperateDrawer from './modules/store-silk-operate-drawer.vue';
import StoreSilkSearch from './modules/store-silk-search.vue';
import StoreSilkDetail from './modules/store-silk-detail.vue';
+import StoreSilkSankey from './modules/store-silk-sankey.vue';
defineOptions({
name: 'StoreSilkList'
@@ -20,8 +21,32 @@
const { download } = useDownload();
const { hasAuth } = useAuth();
+
+
const selectedRollerDetailList = ref<any[]>([]);
const selectedPackerDetailList = ref<any[]>([]);
+
+// 妗戝熀鍥緎tart
+const showSankey = ref(false);
+const rollerRecordList = ref<any[]>([]);
+const packerRecordList = ref<any[]>([]);
+// 妗戝熀鍥緀nd
+
+const sankeyRollerBoxList = computed(() => {
+ return (rollerRecordList.value || []).map(item => {
+ const v = calcRollerBox((item as any).output);
+ const output = v === null ? null : Number(v.toFixed(2));
+ return { ...(item as any), output };
+ });
+});
+
+const sankeyPackerBoxList = computed(() => {
+ return (packerRecordList.value || []).map(item => {
+ const v = calcPackerBox((item as any).output);
+ const output = v === null ? null : Number(v.toFixed(2));
+ return { ...(item as any), output };
+ });
+});
const searchParams = ref<Api.Analy.StoreSilkSearchParams>({
pageNum: 1,
@@ -45,9 +70,33 @@
}
const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
- useNaivePaginatedTable({
+ useNaivePaginatedTable<any, any>({
api: () => fetchGetStoreSilkList(searchParams.value),
- transform: response => defaultTransform(response),
+ transform: response => {
+ const respData = (response as any).data;
+ const error = (response as any).error;
+
+ if (!error) {
+ const rows = Array.isArray(respData?.rows) ? respData.rows : [];
+ const apiRollerRecordList = respData?.rollerRecordList;
+ const apiPackerRecordList = respData?.packerRecordList;
+
+ rollerRecordList.value =
+ Array.isArray(apiRollerRecordList) && apiRollerRecordList.length > 0
+ ? apiRollerRecordList
+ : rows.flatMap((r: any) => (Array.isArray(r?.rollerDetailList) ? r.rollerDetailList : []));
+
+ packerRecordList.value =
+ Array.isArray(apiPackerRecordList) && apiPackerRecordList.length > 0
+ ? apiPackerRecordList
+ : rows.flatMap((r: any) => (Array.isArray(r?.packerDetailList) ? r.packerDetailList : []));
+ } else {
+ rollerRecordList.value = [];
+ packerRecordList.value = [];
+ }
+
+ return defaultTransform(response as any);
+ },
onPaginationParamsChange: params => {
searchParams.value.pageNum = params.page;
searchParams.value.pageSize = params.pageSize;
@@ -64,19 +113,19 @@
key: 'materialname',
title: '鐗屽彿',
align: 'center',
- minWidth: 120
+ minWidth: 96
},
{
key: 'batchcode',
title: '鎵规鍙�',
align: 'center',
- minWidth: 130
+ minWidth: 110
},
{
key: 'rollerOutput',
title: '鍗锋帴浜ч噺(绠�)',
align: 'center',
- minWidth: 120,
+ minWidth: 112,
render: row => {
const v = calcRollerBox((row as any).rollerOutput);
if (v === null) return '-';
@@ -84,10 +133,27 @@
}
},
{
+ key: 'rollerUnitCost',
+ title: '鍗锋帴鍗曡��',
+ align: 'center',
+ minWidth: 96,
+ render: row => {
+ const box = calcRollerBox((row as any).rollerOutput);
+ if (box === null || box <= 0) return '-';
+ const jobinput = Number((row as any).jobinput);
+ const weight = Number((row as any).weight);
+ const diff = jobinput - weight;
+ if (!Number.isFinite(diff)) return '-';
+ const val = diff / box;
+ if (!Number.isFinite(val)) return '-';
+ return val.toFixed(2);
+ }
+ },
+ {
key: 'packerOutput',
title: '鍖呰浜ч噺(绠�)',
align: 'center',
- minWidth: 120,
+ minWidth: 112,
render: row => {
const v = calcPackerBox((row as any).packerOutput);
if (v === null) return '-';
@@ -95,46 +161,63 @@
}
},
{
+ key: 'packerUnitCost',
+ title: '鍖呰鍗曡��',
+ align: 'center',
+ minWidth: 96,
+ render: row => {
+ const box = calcPackerBox((row as any).packerOutput);
+ if (box === null || box <= 0) return '-';
+ const jobinput = Number((row as any).jobinput);
+ const weight = Number((row as any).weight);
+ const diff = jobinput - weight;
+ if (!Number.isFinite(diff)) return '-';
+ const val = diff / box;
+ if (!Number.isFinite(val)) return '-';
+ return val.toFixed(2);
+ }
+ },
+ {
key: 'actualstarttime',
title: '鎶曟枡鏃ユ湡',
align: 'center',
- width: 180
+ width: 160
},
{
key: 'jobinput',
title: '鎶曟枡閲嶉噺',
align: 'center',
- minWidth: 120
+ minWidth: 96
},
{
key: 'weight',
title: '鍌ㄤ笣鏌滈噸閲�',
align: 'center',
- minWidth: 120
+ minWidth: 96
},
{
key: 'distimebegin',
title: '鍌ㄤ笣鏌滃嚭鏂欏紑濮嬫椂闂�',
align: 'center',
- width: 180
+ width: 160
},
{
key: 'distimeend',
title: '鍌ㄤ笣鏌滃嚭鏂欑粨鏉熸椂闂�',
align: 'center',
- width: 180
+ width: 160
},
{
key: 'siloid',
title: '鏌滃瓙鍙�(鏈綅)',
align: 'center',
- width: 160
+ width: 120
}
]
});
const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
- useTableOperate(data, 'id', getData);
+ useTableOperate<any>(data, 'id', getData);
async function handleBatchDelete() {
// request
@@ -194,12 +277,22 @@
:loading="loading"
:show-add="false"
:show-delete="false"
- :show-export="hasAuth('analy:storeSilk:export')"
+ :show-export="!showSankey && hasAuth('analy:storeSilk:export')"
@add="handleAdd"
@delete="handleBatchDelete"
@export="handleExport"
@refresh="getData"
>
+ <template #prefix>
+ <NButton
+ size="small"
+ ghost
+ :type="showSankey ? 'primary' : 'default'"
+ @click="showSankey = !showSankey"
+ >
+ {{ showSankey ? '鍒楄〃' : '妗戝熀鍥�' }}
+ </NButton>
+ </template>
<template #suffix>
<NPopover placement="bottom-end" trigger="click">
<template #trigger>
@@ -221,8 +314,16 @@
</template>
</TableHeaderOperation>
</template>
+ <StoreSilkSankey
+ v-if="showSankey"
+ :roller-record-list="sankeyRollerBoxList"
+ :packer-record-list="sankeyPackerBoxList"
+ :rows="data"
+ class="h-full"
+ />
<NDataTable
- :columns="columns"
+ v-else
+ :columns="columns as any"
:data="data"
:size="tableSize"
:flex-height="!appStore.isMobile"
@@ -242,6 +343,7 @@
/>
</NCard>
<StoreSilkDetail
+ v-if="!showSankey"
:roller-detail-list="selectedRollerDetailList"
:packer-detail-list="selectedPackerDetailList"
class="h-[192px] overflow-hidden"
@@ -252,7 +354,6 @@
<style scoped>
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
- padding-top: 4px;
- padding-bottom: 4px;
+ padding: 4px 6px;
}
</style>
diff --git a/ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-detail.vue b/ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-detail.vue
index d652e37..9c0252b 100644
--- a/ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-detail.vue
+++ b/ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-detail.vue
@@ -55,38 +55,38 @@
key: 'index',
title: $t('common.index'),
align: 'center',
- width: 64,
+ width: 56,
render: (_: any, index: number) => index + 1
},
{
key: 'fsNum',
title: '鍠備笣鏈哄彿',
align: 'center',
- width: 100
+ width: 84
},
{
key: 'siloNum',
title: '鍌ㄤ笣鏌滃彿',
align: 'center',
- width: 100
+ width: 84
},
{
key: 'pipeNum',
title: '绠¢亾鍙�',
align: 'center',
- width: 100
+ width: 84
},
{
key: 'equNo',
title: '鏈哄彴鍙�',
align: 'center',
- width: 100
+ width: 72
},
{
key: 'shiftCode',
title: '鐝浠g爜',
align: 'center',
- width: 100,
+ width: 88,
render: (row: StoreSilkDetailVo) => {
const map: Record<string, string> = {
'1': '鏃╃彮',
@@ -100,19 +100,19 @@
key: 'shiftStartTime',
title: '鐝寮�濮嬫椂闂�',
align: 'center',
- width: 160
+ width: 148
},
{
key: 'shiftEndTime',
title: '鐝缁撴潫鏃堕棿',
align: 'center',
- width: 160
+ width: 148
},
{
key: 'output',
title: '浜ч噺(鍗冩敮)',
align: 'center',
- width: 120,
+ width: 96,
render: (row: StoreSilkDetailVo) => {
if (row.output === null || row.output === undefined) return '-';
const v = Number(row.output);
@@ -124,7 +124,7 @@
key: 'outputBox',
title: '浜ч噺(绠�)',
align: 'center',
- width: 100,
+ width: 84,
render: (row: StoreSilkDetailVo) => {
const v = detailType.value === 'roller' ? calcRollerBox(row.output) : calcPackerBox(row.output);
if (v === null) return '-';
@@ -170,4 +170,9 @@
:deep(.n-card__content) {
padding: 8px 12px;
}
+
+:deep(.n-data-table-th),
+:deep(.n-data-table-td) {
+ padding: 4px 6px;
+}
</style>
diff --git a/ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-search.vue b/ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-search.vue
index ce8a1d2..ffb40b6 100644
--- a/ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-search.vue
+++ b/ruoyi-plus-soybean/src/views/analy/store-silk/modules/store-silk-search.vue
@@ -34,51 +34,78 @@
const dateRange = ref<[string, string] | null>(null);
-onMounted(() => {
- if (model.value.params?.beginTime && model.value.params?.endTime) {
- dateRange.value = [model.value.params.beginTime as string, model.value.params.endTime as string];
+function onDateRangeUpdate(value: [string, string] | null) {
+ if (!model.value.params) {
+ model.value.params = {};
+ }
+
+ const beginTime = value?.[0] ? String(value[0]).trim() : '';
+ const endTime = value?.[1] ? String(value[1]).trim() : '';
+
+ if (beginTime && endTime) {
+ model.value.params.beginTime = beginTime;
+ model.value.params.endTime = endTime;
} else {
- dateRange.value = getDefaultRange();
- if (!model.value.params) {
- model.value.params = {};
- }
- model.value.params.beginTime = dateRange.value[0];
- model.value.params.endTime = dateRange.value[1];
+ delete model.value.params.beginTime;
+ delete model.value.params.endTime;
+ }
+}
+
+function setDefaultRange() {
+ const range = getDefaultRange();
+ dateRange.value = range;
+ onDateRangeUpdate(range);
+}
+
+onMounted(() => {
+ if (!model.value.params) {
+ model.value.params = {};
+ }
+
+ const beginTime = model.value.params.beginTime ? String(model.value.params.beginTime).trim() : '';
+ const endTime = model.value.params.endTime ? String(model.value.params.endTime).trim() : '';
+
+ if (beginTime && endTime) {
+ dateRange.value = [beginTime, endTime];
+ } else {
+ setDefaultRange();
}
});
-
-watch(
- dateRange,
- val => {
- if (!model.value.params) {
- model.value.params = {};
- }
- if (val && val[0] && val[1]) {
- model.value.params.beginTime = val[0];
- model.value.params.endTime = val[1];
- } else {
- model.value.params.beginTime = null;
- model.value.params.endTime = null;
- }
- },
- { deep: true }
-);
async function reset() {
await restoreValidation();
resetModel();
- dateRange.value = getDefaultRange();
- if (!model.value.params) {
- model.value.params = {};
- }
- model.value.params.beginTime = dateRange.value[0];
- model.value.params.endTime = dateRange.value[1];
+ setDefaultRange();
emit('search');
}
async function search() {
await validate();
emit('search');
+}
+
+const siloOptions = Array.from({ length: 12 }, (_, i) => ({
+ label: `${i + 1}鍙峰偍涓濇煖`,
+ value: String(i + 1)
+}));
+
+const selectedSilos = ref<string[]>([]);
+
+watch(
+ () => model.value.siloid,
+ val => {
+ if (val) {
+ selectedSilos.value = (val as string).split(',');
+ } else {
+ selectedSilos.value = [];
+ }
+ },
+ { immediate: true }
+);
+
+function handleSiloChange(val: string[]) {
+ selectedSilos.value = val;
+ model.value.siloid = val.join(',');
}
</script>
@@ -95,10 +122,10 @@
path="materialname"
class="pr-24px"
>
- <NInput v-model:value="model.materialname" placeholder="璇疯緭鍏ョ墝鍙�" />
+ <NInput v-model:value="model.materialname" clearable placeholder="璇疯緭鍏ョ墝鍙�" />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:8 l:8 xl:8" label="鎵规鍙�" label-width="auto" path="batchcode" class="pr-24px">
- <NInput v-model:value="model.batchcode" placeholder="璇疯緭鍏ユ壒娆″彿" />
+ <NInput v-model:value="model.batchcode" clearable placeholder="璇疯緭鍏ユ壒娆″彿" />
</NFormItemGi>
<NFormItemGi
span="24 s:12 m:8 l:8 xl:8"
@@ -109,9 +136,10 @@
>
<NDatePicker
v-model:formatted-value="model.actualstarttime"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
+ type="date"
+ value-format="yyyy-MM-dd"
clearable
+ class="w-full"
/>
</NFormItemGi>
<NFormItemGi
@@ -127,6 +155,8 @@
:default-time="['00:00:00', '23:59:59']"
value-format="yyyy-MM-dd HH:mm:ss"
clearable
+ class="w-full"
+ @update:formatted-value="onDateRangeUpdate"
/>
</NFormItemGi>
<NFormItemGi
@@ -136,7 +166,14 @@
path="siloid"
class="pr-24px"
>
- <NInput v-model:value="model.siloid" placeholder="璇疯緭鍏ユ煖瀛愬彿(鏈綅)" />
+ <NSelect
+ v-model:value="selectedSilos"
+ multiple
+ clearable
+ :options="siloOptions"
+ placeholder="璇烽�夋嫨鏌滃瓙鍙�"
+ @update:value="handleSiloChange"
+ />
</NFormItemGi>
<NFormItemGi :show-feedback="false" span="24" class="pr-24px">
<NSpace class="w-full" justify="end">
--
Gitblit v1.9.3