| | |
| | | div<template> |
| | | <template> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | :title="dialogType === 'add' ? '新增生产加工' : '编辑生产加工'" |
| | |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <el-button type="primary" @click="handlData">选择数据</el-button> |
| | | <ETableModify |
| | | :columns="columns" |
| | | height="200" |
| | | @cell-edit="handleCellEdit" |
| | | :showOperations="false" |
| | | :tableData="tableData" |
| | | @row-click="handleRowClick" |
| | | :editableColumns="['used']" |
| | | /> |
| | | <div class="empty-table"> |
| | | <h1>生产明细</h1> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="2"> |
| | | <el-button type="primary" @click="addNewRow"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | 新增 |
| | | </el-button> |
| | | <el-row :gutter="10" style="margin-bottom: 10px"> |
| | | <el-col :span="3"> |
| | | <el-button type="primary" @click="handlData" |
| | | ><el-icon> |
| | | <Plus /> </el-icon |
| | | >选择数据</el-button |
| | | > |
| | | </el-col> |
| | | <el-col :span="2"> |
| | | <el-button type="danger" @click="clearAllRows"> |
| | | <el-col :span="4"> |
| | | <el-button |
| | | type="danger" |
| | | @click="removeSelectedData" |
| | | :disabled="tableData.length === 0" |
| | | > |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | 清空 |
| | | 清空已选 |
| | | </el-button> |
| | | </el-col> |
| | | <!-- <el-col :span="2"> |
| | | <el-col :span="17" style="text-align: right; line-height: 32px"> |
| | | <el-text type="info" size="small"> |
| | | 已选择 {{ tableData.length }} 项数据 |
| | | <span v-if="tableData.length > 0"> |
| | | ,总使用量: {{ totalUsedQuantity.toFixed(2) }} |
| | | </span> |
| | | </el-text> |
| | | </el-col> |
| | | </el-row> |
| | | <ETableModify |
| | | :columns="columns" |
| | | :showOperations="false" |
| | | height="200" |
| | | @cell-edit="handleCellEdit" |
| | | :tableData="tableData" |
| | | :showOverflowTooltip="false" |
| | | @row-click="handleRowClick" |
| | | :editableColumns="['usedQuantity']" |
| | | @delete="handleRemoveItem" |
| | | /> |
| | | <div class="empty-table"> |
| | | <h1>生产明细</h1> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="2"> |
| | | <el-button type="primary" @click="addNewRow"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | 新增 |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="2"> |
| | | <el-button type="danger" @click="clearAllRows"> |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | 清空 |
| | | </el-button> |
| | | </el-col> |
| | | <!-- <el-col :span="2"> |
| | | <el-button type="warning" @click="calculateAllCosts"> |
| | | <el-icon> |
| | | <Warning /> |
| | | </el-icon> 重新计算 |
| | | </el-button> |
| | | </el-col> --> |
| | | </el-row> |
| | | <ProductionDetailsTable |
| | | v-model="detailsTableData" |
| | | :border="false" |
| | | :show-operations="true" |
| | | :auto-calculate="true" |
| | | @input-change="handleDetailsChange" |
| | | @delete-row="handleDeleteRow" |
| | | /> |
| | | |
| | | </el-row> |
| | | <ProductionDetailsTable |
| | | v-model="detailsTableData" |
| | | :border="false" |
| | | :show-operations="true" |
| | | :auto-calculate="true" |
| | | @input-change="handleDetailsChange" |
| | | @delete-row="handleDeleteRow" |
| | | /> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="handleClose">取 消</el-button> |
| | | <el-button @click="handleClose" v-if="dialogType === 'add'" |
| | | >取 消</el-button |
| | | > |
| | | <el-button @click="handleReset" v-if="dialogType === 'edit'" |
| | | >重 置</el-button |
| | | > |
| | | <el-button type="primary" :loading="loading" @click="handleSubmit" |
| | | >确 定</el-button |
| | | > |
| | |
| | | center |
| | | append-to-body |
| | | > |
| | | <div style="margin-bottom: 10px"> |
| | | <el-alert |
| | | v-if="tableData.length > 0" |
| | | :title="`当前已选择 ${tableData.length} 条数据`" |
| | | type="info" |
| | | :closable="false" |
| | | show-icon |
| | | /> |
| | | </div> |
| | | <ETable |
| | | @selection-change="handleSelectionChange" |
| | | :showOperations="false" |
| | | ref="etableRef" |
| | | :columns="formalDatabaseColumns" |
| | | :tableData="formalDatabaseData" |
| | | :defaultSelectedIds="selectedIds" |
| | | :rowKey="'id'" |
| | | height="400" |
| | | @cell-edit="handleCellEdit" |
| | | :show-selection="true" |
| | | /> |
| | | <el-row :gutter="24"> |
| | | <el-col :span="2" :offset="22"> |
| | | <el-button type="primary" @click="handleSelectData">确定</el-button> |
| | | <el-row :gutter="24" style="margin-top: 15px"> |
| | | <el-col :span="12"> |
| | | <el-text type="info"> |
| | | 已选择 {{ formalDatabaseSelectedData.length }} 条数据 |
| | | </el-text> |
| | | </el-col> |
| | | <el-col :span="12" style="text-align: right"> |
| | | <el-button @click="innerVisible = false">取消</el-button> |
| | | <el-button |
| | | type="primary" |
| | | @click="handleSelectData" |
| | | :disabled="formalDatabaseSelectedData.length === 0" |
| | | > |
| | | 确定添加 |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, watch } from "vue"; |
| | | import { ref, reactive, watch, onMounted, nextTick, computed } from "vue"; |
| | | import ETable from "@/components/Table/ETable.vue"; |
| | | import ETableModify from "@/components/Table/EtableModify.vue"; |
| | | import ProductionDetailsTable from "./ProductionDetailsTable.vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { ElMessage, ElMessageBox, ElAlert, ElText } from "element-plus"; |
| | | import { Delete, Warning, Plus } from "@element-plus/icons-vue"; |
| | | import { getOfficialAll } from "@/api/production/index.js"; |
| | | import { getOfficialAll, addOrEditPM } from "@/api/production/index.js"; |
| | | import { getCurrentInstance } from "vue"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | |
| | | const tableData = ref([]); |
| | | const currentRow = ref(null); |
| | | const columns = [ |
| | | { label: "供应商名称", prop: "supplierName" }, |
| | | { label: "煤种", prop: "coal" }, |
| | | { label: "单价(不含税)", prop: "priceExcludingTax" }, |
| | | { label: "库存数量", prop: "inventoryQuantity" }, |
| | | { label: "煤种", prop: "coal", minwidth: 120 }, |
| | | { label: "库存数量", prop: "inventoryQuantity", minwidth: 100 }, |
| | | { |
| | | label: "使用数量", |
| | | prop: "used", |
| | | prop: "usedQuantity", |
| | | editable: true, |
| | | width: 120, |
| | | minwidth: 120, |
| | | editType: "number", |
| | | }, |
| | | |
| | | ]; |
| | | const detailsTableData = ref([ |
| | | |
| | | ]); |
| | | const etableRef = ref(null); |
| | | const selectedIds = ref([]); // 默认选中的ID数组 |
| | | // 调试函数:验证ID匹配逻辑 |
| | | const debugIdMatching = () => { |
| | | if (formalDatabaseData.value.length > 0 && selectedIds.value.length > 0) { |
| | | const matchedRows = formalDatabaseData.value.filter((row) => |
| | | selectedIds.value.includes(row.id) |
| | | ); |
| | | } |
| | | }; |
| | | const detailsTableData = ref([]); |
| | | const handleRowClick = (row) => { |
| | | currentRow.value = row; |
| | | }; |
| | |
| | | reviewer: "", |
| | | date: "", |
| | | }); |
| | | const handlData =async () => { |
| | | const handlData = async () => { |
| | | innerVisible.value = true; |
| | | let res = await getOfficialAll(); |
| | | console.log("获取配置数据", res); |
| | | if (res.code === 200) { |
| | | formalDatabaseData.value = res.data; |
| | | const existingOfficialIds = tableData.value |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = existingOfficialIds; |
| | | debugIdMatching(); |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | if (etableRef.value && existingOfficialIds.length > 0) { |
| | | etableRef.value.setDefaultSelection(); |
| | | } |
| | | }, 100); |
| | | }); |
| | | } else { |
| | | ElMessage.error("获取配置数据失败"); |
| | | } |
| | | }; |
| | | // 手动设置表格选中状态 |
| | | const setTableSelection = (ids) => { |
| | | if (!etableRef.value || !Array.isArray(ids) || ids.length === 0) { |
| | | return; |
| | | } |
| | | |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | try { |
| | | // 先清除所有选中 |
| | | etableRef.value.clearSelection(); |
| | | |
| | | // 找到需要选中的行并设置选中状态 |
| | | // 注意:ids中是officialId,需要匹配formalDatabaseData中的id字段 |
| | | const rowsToSelect = formalDatabaseData.value.filter((row) => |
| | | ids.includes(row.id) |
| | | ); |
| | | if (rowsToSelect.length > 0) { |
| | | etableRef.value.setRowsSelection(rowsToSelect, true); |
| | | console.log("选中状态设置完成"); |
| | | } else { |
| | | } |
| | | } catch (error) { |
| | | console.error("设置选中状态失败:", error); |
| | | } |
| | | }, 150); |
| | | }); |
| | | }; |
| | | |
| | | const formalDatabaseData = ref([]); |
| | | const formalDatabaseSelectedData = ref([]); |
| | | formalDatabaseData.value = [ |
| | | ]; |
| | | formalDatabaseData.value = []; |
| | | // 初始化 |
| | | const Initialization = () => { |
| | | tableData.value = []; |
| | | detailsTableData.value = []; |
| | | copyForm.value = null; |
| | | dialogType.value = "add"; |
| | | }; |
| | | const copyForm = ref(null); |
| | | const editInitialization = (data) => { |
| | | copyForm.value = { ...data }; // 深拷贝数据 |
| | | tableData.value = data.productionInventoryList || []; |
| | | detailsTableData.value = data.productionList || []; |
| | | dialogType.value = "edit"; |
| | | |
| | | // 设置默认选中的ID,使用officialId来匹配 |
| | | const existingOfficialIds = tableData.value |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = existingOfficialIds; |
| | | }; |
| | | // 监听对话框状态,在打开时设置选中状态 |
| | | watch(innerVisible, (newVal) => { |
| | | if (newVal && selectedIds.value.length > 0) { |
| | | console.log("对话框打开,设置选中状态"); |
| | | setTimeout(() => setTableSelection(selectedIds.value), 200); |
| | | } |
| | | // 对话框关闭时清空选择状态 |
| | | if (!newVal) { |
| | | formalDatabaseSelectedData.value = []; |
| | | } |
| | | }); |
| | | |
| | | defineExpose({ |
| | | Initialization |
| | | Initialization, |
| | | editInitialization, |
| | | }); |
| | | const handleSelectData = (row) => { |
| | | tableData.value = []; |
| | | if (!innerVisible.value) return; |
| | | // 获取选中的数据 |
| | | const selectedData = formalDatabaseSelectedData.value; |
| | | if (selectedData.length === 0) { |
| | | ElMessage.warning("请至少选择一条数据"); |
| | | return; |
| | | } |
| | | // 将选中的数据根据需要筛选到表格中 |
| | | let addedCount = 0; |
| | | let duplicateCount = 0; |
| | | selectedData.forEach((item) => { |
| | | const existingItem = tableData.value.find( |
| | | (row) => row.id === item.id |
| | | ); |
| | | if (!existingItem) { |
| | | tableData.value.push( |
| | | Object.assign({}, item, { |
| | | used: 0, // 初始使用数量为0 |
| | | }) |
| | | ); |
| | | } |
| | | const newItem = { |
| | | ...item, // 复制所有原始数据 |
| | | officialId: item.id, // 保存原始的id作为officialId |
| | | usedQuantity: 0, // 初始使用数量为0 |
| | | // 可以根据需要添加其他字段 |
| | | }; |
| | | tableData.value.push(newItem); |
| | | addedCount++; |
| | | }); |
| | | |
| | | // 更新selectedIds,确保包含所有当前tableData中的officialId |
| | | const allOfficialIds = tableData.value |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = allOfficialIds; |
| | | |
| | | console.log("更新后的表格数据:", tableData.value); |
| | | console.log("更新后的选中ID:", selectedIds.value); |
| | | |
| | | // 关闭选择对话框 |
| | | innerVisible.value = false; |
| | | |
| | | // 显示结果消息 |
| | | let message = ""; |
| | | if (addedCount > 0) { |
| | | message += `成功添加 ${addedCount} 条数据`; |
| | | } |
| | | if (duplicateCount > 0) { |
| | | message += (message ? "," : "") + `跳过 ${duplicateCount} 条重复数据`; |
| | | } |
| | | if (message) { |
| | | ElMessage.success(message); |
| | | } else { |
| | | ElMessage.info("没有新数据被添加"); |
| | | } |
| | | }; |
| | | const handleSelectionChange = (selection) => { |
| | | formalDatabaseSelectedData.value = selection; |
| | | }; |
| | | const reset = () => { |
| | | // formRef |
| | | formRef.value?.resetFields(); |
| | | const handleReset = () => { |
| | | console.log(copyForm.value); |
| | | tableData.value = |
| | | JSON.parse(JSON.stringify(copyForm.value.productionInventoryList)) || []; |
| | | detailsTableData.value = |
| | | JSON.parse(JSON.stringify(copyForm.value.productionList)) || []; |
| | | }; |
| | | |
| | | const selectChange = (value) => {}; |
| | | |
| | | // 提交表单 |
| | | const handleSubmit = async () => { |
| | | console.log("提交表单数据:", tableData.value); |
| | | console.log(detailsTableData.value); |
| | | let data = { |
| | | productionList: detailsTableData.value, |
| | | productionInventoryList: tableData.value, |
| | | ...copyForm.value, |
| | | }; |
| | | console.log("提交数据", data); |
| | | // dialogVisible.value = false; |
| | | let res = await addOrEditPM(data); |
| | | if (res.code === 200) { |
| | | dialogVisible.value = false; |
| | | emit("success"); |
| | | } else { |
| | | ElMessage.error("提交失败"); |
| | | } |
| | | }; |
| | | |
| | | // 关闭弹窗 |
| | |
| | | |
| | | // 添加单元格编辑处理函数 |
| | | const handleCellEdit = (row, prop, value) => { |
| | | if (prop === "used" && Number(value) > Number(row.stock)) { |
| | | ElMessage.warning("使用数量不能大于库存数量!"); |
| | | row.used = row.stock; |
| | | if (prop === "usedQuantity") { |
| | | const numValue = Number(value); |
| | | const inventory = Number(row.inventoryQuantity); |
| | | |
| | | // 验证输入值 |
| | | if (isNaN(numValue) || numValue < 0) { |
| | | ElMessage.warning("使用数量必须是非负数!"); |
| | | row.usedQuantity = 0; |
| | | return; |
| | | } |
| | | |
| | | if (numValue > inventory) { |
| | | ElMessage.warning(`使用数量不能大于库存数量(${inventory})!`); |
| | | row.usedQuantity = inventory; |
| | | return; |
| | | } |
| | | |
| | | // 更新值 |
| | | row.usedQuantity = numValue; |
| | | console.log(`更新 ${row.coal} 的使用数量为: ${numValue}`); |
| | | } |
| | | }; |
| | | |
| | | // 处理生产明细表格的操作 |
| | | const addNewRow = () => { |
| | | detailsTableData.value.push({ |
| | | coalType: "", |
| | | coal: "", |
| | | productionQuantity: "", |
| | | laborCost: "", |
| | | energyConsumptionCost: "", |
| | | equipmentDepreciation: "", |
| | | purchasePrice: "", |
| | | autoCalculate: "0.00", |
| | | producer:"", |
| | | producer: "", |
| | | }); |
| | | }; |
| | | |
| | | const clearAllRows = () => { |
| | | detailsTableData.value = []; |
| | | ElMessage.success("已清空所有数据"); |
| | | }; |
| | | |
| | | const calculateAllCosts = () => { |
| | | detailsTableData.value.forEach((row) => { |
| | | const laborCost = parseFloat(row.laborCost) || 0; |
| | | const energyCost = parseFloat(row.energyCost) || 0; |
| | | const equipmentDepreciation = parseFloat(row.equipmentDepreciation) || 0; |
| | | const purchasePrice = parseFloat(row.purchasePrice) || 0; |
| | | |
| | | row.totalCost = ( |
| | | laborCost + |
| | | energyCost + |
| | | equipmentDepreciation + |
| | | purchasePrice |
| | | ).toFixed(2); |
| | | }); |
| | | ElMessage.success("重新计算完成"); |
| | | }; |
| | | |
| | | const handleDetailsChange = (data) => { |
| | |
| | | const handleDeleteRow = (index) => { |
| | | ElMessage.success(`已删除第 ${index + 1} 行数据`); |
| | | }; |
| | | |
| | | // 删除单个已选数据项 |
| | | const handleRemoveItem = (row) => { |
| | | console.log("删除项:", row); |
| | | const index = tableData.value.findIndex( |
| | | (item) => item.officialId === row.officialId |
| | | ); |
| | | if (index > -1) { |
| | | tableData.value.splice(index, 1); |
| | | |
| | | // 更新selectedIds |
| | | const updatedOfficialIds = tableData.value |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = updatedOfficialIds; |
| | | |
| | | console.log("删除后的表格数据:", tableData.value); |
| | | console.log("更新后的选中ID:", selectedIds.value); |
| | | |
| | | ElMessage.success("已删除选中项"); |
| | | } |
| | | }; |
| | | |
| | | // 清空所有已选数据 |
| | | const removeSelectedData = () => { |
| | | if (tableData.value.length === 0) { |
| | | ElMessage.warning("没有可清空的数据"); |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm("确认清空所有已选择的数据吗?", "警告", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableData.value = []; |
| | | selectedIds.value = []; |
| | | console.log("已清空所有已选数据"); |
| | | ElMessage.success("已清空所有数据"); |
| | | }) |
| | | .catch(() => { |
| | | console.log("取消清空操作"); |
| | | }); |
| | | }; |
| | | |
| | | // 计算总使用量 |
| | | const totalUsedQuantity = computed(() => { |
| | | return tableData.value.reduce((total, item) => { |
| | | const usedQty = Number(item.usedQuantity) || 0; |
| | | return total + usedQty; |
| | | }, 0); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | .el-row > .el-col > h1 { |
| | | font-weight: bolder; |
| | | } |
| | | .empty-table > .el-row{ |
| | | .empty-table > .el-row { |
| | | margin-bottom: 12px; |
| | | } |
| | | </style> |