From df4a21d1c2af8d05d13725c9791a4df81c4a0dc8 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期三, 18 三月 2026 15:13:21 +0800
Subject: [PATCH] 能耗成本核算
---
src/views/productionPlan/productionPlan/index.vue | 387 +++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 319 insertions(+), 68 deletions(-)
diff --git a/src/views/productionPlan/productionPlan/index.vue b/src/views/productionPlan/productionPlan/index.vue
index d3fb161..8289f26 100644
--- a/src/views/productionPlan/productionPlan/index.vue
+++ b/src/views/productionPlan/productionPlan/index.vue
@@ -18,7 +18,7 @@
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="浜у搧瑙勬牸:">
- <el-input v-model="searchForm.specification"
+ <el-input v-model="searchForm.model"
placeholder="璇疯緭鍏�"
clearable
style="width: 160px;"
@@ -47,6 +47,20 @@
value-format="YYYY-MM-DD"
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"
@@ -102,7 +116,7 @@
<el-row :gutter="20">
<el-col :span="10">
<el-form-item label="浜у搧瑙勬牸">
- <div class="info-display">{{ mergeForm.specification || '-' }}</div>
+ <div class="info-display">{{ mergeForm.model || '-' }}</div>
</el-form-item>
</el-col>
<el-col :span="10">
@@ -116,6 +130,21 @@
type="date"
value-format="YYYY-MM-DD"
style="width: 100%" />
+ </el-form-item>
+ <el-form-item label="寮哄害"
+ v-if="mergeForm.productName === '鐮屽潡'">
+ <div v-if="strengthError"
+ class="strength-error"
+ style="color: red; margin-bottom: 8px;">{{ strengthError }}</div>
+ <el-select v-model="mergeForm.strength"
+ placeholder="璇烽�夋嫨寮哄害"
+ style="width: 100%"
+ required>
+ <el-option v-for="item in block_strength"
+ :key="item.id"
+ :label="item.label"
+ :value="item.id" />
+ </el-select>
</el-form-item>
<el-form-item label="鐢熶骇鏂规暟">
<el-input-number v-model="mergeForm.totalAssignedQuantity"
@@ -234,19 +263,27 @@
placeholder="璇疯緭鍏ュ鎴峰悕绉�" />
</el-form-item>
<el-form-item label="浜у搧鍚嶇О"
- prop="productName">
- <el-input v-model="form.productName"
- placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+ prop="productMaterialId">
+ <el-tree-select v-model="form.productMaterialId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :data="productOptions"
+ :render-after-expand="false"
+ filterable
+ @change="handleProductChange"
+ style="width: 100%" />
</el-form-item>
<el-form-item label="浜у搧瑙勬牸"
- prop="specification">
- <el-input v-model="form.specification"
- placeholder="璇疯緭鍏ヤ骇鍝佽鏍�" />
- </el-form-item>
- <el-form-item label="鐗╂枡缂栫爜"
- prop="materialCode">
- <el-input v-model="form.materialCode"
- placeholder="璇疯緭鍏ョ墿鏂欑紪鐮�" />
+ prop="productMaterialSkuId">
+ <el-select v-model="form.productMaterialSkuId"
+ @change="handleChangeSpecification"
+ filterable
+ placeholder="璇烽�夋嫨">
+ <el-option v-for="item in specificationOptions"
+ :key="item.id"
+ :label="item.model"
+ :value="item.id" />
+ </el-select>
</el-form-item>
<el-form-item label="鍧楁暟"
prop="quantity">
@@ -293,9 +330,16 @@
placeholder="璇烽�夋嫨璁″垝缁撴潫鏃ユ湡" />
</el-form-item>
<el-form-item label="寮哄害"
- prop="strength">
- <el-input v-model="form.strength"
- placeholder="璇疯緭鍏ュ己搴�" />
+ prop="strength"
+ v-if="form.productName === '鐮屽潡'">
+ <el-select v-model="form.strength"
+ placeholder="璇烽�夋嫨寮哄害"
+ style="width: 100%">
+ <el-option v-for="item in block_strength"
+ :key="item.id"
+ :label="item.label"
+ :value="item.id" />
+ </el-select>
</el-form-item>
<el-form-item label="澶囨敞 1"
prop="remarkOne">
@@ -320,11 +364,12 @@
</template>
<script setup>
- import { onMounted, ref, reactive, getCurrentInstance } from "vue";
+ import { onMounted, ref, reactive, getCurrentInstance, toRefs } from "vue";
import { ElMessage } from "element-plus";
import dayjs from "dayjs";
import ImportDialog from "@/components/Dialog/ImportDialog.vue";
import { getToken } from "@/utils/auth";
+ import { useDict } from "@/utils/dict";
import {
productionPlanListPage,
loadProdData,
@@ -335,15 +380,33 @@
productionPlanCombine,
} from "@/api/productionPlan/productionPlan.js";
import PIMTable from "./components/PIMTable.vue";
+ import {
+ modelListPage,
+ productTreeList,
+ productTreeListQuery,
+ } from "@/api/basicData/newProduct.js";
const { proxy } = getCurrentInstance();
const tableColumn = ref([
{
+ label: "鏁版嵁鏉ユ簮",
+ width: "100px",
+ prop: "dataSourceType",
+ dataType: "tag",
+ formatType: params => {
+ const typeMap = {
+ 2: "warning",
+ 1: "primary",
+ };
+ return typeMap[params] || "info";
+ },
+ formatData: cell => (cell == 1 ? "閽夐拤鍚屾" : "鎵嬪姩鏂板"),
+ },
+ {
label: "鐢宠鍗曠紪鍙�",
prop: "applyNo",
width: "150px",
- className: "code-cell",
},
{
label: "瀹㈡埛鍚嶇О",
@@ -353,19 +416,20 @@
{
label: "浜у搧鍚嶇О",
prop: "productName",
- width: "100px",
+ width: "200px",
dataType: "tag",
formatType: params => {
- const typeMap = {
- 鏉挎潗: "primary",
- 鐮屽潡: "info",
- };
- return typeMap[params] || "info";
+ // const typeMap = {
+ // 鏉挎潗: "primary",
+ // 鐮屽潡: "warning",
+ // };
+ // return typeMap[params] || "info";
+ return "primary";
},
},
{
label: "浜у搧瑙勬牸",
- prop: "specification",
+ prop: "model",
width: "150px",
className: "spec-cell",
},
@@ -373,46 +437,73 @@
label: "鐗╂枡缂栫爜",
prop: "materialCode",
width: "150px",
- className: "code-cell",
},
{
label: "鍧楁暟",
prop: "quantity",
- className: "quantity-cell",
+ formatData: cell => (cell ? `${cell}鍧梎 : ""),
},
{
label: "鏂规暟",
prop: "volume",
width: "150px",
className: "volume-cell",
+ formatData: cell => (cell ? `${cell}鏂筦 : ""),
+ },
+ {
+ label: "涓嬪彂鐘舵��",
+ prop: "status",
+ width: "150px",
+ className: "status-cell",
+ dataType: "tag",
+ formatType: params => {
+ const typeMap = {
+ 0: "warning",
+ 1: "primary",
+ 2: "info",
+ };
+ return typeMap[params] || "info";
+ },
+ formatData: cell => {
+ const statusMap = {
+ 0: "寰呬笅鍙�",
+ 1: "閮ㄥ垎涓嬪彂",
+ 2: "宸蹭笅鍙�",
+ };
+ return statusMap[cell] || "";
+ },
},
{
label: "宸蹭笅鍙戞柟鏁�",
prop: "assignedQuantity",
width: "150px",
className: "spec-cell",
+ formatData: cell => (cell ? `${cell}鏂筦 : 0),
},
{
label: "闀�",
prop: "length",
className: "dimension-cell",
+ formatData: cell => (cell ? `${cell}mm` : ""),
},
{
label: "瀹�",
prop: "width",
className: "dimension-cell",
+ formatData: cell => (cell ? `${cell}mm` : ""),
},
{
label: "楂�",
prop: "height",
className: "dimension-cell",
+ formatData: cell => (cell ? `${cell}mm` : ""),
},
- {
- label: "娴佹按鍙�",
- prop: "serialNo",
- width: "150px",
- className: "code-cell",
- },
+ // {
+ // label: "娴佹按鍙�",
+ // prop: "serialNo",
+ // width: "150px",
+ // className: "code-cell",
+ // },
{
label: "璁″垝寮�濮嬫棩鏈�",
prop: "startDate",
@@ -430,19 +521,21 @@
{
label: "寮哄害",
prop: "strength",
+ formatData: cell => {
+ if (!cell) return "";
+ const strengthItem = block_strength.value.find(item => item.id === cell);
+ return strengthItem ? strengthItem.label : cell;
+ },
},
- // {
- // label: "鏁版嵁鏉ユ簮",
- // width: "100px",
- // prop: "dataSourceType",
- // formatData: cell => (cell == 1 ? "鍚屾" : "鎵嬪姩"),
- // },
+
{
label: "澶囨敞 1",
+ width: "150px",
prop: "remarkOne",
},
{
label: "澶囨敞 2",
+ width: "150px",
prop: "remarkTwo",
},
@@ -457,6 +550,10 @@
name: "缂栬緫",
type: "primary",
link: true,
+ showHide: row => {
+ return row.status == 0;
+ //status锛�0锛氬緟涓嬪彂锛�1锛氶儴鍒嗕笅鍙戯紝2锛氬凡涓嬪彂
+ },
clickFun: row => {
handleEdit(row);
},
@@ -465,6 +562,9 @@
name: "鍒犻櫎",
type: "danger",
link: true,
+ showHide: row => {
+ return row.status == 0;
+ },
clickFun: row => {
handleDelete(row);
},
@@ -472,25 +572,28 @@
{
name: "涓嬪彂",
type: "text",
- disabled: row => {
+ showHide: row => {
// 璁$畻鍓╀綑鏂规暟
const remainingVolume =
(row.volume || 0) - (row.assignedQuantity || 0);
// 濡傛灉鍓╀綑鏂规暟灏忎簬绛変簬0锛岀姝㈤�夋嫨
- return remainingVolume <= 0;
+ return remainingVolume > 0;
},
clickFun: row => {
// 鍗曠嫭涓嬪彂鎿嶄綔
// 璁剧疆琛ㄥ崟鏁版嵁
+ strengthError.value = "";
+ mergeForm.ids = [row.id];
mergeForm.materialCode = row.materialCode;
mergeForm.productName = row.productName || "";
- mergeForm.specification = row.specification || "";
+ mergeForm.model = row.model || "";
mergeForm.length = row.length || 0;
mergeForm.width = row.width || 0;
mergeForm.height = row.height || 0;
mergeForm.totalAssignedQuantity =
- Number(row.volume) - Number(row.assignedQuantity) || 0;
+ (Number(row.volume) - Number(row.assignedQuantity)).toFixed(4) || 0;
mergeForm.planCompleteTime = row.planCompleteTime || "";
+ mergeForm.strength = row.strength || "";
sumAssignedQuantity.value = mergeForm.totalAssignedQuantity;
// 鎵撳紑寮圭獥
isShowNewModal.value = true;
@@ -526,12 +629,13 @@
const mergeForm = reactive({
materialCode: "",
productName: "",
- specification: "",
+ model: "",
length: 0,
width: 0,
height: 0,
totalAssignedQuantity: 0,
planCompleteTime: "",
+ strength: "",
});
// 杩借釜杩涘害寮圭獥鎺у埗
@@ -557,13 +661,19 @@
// 鏂板/缂栬緫鐩稿叧
const dialogVisible = ref(false);
const operationType = ref("add"); // add | edit
+ const productOptions = ref([]);
+ const specificationOptions = ref([]);
const formRef = ref(null);
+ // 鑾峰彇寮哄害瀛楀吀
+ const { block_strength } = useDict("block_strength");
const form = reactive({
id: undefined,
applyNo: "",
customerName: "",
+ productMaterialId: undefined,
+ productMaterialSkuId: undefined,
productName: "",
- specification: "",
+ model: "",
materialCode: "",
quantity: 0,
volume: 0,
@@ -572,6 +682,7 @@
height: 0,
startDate: "",
endDate: "",
+ status: "",
strength: "",
remarkOne: "",
remarkTwo: "",
@@ -581,12 +692,25 @@
customerName: [
{ required: true, message: "璇疯緭鍏ュ鎴峰悕绉�", trigger: "blur" },
],
- productName: [{ required: true, message: "璇疯緭鍏ヤ骇鍝佸悕绉�", trigger: "blur" }],
- specification: [
- { required: true, message: "璇疯緭鍏ヤ骇鍝佽鏍�", trigger: "blur" },
+ productMaterialSkuId: [
+ { required: true, message: "璇烽�夋嫨浜у搧瑙勬牸", trigger: "change" },
],
- materialCode: [
- { required: true, message: "璇疯緭鍏ョ墿鏂欑紪鐮�", trigger: "blur" },
+ volume: [{ required: true, message: "璇疯緭鍏ユ柟鏁�", trigger: "blur" }],
+ productMaterialId: [
+ { required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" },
+ ],
+ strength: [
+ {
+ validator: (rule, value, callback) => {
+ if (form.productName === "鐮屽潡" && !value) {
+ callback(new Error("鐮屽潡浜у搧鐨勫己搴︿负蹇呭~椤�"));
+ } else {
+ callback();
+ }
+ },
+ trigger: ["blur", "change"],
+ required: false,
+ },
],
});
@@ -611,6 +735,85 @@
const onBlur = value => {
// 闄愬埗鍥涗綅灏忔暟
mergeForm.totalAssignedQuantity = Number(value.toFixed(4));
+ };
+
+ const fetchProductOptions = () => {
+ return productTreeList({ type: 2 }).then(res => {
+ productOptions.value = convertIdToValue(res.data);
+ return res;
+ });
+ };
+
+ const convertIdToValue = data => {
+ return data.map(item => {
+ const newItem = {
+ value: `config_${item.configId}`, // 浣跨敤config_鍓嶇紑纭繚鍞竴鎬�
+ label: item.configName,
+ disabled: item.materialList.length === 0,
+ };
+ if (item.materialList && item.materialList.length > 0) {
+ newItem.children = item.materialList.map(material => ({
+ value: material.id, // 浣跨敤material鐨刬d浣滀负value
+ label: material.productName, // 浣跨敤materialName浣滀负label
+ }));
+ }
+
+ return newItem;
+ });
+ };
+
+ const handleProductChange = value => {
+ form.productMaterialSkuId = undefined;
+ // 鏌ユ壘閫変腑鐨勪骇鍝佸悕绉�
+ const findProductName = (options, value) => {
+ for (const option of options) {
+ if (option.value === value) {
+ return option.label;
+ }
+ if (option.children) {
+ const found = findProductName(option.children, value);
+ if (found) {
+ return found;
+ }
+ }
+ }
+ return "";
+ };
+ form.productName = findProductName(productOptions.value, value);
+ // 瑙﹀彂寮哄害瀛楁楠岃瘉
+ if (formRef.value) {
+ formRef.value.validateField("strength");
+ }
+ fetchSpecificationOptions(value);
+ };
+
+ const fetchSpecificationOptions = productId => {
+ specificationOptions.value = [];
+ if (productId) {
+ modelListPage({ productId: productId, size: -1, current: -1 }).then(res => {
+ specificationOptions.value = res.data.records;
+ });
+ }
+ };
+
+ const handleChangeSpecification = value => {
+ form.materialCode = undefined;
+ const selectedModel = specificationOptions.value.find(
+ item => item.id === value
+ );
+ if (selectedModel) {
+ form.materialCode = selectedModel.materialCode;
+ // 瑙f瀽瑙勬牸瀛楃涓茶幏鍙栭暱瀹介珮
+ const model = selectedModel.model;
+ if (model) {
+ const dimensions = model.match(/^(\d+)\*(\d+)\*(\d+)$/);
+ if (dimensions && dimensions.length === 4) {
+ form.length = parseInt(dimensions[1]);
+ form.width = parseInt(dimensions[2]);
+ form.height = parseInt(dimensions[3]);
+ }
+ }
+ }
};
// 鐢熸垚妯℃嫙杩涘害璇︽儏鏁版嵁
@@ -688,7 +891,7 @@
searchForm: {
customerName: "",
productName: "",
- specification: "",
+ model: "",
materialCode: "",
applyNo: "",
dateRange: [],
@@ -708,7 +911,7 @@
Object.assign(searchForm.value, {
customerName: "",
productName: "",
- specification: "",
+ model: "",
materialCode: "",
applyNo: "",
dateRange: [],
@@ -734,8 +937,9 @@
totalAssignedQuantity: 0,
};
}
- summary[category].totalAssignedQuantity +=
- Number(row.volume) - Number(row.assignedQuantity);
+ summary[category].totalAssignedQuantity += (
+ Number(row.volume) - Number(row.assignedQuantity)
+ ).toFixed(4);
});
// 杞崲涓烘暟缁勬牸寮�
@@ -796,10 +1000,15 @@
// 鎷夊彇鏁版嵁鎸夐挳鎿嶄綔
const getLoadProdData = () => {
loadProdData()
- .then(res => {})
+ .then(res => {
+ getList();
+ })
.catch(() => {});
};
const sumAssignedQuantity = ref(0);
+ // 鍝嶅簲寮忔暟鎹�
+ const strengthError = ref("");
+
// 澶勭悊鍚堝苟涓嬪彂鎸夐挳鐐瑰嚮
const handleMerge = () => {
if (selectedRows.value.length === 0) {
@@ -807,27 +1016,48 @@
return;
}
console.log(selectedRows.value);
+ // 妫�鏌ュ己搴︿竴鑷存��
+ const firstRow = selectedRows.value[0];
+ const productName = firstRow.productName || "";
+ let strengthConsistent = true;
+ let firstStrength = firstRow.strength || "";
+ strengthError.value = "";
+
+ if (productName === "鐮屽潡") {
+ for (const row of selectedRows.value) {
+ if (row.strength !== firstStrength) {
+ strengthConsistent = false;
+ break;
+ }
+ }
+
+ if (!strengthConsistent) {
+ strengthError.value = "閫夋嫨鐨勭爩鍧楀己搴︿笉涓�鑷达紝璇烽噸鏂伴�夋嫨";
+ }
+ }
+
// 璁$畻鎬诲埗閫犳暟閲�
const totalAssignedQuantity = selectedRows.value.reduce((sum, row) => {
return (
sum +
(row.volume == null
? 0
- : Number(row.volume) - Number(row.assignedQuantity))
+ : (Number(row.volume) - Number(row.assignedQuantity)).toFixed(4))
);
}, 0);
sumAssignedQuantity.value = totalAssignedQuantity;
console.log(totalAssignedQuantity);
// 璁剧疆琛ㄥ崟鏁版嵁
- const firstRow = selectedRows.value[0];
mergeForm.materialCode = selectedserialNo.value;
- mergeForm.productName = firstRow.productName || "";
- mergeForm.specification = firstRow.specification || "";
+ mergeForm.productName = productName;
+ mergeForm.model = firstRow.model || "";
mergeForm.length = firstRow.length || 0;
mergeForm.width = firstRow.width || 0;
mergeForm.height = firstRow.height || 0;
mergeForm.totalAssignedQuantity = totalAssignedQuantity;
mergeForm.planCompleteTime = firstRow.planCompleteTime || "";
+ mergeForm.strength = firstStrength;
+ mergeForm.ids = selectedRows.value.map(row => row.id);
// 鎵撳紑寮圭獥
isShowNewModal.value = true;
@@ -835,6 +1065,15 @@
// 澶勭悊鍚堝苟涓嬪彂鎻愪氦
const handleMergeSubmit = () => {
+ if (mergeForm.totalAssignedQuantity === 0) {
+ ElMessage.warning("璇疯緭鍏ョ敓浜ф柟鏁�");
+ return;
+ }
+ // 楠岃瘉鐮屽潡浜у搧鐨勫己搴�
+ if (mergeForm.productName === "鐮屽潡" && !mergeForm.strength) {
+ ElMessage.error("鐮屽潡浜у搧鐨勫己搴︿负蹇呭~椤�");
+ return;
+ }
console.log(sumAssignedQuantity.value, "sumAssignedQuantity");
// 璁$畻褰撳墠閫変腑琛岀殑鎬绘柟鏁�
const totalVolume = selectedRows.value.reduce((sum, row) => {
@@ -847,16 +1086,17 @@
return;
}
- mergeForm.ids = selectedRows.value.map(row => row.id);
console.log(mergeForm, "mergeForm");
productionPlanCombine(mergeForm)
.then(res => {
if (res.code === 200) {
- ElMessage.success("鍚堝苟涓嬪彂鎴愬姛");
+ ElMessage.success("涓嬪彂鎴愬姛");
+ getList();
isShowNewModal.value = false;
// 鍙互閫夋嫨鍒锋柊鍒楄〃鎴栧叾浠栨搷浣�
+ getList();
} else {
- ElMessage.error(res.message || "鍚堝苟涓嬪彂澶辫触");
+ ElMessage.error(res.message || "涓嬪彂澶辫触");
}
})
.catch(err => {
@@ -950,7 +1190,9 @@
applyNo: "",
customerName: "",
productName: "",
- specification: "",
+ productMaterialId: undefined,
+ productMaterialSkuId: undefined,
+ model: "",
materialCode: "",
quantity: 0,
volume: 0,
@@ -964,6 +1206,7 @@
remarkTwo: "",
});
dialogVisible.value = true;
+ fetchProductOptions();
};
// 缂栬緫
@@ -974,7 +1217,9 @@
applyNo: row.applyNo || "",
customerName: row.customerName || "",
productName: row.productName || "",
- specification: row.specification || "",
+ productMaterialId: row.productMaterialId || undefined,
+ productMaterialSkuId: row.productMaterialSkuId || undefined,
+ model: row.model || "",
materialCode: row.materialCode || "",
quantity: row.quantity || 0,
volume: row.volume || 0,
@@ -988,6 +1233,8 @@
remarkTwo: row.remarkTwo || "",
});
dialogVisible.value = true;
+ fetchProductOptions();
+ fetchSpecificationOptions(row.productMaterialId);
};
// 鍒犻櫎
@@ -1015,8 +1262,16 @@
const handleSubmit = () => {
formRef.value.validate(valid => {
if (valid) {
+ if (form.volume === 0) {
+ proxy.$modal.msgError("鏂规暟涓嶈兘涓�0");
+ return;
+ }
+ if (form.v === "add") {
+ payload.id = null;
+ }
const payload = { ...form };
if (operationType.value === "add") {
+ payload.id = null;
productionPlanAdd(payload)
.then(() => {
proxy.$modal.msgSuccess(
@@ -1102,7 +1357,6 @@
color: #ffffff;
border-bottom: none;
padding: 16px 0;
- font-size: 14px;
letter-spacing: 0.5px;
}
}
@@ -1125,7 +1379,6 @@
border-bottom: 1px solid #f0f0f0;
padding: 14px 0;
color: #303133;
- font-size: 13px;
}
}
@@ -1144,7 +1397,6 @@
font-weight: 600;
color: #409eff;
font-family: "Courier New", monospace;
- font-size: 14px;
text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2);
}
@@ -1169,7 +1421,6 @@
// 鏃ユ湡瀛楁鏍峰紡
.date-cell {
color: #909399;
- font-size: 12px;
font-style: italic;
}
--
Gitblit v1.9.3