695593266@qq.com 3 luni în urmă
părinte
comite
b6fc3d02b4

+ 216 - 10
pages/pda/feeding/components/workOrderBom.vue

@@ -92,13 +92,29 @@
       </view>
     </view>
     <!-- {{ clientEnvironmentId }} {{ pType }} -->
-    <view class="title_box mt20 rx-bc" v-if="pType == 'feed' || pType == 'job'">
-      <view class="name"
-        >{{ pType == "feed" ? "实际投料时间" : "实际报工时间" }}
+    <view class="title_box mt20 rx-bc" v-if="pType == 'feed'">
+      <view class="name"> 实际投料时间 </view>
+    </view>
+
+    <view class="material" v-if="pType == 'feed'">
+      <view class="content_table">
+        <view class="item">
+          <view class="content">
+            <uni-datetime-picker
+              type="datetime"
+              :value="currentExecutorTime"
+              @change="changeTime($event, item)"
+            />
+          </view>
+        </view>
       </view>
     </view>
 
-    <view class="material" v-if="pType == 'feed' || pType == 'job'">
+    <view class="title_box mt20 rx-bc" v-if="pType == 'job' && !isReportTime">
+      <view class="name"> 实际报工时间 </view>
+    </view>
+
+    <view class="material" v-if="pType == 'job' && !isReportTime">
       <view class="content_table">
         <view class="item">
           <view class="content">
@@ -111,6 +127,32 @@
         </view>
       </view>
     </view>
+
+    <view class="title_box mt20 rx-bc" v-if="pType == 'job' && isReportTime">
+      <view class="name"> 实际报工时间 </view>
+    </view>
+
+    <view class="material" v-if="pType == 'job' && isReportTime">
+      <view class="content_table">
+        <view class="item">
+          <view class="content">
+            <uni-datetime-picker
+              v-model="datetimerange"
+              type="datetimerange"
+              rangeSeparator="至"
+            />
+          </view>
+        </view>
+
+        <view class="item" v-if="isReportWork && pType == 'job'">
+          <view class="lable rx-cc">工时</view>
+
+          <view class="content content_num">
+            <input style="width: 40%" v-model="item.workTime" />小时
+          </view>
+        </view>
+      </view>
+    </view>
   </view>
 </template>
 
@@ -148,8 +190,47 @@ export default {
         uni.getStorageSync("userInfo") &&
         uni.getStorageSync("userInfo").clientEnvironmentId,
       currentExecutorTime: "",
+      isReportTime: false,
+      datetimerange: [],
     };
   },
+  watch: {
+    datetimerange: {
+      deep: true,
+      handler(val) {
+        if (!(this.pType == "job" && this.isReportTime)) return;
+        this.applyDateTimeRange(val);
+      },
+    },
+    item: {
+      immediate: true,
+      deep: true,
+      handler() {
+        // 初始化/回显:当外部把 start/end 带进来时,同步到 range 组件
+        if (!(this.pType == "job" && this.isReportTime)) return;
+        const start =
+          this.item?.workReportInfo?.executorStartTime ||
+          this.item?.executorStartTime ||
+          "";
+        const end =
+          this.item?.workReportInfo?.executorTime ||
+          this.item?.executorTime ||
+          "";
+        if (start && end) {
+          const range = [this.normalizeDateTime(start), this.normalizeDateTime(end)];
+          // 避免反复触发 watch 造成抖动
+          if (
+            !Array.isArray(this.datetimerange) ||
+            this.datetimerange.length !== 2 ||
+            this.datetimerange[0] !== range[0] ||
+            this.datetimerange[1] !== range[1]
+          ) {
+            this.datetimerange = range;
+          }
+        }
+      },
+    },
+  },
   // watch: {
   //   item: {
   //     immediate: true,
