From bbaf8175e73c8579ef14a6b4a678bcb98177834b Mon Sep 17 00:00:00 2001
From: 张诺 <zhang_12370@163.com>
Date: 星期一, 27 四月 2026 14:00:05 +0800
Subject: [PATCH] feat(生产报工): 合并开始与结束报工为单一报工流程
---
src/pages/productionManagement/productionReport/index.vue | 171 +++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 130 insertions(+), 41 deletions(-)
diff --git a/src/pages/productionManagement/productionReport/index.vue b/src/pages/productionManagement/productionReport/index.vue
index f5f345c..0bbce64 100644
--- a/src/pages/productionManagement/productionReport/index.vue
+++ b/src/pages/productionManagement/productionReport/index.vue
@@ -55,10 +55,6 @@
<text class="detail-value">{{ item.model || '鏃�' }}</text>
</view>
<view class="detail-row">
- <text class="detail-label">鏈哄彴鍚嶇О</text>
- <text class="detail-value">{{ item.deviceName || '鏃�' }}</text>
- </view>
- <view class="detail-row">
<text class="detail-label">宸ュ簭鍚嶇О / 璁¢噺鍗曚綅</text>
<text class="detail-value">{{ item.processName || '鏃�' }} / {{ item.unit || '鏃�' }}</text>
</view>
@@ -77,26 +73,11 @@
></up-line-progress>
</view>
</view>
- <view class="detail-row">
- <text class="detail-label">瀹為檯寮�濮�</text>
- <text class="detail-value">{{ item.startProductTime || '-' }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">瀹為檯缁撴潫</text>
- <text class="detail-value">{{ item.endProductTime || '-' }}</text>
- </view>
</view>
<view class="item-actions" v-if="!isEnded(item)">
<up-button
- text="寮�濮嬫姤宸�"
- size="mini"
- type="primary"
- :disabled="!canStartProduction(item) || startSubmittingId === item.id"
- @click.stop="handleStartProduction(item)"
- />
- <up-button
- text="缁撴潫鎶ュ伐"
+ text="鎶ュ伐"
size="mini"
type="success"
:disabled="!canEndProduction(item)"
@@ -176,7 +157,7 @@
</view>
</up-popup>
- <!-- 缁撴潫鎶ュ伐寮圭獥 -->
+ <!-- 鎶ュ伐寮圭獥 -->
<up-popup
v-model:show="endReportVisible"
mode="bottom"
@@ -187,7 +168,7 @@
<view class="report-modal">
<view class="modal-header">
<view class="modal-header-left">
- <text class="modal-title">缁撴潫鎶ュ伐</text>
+ <text class="modal-title">鎶ュ伐</text>
<text class="modal-subtitle" v-if="endReportRow">
{{ endReportRow.workOrderNo || '-' }} 路 {{ endReportRow.deviceName || '-' }}
</text>
@@ -198,7 +179,7 @@
</view>
<scroll-view class="modal-content" scroll-y>
- <view class="report-summary" v-if="endReportRow">
+ <!-- <view class="report-summary" v-if="endReportRow">
<view class="summary-left">
<text class="summary-title">{{ endReportRow.productName || '-' }}</text>
<text class="summary-sub">{{ endReportRow.processName || '-' }} 路 {{ endReportRow.model || '-' }}</text>
@@ -207,7 +188,7 @@
<text class="summary-num">{{ endReportForm.planQuantity || '0' }}</text>
<text class="summary-label">寰呯敓浜�</text>
</view>
- </view>
+ </view> -->
<up-form :model="endReportForm" labelWidth="120">
<view class="form-section">
@@ -216,7 +197,7 @@
<up-input v-model="endReportForm.planQuantity" disabled />
</up-form-item>
<up-form-item label="鏈鐢熶骇鏁伴噺" required>
- <up-input v-model="endReportForm.quantity" disabled />
+ <up-input v-model="endReportForm.quantity" />
</up-form-item>
<up-form-item label="琛ヤ骇鏁伴噺">
<up-input v-model="endReportForm.replenishQty" type="number" placeholder="璇疯緭鍏�" />
@@ -224,9 +205,35 @@
<up-form-item label="鎶ュ簾鏁伴噺">
<up-input v-model="endReportForm.scrapQty" type="number" placeholder="璇疯緭鍏�" />
</up-form-item>
+ <up-form-item label="寮�濮嬫椂闂�" required>
+ <up-input
+ v-model="endReportForm.startTime"
+ readonly
+ placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
+ @click="startTimePickerVisible = true"
+ />
+</up-form-item>
+
+<up-form-item label="缁撴潫鏃堕棿" required>
+ <up-input
+ v-model="endReportForm.endTime"
+ readonly
+ placeholder="璇烽�夋嫨缁撴潫鏃堕棿"
+ @click="endTimePickerVisible = true"
+ />
+</up-form-item>
</view>
<view class="form-section">
+ <up-form-item label="鏈哄彴" required>
+ <up-input
+ v-model="endReportForm.deviceName"
+ readonly
+ placeholder="璇烽�夋嫨"
+ @click="openDevicePicker"
+ suffixIcon="arrow-down"
+ />
+ </up-form-item>
<up-form-item label="鐝粍浜哄憳">
<up-input
v-model="teamDisplayText"
@@ -298,6 +305,13 @@
@select="onAuditSelect"
@close="auditPickerVisible = false"
/>
+ <up-action-sheet
+ :show="devicePickerVisible"
+ :actions="deviceActions"
+ title="閫夋嫨鏈哄彴"
+ @select="onDeviceSelect"
+ @close="devicePickerVisible = false"
+ />
<!-- 鏃堕棿閫夋嫨鍣� -->
<up-datetime-picker
@@ -324,6 +338,7 @@
import { ref, reactive, toRefs, computed, getCurrentInstance } from "vue";
import { onShow, onLoad, onReachBottom } from "@dcloudio/uni-app";
import { productWorkOrderPage, addProductMain, startProduction, getProductWorkOrderById,getProductionProductMain } from "@/api/productionManagement/productionReporting.js";
+import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
import { userListNoPageByTenantId } from "@/api/system/user.js";
import PageHeader from "@/components/PageHeader.vue";
import FilesDia from "./components/filesDia.vue";
@@ -368,6 +383,8 @@
quantity: "",
replenishQty: "0",
scrapQty: "0",
+ deviceLedgerId: "",
+ deviceName: "",
teamList: [],
startTime: "",
endTime: "",
@@ -384,6 +401,10 @@
const userOptions = ref([]);
const auditPickerVisible = ref(false);
const auditActions = computed(() => userOptions.value.map(u => ({ name: u.name, value: u.value })));
+
+const deviceOptions = ref([]);
+const devicePickerVisible = ref(false);
+const deviceActions = computed(() => deviceOptions.value.map(d => ({ name: d?.deviceName || "", value: d?.id })));
const teamPickerVisible = ref(false);
const teamCheckedIds = ref([]);
@@ -456,8 +477,17 @@
}
};
+const ensureDeviceOptions = async () => {
+ if (deviceOptions.value.length > 0) return;
+ try {
+ const res = await getDeviceLedger();
+ deviceOptions.value = res?.data || [];
+ } catch {
+ deviceOptions.value = [];
+ }
+};
+
const getList = () => {
- console.log(searchForm.value);
if (loading.value) return;
loading.value = true;
@@ -607,10 +637,8 @@
const canEndProduction = (row) => {
if (!row?.id) return false;
- if (getPendingQty(row) <= 0) return false;
if (isEnded(row)) return false;
- return isStarted(row);
-
+ return true;
};
// 鍒ゆ柇鏄惁鍙互寮�濮嬫姤宸�
@@ -626,7 +654,9 @@
// 鏍规嵁userIds鍒ゆ柇鏄惁鏈夌敤鎴峰彲浠ユ姤宸�
const canStartProductionByUserIds = (userId, row) => {
const team = row?.userIds || "";
- return team.includes(userId);
+ if (!userId) return true;
+ if (!team) return true;
+ return String(team).includes(String(userId));
};
const handleStartProduction = (row) => {
@@ -677,11 +707,14 @@
endReportRow.value = row;
await ensureUserInfo();
await ensureUserOptions();
+ await ensureDeviceOptions();
endReportForm.planQuantity = String(getPendingQty(row));
endReportForm.quantity = String(getPendingQty(row));
endReportForm.replenishQty = "0";
endReportForm.scrapQty = "0";
+ endReportForm.deviceLedgerId = "";
+ endReportForm.deviceName = "";
endReportForm.teamList = [];
teamCheckedIds.value = [];
@@ -704,6 +737,14 @@
endTimeValue.value = Date.now();
endReportForm.endTime = formatDateTime(endTimeValue.value);
+ if (row?.deviceName) {
+ const matched = deviceOptions.value.find(d => String(d?.deviceName || "") === String(row.deviceName));
+ if (matched) {
+ endReportForm.deviceLedgerId = String(matched.id ?? "");
+ endReportForm.deviceName = String(matched.deviceName ?? "");
+ }
+ }
+
endReportVisible.value = true;
};
@@ -721,6 +762,17 @@
endReportForm.auditUserId = String(e?.value ?? "");
endReportForm.auditUserName = String(e?.name ?? "");
auditPickerVisible.value = false;
+};
+
+const openDevicePicker = async () => {
+ await ensureDeviceOptions();
+ devicePickerVisible.value = true;
+};
+
+const onDeviceSelect = (e) => {
+ endReportForm.deviceLedgerId = String(e?.value ?? "");
+ endReportForm.deviceName = String(e?.name ?? "");
+ devicePickerVisible.value = false;
};
const openTeamPicker = async () => {
@@ -741,12 +793,25 @@
};
const onStartTimeConfirm = (e) => {
- endReportForm.startTime = formatDateTime(e.value);
+ const start = e.value;
+ endReportForm.startTime = formatDateTime(start);
startTimePickerVisible.value = false;
+
+ // 馃憠 鑷姩缁欑粨鏉熸椂闂� +1灏忔椂
+ const end = start + 60 * 60 * 1000;
+ endTimeValue.value = end;
+ endReportForm.endTime = formatDateTime(end);
};
const onEndTimeConfirm = (e) => {
- endReportForm.endTime = formatDateTime(e.value);
+ const end = e.value;
+
+ if (end <= startTimeValue.value) {
+ showToast("缁撴潫鏃堕棿蹇呴』澶т簬寮�濮嬫椂闂�");
+ return;
+ }
+
+ endReportForm.endTime = formatDateTime(end);
endTimePickerVisible.value = false;
};
@@ -780,9 +845,31 @@
showToast("鎶ュ簾鏁伴噺蹇呴』涓哄ぇ浜庣瓑浜�0鐨勬暣鏁�");
return;
}
+ if (!endReportForm.startTime) {
+ showToast("璇烽�夋嫨寮�濮嬫椂闂�");
+ return;
+}
+
+if (!endReportForm.endTime) {
+ showToast("璇烽�夋嫨缁撴潫鏃堕棿");
+ return;
+}
+
+const start = new Date(endReportForm.startTime).getTime();
+const end = new Date(endReportForm.endTime).getTime();
+
+if (end <= start) {
+ showToast("缁撴潫鏃堕棿蹇呴』澶т簬寮�濮嬫椂闂�");
+ return;
+}
if (!endReportForm.auditUserId) {
showToast("璇烽�夋嫨瀹℃牳浜�");
+ return;
+ }
+
+ if (!endReportForm.deviceLedgerId) {
+ showToast("璇烽�夋嫨鏈哄彴");
return;
}
@@ -799,17 +886,19 @@
userName: endReportForm.userName || userStore.nickName,
auditUserId: endReportForm.auditUserId,
auditUserName: endReportForm.auditUserName,
+ deviceLedgerId: endReportForm.deviceLedgerId,
+ deviceName: endReportForm.deviceName,
};
const res = await addProductMain(submitData);
if (res?.code === 200) {
- showToast("缁撴潫鎶ュ伐鎴愬姛");
+ showToast("鎶ュ伐鎴愬姛");
closeEndReport();
handleQuery();
} else {
- showToast(res?.msg || "缁撴潫鎶ュ伐澶辫触");
+ showToast(res?.msg || "鎶ュ伐澶辫触");
}
} catch {
- showToast("缁撴潫鎶ュ伐澶辫触");
+ showToast("鎶ュ伐澶辫触");
} finally {
uni.hideLoading();
}
@@ -878,9 +967,9 @@
}
.qr-popup {
- width: 620rpx;
- max-width: 88vw;
- max-height: 80vh;
+ width: 90vw;
+ max-width: 900rpx;
+ max-height: 85vh; // 鍘熸潵 80 鈫� 鍔犲ぇ
padding: 32rpx 28rpx;
background: #fff;
border-radius: 20rpx;
@@ -934,7 +1023,7 @@
text-align: center;
}
.transfer-records-list {
- max-height: 420rpx;
+ max-height: 500rpx;
overflow: auto;
}
.transfer-record-item {
@@ -942,6 +1031,7 @@
border-radius: 16rpx;
background: #f7f8fa;
}
+
.transfer-record-item + .transfer-record-item {
margin-top: 16rpx;
}
@@ -975,8 +1065,7 @@
margin-top: 18rpx;
}
.transfer-record-cell {
- width: calc(50% - 8rpx);
- min-width: 0;
+ width: 100%; // 鍘熸潵涓�琛屼袱涓� 鈫� 鏀规垚涓�琛屼竴涓�
}
.transfer-record-cell.is-wide {
width: 100%;
--
Gitblit v1.9.3