From 48632e6d9a04e28d2f1ddd22e6896b281b21b128 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 16 四月 2026 13:19:33 +0800
Subject: [PATCH] 种形式想 1.报工传参错误
---
src/views/productionManagement/productionOrder/New.vue | 456 +++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 350 insertions(+), 106 deletions(-)
diff --git a/src/views/productionManagement/productionOrder/New.vue b/src/views/productionManagement/productionOrder/New.vue
index c9c478b..578f42b 100644
--- a/src/views/productionManagement/productionOrder/New.vue
+++ b/src/views/productionManagement/productionOrder/New.vue
@@ -1,68 +1,137 @@
<template>
<div>
<el-dialog
- v-model="isShow"
- title="鏂板鐢熶骇璁㈠崟"
- width="800"
- @close="closeModal"
+ v-model="isShow"
+ title="鏂板鐢熶骇璁㈠崟"
+ width="800"
+ @close="closeModal"
>
- <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
+ <el-form
+ ref="formRef"
+ :model="formState"
+ label-width="140px"
+ label-position="top"
+ >
<el-form-item
- label="浜у搧鍚嶇О"
- prop="productModelId"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨浜у搧',
- trigger: 'change',
- }
- ]"
+ label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧',
+ trigger: 'change',
+ },
+ ]"
>
<el-button type="primary" @click="showProductSelectDialog = true">
- {{ formState.productName ? formState.productName : '閫夋嫨浜у搧' }}
+ {{ formState.productName || "閫夋嫨浜у搧" }}
</el-button>
</el-form-item>
- <el-form-item
- label="瑙勬牸"
- prop="productModelName"
- >
- <el-input v-model="formState.productModelName" disabled />
+ <el-form-item label="瑙勬牸" prop="productModelName">
+ <el-input v-model="formState.productModelName" disabled />
+ </el-form-item>
+
+ <el-form-item label="鍗曚綅" prop="unit">
+ <el-input v-model="formState.unit" disabled />
</el-form-item>
<el-form-item
- label="鍗曚綅"
- prop="unit"
+ label="宸ヨ壓璺嚎"
+ prop="routeId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨宸ヨ壓璺嚎',
+ trigger: 'change',
+ },
+ ]"
>
- <el-input v-model="formState.unit" disabled />
- </el-form-item>
-
- <el-form-item label="宸ヨ壓璺嚎">
- <el-select v-model="formState.routeId"
- placeholder="璇烽�夋嫨宸ヨ壓璺嚎"
- style="width: 100%;"
- :loading="bindRouteLoading">
- <el-option v-for="item in routeOptions"
- :key="item.id"
- :label="`${item.processRouteCode || ''}`"
- :value="item.id" />
+ <el-select
+ v-model="formState.routeId"
+ placeholder="璇烽�夋嫨宸ヨ壓璺嚎"
+ style="width: 100%"
+ :loading="bindRouteLoading"
+ @change="handleRouteChange"
+ >
+ <el-option
+ v-for="item in routeOptions"
+ :key="item.id"
+ :label="item.processRouteCode || ''"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
<el-form-item
- label="闇�姹傛暟閲�"
- prop="quantity"
+ v-if="processListData.length"
+ label="宸ュ簭鎶ュ伐浜�"
+ prop="processUserList"
+ :rules="[
+ {
+ validator: validateProcessUsers,
+ trigger: 'change',
+ },
+ ]"
>
- <el-input-number v-model="formState.quantity" :step="1" :min="1" style="width: 100%" />
+ <div class="process-user-list">
+ <div
+ v-for="(item, index) in processListData"
+ :key="item.id || `${item.processId}-${index}`"
+ class="process-user-item"
+ >
+ <div class="process-user-header">
+ <div class="process-user-name">
+ {{ item.name || item.processName || item.no || `宸ュ簭${index + 1}` }}
+ </div>
+ <el-button
+ type="danger"
+ link
+ class="process-user-remove"
+ @click="removeProcessItem(index)"
+ >
+ 鍒犻櫎
+ </el-button>
+ </div>
+ <el-select
+ v-model="formState.processUserList[index].userIds"
+ placeholder="璇烽�夋嫨鎶ュ伐浜�"
+ class="process-user-select"
+ filterable
+ clearable
+ multiple
+ collapse-tags
+ collapse-tags-tooltip
+ :max-collapse-tags="3"
+ @change="handleProcessUserChange(index, $event)"
+ >
+ <el-option
+ v-for="user in userOptions"
+ :key="user.userId"
+ :label="user.nickName"
+ :value="user.userId"
+ />
+ </el-select>
+ </div>
+ </div>
+ </el-form-item>
+
+ <el-form-item label="闇�姹傛暟閲�" prop="quantity">
+ <el-input-number
+ v-model="formState.quantity"
+ :step="1"
+ :min="1"
+ style="width: 100%"
+ />
</el-form-item>
</el-form>
- <!-- 浜у搧閫夋嫨寮圭獥 -->
<ProductSelectDialog
- v-model="showProductSelectDialog"
- @confirm="handleProductSelect"
- single
+ v-model="showProductSelectDialog"
+ single
+ @confirm="handleProductSelect"
/>
+
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleSubmit">纭</el-button>
@@ -74,115 +143,238 @@
</template>
<script setup>
-import {ref, computed, getCurrentInstance} from "vue";
+import { computed, getCurrentInstance, nextTick, ref } from "vue";
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-import {addProductOrder, listProcessRoute} from "@/api/productionManagement/productionOrder.js";
+import { addProductOrder, listProcessRoute } from "@/api/productionManagement/productionOrder.js";
+import { processList } from "@/api/productionManagement/productionProcess.js";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import {findProcessRouteItemList} from "@/api/productionManagement/processRouteItem.js";
const props = defineProps({
visible: {
type: Boolean,
required: true,
},
-
type: {
type: String,
- required: true,
- default: 'qualified',
+ default: "qualified",
},
});
-const emit = defineEmits(['update:visible', 'completed']);
+const emit = defineEmits(["update:visible", "completed"]);
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
-const formState = ref({
+const createDefaultFormState = () => ({
productId: undefined,
productModelId: undefined,
routeId: undefined,
productName: "",
productModelName: "",
unit: "",
- quantity: 0,
+ quantity: 1,
+ processUserList: [],
});
+
+const formState = ref(createDefaultFormState());
const isShow = computed({
get() {
return props.visible;
},
set(val) {
- emit('update:visible', val);
+ emit("update:visible", val);
},
});
const showProductSelectDialog = ref(false);
+const routeOptions = ref([]);
+const bindRouteLoading = ref(false);
+const processListData = ref([]);
+const userOptions = ref([]);
+const userLoading = ref(false);
-let { proxy } = getCurrentInstance()
+const { proxy } = getCurrentInstance();
+const formRef = ref();
+
+const validateProcessUserField = async (shouldValidate = false) => {
+ await nextTick();
+ if (!formRef.value) return;
+
+ if (processListData.value.length && shouldValidate) {
+ formRef.value.validateField("processUserList");
+ return;
+ }
+
+ formRef.value.clearValidate("processUserList");
+};
+
+const resetProcessUsers = () => {
+ processListData.value = [];
+ formState.value.processUserList = [];
+};
const closeModal = () => {
- // 閲嶇疆琛ㄥ崟鏁版嵁
- formState.value = {
- productId: undefined,
- productModelId: undefined,
- routeId: undefined,
- productName: "",
- productModelName: "",
- quantity: '',
- };
+ formState.value = createDefaultFormState();
+ routeOptions.value = [];
+ resetProcessUsers();
isShow.value = false;
};
-// 浜у搧閫夋嫨澶勭悊
-const handleProductSelect = async (products) => {
- if (products && products.length > 0) {
- const product = products[0];
- formState.value.productId = product.productId;
- formState.value.productName = product.productName;
- formState.value.productModelName = product.model;
- formState.value.productModelId = product.id;
- formState.value.unit = product.unit;
- showProductSelectDialog.value = false;
- fetchRouteOptions( product.id);
- // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
- proxy.$refs["formRef"]?.validateField('productModelId');
- }
+const ensureUserOptions = () => {
+ if (userOptions.value.length || userLoading.value) return;
+
+ userLoading.value = true;
+ userListNoPageByTenantId()
+ .then(res => {
+ userOptions.value = res.data || [];
+ })
+ .finally(() => {
+ userLoading.value = false;
+ });
};
-const routeOptions = ref([]);
-const bindRouteLoading = ref(false);
-const fetchRouteOptions = (productModelId) => {
- formState.value.routeId = undefined;
- routeOptions.value = []
- bindRouteLoading.value = true;
- listProcessRoute({ productModelId: productModelId }).then(res => {
- routeOptions.value = res.data || [];
- }).finally(() => {
- bindRouteLoading.value = false;
+const createProcessUserList = list =>
+ list.map(item => ({
+ processId: item.processId,
+ processName: item.name || item.processName || item.no || "",
+ userIds: [],
+ userNames: "",
+ }));
+
+const fetchProcessList = routeId => {
+ if (!routeId) {
+ resetProcessUsers();
+ return;
+ }
+
+ findProcessRouteItemList({
+ routeId,
+ productModelId: formState.value.productModelId,
})
-}
+ .then(res => {
+ processListData.value = res.data || [];
+ formState.value.processUserList = createProcessUserList(processListData.value);
+ ensureUserOptions();
+ validateProcessUserField();
+ })
+ .catch(() => {
+ resetProcessUsers();
+ });
+};
+
+const handleRouteChange = routeId => {
+ fetchProcessList(routeId);
+};
+
+const handleProcessUserChange = (index, userIds) => {
+ const selectedUsers = userOptions.value.filter(user => Array.isArray(userIds) && userIds.includes(user.userId));
+ formState.value.processUserList[index].userNames = selectedUsers.map(user => user.nickName).join(",");
+ validateProcessUserField(true);
+};
+
+const removeProcessItem = index => {
+ processListData.value.splice(index, 1);
+ formState.value.processUserList.splice(index, 1);
+ validateProcessUserField(true);
+};
+
+const validateProcessUsers = (_, value, callback) => {
+ if (!formState.value.routeId) {
+ callback();
+ return;
+ }
+ if (!processListData.value.length) {
+ callback(new Error("褰撳墠宸ヨ壓璺嚎涓嬫病鏈夊伐搴�"));
+ return;
+ }
+ if (!Array.isArray(value) || value.length !== processListData.value.length) {
+ callback(new Error("璇蜂负姣忛亾宸ュ簭閫夋嫨鎶ュ伐浜�"));
+ return;
+ }
+
+ const hasEmptyUser = value.some(item => !Array.isArray(item.userIds) || item.userIds.length === 0);
+ if (hasEmptyUser) {
+ callback(new Error("璇蜂负姣忛亾宸ュ簭閫夋嫨鎶ュ伐浜�"));
+ return;
+ }
+ callback();
+};
+
+const handleProductSelect = products => {
+ if (!products?.length) return;
+
+ const product = products[0];
+ formState.value.productId = product.id;
+ formState.value.productName = product.productName;
+ formState.value.productModelName = product.model;
+ formState.value.productModelId = product.id;
+ formState.value.unit = product.unit;
+ formState.value.routeId = undefined;
+ routeOptions.value = [];
+ resetProcessUsers();
+ showProductSelectDialog.value = false;
+ fetchRouteOptions(product.id);
+ formRef.value?.validateField("productModelId");
+};
+
+const fetchRouteOptions = productModelId => {
+ formState.value.routeId = undefined;
+ routeOptions.value = [];
+ resetProcessUsers();
+ bindRouteLoading.value = true;
+ listProcessRoute({ productModelId })
+ .then(res => {
+ routeOptions.value = res.data || [];
+ })
+ .finally(() => {
+ bindRouteLoading.value = false;
+ });
+};
+
+const buildProcessRouteItems = () =>
+ processListData.value.map((item, index) => {
+ const processUser = formState.value.processUserList[index] || {};
+ return {
+ productOrderId: undefined,
+ productRouteId: formState.value.routeId,
+ processId: item.processId,
+ productModelId: formState.value.productModelId,
+ dragSort: item.dragSort ?? index + 1,
+ isQuality: item.isQuality ?? false,
+ reportUserIds: Array.isArray(processUser.userIds) ? processUser.userIds.join(",") : "",
+ };
+ });
const handleSubmit = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰瑙勬牸
- if (!formState.value.productModelId) {
- proxy.$modal.msgError("璇烽�夋嫨浜у搧");
- return;
- }
- if (!formState.value.productModelId) {
- proxy.$modal.msgError("璇烽�夋嫨瑙勬牸");
- return;
- }
+ formRef.value.validate(valid => {
+ if (!valid) return;
- addProductOrder(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- })
+ if (!formState.value.productModelId) {
+ proxy.$modal.msgError("璇烽�夋嫨浜у搧");
+ return;
}
- })
-};
+ if (!formState.value.routeId) {
+ proxy.$modal.msgError("璇烽�夋嫨宸ヨ壓璺嚎");
+ return;
+ }
+ if (!formState.value.processUserList.length) {
+ proxy.$modal.msgError("褰撳墠宸ヨ壓璺嚎涓嬫病鏈夊伐搴�");
+ return;
+ }
+ if (formState.value.processUserList.some(item => !Array.isArray(item.userIds) || item.userIds.length === 0)) {
+ proxy.$modal.msgError("璇蜂负姣忛亾宸ュ簭閫夋嫨鎶ュ伐浜�");
+ return;
+ }
+ addProductOrder({
+ ...formState.value,
+ processRouteItems: buildProcessRouteItems(),
+ }).then(() => {
+ isShow.value = false;
+ emit("completed");
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ });
+ });
+};
defineExpose({
closeModal,
@@ -190,3 +382,55 @@
isShow,
});
</script>
+
+<style scoped>
+.process-user-list {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 14px;
+ padding: 14px;
+ border-radius: 12px;
+ background: #f7f9fc;
+ border: 1px solid #e8eef5;
+}
+
+.process-user-item {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr);
+ gap: 16px;
+ padding: 12px 14px;
+ border-radius: 10px;
+ background: #fff;
+ border: 1px solid #edf2f7;
+}
+
+.process-user-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+
+.process-user-name {
+ color: #1f2d3d;
+ font-weight: 500;
+ line-height: 1.4;
+}
+
+.process-user-remove {
+ flex-shrink: 0;
+ padding: 0;
+}
+
+.process-user-select {
+ width: 100%;
+}
+
+@media (max-width: 768px) {
+ .process-user-item {
+ grid-template-columns: 1fr;
+ gap: 10px;
+ }
+}
+</style>
--
Gitblit v1.9.3