From d1733a6f090c0caf96c30c4b2f4f08c7d43c8d3c Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期三, 18 三月 2026 14:35:34 +0800
Subject: [PATCH] Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventory-management into dev_银川_中盛建材

---
 src/views/productionPlan/productionPlan/index.vue                |   15 +
 src/views/productionManagement/productStructure/ImportDialog.vue |  242 ++++++++++++++++++++++++++++++
 src/views/productionManagement/productStructure/index.vue        |  186 ++++++++++++++++-------
 3 files changed, 387 insertions(+), 56 deletions(-)

diff --git a/src/views/productionManagement/productStructure/ImportDialog.vue b/src/views/productionManagement/productStructure/ImportDialog.vue
new file mode 100644
index 0000000..5e5e58f
--- /dev/null
+++ b/src/views/productionManagement/productStructure/ImportDialog.vue
@@ -0,0 +1,242 @@
+<template>
+  <el-dialog :title="title"
+             v-model="dialogVisible"
+             :width="width"
+             :append-to-body="appendToBody"
+             @close="handleClose">
+    <div v-if="showProductTypeSelect"
+         style="margin-bottom: 20px;">
+      <el-form :inline="true"
+               :model="form">
+        <el-form-item label="浜у搧绫诲瀷"
+                      prop="dictCode"
+                      style="margin-bottom: 0;">
+          <el-select v-model="form.dictCode"
+                     placeholder="璇烽�夋嫨浜у搧绫诲瀷"
+                     clearable
+                     style="width: 200px;">
+            <el-option v-for="option in productTypeOptions"
+                       :key="option.dictCode"
+                       :label="option.dictLabel"
+                       :value="option.dictCode" />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+    <el-upload ref="uploadRef"
+               :limit="limit"
+               :accept="accept"
+               :headers="headers"
+               :action="action"
+               :data="uploadData"
+               :disabled="disabled"
+               :before-upload="beforeUpload"
+               :on-progress="onProgress"
+               :on-success="onSuccess"
+               :on-error="onError"
+               :on-change="onChange"
+               :auto-upload="autoUpload"
+               drag>
+      <el-icon class="el-icon--upload">
+        <UploadFilled />
+      </el-icon>
+      <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+      <template #tip>
+        <div class="el-upload__tip text-center">
+          <span>{{ tipText }}</span>
+          <el-link v-if="showDownloadTemplate"
+                   type="primary"
+                   :underline="false"
+                   style="font-size: 12px; vertical-align: baseline; margin-left: 5px;"
+                   @click="handleDownloadTemplate">涓嬭浇妯℃澘</el-link>
+        </div>
+      </template>
+    </el-upload>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button type="primary"
+                   @click="handleConfirm">纭� 瀹�</el-button>
+        <el-button @click="handleCancel">鍙� 娑�</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+  import { computed, ref, reactive, watch } from "vue";
+  import { UploadFilled } from "@element-plus/icons-vue";
+  import { ElMessage } from "element-plus";
+  import { getDicts } from "@/api/system/dict/data";
+
+  const props = defineProps({
+    modelValue: {
+      type: Boolean,
+      default: false,
+    },
+    title: {
+      type: String,
+      default: "瀵煎叆",
+    },
+    width: {
+      type: String,
+      default: "400px",
+    },
+    appendToBody: {
+      type: Boolean,
+      default: true,
+    },
+    limit: {
+      type: Number,
+      default: 1,
+    },
+    accept: {
+      type: String,
+      default: ".xlsx, .xls",
+    },
+    headers: {
+      type: Object,
+      default: () => ({}),
+    },
+    action: {
+      type: String,
+      required: true,
+    },
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
+    autoUpload: {
+      type: Boolean,
+      default: false,
+    },
+    tipText: {
+      type: String,
+      default: "浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�",
+    },
+    showDownloadTemplate: {
+      type: Boolean,
+      default: true,
+    },
+    showProductTypeSelect: {
+      type: Boolean,
+      default: false,
+    },
+    beforeUpload: {
+      type: Function,
+      default: null,
+    },
+    onProgress: {
+      type: Function,
+      default: null,
+    },
+    onSuccess: {
+      type: Function,
+      default: null,
+    },
+    onError: {
+      type: Function,
+      default: null,
+    },
+    onChange: {
+      type: Function,
+      default: null,
+    },
+  });
+
+  const emit = defineEmits([
+    "update:modelValue",
+    "close",
+    "confirm",
+    "cancel",
+    "download-template",
+  ]);
+
+  const dialogVisible = computed({
+    get: () => props.modelValue,
+    set: val => emit("update:modelValue", val),
+  });
+
+  const uploadRef = ref(null);
+  const productTypeOptions = ref([]);
+  const form = reactive({
+    dictCode: "",
+  });
+
+  // 鑾峰彇浜у搧绫诲瀷瀛楀吀
+  const getProductTypeOptions = () => {
+    getDicts("product_type")
+      .then(res => {
+        if (res.code === 200) {
+          productTypeOptions.value = res.data;
+        }
+      })
+      .catch(err => {
+        console.error("鑾峰彇浜у搧绫诲瀷瀛楀吀澶辫触锛�", err);
+      });
+  };
+
+  // 鐩戝惉瀵硅瘽妗嗘樉绀猴紝鍔犺浇浜у搧绫诲瀷瀛楀吀
+  watch(
+    () => props.modelValue,
+    newVal => {
+      if (newVal && props.showProductTypeSelect) {
+        getProductTypeOptions();
+      }
+    }
+  );
+
+  // 涓婁紶鏁版嵁
+  const uploadData = computed(() => {
+    if (props.showProductTypeSelect) {
+      return {
+        dictCode: form.dictCode,
+      };
+    }
+    return {};
+  });
+
+  const handleClose = () => {
+    form.dictCode = "";
+    emit("close");
+  };
+
+  const handleConfirm = () => {
+    if (props.showProductTypeSelect && !form.dictCode) {
+      ElMessage.warning("璇烽�夋嫨浜у搧绫诲瀷");
+      return;
+    }
+    emit("confirm");
+  };
+
+  const submit = () => {
+    if (uploadRef.value) {
+      uploadRef.value.submit();
+    }
+  };
+
+  const handleCancel = () => {
+    form.dictCode = "";
+    emit("cancel");
+    dialogVisible.value = false;
+  };
+
+  const handleDownloadTemplate = () => {
+    emit("download-template");
+  };
+
+  defineExpose({
+    uploadRef,
+    submit,
+    clearFiles: () => {
+      if (uploadRef.value) {
+        uploadRef.value.clearFiles();
+      }
+    },
+  });
+</script>
+
+<style scoped>
+  .dialog-footer {
+    text-align: center;
+  }
+</style>
\ No newline at end of file
diff --git a/src/views/productionManagement/productStructure/index.vue b/src/views/productionManagement/productStructure/index.vue
index abf4fd2..7032c09 100644
--- a/src/views/productionManagement/productStructure/index.vue
+++ b/src/views/productionManagement/productStructure/index.vue
@@ -1,23 +1,49 @@
 <template>
   <div class="app-container">
