张诺
昨天 7c86b549b27bd54f6bd5de81c13f8242f91c87ff
src/views/production/components/ProductionDialog.vue
@@ -2,187 +2,222 @@
  <el-dialog
    v-model="dialogVisible"
    :title="dialogType === 'add' ? '新增生产加工' : '编辑生产加工'"
    width="800px"
    width="1200px"
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <el-form
      ref="formRef"
      :model="formData"
      :rules="rules"
      label-width="120px"
      class="production-form"
    >
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="煤种" prop="category">
            <el-select v-model="formData.category" placeholder="请选择煤种" clearable style="width: 100%">
              <el-option label="炼焦" value="炼焦" />
              <el-option label="气煤" value="气煤" />
              <el-option label="无烟煤" value="无烟煤" />
              <el-option label="长焰煤" value="长焰煤" />
              <el-option label="贫煤" value="贫煤" />
            </el-select>
          </el-form-item>
    <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="4">
        <el-button
          type="danger"
          @click="removeSelectedData"
          :disabled="tableData.length === 0"
        >
          <el-icon>
            <Delete />
          </el-icon>
          清空已选
        </el-button>
      </el-col>
      <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="12">
          <el-form-item label="单位" prop="unit">
            <el-select v-model="formData.unit" placeholder="请选择单位" clearable style="width: 100%">
              <el-option label="吨位" value="吨位" />
              <el-option label="千克" value="千克" />
            </el-select>
          </el-form-item>
        <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>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="生产数量" prop="productionVolume">
            <el-input-number
              v-model="formData.productionVolume"
              :min="0"
              :precision="2"
              style="width: 100%"
              @change="calculateTotal"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="人工成本" prop="laborCost">
            <el-input-number
              v-model="formData.laborCost"
              :min="0"
              :precision="2"
              style="width: 100%"
              @change="calculateTotal"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="原料成本" prop="materialCost">
            <el-input-number
              v-model="formData.materialCost"
              :min="0"
              :precision="2"
              style="width: 100%"
              @change="calculateTotal"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="设备费用" prop="equipmentCost">
            <el-input-number
              v-model="formData.equipmentCost"
              :min="0"
              :precision="2"
              style="width: 100%"
              @change="calculateTotal"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="总成本" prop="totalCost">
            <el-input-number
              v-model="formData.totalCost"
              :min="0"
              :precision="2"
              style="width: 100%"
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="总价格" prop="totalPrice">
            <el-input-number
              v-model="formData.totalPrice"
              :min="0"
              :precision="2"
              style="width: 100%"
              @change="calculateProfit"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="利润" prop="profit">
            <el-input-number
              v-model="formData.profit"
              :min="0"
              :precision="2"
              style="width: 100%"
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="复记人" prop="reviewer">
            <el-input v-model="formData.reviewer" placeholder="请输入复记人" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="日期" prop="date">
            <el-date-picker
              v-model="formData.date"
              type="date"
              placeholder="请选择日期"
              style="width: 100%"
              value-format="YYYY-MM-DD"
            />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
      <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 type="primary" :loading="loading" @click="handleSubmit">确 定</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
        >
      </div>
    </template>
  </el-dialog>
  <el-dialog
    v-model="innerVisible"
    width="1000"
    title="选择配置数据"
    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" 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 { ElMessage } from 'element-plus'
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, ElMessageBox, ElAlert, ElText } from "element-plus";
import { Delete, Warning, Plus } from "@element-plus/icons-vue";
import { getOfficialAll, addOrEditPM } from "@/api/production/index.js";
import { getCurrentInstance } from "vue";
const props = defineProps({
  visible: {
    type: Boolean,
    default: false
    default: false,
  },
  type: {
    type: String,
    default: 'add' // 'add' 或 'edit'
    default: "add", // 'add' 或 'edit'
  },
  rowData: {
    type: Object,
    default: () => ({})
    default: () => ({}),
  },
});
const dialogVisible = defineModel("visible", {
  type: Boolean,
  default: false,
});
const emit = defineEmits(["update:visible", "success"]);
const innerVisible = ref(false);
const dialogType = ref("add");
const loading = ref(false);
const formRef = ref(null);
const tableData = ref([]);
const currentRow = ref(null);
const columns = [
  { label: "煤种", prop: "coal", minwidth: 120 },
  { label: "库存数量", prop: "inventoryQuantity", minwidth: 100 },
  {
    label: "使用数量",
    prop: "usedQuantity",
    editable: true,
    minwidth: 120,
    editType: "number",
  },
];
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 emit = defineEmits(['update:visible', 'success'])
const dialogVisible = ref(false)
const dialogType = ref('add')
const loading = ref(false)
const formRef = ref(null)
};
const detailsTableData = ref([]);
const handleRowClick = (row) => {
  currentRow.value = row;
};
const formalDatabaseColumns = ref([
  { prop: "supplierName", label: "供应商名称", minwidth: 150 },
  { prop: "coal", label: "煤种类型", minwidth: 60 },
  { prop: "inventoryQuantity", label: "库存数量", minwidth: 80 },
  { prop: "unit", label: "单位", minwidth: 100 },
  { prop: "priceExcludingTax", label: "单价(不含税)", minwidth: 80 },
  { prop: "createTime", label: "登记日期", minwidth: 400 },
]);
// 表单数据
const formData = reactive({
  category: '',
  unit: '',
  category: "",
  unit: "",
  productionVolume: 0,
  laborCost: 0,
  materialCost: 0,
@@ -190,76 +225,178 @@
  totalCost: 0,
  totalPrice: 0,
  profit: 0,
  reviewer: '',
  date: ''
})
// 表单验证规则
const rules = {
  category: [{ required: true, message: '请选择煤种', trigger: 'change' }],
  unit: [{ required: true, message: '请选择单位', trigger: 'change' }],
  productionVolume: [{ required: true, message: '请输入生产数量', trigger: 'blur' }],
  laborCost: [{ required: true, message: '请输入人工成本', trigger: 'blur' }],
  materialCost: [{ required: true, message: '请输入原料成本', trigger: 'blur' }],
  equipmentCost: [{ required: true, message: '请输入设备费用', trigger: 'blur' }],
  totalPrice: [{ required: true, message: '请输入总价格', trigger: 'blur' }],
  reviewer: [{ required: true, message: '请输入复记人', trigger: 'blur' }],
  date: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
// 监听visible变化
watch(() => props.visible, (val) => {
  dialogVisible.value = val
  if (val) {
    dialogType.value = props.type
    if (props.type === 'edit') {
      Object.assign(formData, props.rowData)
    }
  reviewer: "",
  date: "",
});
const handlData = async () => {
  innerVisible.value = true;
  let res = await getOfficialAll();
  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;
  }
// 监听dialogVisible变化
watch(() => dialogVisible.value, (val) => {
  emit('update:visible', val)
})
  nextTick(() => {
    setTimeout(() => {
      try {
        // 先清除所有选中
        etableRef.value.clearSelection();
// 计算总成本
const calculateTotal = () => {
  formData.totalCost = (
    formData.laborCost +
    formData.materialCost +
    formData.equipmentCost
  )
  calculateProfit()
}
        // 找到需要选中的行并设置选中状态
        // 注意: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 calculateProfit = () => {
  formData.profit = formData.totalPrice - formData.totalCost
}
const formalDatabaseData = ref([]);
const formalDatabaseSelectedData = ref([]);
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,
  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 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 handleReset = () => {
  console.log(copyForm.value);
  tableData.value =
    JSON.parse(JSON.stringify(copyForm.value.productionInventoryList)) || [];
  detailsTableData.value =
    JSON.parse(JSON.stringify(copyForm.value.productionList)) || [];
};
// 提交表单
const handleSubmit = async () => {
  if (!formRef.value) return
  await formRef.value.validate((valid) => {
    if (valid) {
      loading.value = true
      // 触发成功事件,传递表单数据
      emit('success', { ...formData })
      loading.value = false
      handleClose()
    }
  })
}
  let data = {
    productionList: detailsTableData.value,
    productionInventoryList: tableData.value,
    ...copyForm.value,
  };
  let res = await addOrEditPM(data);
  if (res.code === 200) {
    dialogVisible.value = false;
    emit("success");
  } else {
    ElMessage.error("提交失败");
  }
};
// 关闭弹窗
const handleClose = () => {
  dialogVisible.value = false
  formRef.value?.resetFields()
  dialogVisible.value = false;
  formRef.value?.resetFields();
  Object.assign(formData, {
    category: '',
    unit: '',
    category: "",
    unit: "",
    productionVolume: 0,
    laborCost: 0,
    materialCost: 0,
@@ -267,32 +404,129 @@
    totalCost: 0,
    totalPrice: 0,
    profit: 0,
    reviewer: '',
    date: ''
    reviewer: "",
    date: "",
  });
};
// 添加单元格编辑处理函数
const handleCellEdit = (row, prop, value) => {
  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({
    coal: "",
    productionQuantity: "",
    laborCost: "",
    energyConsumptionCost: "",
    equipmentDepreciation: "",
    purchasePrice: "",
    autoCalculate: "0.00",
    producer: "",
  });
};
const clearAllRows = () => {
  detailsTableData.value = [];
  ElMessage.success("已清空所有数据");
};
const handleDetailsChange = (data) => {
  console.log("生产明细数据变化:", 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>
.production-form {
  padding: 20px;
<style scoped lang="scss">
.el-form {
  .el-row {
    padding-top: 20px;
    background: rgba($color: #f8fafb, $alpha: 0.5);
  }
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
.el-row > .el-col > h1 {
  font-weight: bolder;
}
:deep(.el-form-item__label) {
  font-weight: bold;
.empty-table > .el-row {
  margin-bottom: 12px;
}
:deep(.el-input-number) {
  width: 100%;
}
:deep(.el-select) {
  width: 100%;
}
</style>
</style>