From 0cc7997b26301527f6928ba663a532989cf6db56 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期四, 16 四月 2026 16:17:02 +0800
Subject: [PATCH] 工序/排产
---
src/views/productionManagement/productionProcess/index.vue | 57 ++++
src/views/productionManagement/productionProcess/Edit.vue | 269 +++++++++++++++++++++---
src/views/productionManagement/workOrderEdit/index.vue | 69 +++++
src/components/Dialog/ImportDialog.vue | 8
src/views/productionManagement/productionProcess/New.vue | 244 ++++++++++++++++++---
5 files changed, 560 insertions(+), 87 deletions(-)
diff --git a/src/components/Dialog/ImportDialog.vue b/src/components/Dialog/ImportDialog.vue
index 5b126dc..45b442a 100644
--- a/src/components/Dialog/ImportDialog.vue
+++ b/src/components/Dialog/ImportDialog.vue
@@ -39,8 +39,8 @@
</el-upload>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="handleConfirm">纭� 瀹�</el-button>
- <el-button @click="handleCancel">鍙� 娑�</el-button>
+ <el-button type="primary" :loading="loading" @click="handleConfirm">纭� 瀹�</el-button>
+ <el-button :disabled="loading" @click="handleCancel">鍙� 娑�</el-button>
</div>
</template>
</el-dialog>
@@ -118,6 +118,10 @@
onChange: {
type: Function,
default: null
+ },
+ loading: {
+ type: Boolean,
+ default: false
}
})
diff --git a/src/views/productionManagement/productionProcess/Edit.vue b/src/views/productionManagement/productionProcess/Edit.vue
index 3d35f7c..f12e5a5 100644
--- a/src/views/productionManagement/productionProcess/Edit.vue
+++ b/src/views/productionManagement/productionProcess/Edit.vue
@@ -3,29 +3,64 @@
<el-dialog
v-model="isShow"
title="缂栬緫閮ㄤ欢"
- width="400"
+ width="760"
@close="closeModal"
>
<el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
- <el-form-item
- label="閮ㄤ欢锛�"
- prop="name"
+ <el-row :gutter="16">
+ <el-col :span="12">
+ <el-form-item
+ label="浜у搧鍚嶇О锛�"
+ prop="productId"
:rules="[
{
required: true,
- message: '璇疯緭鍏ラ儴浠�',
+ message: '璇烽�夋嫨浜у搧鍚嶇О',
},
- {
- max: 100,
- message: '鏈�澶�100涓瓧绗�',
- }
]">
- <el-input v-model="formState.name" />
- </el-form-item>
- <el-form-item label="閮ㄤ欢缂栧彿" prop="no">
- <el-input v-model="formState.no" />
- </el-form-item>
- <el-form-item
+ <el-tree-select
+ v-model="formState.productId"
+ placeholder="璇烽�夋嫨浜у搧鍚嶇О"
+ clearable
+ filterable
+ check-strictly
+ :data="productCategoryOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ @change="handleProductChange"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item
+ label="浜у搧瑙勬牸锛�"
+ prop="productModelId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧瑙勬牸',
+ },
+ ]">
+ <el-select v-model="formState.productModelId"
+ placeholder="璇烽�夋嫨浜у搧瑙勬牸"
+ clearable
+ filterable
+ :disabled="!formState.productId"
+ style="width: 100%">
+ <el-option v-for="item in modelOptions"
+ :key="item.id"
+ :label="item.model"
+ :value="item.id" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閮ㄤ欢缂栧彿" prop="no">
+ <el-input v-model="formState.no" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item
label="閮ㄤ欢绫诲瀷"
prop="type"
:rules="[
@@ -34,25 +69,58 @@
message: '璇烽�夋嫨閮ㄤ欢绫诲瀷',
}
]"
- >
- <el-select v-model="formState.type" placeholder="璇烽�夋嫨閮ㄤ欢绫诲瀷">
- <el-option label="鍔犲伐" :value="1" />
- <el-option label="鍒澘鍐疯姱鍒朵綔" :value="2" />
- <el-option label="绠¤矾缁勫" :value="3" />
- <el-option label="缃愪綋杩炴帴鍙婅皟璇�" :value="4" />
- <el-option label="娴嬭瘯鎵撳帇" :value="5" />
- <el-option label="鍏朵粬" :value="6" />
- </el-select>
- </el-form-item>
- <el-form-item label="宸ヨ祫瀹氶" prop="salaryQuota">
- <el-input v-model="formState.salaryQuota" type="number" :step="0.001" />
- </el-form-item>
- <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
- <el-switch v-model="formState.isQuality" :active-value="true" inactive-value="false"/>
- </el-form-item>
- <el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="formState.remark" type="textarea" />
- </el-form-item>
+ >
+ <el-select v-model="formState.type" placeholder="璇烽�夋嫨閮ㄤ欢绫诲瀷">
+ <el-option label="鍔犲伐" :value="1" />
+ <el-option label="鍒澘鍐疯姱鍒朵綔" :value="2" />
+ <el-option label="绠¤矾缁勫" :value="3" />
+ <el-option label="缃愪綋杩炴帴鍙婅皟璇�" :value="4" />
+ <el-option label="娴嬭瘯鎵撳帇" :value="5" />
+ <el-option label="鍏朵粬" :value="6" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item
+ label="璁″垝宸ユ椂(灏忔椂)"
+ prop="salaryQuota"
+ :rules="[
+ { validator: validateNonNegativeSalaryQuota, trigger: ['blur', 'change'] }
+ ]"
+ >
+ <el-input v-model="formState.salaryQuota" type="number" :step="0.001" :min="0" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁″垝浜哄憳" prop="plannerId">
+ <el-select
+ v-model="formState.plannerId"
+ placeholder="璇烽�夋嫨璁″垝浜哄憳"
+ clearable
+ filterable
+ style="width: 100%"
+ @change="handlePlannerChange"
+ >
+ <el-option
+ v-for="item in plannerOptions"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
+ <el-switch v-model="formState.isQuality" :active-value="true" inactive-value="false"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="24">
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="formState.remark" type="textarea" />
+ </el-form-item>
+ </el-col>
+ </el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
@@ -65,8 +133,10 @@
</template>
<script setup>
-import { ref, computed, getCurrentInstance, watch } from "vue";
+import { ref, computed, getCurrentInstance, watch, onMounted } from "vue";
import {update} from "@/api/productionManagement/productionProcess.js";
+import { modelListPage, productTreeList } from "@/api/basicData/product";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
const props = defineProps({
visible: {
@@ -86,12 +156,19 @@
const formState = ref({
id: props.record.id,
name: props.record.name,
+ productId: props.record.productId,
+ productModelId: props.record.productModelId,
type: props.record.type,
no: props.record.no,
remark: props.record.remark,
salaryQuota: props.record.salaryQuota,
+ plannerId: props.record.plannerId,
+ plannerName: props.record.plannerName,
isQuality: props.record.isQuality,
});
+const productCategoryOptions = ref([]);
+const modelOptions = ref([]);
+const plannerOptions = ref([]);
const isShow = computed({
get() {
@@ -108,10 +185,14 @@
formState.value = {
id: newRecord.id,
name: newRecord.name || '',
+ productId: newRecord.productId,
+ productModelId: newRecord.productModelId,
no: newRecord.no || '',
type: newRecord.type,
remark: newRecord.remark || '',
salaryQuota: newRecord.salaryQuota || '',
+ plannerId: newRecord.plannerId,
+ plannerName: newRecord.plannerName || '',
isQuality: props.record.isQuality,
};
}
@@ -123,16 +204,129 @@
formState.value = {
id: props.record.id,
name: props.record.name || '',
+ productId: props.record.productId,
+ productModelId: props.record.productModelId,
no: props.record.no || '',
type: props.record.type,
remark: props.record.remark || '',
salaryQuota: props.record.salaryQuota || '',
+ plannerId: props.record.plannerId,
+ plannerName: props.record.plannerName || '',
isQuality: props.record.isQuality,
};
}
});
let { proxy } = getCurrentInstance()
+
+const validateNonNegativeSalaryQuota = (rule, value, callback) => {
+ if (value === '' || value === null || value === undefined) {
+ callback(new Error('璇疯緭鍏ヨ鍒掑伐鏃�'));
+ return;
+ }
+ const num = Number(value);
+ if (Number.isNaN(num) || num < 0) {
+ callback(new Error('璁″垝宸ユ椂涓嶈兘灏忎簬0'));
+ return;
+ }
+ callback();
+};
+
+const convertProductTree = list => {
+ return (list || []).map(item => {
+ const children = convertProductTree(item.children || item.childList || []);
+ return {
+ ...item,
+ value: item.id,
+ label: item.name || item.label,
+ children,
+ disabled: children.length > 0,
+ };
+ });
+};
+
+const findNodeById = (nodes, targetId) => {
+ for (const node of nodes || []) {
+ if (String(node.value) === String(targetId)) {
+ return node;
+ }
+ if (node.children && node.children.length > 0) {
+ const found = findNodeById(node.children, targetId);
+ if (found) return found;
+ }
+ }
+ return null;
+};
+
+const findNodeIdByLabel = (nodes, targetLabel) => {
+ for (const node of nodes || []) {
+ if (node.label === targetLabel) {
+ return node.value;
+ }
+ if (node.children && node.children.length > 0) {
+ const found = findNodeIdByLabel(node.children, targetLabel);
+ if (found !== null && found !== undefined) return found;
+ }
+ }
+ return undefined;
+};
+
+const getProductCategoryOptions = async () => {
+ try {
+ const res = await productTreeList();
+ const list = Array.isArray(res) ? res : res?.data || [];
+ productCategoryOptions.value = convertProductTree(list);
+ if (!formState.value.productId && formState.value.name) {
+ formState.value.productId = findNodeIdByLabel(productCategoryOptions.value, formState.value.name);
+ }
+ await getModelOptions(formState.value.productId);
+ } catch (e) {
+ productCategoryOptions.value = [];
+ }
+};
+
+const getModelOptions = async productId => {
+ if (!productId) {
+ modelOptions.value = [];
+ return;
+ }
+ try {
+ const res = await modelListPage({
+ id: productId,
+ current: 1,
+ size: 999,
+ });
+ const records = res?.records || res?.data?.records || [];
+ modelOptions.value = records;
+ } catch (e) {
+ modelOptions.value = [];
+ }
+};
+
+const getPlannerOptions = async () => {
+ try {
+ const res = await userListNoPageByTenantId();
+ plannerOptions.value = res?.data || [];
+ if (!formState.value.plannerId && formState.value.plannerName) {
+ const selectedUser = plannerOptions.value.find(item => item.nickName === formState.value.plannerName);
+ formState.value.plannerId = selectedUser?.userId;
+ }
+ } catch (e) {
+ plannerOptions.value = [];
+ }
+};
+
+const handlePlannerChange = value => {
+ const selectedUser = plannerOptions.value.find(item => String(item.userId) === String(value));
+ formState.value.plannerName = selectedUser?.nickName || '';
+};
+
+const handleProductChange = async value => {
+ const selectedNode = findNodeById(productCategoryOptions.value, value);
+ formState.value.name = selectedNode?.label || '';
+ formState.value.productModelId = undefined;
+ await getModelOptions(value);
+};
const closeModal = () => {
isShow.value = false;
@@ -152,6 +346,11 @@
})
};
+onMounted(() => {
+ getProductCategoryOptions();
+ getPlannerOptions();
+});
+
defineExpose({
closeModal,
handleSubmit,
diff --git a/src/views/productionManagement/productionProcess/New.vue b/src/views/productionManagement/productionProcess/New.vue
index 4fa2c97..250e229 100644
--- a/src/views/productionManagement/productionProcess/New.vue
+++ b/src/views/productionManagement/productionProcess/New.vue
@@ -3,29 +3,64 @@
<el-dialog
v-model="isShow"
title="鏂板閮ㄤ欢"
- width="400"
+ width="760"
@close="closeModal"
>
<el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
- <el-form-item
- label="閮ㄤ欢锛�"
- prop="name"
+ <el-row :gutter="16">
+ <el-col :span="12">
+ <el-form-item
+ label="浜у搧鍚嶇О锛�"
+ prop="productId"
:rules="[
{
required: true,
- message: '璇疯緭鍏ラ儴浠�',
+ message: '璇烽�夋嫨浜у搧鍚嶇О',
},
- {
- max: 100,
- message: '鏈�澶�100涓瓧绗�',
- }
]">
- <el-input v-model="formState.name" />
- </el-form-item>
- <el-form-item label="閮ㄤ欢缂栧彿" prop="no">
- <el-input v-model="formState.no" />
- </el-form-item>
- <el-form-item
+ <el-tree-select
+ v-model="formState.productId"
+ placeholder="璇烽�夋嫨浜у搧鍚嶇О"
+ clearable
+ filterable
+ check-strictly
+ :data="productCategoryOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ @change="handleProductChange"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item
+ label="浜у搧瑙勬牸锛�"
+ prop="productModelId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧瑙勬牸',
+ },
+ ]">
+ <el-select v-model="formState.productModelId"
+ placeholder="璇烽�夋嫨浜у搧瑙勬牸"
+ clearable
+ filterable
+ :disabled="!formState.productId"
+ style="width: 100%">
+ <el-option v-for="item in modelOptions"
+ :key="item.id"
+ :label="item.model"
+ :value="item.id" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閮ㄤ欢缂栧彿" prop="no">
+ <el-input v-model="formState.no" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item
label="閮ㄤ欢绫诲瀷"
prop="type"
:rules="[
@@ -34,27 +69,60 @@
message: '璇烽�夋嫨閮ㄤ欢绫诲瀷',
}
]"
- >
- <el-select v-model="formState.type" placeholder="璇烽�夋嫨閮ㄤ欢绫诲瀷">
- <el-option label="鍔犲伐" :value="1" />
- <el-option label="鍒澘鍐疯姱鍒朵綔" :value="2" />
- <el-option label="绠¤矾缁勫" :value="3" />
- <el-option label="缃愪綋杩炴帴鍙婅皟璇�" :value="4" />
- <el-option label="娴嬭瘯鎵撳帇" :value="5" />
- <el-option label="鍏朵粬" :value="6" />
- </el-select>
- </el-form-item>
- <el-form-item label="宸ヨ祫瀹氶" prop="salaryQuota">
- <el-input v-model="formState.salaryQuota" type="number" :step="0.001">
- <template #append>鍏�</template>
- </el-input>
- </el-form-item>
- <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
- <el-switch v-model="formState.isQuality" :active-value="true" inactive-value="false"/>
- </el-form-item>
- <el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="formState.remark" type="textarea" />
- </el-form-item>
+ >
+ <el-select v-model="formState.type" placeholder="璇烽�夋嫨閮ㄤ欢绫诲瀷">
+ <el-option label="鍔犲伐" :value="1" />
+ <el-option label="鍒澘鍐疯姱鍒朵綔" :value="2" />
+ <el-option label="绠¤矾缁勫" :value="3" />
+ <el-option label="缃愪綋杩炴帴鍙婅皟璇�" :value="4" />
+ <el-option label="娴嬭瘯鎵撳帇" :value="5" />
+ <el-option label="鍏朵粬" :value="6" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item
+ label="璁″垝宸ユ椂(灏忔椂)"
+ prop="salaryQuota"
+ :rules="[
+ { validator: validateNonNegativeSalaryQuota, trigger: ['blur', 'change'] }
+ ]"
+ >
+ <el-input v-model="formState.salaryQuota" type="number" :step="0.001" :min="0">
+ <template #append>灏忔椂</template>
+ </el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁″垝浜哄憳" prop="plannerId">
+ <el-select
+ v-model="formState.plannerId"
+ placeholder="璇烽�夋嫨璁″垝浜哄憳"
+ clearable
+ filterable
+ style="width: 100%"
+ @change="handlePlannerChange"
+ >
+ <el-option
+ v-for="item in plannerOptions"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
+ <el-switch v-model="formState.isQuality" :active-value="true" inactive-value="false"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="24">
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="formState.remark" type="textarea" />
+ </el-form-item>
+ </el-col>
+ </el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
@@ -67,8 +135,10 @@
</template>
<script setup>
-import { ref, computed, getCurrentInstance } from "vue";
+import { ref, computed, getCurrentInstance, onMounted } from "vue";
import {add} from "@/api/productionManagement/productionProcess.js";
+import { modelListPage, productTreeList } from "@/api/basicData/product";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
const props = defineProps({
visible: {
@@ -82,11 +152,18 @@
// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
const formState = ref({
name: '',
+ productId: undefined,
+ productModelId: undefined,
type: undefined,
remark: '',
salaryQuota: '',
+ plannerId: undefined,
+ plannerName: '',
isQuality: false,
});
+const productCategoryOptions = ref([]);
+const modelOptions = ref([]);
+const plannerOptions = ref([]);
const isShow = computed({
get() {
@@ -98,6 +175,94 @@
});
let { proxy } = getCurrentInstance()
+
+const validateNonNegativeSalaryQuota = (rule, value, callback) => {
+ if (value === '' || value === null || value === undefined) {
+ callback(new Error('璇疯緭鍏ヨ鍒掑伐鏃�'));
+ return;
+ }
+ const num = Number(value);
+ if (Number.isNaN(num) || num < 0) {
+ callback(new Error('璁″垝宸ユ椂涓嶈兘灏忎簬0'));
+ return;
+ }
+ callback();
+};
+
+const convertProductTree = list => {
+ return (list || []).map(item => {
+ const children = convertProductTree(item.children || item.childList || []);
+ return {
+ ...item,
+ value: item.id,
+ label: item.name || item.label,
+ children,
+ disabled: children.length > 0,
+ };
+ });
+};
+
+const findNodeById = (nodes, targetId) => {
+ for (const node of nodes || []) {
+ if (String(node.value) === String(targetId)) {
+ return node;
+ }
+ if (node.children && node.children.length > 0) {
+ const found = findNodeById(node.children, targetId);
+ if (found) return found;
+ }
+ }
+ return null;
+};
+
+const getProductCategoryOptions = async () => {
+ try {
+ const res = await productTreeList();
+ const list = Array.isArray(res) ? res : res?.data || [];
+ productCategoryOptions.value = convertProductTree(list);
+ } catch (e) {
+ productCategoryOptions.value = [];
+ }
+};
+
+const getModelOptions = async productId => {
+ if (!productId) {
+ modelOptions.value = [];
+ return;
+ }
+ try {
+ const res = await modelListPage({
+ id: productId,
+ current: 1,
+ size: 999,
+ });
+ const records = res?.records || res?.data?.records || [];
+ modelOptions.value = records;
+ } catch (e) {
+ modelOptions.value = [];
+ }
+};
+
+const getPlannerOptions = async () => {
+ try {
+ const res = await userListNoPageByTenantId();
+ plannerOptions.value = res?.data || [];
+ } catch (e) {
+ plannerOptions.value = [];
+ }
+};
+
+const handlePlannerChange = value => {
+ const selectedUser = plannerOptions.value.find(item => String(item.userId) === String(value));
+ formState.value.plannerName = selectedUser?.nickName || '';
+};
+
+const handleProductChange = async value => {
+ const selectedNode = findNodeById(productCategoryOptions.value, value);
+ formState.value.name = selectedNode?.label || '';
+ formState.value.productModelId = undefined;
+ await getModelOptions(value);
+};
const closeModal = () => {
isShow.value = false;
@@ -117,6 +282,11 @@
})
};
+onMounted(() => {
+ getProductCategoryOptions();
+ getPlannerOptions();
+});
+
defineExpose({
closeModal,
handleSubmit,
diff --git a/src/views/productionManagement/productionProcess/index.vue b/src/views/productionManagement/productionProcess/index.vue
index ebc50a4..a6c9c2f 100644
--- a/src/views/productionManagement/productionProcess/index.vue
+++ b/src/views/productionManagement/productionProcess/index.vue
@@ -3,13 +3,33 @@
<div class="search_form">
<el-form :model="searchForm"
:inline="true">
- <el-form-item label="閮ㄤ欢:">
+ <el-form-item label="浜у搧鍚嶇О:">
<el-input v-model="searchForm.name"
- placeholder="璇疯緭鍏�"
+ placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
clearable
prefix-icon="Search"
style="width: 200px;"
@change="handleQuery" />
+ </el-form-item>
+ <el-form-item label="閮ㄤ欢绫诲瀷:">
+ <el-select v-model="searchForm.type"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 200px;"
+ @change="handleQuery">
+ <el-option label="鍔犲伐"
+ :value="1" />
+ <el-option label="鍒澘鍐疯姱鍒朵綔"
+ :value="2" />
+ <el-option label="绠¤矾缁勫"
+ :value="3" />
+ <el-option label="缃愪綋杩炴帴鍙婅皟璇�"
+ :value="4" />
+ <el-option label="娴嬭瘯鎵撳帇"
+ :value="5" />
+ <el-option label="鍏朵粬"
+ :value="6" />
+ </el-select>
</el-form-item>
<el-form-item label="閮ㄤ欢缂栧彿:">
<el-input v-model="searchForm.no"
@@ -60,7 +80,10 @@
title="瀵煎叆閮ㄤ欢"
:action="importAction"
:headers="importHeaders"
+ :loading="importLoading"
+ :disabled="importLoading"
:auto-upload="false"
+ :on-progress="handleImportProgress"
:on-success="handleImportSuccess"
:on-error="handleImportError"
@confirm="handleImportConfirm"
@@ -85,26 +108,36 @@
const data = reactive({
searchForm: {
name: "",
+ type: undefined,
no: "",
},
});
const { searchForm } = toRefs(data);
const tableColumn = ref([
+
+ {
+ label: "浜у搧鍚嶇О",
+ prop: "name",
+ },
+ {
+ label: "浜у搧瑙勬牸",
+ prop: "productModel",
+ },
{
label: "閮ㄤ欢缂栧彿",
prop: "no",
- },
- {
- label: "閮ㄤ欢",
- prop: "name",
},
{
label: "閮ㄤ欢绫诲瀷",
prop: "typeText",
},
{
- label: "宸ヨ祫瀹氶",
+ label: "璁″垝宸ユ椂(灏忔椂)",
prop: "salaryQuota",
+ },
+ {
+ label: "璁″垝浜哄憳",
+ prop: "plannerName",
},
{
label: "鏄惁璐ㄦ",
@@ -145,6 +178,7 @@
const isShowEditModal = ref(false);
const record = ref({});
const importDialogVisible = ref(false);
+ const importLoading = ref(false);
const importDialogRef = ref(null);
const page = reactive({
current: 1,
@@ -152,6 +186,7 @@
total: 0,
});
const { proxy } = getCurrentInstance();
+
// 瀵煎叆鐩稿叧閰嶇疆
const importAction =
@@ -251,8 +286,14 @@
}
};
+ // 瀵煎叆涓�
+ const handleImportProgress = () => {
+ importLoading.value = true;
+ };
+
// 瀵煎叆鎴愬姛
const handleImportSuccess = response => {
+ importLoading.value = false;
if (response.code === 200) {
proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
importDialogVisible.value = false;
@@ -267,11 +308,13 @@
// 瀵煎叆澶辫触
const handleImportError = error => {
+ importLoading.value = false;
proxy.$modal.msgError("瀵煎叆澶辫触锛�" + (error.message || "鏈煡閿欒"));
};
// 鍏抽棴瀵煎叆寮圭獥
const handleImportClose = () => {
+ importLoading.value = false;
if (importDialogRef.value) {
importDialogRef.value.clearFiles();
}
diff --git a/src/views/productionManagement/workOrderEdit/index.vue b/src/views/productionManagement/workOrderEdit/index.vue
index 50f9fce..deca368 100644
--- a/src/views/productionManagement/workOrderEdit/index.vue
+++ b/src/views/productionManagement/workOrderEdit/index.vue
@@ -40,17 +40,33 @@
label-width="120px">
<el-form-item label="璁″垝寮�濮嬫椂闂�">
<el-date-picker v-model="editrow.planStartTime"
- type="date"
+ type="datetime"
placeholder="璇烽�夋嫨"
- value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss"
style="width: 300px" />
</el-form-item>
<el-form-item label="璁″垝缁撴潫鏃堕棿">
<el-date-picker v-model="editrow.planEndTime"
- type="date"
+ type="datetime"
placeholder="璇烽�夋嫨"
- value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss"
style="width: 300px" />
+ </el-form-item>
+ <el-form-item label="鎶ュ伐浜�">
+ <el-select v-model="editrow.reportWorkUserIds"
+ multiple
+ filterable
+ collapse-tags
+ collapse-tags-tooltip
+ placeholder="璇烽�夋嫨鎶ュ伐浜�"
+ style="width: 300px">
+ <el-option v-for="user in userOptions"
+ :key="user.userId"
+ :label="user.nickName"
+ :value="user.userId" />
+ </el-select>
</el-form-item>
</el-form>
<template #footer>
@@ -72,6 +88,7 @@
productWorkOrderPage,
updateProductWorkOrder,
} from "@/api/productionManagement/workOrder.js";
+ import { userListNoPageByTenantId } from "@/api/system/user.js";
import { getCurrentInstance, reactive, toRefs } from "vue";
const { proxy } = getCurrentInstance();
@@ -163,6 +180,7 @@
]);
const tableData = ref([]);
+ const userOptions = ref([]);
const tableLoading = ref(false);
const editDialogVisible = ref(false);
let editrow = ref(null);
@@ -210,7 +228,11 @@
productWorkOrderPage(params)
.then(res => {
tableLoading.value = false;
- tableData.value = res.data.records;
+ tableData.value = (res.data.records || []).map(item => ({
+ ...item,
+ planStartTime: formatDateTime(item.planStartTime),
+ planEndTime: formatDateTime(item.planEndTime),
+ }));
page.total = res.data.total;
})
.catch(() => {
@@ -220,11 +242,45 @@
const handleEdit = row => {
editrow.value = JSON.parse(JSON.stringify(row));
+ if (typeof editrow.value.reportWorkUserIds === "string") {
+ editrow.value.reportWorkUserIds = editrow.value.reportWorkUserIds
+ .split(",")
+ .map(v => Number(v))
+ .filter(v => Number.isFinite(v));
+ } else if (!Array.isArray(editrow.value.reportWorkUserIds)) {
+ editrow.value.reportWorkUserIds = [];
+ }
editDialogVisible.value = true;
};
+ const formatDateTime = value => {
+ if (!value) return "";
+ const date = dayjs(value);
+ return date.isValid() ? date.format("YYYY-MM-DD HH:mm:ss") : value;
+ };
+
+ const getUserList = () => {
+ userListNoPageByTenantId()
+ .then(res => {
+ if (res.code === 200) {
+ userOptions.value = res.data || [];
+ }
+ })
+ .catch(() => {
+ userOptions.value = [];
+ });
+ };
+
const handleUpdate = () => {
- updateProductWorkOrder(editrow.value)
+ const selectedUsers = userOptions.value.filter(user =>
+ (editrow.value.reportWorkUserIds || []).includes(user.userId)
+ );
+ const submitData = {
+ ...editrow.value,
+ reportWorkUserIds: editrow.value.reportWorkUserIds || [],
+ reportWork: selectedUsers.map(user => user.nickName).join(","),
+ };
+ updateProductWorkOrder(submitData)
.then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
editDialogVisible.value = false;
@@ -239,6 +295,7 @@
onMounted(() => {
getList();
+ getUserList();
});
</script>
--
Gitblit v1.9.3