-    <div style="text-align: right; margin-bottom: 10px;">
-      <el-button type="info"
-                 plain
-                 icon="Upload"
-                 @click="handleImport"
-                 v-hasPermi="['product:bom:import']">瀵煎叆</el-button>
-      <el-button type="warning"
-                 plain
-                 icon="Download"
-                 @click="handleExport"
-                 :disabled="selectedRows.length !== 1"
-                 v-hasPermi="['product:bom:export']">瀵煎嚭</el-button>
-      <el-button type="primary"
-                 @click="handleAdd">鏂板</el-button>
-      <el-button type="danger"
-                 plain
-                 @click="handleBatchDelete"
-                 :disabled="selectedRows.length === 0">鍒犻櫎</el-button>
+    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
+      <!-- 鎼滅储鍖哄煙 -->
+      <div class="search-form">
+        <el-form :inline="true"
+                 :model="searchForm">
+          <el-form-item label="浜у搧绫诲瀷"
+                        style="margin-bottom: 0px !important;">
+            <el-select v-model="searchForm.dictCode"
+                       style="width: 200px;"
+                       placeholder="璇烽�夋嫨浜у搧绫诲瀷"
+                       clearable>
+              <el-option v-for="option in productTypeOptions"
+                         :key="option.dictCode"
+                         :label="option.dictLabel"
+                         :value="option.dictCode" />
+            </el-select>
+          </el-form-item>
+          <el-form-item style="margin-bottom: 0px !important;">
+            <el-button type="primary"
+                       @click="handleSearch">鎼滅储</el-button>
+            <el-button @click="handleReset">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <!-- 鎸夐挳鍖哄煙 -->
+      <div>
+        <el-button type="info"
+                   plain
+                   icon="Upload"
+                   @click="handleImport"
+                   v-hasPermi="['product:bom:import']">瀵煎叆</el-button>
+        <el-button type="warning"
+                   plain
+                   icon="Download"
+                   @click="handleExport"
+                   :disabled="selectedRows.length !== 1"
+                   v-hasPermi="['product:bom:export']">瀵煎嚭</el-button>
+        <el-button type="primary"
+                   @click="handleAdd">鏂板</el-button>
+        <el-button type="danger"
+                   plain
+                   @click="handleBatchDelete"
+                   :disabled="selectedRows.length === 0">鍒犻櫎</el-button>
+      </div>
     </div>
     <PIMTable rowKey="id"
               :column="tableColumn"
