From 0f5c5f11d13711db618ae2947bf35ed2effba8a2 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期五, 17 四月 2026 09:59:58 +0800
Subject: [PATCH] 标识

---
 src/views/productionManagement/productionProcess/Edit.vue |  271 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 237 insertions(+), 34 deletions(-)

diff --git a/src/views/productionManagement/productionProcess/Edit.vue b/src/views/productionManagement/productionProcess/Edit.vue
index fb0ee74..f12e5a5 100644
--- a/src/views/productionManagement/productionProcess/Edit.vue
+++ b/src/views/productionManagement/productionProcess/Edit.vue
@@ -2,53 +2,125 @@
   <div>
     <el-dialog
         v-model="isShow"
-        title="缂栬緫宸ュ簭"
-        width="400"
+        title="缂栬緫閮ㄤ欢"
+        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
-            label="宸ュ簭绫诲瀷"
+              <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="[
                 {
                 required: true,
-                message: '璇烽�夋嫨宸ュ簭绫诲瀷',
+                message: '璇烽�夋嫨閮ㄤ欢绫诲瀷',
               }
             ]"
-        >
-          <el-select v-model="formState.type" placeholder="璇烽�夋嫨宸ュ簭绫诲瀷">
-            <el-option label="璁℃椂" :value="0" />
-            <el-option label="璁′欢" :value="1" />
-          </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">
@@ -61,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: {
@@ -82,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() {
@@ -104,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,
     };
   }
@@ -119,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;
@@ -148,6 +346,11 @@
   })
 };
 
+onMounted(() => {
+  getProductCategoryOptions();
+  getPlannerOptions();
+});
+
 defineExpose({
   closeModal,
   handleSubmit,

--
Gitblit v1.9.3