@@ -169,8 +250,8 @@ export default {
   // },
 
   created() {
-    console.log("item", this.item);
     this.getByCode();
+    this.getChooseEngrave();
   },
   methods: {
     changeTime(e, val) {
@@ -183,8 +264,127 @@ export default {
       }
       this.item.executorTime = this.currentExecutorTime;
     },
+
+    normalizeDateTime(value) {
+      if (!value) return "";
+      const v = String(value).trim();
+      // yyyy-MM-dd => yyyy-MM-dd 00:00:00
+      const dateOnly = /^\d{4}-\d{2}-\d{2}$/;
+      if (dateOnly.test(v)) return `${v} 00:00:00`;
+      return v;
+    },
+
+    parseDateTime(value) {
+      const v = this.normalizeDateTime(value);
+      if (!v) return null;
+      // 兼容部分环境 Date("yyyy-MM-dd HH:mm:ss") 的解析问题
+      const safe = v.replace(/-/g, "/");
+      const d = new Date(safe);
+      return Number.isNaN(d.getTime()) ? null : d;
+    },
+
+    hoursDiff(start, end) {
+      const s = this.parseDateTime(start);
+      const e = this.parseDateTime(end);
+      if (!s || !e) return "";
+      const ms = e.getTime() - s.getTime();
+      if (ms < 0) return "";
+      // 保留 2 位小数(小时)
+      return (ms / 36e5).toFixed(2);
+    },
+
+    applyDateTimeRange(range) {
+      // 清空时间范围时,同步清空开始/结束/工时,避免残留
+      if (
+        !Array.isArray(range) ||
+        range.length !== 2 ||
+        !range[0] ||
+        !range[1]
+      ) {
+        this.clearReportTimesAndWorkTime();
+        return;
+      }
+      const start = this.normalizeDateTime(range[0]);
+      const end = this.normalizeDateTime(range[1]);
+      if (!start || !end) {
+        this.clearReportTimesAndWorkTime();
+        return;
+      }
+
+      const s = this.parseDateTime(start);
+      const e = this.parseDateTime(end);
+      if (!s || !e) return;
+
+      // 结束时间不能大于当前时间:超出则回填为当前时间
+      const now = new Date();
+      if (e.getTime() > now.getTime()) {
+        const pad2 = (n) => String(n).padStart(2, "0");
+        const nowStr = `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())} ${pad2(now.getHours())}:${pad2(now.getMinutes())}:${pad2(now.getSeconds())}`;
+        this.datetimerange = [start, nowStr];
+        uni.showToast({
+          title: "结束时间不能大于当前时间",
+          icon: "none",
+        });
+        this.setReportTimes(start, nowStr);
+        this.setWorkTime(this.hoursDiff(start, nowStr));
+        return;
+      }
+
+      if (e.getTime() < s.getTime()) {
+        // 结束不能小于开始:直接把结束回填为开始,并提示
+        this.datetimerange = [start, start];
+        uni.showToast({
+          title: "结束时间不能小于开始时间",
+          icon: "none",
+        });
+        this.setReportTimes(start, start);
+        this.setWorkTime(this.hoursDiff(start, start));
+        return;
+      }
+
+      this.setReportTimes(start, end);
+      this.setWorkTime(this.hoursDiff(start, end));
+    },
+
+    clearReportTimesAndWorkTime() {
+      if (!this.item) return;
+      if (!this.item.workReportInfo) {
+        this.$set(this.item, "workReportInfo", {});
+      }
+      this.$set(this.item.workReportInfo, "executorStartTime", "");
+      this.$set(this.item.workReportInfo, "executorTime", "");
+      this.$set(this.item.workReportInfo, "workTime", "");
+
+      this.$set(this.item, "executorStartTime", "");
+      this.$set(this.item, "executorTime", "");
+      this.$set(this.item, "workTime", "");
+      this.$forceUpdate();
+    },
+
+    setReportTimes(start, end) {
+      if (!this.item) return;
+      if (!this.item.workReportInfo) {
+        this.$set(this.item, "workReportInfo", {});
+      }
+      this.$set(this.item.workReportInfo, "executorStartTime", start);
+      this.$set(this.item.workReportInfo, "executorTime", end);
+
+      // 兼容页面上其他逻辑可能直接读 item 上的字段
+      this.$set(this.item, "executorStartTime", start);
+      this.$set(this.item, "executorTime", end);
+    },
+
+    setWorkTime(hours) {
+      if (hours === "") return;
+      if (!this.item) return;
+      if (!this.item.workReportInfo) {
+        this.$set(this.item, "workReportInfo", {});
+      }
+      this.$set(this.item.workReportInfo, "workTime", hours);
+      this.$set(this.item, "workTime", hours);
+      this.$forceUpdate();
+    },
     async getByCode() {
-      console.log("11111");
       await parameterGetByCode({ code: "mes_order_feed_by_default_date" }).then(
         (res) => {
           console.log("res", res);
@@ -204,16 +404,22 @@ export default {
               this.$set(
                 this.item.workReportInfo,
                 "executorTime",
-                this.currentExecutorTime
+                this.currentExecutorTime,
               );
-              console.log("executorTime", this.item.executorTime);
-              console.log("item", this.item);
               this.$forceUpdate();
             }
           }
-        }
+        },
       );
     },