@@ -46,12 +72,16 @@
                :model="form"
                :rules="rules"
                label-width="120px">
-        <el-form-item label="浜у搧鍚嶇О"
-                      prop="productModelId">
-          <el-button type="primary"
-                     @click="showProductSelectDialog = true">
-            {{ form.productName || '閫夋嫨浜у搧' }}-{{ form.productModelName }}
-          </el-button>
+        <el-form-item label="浜у搧绫诲瀷"
+                      prop="dictCode">
+          <el-select v-model="form.dictCode"
+                     placeholder="璇烽�夋嫨浜у搧绫诲瀷"
+                     clearable>
+            <el-option v-for="option in productTypeOptions"
+                       :key="option.dictCode"
+                       :label="option.dictLabel"
+                       :value="option.dictCode" />
+          </el-select>
         </el-form-item>
         <el-form-item label="鐗堟湰鍙�"
                       prop="version">
@@ -74,10 +104,6 @@
                    @click="handleSubmit">纭畾</el-button>
       </template>
     </el-dialog>
-    <!-- 浜у搧閫夋嫨寮圭獥 -->
-    <ProductSelectDialog v-model="showProductSelectDialog"
-                         @confirm="handleProductSelect"
-                         single />
     <!-- BOM瀵煎叆瀵硅瘽妗� -->
     <ImportDialog ref="uploadRef"
                   v-model="upload.open"
@@ -88,6 +114,7 @@
                   :on-progress="handleFileUploadProgress"
                   :on-success="handleFileSuccess"
                   :show-download-template="true"
+                  :show-product-type-select="true"
                   @confirm="submitFileForm"
                   @download-template="handleDownloadTemplate"
                   @close="handleImportClose" />
@@ -115,7 +142,8 @@
   import { useRouter } from "vue-router";
   import { ElMessageBox } from "element-plus";
   import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-  import ImportDialog from "@/components/Dialog/ImportDialog.vue";
+  import ImportDialog from "./ImportDialog.vue";
+  import { getDicts } from "@/api/system/dict/data";
 
   const router = useRouter();
   const { proxy } = getCurrentInstance();
@@ -132,26 +160,41 @@
       minWidth: 140,
     },
     {
-      label: "浜у搧缂栫爜",
-      prop: "productCode",
+      label: "浜у搧绫诲瀷",
+      prop: "dictLabel",
+      dataType: "tag",
+      formatType: params => {
+        if (params == "3.5鐮屽潡") {
+          return "warning";
+        } else if (params == "5.0鐮屽潡") {
+          return "primary";
+        } else if (params == "鏉挎潗") {
+          return "success";
+        } else {
+          return "info";
+        }
+      },
+    },
+    // {
+    //   label: "浜у搧缂栫爜",
+    //   prop: "productCode",
 
