From 0365c235877b5d09b3f02423681417da0a4a8b81 Mon Sep 17 00:00:00 2001
From: chenhj <1263187585@qq.com>
Date: 星期四, 16 四月 2026 17:54:53 +0800
Subject: [PATCH] Merge branch 'dev_天津_君歌化工' of http://114.132.189.42:9002/r/product-inventory-management into dev_天津_君歌化工

---
 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