+
+    async getChooseEngrave() {
+      await parameterGetByCode({
+        code: "work_hour",
+      }).then((res) => {
+        this.isReportTime = res.value == "1" ? true : false;
+      });
+    },
     handleScan(id) {
       this.$emit("handleScan", id, "wordOrder");
     },

+ 23 - 31
pages/pda/jobBooking/index/index.vue

@@ -467,6 +467,7 @@ import oneJobQualityBom from "../components/oneJobQualityBom.vue";
 import oneJobQualityBomPL from "../components/oneJobQualityBomPL.vue";
 import batchJobBom from "../components/batchJobBom.vue";
 import workInProgressList from "../components/workInProgressList.vue";
+import { parameterGetByCode } from "@/api/mainData/index.js";
 
 export default {
   components: {
@@ -588,7 +589,7 @@ export default {
         this.$set(
           this.objData.workReportInfo,
           "notFormedWeight",
-          notFormedWeight
+          notFormedWeight,
         );
       });
       this.$forceUpdate();
@@ -865,6 +866,9 @@ export default {
             executorTime: "",
             lossNum: null,
             lossWeight: null,
+            executorStartTime: null,
+            reportTime: "",
+            workTime: "",
           };
 
           this.objData.notFormedList = [
@@ -888,7 +892,7 @@ export default {
 
               console.log(item, "item");
               return item;
-            }
+            },
           );
 
           this.objData.product = this.objData.product.map((item) => {
@@ -997,7 +1001,7 @@ export default {
         this.$set(
           this.objData.notFormedList[0],
           "warehouseId",
-          this.formData.warehouseId || null
+          this.formData.warehouseId || null,
         );
       } else {
         this.objData.productRecycleList[this.penalizeIndex].warehouseId =
@@ -1019,28 +1023,12 @@ export default {
     async save(type) {
       // 验证判断条件
       this.$isJobExls(1, this.objData);
-
-      console.log(this.objData, "this.objData");
-
       // return;
 
-      // for (let i = 0; i < this.List.length; i++) {
-      //   if (
-      //     !this.List[i].executorTime &&
-      //     this.List[i].executorTime == undefined
-      //   ) {
-      //     uni.showToast({
-      //       title: `请先选择报工时间`,
-      //       icon: "none",
-      //     });
-      //     return;
-      //   }
-      // }
-
       if (!(this.clientEnvironmentId == 3 || this.objData.singleReport !== 1)) {
         if (this.objData.semiProductList.length) {
           let arr = this.objData.semiProductList.filter(
-            (v) => v.selected == true
+            (v) => v.selected == true,
           );
           this.objData.semiProductList = arr;
           if (!arr.length) {
@@ -1049,19 +1037,23 @@ export default {
               icon: "none",
             });
           }
-          // else{
-          // 	let engraveList = arr.filter(v=> v.extInfo.engrave ==null);
-
-          // 	if(engraveList.length){
-          // 		return uni.showToast({
-          // 			title: '请输入刻码',
-          // 			icon: 'none'
-          // 		})
-          // 	}
-          // }
         }
       }
 
+      await parameterGetByCode({
+        code: "work_hour",
+      }).then((res) => {
+        if (res.value == "1") {
+          if (!this.objData.workReportInfo["executorStartTime"]) {
+            uni.showToast({
+              title: `请先选择报工时间`,
+              icon: "none",
+            });
+            return false;
+          }
+        }
+      });
+
       uni.showLoading({
         title: "加载中",
       });
@@ -1479,7 +1471,7 @@ export default {
       this.$set(
         this.objData.workReportInfo,
         "notFormedWeight",
-        notFormedWeightCount
+        notFormedWeightCount,
       ); //不合格总重量
       // this.$refs.jobReftg.formedTotal(
       //   formedNumCount,

+ 45 - 7
pages/pda/workOrder/index/details.vue

@@ -14,10 +14,25 @@
     <view class="list_box">
       <u-list @scrolltolower="scrolltolower" v-if="taskType != 5">
         <view class="card_box" v-for="(objData, index) in list" :key="index">
-          <view class="rx-bc title_card">
+          <view class="rx-bc title_card" v-if="!isReportTime">
             <view>{{ index + 1 }}</view>
             <view>报工时间: {{ objData.workReportInfo.executorTime }}</view>
           </view>
+
+          <view class="rx-bc title_card" v-if="isReportTime">
+            <view>{{ index + 1 }}</view>
+            <view class="report_row">
+              <view class="report_item">
+                报工时间: {{ objData.workReportInfo.executorStartTime }}-{{
+                  objData.workReportInfo.executorTime
+                }}
+              </view>
+              <view class="report_item">
+                工时: {{ objData.workReportInfo.workTime
+                }}{{ objData.workReportInfo.workTimeUnit }}
+              </view>
+            </view>
+          </view>
           <workOrderBom
             :item="objData"
             v-if="objData"
@@ -57,7 +72,7 @@
             v-if="
               Object.prototype.hasOwnProperty.call(
                 objData,
-                'semiProductList'
+                'semiProductList',
               ) &&
               objData.semiProductList.length &&
               taskType == 3
@@ -316,11 +331,10 @@ import newPackingBomDetails from "../../jobBooking/components/newPackingBomDetai
 import packingQtBom from "../../jobBooking/components/packingQtBom.vue";
 import batchProductJobBom from "../../jobBooking/components/batchProductJobBom.vue";
 
-//
-
 import detailsBom from "../../warehousing/components/detailsBom.vue";
 import detailsBatchBom from "../../warehousing/components/detailsBatchBom.vue";
 import workOrderBom2 from "../../warehousing/components/workOrderBom.vue";
+import { parameterGetByCode } from "@/api/mainData/index.js";
 
 export default {
   components: {
@@ -358,6 +372,7 @@ export default {
       taskId: null,
       list: [],
       taskType: 1,
+      isReportTime: false,
 
       clientEnvironmentId:
         uni.getStorageSync("userInfo") &&
@@ -370,6 +385,7 @@ export default {
     this.taskId = options.taskId;
     this.taskType = options.taskType;
     this.getList();
+    this.getChooseEngrave();
   },
 
   methods: {
@@ -384,6 +400,14 @@ export default {
       });
     },
 
+    async getChooseEngrave() {
+      await parameterGetByCode({
+        code: "work_hour",
+      }).then((res) => {
+        this.isReportTime = res.value == "1" ? true : false;
+      });
+    },
+
     scrolltolower() {},
   },
 };
@@ -434,13 +458,27 @@ export default {
 }
 
 .title_card {
-  height: 70rpx;
+  height: 90rpx;
   width: 100%;
   background: #157a2c;
-  font-size: 30rpx;
+  font-size: 24rpx;
   color: #fff;
-  line-height: 70rpx;
+  // line-height: 70rpx;
   padding: 0 22rpx;
   box-sizing: border-box;
 }
+
+.report_row {
+  // flex: 1;
+  display: flex;
+  flex-direction: column;
+  min-width: 0;
+}
+
+.report_item {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  min-width: 0;
+}
 </style>