-      minWidth: 160,
-    },
-    {
-      label: "浜у搧鍚嶇О",
-      prop: "productName",
+    //   minWidth: 160,
+    // },
+    // {
+    //   label: "浜у搧鍚嶇О",
+    //   prop: "productName",
 
-      minWidth: 160,
-    },
-    {
-      label: "瑙勬牸鍨嬪彿",
-      prop: "productModelName",
-      minWidth: 140,
-    },
+    //   minWidth: 160,
+    // },
+    // {
+    //   label: "瑙勬牸鍨嬪彿",
+    //   prop: "productModelName",
+    //   minWidth: 140,
+    // },
     {
       label: "鐗堟湰鍙�",
       prop: "version",
-      width: 100,
     },
     {
       label: "澶囨敞",
@@ -217,21 +260,23 @@
   const data = reactive({
     form: {
       id: undefined,
-      productName: "",
-      productModelName: "",
-      productModelId: "",
+      dictCode: "",
       remark: "",
       version: "",
     },
     rules: {
-      productModelId: [
-        { required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" },
+      dictCode: [
+        { required: true, message: "璇烽�夋嫨浜у搧绫诲瀷", trigger: "change" },
       ],
       version: [{ required: true, message: "璇疯緭鍏ョ増鏈彿", trigger: "blur" }],
     },
+    searchForm: {
+      dictCode: "",
+    },
+    productTypeOptions: [],
   });
 
-  const { form, rules } = toRefs(data);
+  const { form, rules, searchForm, productTypeOptions } = toRefs(data);
 
   // 琛ㄦ牸閫夋嫨鏁版嵁
   const handleSelectionChange = selection => {
@@ -245,12 +290,37 @@
     getList();
   };
 
+  // 鑾峰彇浜у搧绫诲瀷瀛楀吀
+  const getProductTypeOptions = () => {
+    getDicts("product_type")
+      .then(res => {
+        if (res.code === 200) {
+          productTypeOptions.value = res.data;
+        }
+      })
+      .catch(err => {
+        console.error("鑾峰彇浜у搧绫诲瀷瀛楀吀澶辫触锛�", err);
+      });
+  };
+
+  // 鎼滅储
+  const handleSearch = () => {
+    getList();
+  };
+
+  // 閲嶇疆
+  const handleReset = () => {
+    searchForm.value.dictCode = "";
+    getList();
+  };
+
   // 鏌ヨ鍒楄〃
   const getList = () => {
     tableLoading.value = true;
     listPage({
       current: page.current,
       size: page.size,
+      dictCode: searchForm.value.dictCode,
     })
       .then(res => {
         const records = res?.data?.records || [];
@@ -270,9 +340,7 @@
     operationType.value = "add";
     Object.assign(form.value, {
       id: undefined,
-      productName: "",
-      productModelName: "",
-      productModelId: "",
+      dictCode: "",
       remark: "",
       version: "",
     });
@@ -284,9 +352,7 @@
     operationType.value = "edit";
     Object.assign(form.value, {
       id: row.id,
-      productName: row.productName || "",
-      productModelName: row.productModelName || "",
-      productModelId: row.productModelId || "",
+      dictCode: row.dictCode || "",
       remark: row.remark || "",
       version: row.version || "",
     });
@@ -508,6 +574,14 @@
   };
 
   onMounted(() => {
+    getProductTypeOptions();
     getList();
   });
 </script>
+<style scoped lang="scss">
+  .search-form {
+    :deep(.search-form) {
+      margin-bottom: 0px !important;
+    }
+  }
+</style>
diff --git a/src/views/productionPlan/productionPlan/index.vue b/src/views/productionPlan/productionPlan/index.vue
index e6f209b..8289f26 100644
--- a/src/views/productionPlan/productionPlan/index.vue
+++ b/src/views/productionPlan/productionPlan/index.vue
@@ -48,6 +48,20 @@
                           style="width: 240px;"
                           @change="handleQuery" />
         </el-form-item>
+        <el-form-item label="涓嬪彂鐘舵��:">
+          <el-select v-model="searchForm.status"
+                     placeholder="璇烽�夋嫨鐘舵��" 
+                     clearable
+                     filterable
+                     style="width: 100px">
+            <el-option label="寰呬笅鍙�"
+                       value="0" />
+            <el-option label="閮ㄥ垎涓嬪彂"
+                       value="1" />
+            <el-option label="宸蹭笅鍙�"
+                       value="2" />
+          </el-select>
+        </el-form-item>
         <el-form-item>
           <el-button type="primary"
                      @click="handleQuery">鎼滅储</el-button>
@@ -668,6 +682,7 @@
     height: 0,
     startDate: "",
     endDate: "",
+    status: "",
     strength: "",
     remarkOne: "",
     remarkTwo: "",

--
Gitblit v1.9.3