liding
7 小时以前 50552c590564e51349229d4f2e26a147109adc60
feat:1.生产订单增加领用弹窗(数据输入和输出)
已添加1个文件
已修改2个文件
269 ■■■■■ 文件已修改
src/api/productionManagement/productionOrder.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/MaterialRequisitionDialog.vue 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/productionOrder.js
@@ -147,6 +147,24 @@
  });
}
//根据订单的bomId查询库存原材料
export function getByBomId(query) {
  return request({
    url: "/productOrder/getByBomId",
    method: "get",
    params: query,
  });
}
//保存生产订单领料
export function drawMaterials(data) {
  return request({
    url: "/productOrder/drawMaterials",
    method: "post",
    data: data,
  });
}
export function getProductOrderBatchNoOptions() {
  return request({
    url: "/productOrder/getProductOrderBatchNo",
src/views/productionManagement/productionOrder/MaterialRequisitionDialog.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,226 @@
<template>
  <el-dialog
    v-model="visible"
    title="领料"
    width="1000px"
    top="3vh"
    :close-on-click-modal="false"
    destroy-on-close
    class="material-requisition-dialog"
  >
    <div class="material-requisition-form">
      <!-- åŽŸææ–™åˆ—è¡¨ -->
      <el-table :data="materialList" border style="width: 100%" height="65vh">
        <el-table-column type="index" label="序号" width="60" align="center" />
        <el-table-column prop="productName" label="产品名称" min-width="150" />
        <el-table-column prop="model" label="型号" min-width="150" />
        <!-- <el-table-column prop="batchNo" label="批号" min-width="150">
          <template #default="{ row }">
            <el-select
              v-model="row.batchNo"
              placeholder="请选择批号"
              clearable
              style="width: 100%"
            >
              <el-option
                v-for="item in row.batchOptions || []"
                :key="item.batchNo"
                :label="item.batchNo"
                :value="item.batchNo"
              />
            </el-select>
          </template>
        </el-table-column> -->
        <el-table-column prop="unit" label="单位" width="80" align="center" />
        <el-table-column prop="qualitity" label="数量" width="100" align="center">
          <template #default="{ row }">
            {{ row.qualitity || 0 }}
          </template>
        </el-table-column>
        <el-table-column prop="requisitionQty" label="领用数量" width="120" align="center">
          <template #default="{ row }">
            <el-input-number
              v-model="row.requisitionQty"
              :min="0"
              :precision="2"
              :controls="false"
              :disabled="!row.qualitity || hasDrawMaterials"
              style="width: 100%"
            />
          </template>
        </el-table-column>
        <el-table-column prop="remark" label="备注" min-width="150">
        </el-table-column>
      </el-table>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" :loading="saving" @click="handleConfirm">ç¡® è®¤</el-button>
        <el-button @click="handleCancel">取 æ¶ˆ</el-button>
      </span>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, reactive, computed, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { getByBomId, drawMaterials } from '@/api/productionManagement/productionOrder.js';
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  },
  orderData: {
    type: Object,
    default: () => ({})
  }
});
const emit = defineEmits(['update:modelValue', 'confirm']);
const visible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
});
const loading = ref(false);
const saving = ref(false);
const materialList = ref([]);
const hasDrawMaterials = ref(false);
// ç›‘听弹框打开,加载数据
watch(() => props.modelValue, (val) => {
  if (val && props.orderData) {
    loadMaterialList();
  }
});
const loadMaterialList = async () => {
  const order = props.orderData;
  const drawMaterialsData = order.drawMaterials;
  // å¦‚果已有领料数据,直接使用
  if (drawMaterialsData) {
    hasDrawMaterials.value = true;
    try {
      const list = typeof drawMaterialsData === 'string'
        ? JSON.parse(drawMaterialsData)
        : drawMaterialsData;
      materialList.value = list.map(item => ({
        ...item,
        requisitionQty: item.requisitionQty || 0
      }));
      return;
    } catch (e) {
      console.error('解析领料数据失败:', e);
    }
  }
  // æ²¡æœ‰é¢†æ–™æ•°æ®ï¼Œè°ƒç”¨æŽ¥å£æŸ¥è¯¢
  hasDrawMaterials.value = false;
  const bomId = order?.bomId;
  if (!bomId) {
    ElMessage.warning('当前订单缺少BOM信息');
    return;
  }
  loading.value = true;
  try {
    const res = await getByBomId({ bomId });
    const data = res.data || [];
    // å¤„理数据,添加领用数量字段和批号选项
    materialList.value = data.map(item => ({
      ...item,
      requisitionQty: item.qualitity ? 0 : 0,
      batchNo: item.batchNo || '',
      remark: item.remark || '',
      // æ‰¹å·é€‰é¡¹ï¼Œä»Žåº“存原材料信息中获取
      batchOptions: item.inventoryList || []
    }));
  } catch (error) {
    console.error('查询原材料列表失败:', error);
    ElMessage.error('查询原材料列表失败');
    materialList.value = [];
  } finally {
    loading.value = false;
  }
};
const handleCancel = () => {
  visible.value = false;
  materialList.value = [];
  hasDrawMaterials.value = false;
};
const handleConfirm = async () => {
  const orderId = props.orderData?.id;
  if (!orderId) {
    ElMessage.error('订单ID不存在');
    return;
  }
  const drawMaterialsList = materialList.value.map(item => ({
    ...item,
    requisitionQty: item.requisitionQty || 0
  }));
  const postData = {
    id: orderId,
    drawMaterials: JSON.stringify(drawMaterialsList)
  };
  saving.value = true;
  try {
    await drawMaterials(postData);
    ElMessage.success('领料保存成功');
    visible.value = false;
    materialList.value = [];
    hasDrawMaterials.value = false;
  } catch (error) {
    console.error('保存领料失败:', error);
    ElMessage.error('保存领料失败');
  } finally {
    saving.value = false;
  }
};
</script>
<style scoped lang="scss">
.material-requisition-form {
  .el-table {
    margin-top: 10px;
  }
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
:deep(.el-dialog) {
  height: 85vh;
  margin-top: 3vh !important;
  display: flex;
  flex-direction: column;
}
:deep(.el-dialog__body) {
  flex: 1;
  overflow-y: auto;
  padding: 15px 20px;
}
:deep(.el-dialog__header) {
  padding: 15px 20px;
  border-bottom: 1px solid #e4e7ed;
}
:deep(.el-dialog__footer) {
  padding: 15px 20px;
  border-top: 1px solid #e4e7ed;
}
</style>
src/views/productionManagement/productionOrder/index.vue
@@ -102,6 +102,12 @@
      :order-data="currentOrderData"
      @save="handleSaveClearanceRecord"
    />
    <!-- é¢†æ–™å¼¹æ¡† -->
    <material-requisition-dialog
      v-model="materialRequisitionVisible"
      :order-data="currentOrderData"
    />
  </div>
</template>
@@ -123,6 +129,7 @@
const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue"));
const ClearanceRecordDialog = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/ClearanceRecordDialog.vue"));
const MaterialRequisitionDialog = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/MaterialRequisitionDialog.vue"));
const {proxy} = getCurrentInstance();
@@ -244,6 +251,14 @@
          handleClearanceRecord(row);
        },
      },
      {
        name: "领料",
        type: "text",
        showHide: row => !row.isEnd,
        clickFun: row => {
          handleMaterialRequisition(row);
        },
      },
    ],
  },
]);
@@ -310,6 +325,9 @@
// æ¸…场记录弹框
const clearanceDialogVisible = ref(false);
const currentOrderData = ref({});
// é¢†æ–™å¼¹æ¡†
const materialRequisitionVisible = ref(false);
const bindForm = reactive({
  orderId: null,
  routeId: null,
@@ -525,6 +543,13 @@
    proxy.$modal.msgError("清场记录保存失败");
  }
};
// æ‰“开领料弹框
const handleMaterialRequisition = (row) => {
  currentOrderData.value = row;
  materialRequisitionVisible.value = true;
};
onMounted(() => {
  getList();
});