From 4acf9156ee445cb9f2367d77824e1c6e25b397ab Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期六, 14 三月 2026 10:52:45 +0800
Subject: [PATCH] 工序和公益路线页面开发
---
src/views/productionManagement/productionProcess/index.vue | 1189 ++++++++++++++++++----
/dev/null | 105 --
src/views/productionManagement/processRoute/index.vue | 1515 +++++++++++++++++++++++++---
src/views/basicData/parameterMaintenance/index.vue | 279 ++--
4 files changed, 2,406 insertions(+), 682 deletions(-)
diff --git a/src/views/basicData/parameterMaintenance/index.vue b/src/views/basicData/parameterMaintenance/index.vue
index 0400952..5d7a30c 100644
--- a/src/views/basicData/parameterMaintenance/index.vue
+++ b/src/views/basicData/parameterMaintenance/index.vue
@@ -7,11 +7,12 @@
style="width: 200px"
placeholder="璇疯緭鍏ュ弬鏁板悕绉�"
clearable />
- <span class="search_title ml10">鍏宠仈浜у搧绫诲瀷锛�</span>
+ <!-- 鍏宠仈浜у搧绫诲瀷鎼滅储 -->
+ <!-- <span class="search_title ml10">鍏宠仈浜у搧绫诲瀷锛�</span>
<el-input v-model="searchForm.productName"
style="width: 200px"
placeholder="璇疯緭鍏ュ叧鑱斾骇鍝佺被鍨�"
- clearable />
+ clearable /> -->
<el-button type="primary"
@click="handleQuery"
style="margin-left: 10px">鎼滅储</el-button>
@@ -19,9 +20,10 @@
<el-button type="primary"
@click="handleAdd"
style="margin-left: 10px">鏂板鍙傛暟</el-button>
- <el-button type="primary"
+ <!-- 浜у搧绫诲瀷缁存姢鎸夐挳 -->
+ <!-- <el-button type="primary"
@click="handleProductTypeMaintenance"
- style="margin-left: 10px">浜у搧绫诲瀷缁存姢</el-button>
+ style="margin-left: 10px">浜у搧绫诲瀷缁存姢</el-button> -->
</div>
</div>
<div class="table_list">
@@ -106,7 +108,8 @@
<el-input v-model="formData.parameterFormat"
placeholder="璇疯緭鍏ュ弬鏁版牸寮�" />
</el-form-item>
- <el-form-item label="鍏宠仈浜у搧绫诲瀷"
+ <!-- 鍏宠仈浜у搧绫诲瀷 -->
+ <!-- <el-form-item label="鍏宠仈浜у搧绫诲瀷"
prop="parameterValue">
<el-select v-model="formData.parameterValue"
placeholder="璇烽�夋嫨鍏宠仈浜у搧绫诲瀷">
@@ -115,7 +118,7 @@
:label="item.label"
:value="item.value" />
</el-select>
- </el-form-item>
+ </el-form-item> -->
<el-form-item label="鏍囧噯鍊�"
v-if="formData.parameterType2 === '1'"
prop="standardValue">
@@ -149,7 +152,7 @@
</template>
</el-dialog>
<!-- 浜у搧绫诲瀷缁存姢瀵硅瘽妗� -->
- <el-dialog v-model="productTypeDialogVisible"
+ <!-- <el-dialog v-model="productTypeDialogVisible"
title="浜у搧绫诲瀷缁存姢"
width="600px">
<div class="product-type-header">
@@ -159,9 +162,9 @@
<el-table :data="productTypeList"
border
style="width: 100%; margin-top: 10px; margin-bottom: 20px">
- <!-- <el-table-column prop="typeCode"
+ <el-table-column prop="typeCode"
label="绫诲瀷缂栫爜"
- width="150" /> -->
+ width="150" />
<el-table-column prop="typeName"
label="绫诲瀷鍚嶇О" />
<el-table-column label="鎿嶄綔"
@@ -176,20 +179,20 @@
</template>
</el-table-column>
</el-table>
- </el-dialog>
+ </el-dialog> -->
<!-- 鏂板/缂栬緫浜у搧绫诲瀷瀵硅瘽妗� -->
- <el-dialog v-model="productTypeFormVisible"
+ <!-- <el-dialog v-model="productTypeFormVisible"
:title="productTypeDialogTitle"
width="400px">
<el-form :model="productTypeForm"
:rules="productTypeRules"
ref="productTypeFormRef"
label-width="100px">
- <!-- <el-form-item label="绫诲瀷缂栫爜"
+ <el-form-item label="绫诲瀷缂栫爜"
prop="typeCode">
<el-input v-model="productTypeForm.typeCode"
placeholder="璇疯緭鍏ョ被鍨嬬紪鐮�" />
- </el-form-item> -->
+ </el-form-item>
<el-form-item label="绫诲瀷鍚嶇О"
prop="typeName">
<el-input v-model="productTypeForm.typeName"
@@ -203,7 +206,7 @@
@click="handleProductTypeSubmit">纭畾</el-button>
</span>
</template>
- </el-dialog>
+ </el-dialog> -->
</div>
</template>
@@ -214,7 +217,7 @@
addParameter,
updateParameter,
delParameter,
- getProductTypes as getProductTypesApi,
+ // getProductTypes as getProductTypesApi,
} from "@/api/basicData/parameterMaintenance.js";
import { listType } from "@/api/system/dict/type";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
@@ -252,10 +255,11 @@
label: "鍙傛暟鏍煎紡",
prop: "parameterFormat",
},
- {
- label: "鍏宠仈浜у搧绫诲瀷",
- prop: "parameterValue",
- },
+ // 鍏宠仈浜у搧绫诲瀷鍒�
+ // {
+ // label: "鍏宠仈浜у搧绫诲瀷",
+ // prop: "parameterValue",
+ // },
{
label: "鏍囧噯鍊�",
prop: "standardValue",
@@ -325,7 +329,7 @@
parameterType2: "1",
parameterType: "",
parameterFormat: "",
- parameterValue: "",
+ // parameterValue: "",
standardValue: "",
unit: "",
});
@@ -342,31 +346,31 @@
parameterFormat: [
{ required: true, message: "璇烽�夋嫨鍙傛暟鏍煎紡", trigger: "change" },
],
- parameterValue: [
- { required: true, message: "璇烽�夋嫨鍏宠仈浜у搧绫诲瀷", trigger: "change" },
- ],
+ // parameterValue: [
+ // { required: true, message: "璇烽�夋嫨鍏宠仈浜у搧绫诲瀷", trigger: "change" },
+ // ],
standardValue: [{ required: true, message: "璇疯緭鍏ユ爣鍑嗗��", trigger: "blur" }],
unit: [{ required: true, message: "璇疯緭鍏ュ崟浣�", trigger: "blur" }],
});
- const productTypes = ref([]);
+ // const productTypes = ref([]);
const isEdit = ref(false);
- // 浜у搧绫诲瀷缁存姢鐩稿叧
- const productTypeDialogVisible = ref(false);
- const productTypeFormVisible = ref(false);
- const productTypeDialogTitle = ref("");
- const productTypeFormRef = ref(null);
- const productTypeList = ref([]);
- const productTypeForm = reactive({
- id: null,
- // typeCode: "",
- typeName: "",
- });
- const productTypeRules = reactive({
- // typeCode: [{ required: true, message: "璇疯緭鍏ョ被鍨嬬紪鐮�", trigger: "blur" }],
- typeName: [{ required: true, message: "璇疯緭鍏ョ被鍨嬪悕绉�", trigger: "blur" }],
- });
- const isProductTypeEdit = ref(false);
+ // 浜у搧绫诲瀷缁存姢鐩稿叧 - 宸叉敞閲�
+ // const productTypeDialogVisible = ref(false);
+ // const productTypeFormVisible = ref(false);
+ // const productTypeDialogTitle = ref("");
+ // const productTypeFormRef = ref(null);
+ // const productTypeList = ref([]);
+ // const productTypeForm = reactive({
+ // id: null,
+ // typeCode: "",
+ // typeName: "",
+ // });
+ // const productTypeRules = reactive({
+ // typeCode: [{ required: true, message: "璇疯緭鍏ョ被鍨嬬紪鐮�", trigger: "blur" }],
+ // typeName: [{ required: true, message: "璇疯緭鍏ョ被鍨嬪悕绉�", trigger: "blur" }],
+ // });
+ // const isProductTypeEdit = ref(false);
const handleParameterTypeChange = () => {
if (formData.parameterType === "鏁板�兼牸寮�") {
formData.parameterFormat = "#.0000";
@@ -376,65 +380,65 @@
formData.parameterFormat = "";
}
};
- // 浜у搧绫诲瀷缁存姢鎸夐挳鐐瑰嚮浜嬩欢
- const handleProductTypeMaintenance = () => {
- productTypeDialogVisible.value = true;
- getProductTypeList();
- };
+ // 浜у搧绫诲瀷缁存姢鎸夐挳鐐瑰嚮浜嬩欢 - 宸叉敞閲�
+ // const handleProductTypeMaintenance = () => {
+ // productTypeDialogVisible.value = true;
+ // getProductTypeList();
+ // };
- // 鑾峰彇浜у搧绫诲瀷鍒楄〃
- const getProductTypeList = () => {
- productTypeList.value = [
- { id: 1, typeCode: "TYPE001", typeName: "3.5鐮屽潡" },
- { id: 2, typeCode: "TYPE002", typeName: "5.0鐮屽潡" },
- { id: 3, typeCode: "TYPE003", typeName: "鏉挎潗" },
- ];
- };
+ // 鑾峰彇浜у搧绫诲瀷鍒楄〃 - 宸叉敞閲�
+ // const getProductTypeList = () => {
+ // productTypeList.value = [
+ // { id: 1, typeCode: "TYPE001", typeName: "3.5鐮屽潡" },
+ // { id: 2, typeCode: "TYPE002", typeName: "5.0鐮屽潡" },
+ // { id: 3, typeCode: "TYPE003", typeName: "鏉挎潗" },
+ // ];
+ // };
- // 鏂板浜у搧绫诲瀷
- const handleAddProductType = () => {
- isProductTypeEdit.value = false;
- productTypeDialogTitle.value = "鏂板浜у搧绫诲瀷";
- productTypeForm.id = null;
- productTypeForm.typeCode = "";
- productTypeForm.typeName = "";
- productTypeFormVisible.value = true;
- };
+ // 鏂板浜у搧绫诲瀷 - 宸叉敞閲�
+ // const handleAddProductType = () => {
+ // isProductTypeEdit.value = false;
+ // productTypeDialogTitle.value = "鏂板浜у搧绫诲瀷";
+ // productTypeForm.id = null;
+ // productTypeForm.typeCode = "";
+ // productTypeForm.typeName = "";
+ // productTypeFormVisible.value = true;
+ // };
- // 缂栬緫浜у搧绫诲瀷
- const handleEditProductType = row => {
- isProductTypeEdit.value = true;
- productTypeDialogTitle.value = "缂栬緫浜у搧绫诲瀷";
- productTypeForm.id = row.id;
- productTypeForm.typeCode = row.typeCode;
- productTypeForm.typeName = row.typeName;
- productTypeFormVisible.value = true;
- };
+ // 缂栬緫浜у搧绫诲瀷 - 宸叉敞閲�
+ // const handleEditProductType = row => {
+ // isProductTypeEdit.value = true;
+ // productTypeDialogTitle.value = "缂栬緫浜у搧绫诲瀷";
+ // productTypeForm.id = row.id;
+ // productTypeForm.typeCode = row.typeCode;
+ // productTypeForm.typeName = row.typeName;
+ // productTypeFormVisible.value = true;
+ // };
- // 鍒犻櫎浜у搧绫诲瀷
- const handleDeleteProductType = row => {
- ElMessageBox.confirm("纭畾瑕佸垹闄よ浜у搧绫诲瀷鍚楋紵", "鎻愮ず", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- ElMessage.success("鍒犻櫎鎴愬姛");
- getProductTypeList();
- })
- .catch(() => {});
- };
+ // 鍒犻櫎浜у搧绫诲瀷 - 宸叉敞閲�
+ // const handleDeleteProductType = row => {
+ // ElMessageBox.confirm("纭畾瑕佸垹闄よ浜у搧绫诲瀷鍚楋紵", "鎻愮ず", {
+ // confirmButtonText: "纭畾",
+ // cancelButtonText: "鍙栨秷",
+ // type: "warning",
+ // })
+ // .then(() => {
+ // ElMessage.success("鍒犻櫎鎴愬姛");
+ // getProductTypeList();
+ // })
+ // .catch(() => {});
+ // };
- // 鎻愪氦浜у搧绫诲瀷琛ㄥ崟
- const handleProductTypeSubmit = () => {
- productTypeFormRef.value.validate(valid => {
- if (valid) {
- ElMessage.success(isProductTypeEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
- productTypeFormVisible.value = false;
- getProductTypeList();
- }
- });
- };
+ // 鎻愪氦浜у搧绫诲瀷琛ㄥ崟 - 宸叉敞閲�
+ // const handleProductTypeSubmit = () => {
+ // productTypeFormRef.value.validate(valid => {
+ // if (valid) {
+ // ElMessage.success(isProductTypeEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ // productTypeFormVisible.value = false;
+ // getProductTypeList();
+ // }
+ // });
+ // };
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
@@ -460,15 +464,15 @@
tableLoading.value = true;
// 娉ㄩ噴鎺堿PI璋冪敤锛屼娇鐢ㄥ亣鏁版嵁
/*const params = { ...searchForm, ...page };
- parameterListPage(params)
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data;
- page.total = res.total || 0;
- })
- .catch(() => {
- tableLoading.value = false;
- });*/
+ parameterListPage(params)
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data;
+ page.total = res.total || 0;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });*/
// 鍋囨暟鎹�
setTimeout(() => {
@@ -534,29 +538,14 @@
}, 500);
};
- // 鑾峰彇浜у搧绫诲瀷鍒楄〃
- const getProductTypes = () => {
- // 娉ㄩ噴鎺堿PI璋冪敤锛屼娇鐢ㄥ亣鏁版嵁
- /*getProductTypesApi()
- .then(res => {
- productTypes.value = res.data || [];
- })
- .catch(() => {
- // 澶辫触鏃朵娇鐢ㄦā鎷熸暟鎹�
- productTypes.value = [
- { label: "3.5鐮屽潡", value: "type1" },
- { label: "5.0鐮屽潡", value: "type2" },
- { label: "鏉挎潗", value: "type3" },
- ];
- });*/
-
- // 鍋囨暟鎹�
- productTypes.value = [
- { label: "3.5鐮屽潡", value: "type1" },
- { label: "5.0鐮屽潡", value: "type2" },
- { label: "鏉挎潗", value: "type3" },
- ];
- };
+ // 鑾峰彇浜у搧绫诲瀷鍒楄〃 - 宸叉敞閲�
+ // const getProductTypes = () => {
+ // productTypes.value = [
+ // { label: "3.5鐮屽潡", value: "type1" },
+ // { label: "5.0鐮屽潡", value: "type2" },
+ // { label: "鏉挎潗", value: "type3" },
+ // ];
+ // };
// 鏂板鎸夐挳鐐瑰嚮浜嬩欢
const handleAdd = () => {
@@ -568,7 +557,7 @@
formData.parameterType2 = "1";
formData.parameterType = "";
formData.parameterFormat = "";
- formData.parameterValue = "";
+ // formData.parameterValue = "";
formData.standardValue = "";
formData.unit = "";
dialogVisible.value = true;
@@ -584,7 +573,7 @@
formData.parameterType2 = row.parameterType2 || "1";
formData.parameterType = row.parameterType;
formData.parameterFormat = row.parameterFormat;
- formData.parameterValue = row.parameterValue;
+ // formData.parameterValue = row.parameterValue;
formData.standardValue = row.standardValue;
formData.unit = row.unit;
dialogVisible.value = true;
@@ -600,13 +589,13 @@
.then(() => {
// 娉ㄩ噴鎺堿PI璋冪敤锛屼娇鐢ㄥ亣鏁版嵁
/*delParameter(row.id)
- .then(res => {
- ElMessage.success("鍒犻櫎鎴愬姛");
- getList();
- })
- .catch(() => {
- ElMessage.error("鍒犻櫎澶辫触");
- });*/
+ .then(res => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });*/
// 鍋囨暟鎹ā鎷�
ElMessage.success("鍒犻櫎鎴愬姛");
@@ -623,15 +612,15 @@
if (valid) {
// 娉ㄩ噴鎺堿PI璋冪敤锛屼娇鐢ㄥ亣鏁版嵁
/*const api = isEdit.value ? updateParameter : addParameter;
- api(formData)
- .then(res => {
- ElMessage.success(isEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
- dialogVisible.value = false;
- getList();
- })
- .catch(() => {
- ElMessage.error(isEdit.value ? "缂栬緫澶辫触" : "鏂板澶辫触");
- });*/
+ api(formData)
+ .then(res => {
+ ElMessage.success(isEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ dialogVisible.value = false;
+ getList();
+ })
+ .catch(() => {
+ ElMessage.error(isEdit.value ? "缂栬緫澶辫触" : "鏂板澶辫触");
+ });*/
// 鍋囨暟鎹ā鎷�
ElMessage.success(isEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
@@ -652,7 +641,7 @@
onMounted(() => {
getDictTypes();
getList();
- getProductTypes();
+ // getProductTypes();
});
</script>
diff --git a/src/views/productionManagement/processRoute/Edit.vue b/src/views/productionManagement/processRoute/Edit.vue
deleted file mode 100644
index 0c0fe0f..0000000
--- a/src/views/productionManagement/processRoute/Edit.vue
+++ /dev/null
@@ -1,252 +0,0 @@
-<template>
- <div>
- <el-dialog
- v-model="isShow"
- title="缂栬緫宸ヨ壓璺嚎"
- width="400"
- @close="closeModal"
- >
- <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
- <el-form-item
- label="浜у搧鍚嶇О"
- prop="productModelId"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨浜у搧',
- trigger: 'change',
- }
- ]"
- >
- <el-button type="primary" @click="showProductSelectDialog = true">
- {{ formState.productName && formState.productModelName
- ? `${formState.productName} - ${formState.productModelName}`
- : '閫夋嫨浜у搧' }}
- </el-button>
- </el-form-item>
-
- <el-form-item
- label="BOM"
- prop="bomId"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨BOM',
- trigger: 'change',
- }
- ]"
- >
- <el-select
- v-model="formState.bomId"
- placeholder="璇烽�夋嫨BOM"
- clearable
- :disabled="!formState.productModelId || bomOptions.length === 0"
- style="width: 100%"
- >
- <el-option
- v-for="item in bomOptions"
- :key="item.id"
- :label="item.bomNo || `BOM-${item.id}`"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
-
- <el-form-item label="澶囨敞" prop="description">
- <el-input v-model="formState.description" type="textarea" />
- </el-form-item>
- </el-form>
-
- <!-- 浜у搧閫夋嫨寮圭獥 -->
- <ProductSelectDialog
- v-model="showProductSelectDialog"
- @confirm="handleProductSelect"
- single
- />
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="handleSubmit">纭</el-button>
- <el-button @click="closeModal">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import {ref, computed, getCurrentInstance, onMounted, nextTick, watch} from "vue";
-import {update} from "@/api/productionManagement/processRoute.js";
-import {getByModel} from "@/api/productionManagement/productBom.js";
-import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-
-const props = defineProps({
- visible: {
- type: Boolean,
- required: true,
- },
-
- record: {
- type: Object,
- required: true,
- }
-});
-
-const emit = defineEmits(['update:visible', 'completed']);
-
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
-const formState = ref({
- productId: undefined,
- productModelId: undefined,
- productName: "",
- productModelName: "",
- bomId: undefined,
- description: '',
-});
-
-const isShow = computed({
- get() {
- return props.visible;
- },
- set(val) {
- emit('update:visible', val);
- },
-});
-
-const showProductSelectDialog = ref(false);
-const bomOptions = ref([]);
-
-let { proxy } = getCurrentInstance()
-
-const closeModal = () => {
- isShow.value = false;
-};
-
-// 璁剧疆琛ㄥ崟鏁版嵁
-const setFormData = () => {
- if (props.record) {
- formState.value = {
- ...props.record,
- productId: props.record.productId,
- productModelId: props.record.productModelId,
- productName: props.record.productName || "",
- // 娉ㄦ剰锛歳ecord涓殑瀛楁鏄痬odel锛岄渶瑕佹槧灏勫埌productModelName
- productModelName: props.record.model || props.record.productModelName || "",
- bomId: props.record.bomId,
- description: props.record.description || '',
- };
- // 濡傛灉鏈変骇鍝佸瀷鍙稩D锛屽姞杞紹OM鍒楄〃
- if (props.record.productModelId) {
- loadBomList(props.record.productModelId);
- }
- }
-}
-
-// 鍔犺浇BOM鍒楄〃
-const loadBomList = async (productModelId) => {
- if (!productModelId) {
- bomOptions.value = [];
- return;
- }
- try {
- const res = await getByModel(productModelId);
- // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
- let bomList = [];
- if (Array.isArray(res)) {
- bomList = res;
- } else if (res && res.data) {
- bomList = Array.isArray(res.data) ? res.data : [res.data];
- } else if (res && typeof res === 'object') {
- bomList = [res];
- }
- bomOptions.value = bomList;
- } catch (error) {
- console.error("鍔犺浇BOM鍒楄〃澶辫触锛�", error);
- bomOptions.value = [];
- }
-};
-
-// 浜у搧閫夋嫨澶勭悊
-const handleProductSelect = async (products) => {
- if (products && products.length > 0) {
- const product = products[0];
- // 鍏堟煡璇OM鍒楄〃锛堝繀閫夛級
- try {
- const res = await getByModel(product.id);
- // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
- let bomList = [];
- if (Array.isArray(res)) {
- bomList = res;
- } else if (res && res.data) {
- bomList = Array.isArray(res.data) ? res.data : [res.data];
- } else if (res && typeof res === 'object') {
- bomList = [res];
- }
-
- if (bomList.length > 0) {
- formState.value.productModelId = product.id;
- formState.value.productName = product.productName;
- formState.value.productModelName = product.model;
- // 濡傛灉褰撳墠閫夋嫨鐨凚OM涓嶅湪鏂板垪琛ㄤ腑锛屽垯閲嶇疆BOM閫夋嫨
- const currentBomExists = bomList.some(bom => bom.id === formState.value.bomId);
- if (!currentBomExists) {
- formState.value.bomId = undefined;
- }
- bomOptions.value = bomList;
- showProductSelectDialog.value = false;
- // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
- proxy.$refs["formRef"]?.validateField('productModelId');
- } else {
- proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
- }
- } catch (error) {
- // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
- proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
- }
- }
-};
-
-const handleSubmit = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰BOM
- if (!formState.value.productModelId) {
- proxy.$modal.msgError("璇烽�夋嫨浜у搧");
- return;
- }
- if (!formState.value.bomId) {
- proxy.$modal.msgError("璇烽�夋嫨BOM");
- return;
- }
- update(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- })
- }
- })
-};
-
-defineExpose({
- closeModal,
- handleSubmit,
- isShow,
-});
-
-
-// 鐩戝惉寮圭獥鎵撳紑锛屽垵濮嬪寲琛ㄥ崟鏁版嵁
-watch(() => props.visible, (visible) => {
- if (visible && props.record) {
- nextTick(() => {
- setFormData();
- });
- }
-}, { immediate: true });
-
-onMounted(() => {
- if (props.visible && props.record) {
- setFormData();
- }
-});
-</script>
diff --git a/src/views/productionManagement/processRoute/ItemsForm.vue b/src/views/productionManagement/processRoute/ItemsForm.vue
deleted file mode 100644
index ed6e499..0000000
--- a/src/views/productionManagement/processRoute/ItemsForm.vue
+++ /dev/null
@@ -1,531 +0,0 @@
-<template>
- <div>
- <el-dialog
- v-model="isShow"
- title="宸ヨ壓璺嚎椤圭洰"
- width="800px"
- @close="closeModal"
- >
- <div class="operate-button">
- <el-button
- type="primary"
- @click="isShowProductSelectDialog = true"
- class="mb5"
- style="margin-bottom: 10px;"
- >
- 閫夋嫨浜у搧
- </el-button>
-
- <el-switch
- v-model="isTable"
- inline-prompt
- active-text="琛ㄦ牸"
- inactive-text="鍒楄〃"
- @change="handleViewChange"
- />
- </div>
-
- <el-table
- v-if="isTable"
- ref="multipleTable"
- v-loading="tableLoading"
- border
- :data="routeItems"
- :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
- row-key="id"
- tooltip-effect="dark"
- class="lims-table"
- style="cursor: move;"
- >
- <el-table-column align="center" label="搴忓彿" width="60">
- <template #default="scope">
- {{ scope.$index + 1 }}
- </template>
- </el-table-column>
-
- <el-table-column
- v-for="(item, index) in tableColumn"
- :key="index"
- :label="item.label"
- :width="item.width"
- show-overflow-tooltip
- >
- <template #default="scope" v-if="item.dataType === 'action'">
- <el-button
- v-for="(op, opIndex) in item.operation"
- :key="opIndex"
- :type="op.type"
- :link="op.link"
- size="small"
- @click.stop="op.clickFun(scope.row)"
- >
- {{ op.name }}
- </el-button>
- </template>
-
- <template #default="scope" v-else>
- <template v-if="item.prop === 'processId'">
- <el-select
- v-model="scope.row[item.prop]"
- style="width: 100%;"
- @mousedown.stop
- >
- <el-option
- v-for="process in processOptions"
- :key="process.id"
- :label="process.name"
- :value="process.id"
- />
- </el-select>
- </template>
- <template v-else>
- {{ scope.row[item.prop] || '-' }}
- </template>
- </template>
- </el-table-column>
- </el-table>
-
- <!-- 浣跨敤鏅�歞iv鏇夸唬el-steps -->
- <div
- v-else
- ref="stepsContainer"
- class="mb5 custom-steps"
- style="padding: 10px 0; display: flex; flex-wrap: nowrap; gap: 20px; align-items: flex-start;"
- >
- <div
- v-for="(item, index) in routeItems"
- :key="item.id"
- class="custom-step draggable-step"
- :data-id="item.id"
- style="cursor: move; flex: 0 0 auto; min-width: 220px;"
- >
- <div class="step-content">
- <div class="step-number">{{ index + 1 }}</div>
- <el-card
- :header="item.productName"
- class="step-card"
- style="cursor: move;"
- >
- <div class="step-card-content">
- <p>{{ item.model }}</p>
- <p>{{ item.unit }}</p>
- <el-select
- v-model="item.processId"
- style="width: 100%;"
- @mousedown.stop
- >
- <el-option
- v-for="process in processOptions"
- :key="process.id"
- :label="process.name"
- :value="process.id"
- />
- </el-select>
- </div>
- <template #footer>
- <div class="step-card-footer">
- <el-button type="danger" link size="small" @click.stop="removeItemByID(item.id)">鍒犻櫎</el-button>
- </div>
- </template>
- </el-card>
- </div>
- </div>
- </div>
-
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="handleSubmit">纭</el-button>
- <el-button @click="closeModal">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
-
- <ProductSelectDialog
- v-model="isShowProductSelectDialog"
- @confirm="handelSelectProducts"
- />
- </div>
-</template>
-
-<script setup>
-import { ref, computed, getCurrentInstance, onMounted, onUnmounted, nextTick } from "vue";
-import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-import { findProcessRouteItemList, addOrUpdateProcessRouteItem } from "@/api/productionManagement/processRouteItem.js";
-import { processList } from "@/api/productionManagement/productionProcess.js";
-import Sortable from 'sortablejs';
-
-const props = defineProps({
- visible: {
- type: Boolean,
- required: true,
- default: false
- },
- record: {
- type: Object,
- required: true,
- default: () => ({})
- }
-});
-
-const emit = defineEmits(['update:visible', 'completed']);
-
-const processOptions = ref([]);
-const tableLoading = ref(false);
-const isShowProductSelectDialog = ref(false);
-const routeItems = ref([]);
-let tableSortable = null;
-let stepsSortable = null;
-const multipleTable = ref(null);
-const stepsContainer = ref(null);
-const isTable = ref(true);
-
-const isShow = computed({
- get() {
- return props.visible;
- },
- set(val) {
- emit('update:visible', val);
- }
-});
-
-const tableColumn = ref([
- { label: "浜у搧鍚嶇О", prop: "productName", width: 180 },
- { label: "瑙勬牸鍚嶇О", prop: "model", width: 150 },
- { label: "鍗曚綅", prop: "unit", width: 80 },
- { label: "宸ュ簭鍚嶇О", prop: "processId", width: 180 },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 100,
- operation: [
- {
- name: "鍒犻櫎",
- type: "danger",
- link: true,
- clickFun: (row) => {
- const idx = routeItems.value.findIndex(item => item.id === row.id);
- if (idx > -1) {
- removeItem(idx)
- }
- }
- }
- ]
- }
-]);
-
-const removeItem = (index) => {
- routeItems.value.splice(index, 1);
- nextTick(() => initSortable());
-};
-
-const removeItemByID = (id) => {
- const idx = routeItems.value.findIndex(item => item.id === id);
- if (idx > -1) {
- routeItems.value.splice(idx, 1);
- nextTick(() => initSortable());
- }
-};
-
-const closeModal = () => {
- isShow.value = false;
-};
-
-const handelSelectProducts = (products) => {
- destroySortable();
-
- const newData = products.map(({ id, ...product }) => ({
- ...product,
- productModelId: id,
- routeId: props.record.id,
- id: `${Date.now()}-${Math.random().toString(36).slice(2)}`,
- processId: undefined
- }));
-
- console.log('閫夋嫨浜у搧鍓嶆暟缁�:', routeItems.value);
- routeItems.value.push(...newData);
- routeItems.value = [...routeItems.value];
- console.log('閫夋嫨浜у搧鍚庢暟缁�:', routeItems.value);
-
- // 寤惰繜鍒濆鍖栵紝纭繚DOM瀹屽叏娓叉煋
- nextTick(() => {
- // 寮哄埗閲嶆柊娓叉煋缁勪欢
- if (proxy?.$forceUpdate) {
- proxy.$forceUpdate();
- }
-
- const temp = [...routeItems.value];
- routeItems.value = [];
- nextTick(() => {
- routeItems.value = temp;
- initSortable();
- });
- });
-};
-
-const findProcessRouteItems = () => {
- tableLoading.value = true;
- findProcessRouteItemList({ routeId: props.record.id })
- .then(res => {
- tableLoading.value = false;
- routeItems.value = res.data.map(item => ({
- ...item,
- processId: item.processId === 0 ? undefined : item.processId
- }));
- // 寤惰繜鍒濆鍖栵紝纭繚DOM瀹屽叏娓叉煋
- nextTick(() => {
- setTimeout(() => initSortable(), 100);
- });
- })
- .catch(err => {
- tableLoading.value = false;
- console.error("鑾峰彇鍒楄〃澶辫触锛�", err);
- });
-};
-
-const findProcessList = () => {
- processList({})
- .then(res => {
- processOptions.value = res.data;
- })
- .catch(err => {
- console.error("鑾峰彇宸ュ簭澶辫触锛�", err);
- });
-};
-
-const { proxy } = getCurrentInstance() || {};
-
-const handleSubmit = () => {
- const hasEmptyProcess = routeItems.value.some(item => !item.processId);
- if (hasEmptyProcess) {
- proxy?.$modal?.msgError("璇蜂负鎵�鏈夐」鐩�夋嫨宸ュ簭");
- return;
- }
-
- addOrUpdateProcessRouteItem({
- routeId: props.record.id,
- processRouteItem: routeItems.value.map(({ id, ...item }) => item)
- })
- .then(res => {
- isShow.value = false;
- emit('completed');
- proxy?.$modal?.msgSuccess("鎻愪氦鎴愬姛");
- })
- .catch(err => {
- proxy?.$modal?.msgError(`鎻愪氦澶辫触锛�${err.msg || "缃戠粶寮傚父"}`);
- });
-};
-
-const destroySortable = () => {
- if (tableSortable) {
- tableSortable.destroy();
- tableSortable = null;
- }
- if (stepsSortable) {
- stepsSortable.destroy();
- stepsSortable = null;
- }
-};
-
-const initSortable = () => {
- destroySortable();
-
- if (isTable.value) {
- if (!multipleTable.value) return;
- const tbody = multipleTable.value.$el.querySelector('.el-table__body tbody') ||
- multipleTable.value.$el.querySelector('.el-table__body-wrapper > table > tbody');
- if (!tbody) return;
-
- tableSortable = new Sortable(tbody, {
- animation: 150,
- ghostClass: 'sortable-ghost',
- handle: '.el-table__row',
- filter: '.el-button, .el-select',
- onEnd: (evt) => {
- if (evt.oldIndex === evt.newIndex || !routeItems.value[evt.oldIndex]) return;
-
- // 浣跨敤鏁扮粍 splice 鏂规硶閲嶆柊鎺掑簭锛屼笌琛ㄦ牸妯″紡淇濇寔涓�鑷�
- const moveItem = routeItems.value.splice(evt.oldIndex, 1)[0];
- routeItems.value.splice(evt.newIndex, 0, moveItem);
- routeItems.value = [...routeItems.value];
- console.log('鎺掑簭鍚庢暟缁�:', routeItems.value);
- }
- });
- } else {
- if (!stepsContainer.value) return;
-
- // 淇敼锛氱洿鎺ヤ娇鐢╯tepsContainer.value浣滀负鎷栨嫿瀹瑰櫒
- const stepsList = stepsContainer.value;
- if (!stepsList) {
- console.warn('鏈壘鍒版楠ゆ潯鎷栨嫿瀹瑰櫒');
- return;
- }
-
- // 淇敼锛氱畝鍖栨嫋鎷介厤缃�
- stepsSortable = new Sortable(stepsList, {
- animation: 150,
- ghostClass: 'sortable-ghost',
- draggable: '.draggable-step', // 鍙嫋鎷藉厓绱�
- handle: '.draggable-step, .step-card', // 鎷栨嫿鎵嬫焺
- filter: '.el-button, .el-select, .el-input', // 杩囨护鎸夐挳/閫夋嫨鍣�
- forceFallback: true,
- fallbackClass: 'sortable-fallback',
- preventOnFilter: true,
- scroll: true,
- scrollSensitivity: 30,
- scrollSpeed: 10,
- bubbleScroll: true,
- onEnd: (evt) => {
- if (evt.oldIndex === evt.newIndex || !routeItems.value[evt.oldIndex]) return;
-
- // 浣跨敤鏁扮粍 splice 鏂规硶閲嶆柊鎺掑簭
- const moveItem = routeItems.value.splice(evt.oldIndex, 1)[0];
- routeItems.value.splice(evt.newIndex, 0, moveItem);
- routeItems.value = [...routeItems.value];
- }
- });
-
- // 璋冭瘯锛氭墦鍗板鍣ㄥ拰瀹炰緥锛岀‘璁ょ粦瀹氭垚鍔�
- console.log('姝ラ鏉℃嫋鎷藉鍣�:', stepsList);
- console.log('Sortable瀹炰緥:', stepsSortable);
- }
-};
-
-const handleViewChange = () => {
- destroySortable();
- // 寤惰繜鍒濆鍖栵紝纭繚瑙嗗浘鍒囨崲鍚嶥OM瀹屽叏娓叉煋
- nextTick(() => {
- setTimeout(() => initSortable(), 100);
- });
-};
-
-onMounted(() => {
- findProcessRouteItems();
- findProcessList();
-});
-
-onUnmounted(() => {
- destroySortable();
-});
-
-defineExpose({
- closeModal,
- handleSubmit,
- isShow
-});
-</script>
-
-<style scoped>
-:deep(.sortable-ghost) {
- opacity: 0.6;
- background-color: #f5f7fa !important;
-}
-
-:deep(.el-table__row) {
- transition: background-color 0.2s;
-}
-
-:deep(.el-table__row:hover) {
- background-color: #f9fafc !important;
-}
-
-:deep(.el-card__footer){
- padding: 0 !important;
-}
-
-.operate-button {
- display: flex;
- align-items: center;
- justify-content: space-between;
-}
-
-/* 淇敼锛氳嚜瀹氫箟姝ラ鏉″鍣ㄦ牱寮� */
-.custom-steps {
- display: flex;
- flex-wrap: wrap;
- align-items: flex-start;
- gap: 20px;
- min-height: 100px;
-}
-
-/* 淇敼锛氳嚜瀹氫箟姝ラ椤规牱寮� */
-.custom-step {
- cursor: move !important;
- padding: 8px;
- position: relative;
- transition: all 0.2s ease;
- flex: 0 0 auto;
- min-width: 220px;
- touch-action: none;
-}
-
-/* 鎷栨嫿鎮诞鏍峰紡锛屾彁绀哄彲鎷栨嫿 */
-.custom-step:hover {
- background-color: rgba(64, 158, 255, 0.05);
- transform: translateY(-2px);
-}
-
-.sortable-ghost {
- opacity: 0.4;
- background-color: #f5f7fa !important;
- border: 2px dashed #409eff;
- margin: 10px;
- transform: scale(1.02);
-}
-
-.sortable-fallback {
- opacity: 0.9;
- background-color: #f5f7fa;
- border: 1px solid #409eff;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
- transform: rotate(2deg);
- margin: 10px;
-}
-
-.step-card {
- cursor: move !important;
- transition: box-shadow 0.2s ease;
- user-select: none;
- -webkit-user-select: none;
- pointer-events: auto;
- margin: 10px;
- height: 240px;
-}
-
-.step-card:hover {
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
-}
-
-.step-content {
- width: 220px;
- user-select: none;
-}
-
-.step-card-content {
- display: flex;
- flex-direction: column;
- align-items: center;
-}
-
-.step-card-footer {
- display: flex;
- justify-content: flex-end;
- align-items: center;
- padding: 10px;
-}
-
-/* 鑷畾涔夊簭鍙锋牱寮忎紭鍖� */
-.step-number {
- font-weight: bold;
- text-align: center;
- width: 36px;
- height: 36px;
- line-height: 36px;
- margin: 0 auto 10px;
- background: #409eff;
- color: #fff;
- border-radius: 50%;
- font-size: 14px;
-}
-</style>
diff --git a/src/views/productionManagement/processRoute/New.vue b/src/views/productionManagement/processRoute/New.vue
deleted file mode 100644
index 62c6873..0000000
--- a/src/views/productionManagement/processRoute/New.vue
+++ /dev/null
@@ -1,194 +0,0 @@
-<template>
- <div>
- <el-dialog
- v-model="isShow"
- title="鏂板宸ヨ壓璺嚎"
- width="400"
- @close="closeModal"
- >
- <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
- <el-form-item
- label="浜у搧鍚嶇О"
- prop="productModelId"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨浜у搧',
- trigger: 'change',
- }
- ]"
- >
- <el-button type="primary" @click="showProductSelectDialog = true">
- {{ formState.productName && formState.productModelName
- ? `${formState.productName} - ${formState.productModelName}`
- : '閫夋嫨浜у搧' }}
- </el-button>
- </el-form-item>
-
- <el-form-item
- label="BOM"
- prop="bomId"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨BOM',
- trigger: 'change',
- }
- ]"
- >
- <el-select
- v-model="formState.bomId"
- placeholder="璇烽�夋嫨BOM"
- clearable
- :disabled="!formState.productModelId || bomOptions.length === 0"
- style="width: 100%"
- >
- <el-option
- v-for="item in bomOptions"
- :key="item.id"
- :label="item.bomNo || `BOM-${item.id}`"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
-
- <el-form-item label="澶囨敞" prop="description">
- <el-input v-model="formState.description" type="textarea" />
- </el-form-item>
- </el-form>
-
- <!-- 浜у搧閫夋嫨寮圭獥 -->
- <ProductSelectDialog
- v-model="showProductSelectDialog"
- @confirm="handleProductSelect"
- single
- />
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="handleSubmit">纭</el-button>
- <el-button @click="closeModal">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import {ref, computed, getCurrentInstance} from "vue";
-import {add} from "@/api/productionManagement/processRoute.js";
-import {getByModel} from "@/api/productionManagement/productBom.js";
-import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-
-const props = defineProps({
- visible: {
- type: Boolean,
- required: true,
- },
-});
-
-const emit = defineEmits(['update:visible', 'completed']);
-
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
-const formState = ref({
- productId: undefined,
- productModelId: undefined,
- productName: "",
- productModelName: "",
- bomId: undefined,
- description: '',
-});
-
-const isShow = computed({
- get() {
- return props.visible;
- },
- set(val) {
- emit('update:visible', val);
- },
-});
-
-const showProductSelectDialog = ref(false);
-const bomOptions = ref([]);
-
-let { proxy } = getCurrentInstance()
-
-const closeModal = () => {
- // 閲嶇疆琛ㄥ崟鏁版嵁
- formState.value = {
- productId: undefined,
- productModelId: undefined,
- productName: "",
- productModelName: "",
- bomId: undefined,
- description: '',
- };
- bomOptions.value = [];
- isShow.value = false;
-};
-
-// 浜у搧閫夋嫨澶勭悊
-const handleProductSelect = async (products) => {
- if (products && products.length > 0) {
- const product = products[0];
- // 鍏堟煡璇OM鍒楄〃锛堝繀閫夛級
- try {
- const res = await getByModel(product.id);
- // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
- let bomList = [];
- if (Array.isArray(res)) {
- bomList = res;
- } else if (res && res.data) {
- bomList = Array.isArray(res.data) ? res.data : [res.data];
- } else if (res && typeof res === 'object') {
- bomList = [res];
- }
-
- if (bomList.length > 0) {
- formState.value.productModelId = product.id;
- formState.value.productName = product.productName;
- formState.value.productModelName = product.model;
- formState.value.bomId = undefined; // 閲嶇疆BOM閫夋嫨
- bomOptions.value = bomList;
- showProductSelectDialog.value = false;
- // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
- proxy.$refs["formRef"]?.validateField('productModelId');
- } else {
- proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
- }
- } catch (error) {
- // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
- proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
- }
- }
-};
-
-const handleSubmit = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰BOM
- if (!formState.value.productModelId) {
- proxy.$modal.msgError("璇烽�夋嫨浜у搧");
- return;
- }
- if (!formState.value.bomId) {
- proxy.$modal.msgError("璇烽�夋嫨BOM");
- return;
- }
- add(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- })
- }
- })
-};
-
-
-defineExpose({
- closeModal,
- handleSubmit,
- isShow,
-});
-</script>
diff --git a/src/views/productionManagement/processRoute/index.vue b/src/views/productionManagement/processRoute/index.vue
index 41103f9..33b57ad 100644
--- a/src/views/productionManagement/processRoute/index.vue
+++ b/src/views/productionManagement/processRoute/index.vue
@@ -1,204 +1,1361 @@
<template>
<div class="app-container">
- <div class="search_form">
- <el-form :model="searchForm" :inline="true">
- <el-form-item label="瑙勬牸鍚嶇О:">
- <el-input v-model="searchForm.model" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
- style="width: 200px;"
- @change="handleQuery" />
+ <div class="route-header">
+ <div class="add-route-btn"
+ @click="handleAddRoute">
+ <el-icon>
+ <Plus />
+ </el-icon>
+ <span>鏂板宸ヨ壓璺嚎</span>
+ </div>
+ </div>
+ <div class="route-card-list">
+ <div v-for="route in routeList"
+ :key="route.id"
+ class="route-card">
+ <div class="card-header">
+ <div class="route-info">
+ <span class="route-name"><el-icon style="margin-right: 8px;line-height: 30px;">
+ <ScaleToOriginal />
+ </el-icon>{{ route.routeName }}<el-tag style="margin-left: 8px"
+ :type="route.status == 1 ? 'warning' : 'success'">{{ route.status == 1 ? '鑽夌' : '鎵瑰噯' }}</el-tag></span>
+ <span class="route-code">{{ route.routeCode }}</span>
+ </div>
+ <div class="route-actions">
+ <el-button v-if="route.status === '1'"
+ link
+ type="success"
+ @click="handleApproveRoute(route)">
+ <el-icon>
+ <Check />
+ </el-icon>
+ 鎵瑰噯
+ </el-button>
+ <el-button v-if="route.status === '2'"
+ link
+ type="warning"
+ @click="handleRevokeApproveRoute(route)">
+ <el-icon>
+ <Close />
+ </el-icon>
+ 鎾ら攢鎵瑰噯
+ </el-button>
+ <el-button link
+ type="primary"
+ @click="handleEditRoute(route)">
+ <el-icon>
+ <Edit />
+ </el-icon>
+ 缂栬緫
+ </el-button>
+ <el-button link
+ type="danger"
+ @click="handleDeleteRoute(route)">
+ <el-icon>
+ <Delete />
+ </el-icon>
+ 鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ <div class="card-body">
+ <div class="route-desc">{{ route.routeDesc || '鏆傛棤鎻忚堪' }}</div>
+ <el-button type="primary"
+ link
+ @click="toggleExpand(route)">
+ {{ route.expanded ? '鏀惰捣' : '灞曞紑宸ュ簭璺嚎' }}
+ <el-icon class="expand-icon">
+ <component :is="route.expanded ? 'ArrowUp' : 'ArrowDown'" />
+ </el-icon>
+ </el-button>
+ </div>
+ <div v-if="route.expanded"
+ class="process-route">
+ <div class="process-flow">
+ <div v-for="(process, index) in route.processList"
+ :key="process.id"
+ class="process-flow-item"
+ draggable="true"
+ @dragstart="handleDragStart($event, index, route.id)"
+ @dragover="handleDragOver($event)"
+ @drop="handleDrop($event, index, route.id)"
+ @dragend="handleDragEnd">
+ <div class="process-node"
+ :class="{ expanded: process.expanded }">
+ <div class="process-node-header">
+ <div class="process-number">{{ index + 1 }}</div>
+ <div class="process-actions">
+ <el-button link
+ type="danger"
+ @click="handleDeleteProcess(route.id, process)">
+ <el-icon>
+ <Delete />
+ </el-icon>
+ </el-button>
+ </div>
+ </div>
+ <div class="process-node-body">
+ <div class="process-code">{{ process.processCode }}</div>
+ <div class="process-name">{{ process.processName }}</div>
+ <div class="process-desc">{{ process.processDesc || '鏆傛棤鎻忚堪' }}</div>
+ </div>
+ <div class="process-node-footer">
+ <!-- <el-tag size="small"
+ :type="process.status === '1' ? 'success' : 'info'">
+ {{ process.status === '1' ? '鍚敤' : '鍋滅敤' }}
+ </el-tag> -->
+ <el-button type="primary"
+ link
+ size="small"
+ @click="toggleProcessParams(process)">
+ {{ process.expanded ? '鏀惰捣鍙傛暟' : '灞曞紑鍙傛暟' }}
+ ({{ process.paramList?.length || 0 }})
+ </el-button>
+ </div>
+ <div v-if="process.expanded"
+ class="process-params-section">
+ <div class="params-header">
+ <span>鍙傛暟鍒楄〃</span>
+ <el-button type="primary"
+ link
+ size="small"
+ @click="handleAddParam(route.id, process)">
+ <el-icon>
+ <Plus />
+ </el-icon>鏂板
+ </el-button>
+ </div>
+ <div class="params-list">
+ <div v-for="param in process.paramList"
+ :key="param.id"
+ class="param-item">
+ <div class="param-info">
+ <span class="param-code">{{ param.parameterCode }}</span>
+ <span class="param-name">{{ param.parameterName }}</span>
+ <!-- <el-tag size="small"
+ style="margin-right: 20px;"
+ :type="getParamTypeTag(param.parameterType)">
+ {{ param.parameterType }}
+ </el-tag> -->
+ <span class="param-value">鏍囧噯鍊硷細{{ param.standardValue }} {{ param.unit }}</span>
+ </div>
+ <div class="param-actions">
+ <el-button link
+ type="primary"
+ size="small"
+ @click="handleEditParam(route.id, process, param)">
+ 缂栬緫
+ </el-button>
+ <el-button link
+ type="danger"
+ size="small"
+ @click="handleDeleteParam(route.id, process, param)">
+ 鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ <el-empty v-if="!process.paramList || process.paramList.length === 0"
+ description="鏆傛棤鍙傛暟"
+ :image-size="50" />
+ </div>
+ </div>
+ </div>
+ <div v-if="index < route.processList.length - 1"
+ class="flow-arrow">
+ <el-icon>
+ <Right />
+ </el-icon>
+ </div>
+ </div>
+ <div class="add-process-node"
+ @click="handleSelectProcess(route, index)">
+ <el-icon>
+ <Plus />
+ </el-icon>
+ <span>鏂板宸ュ簭</span>
+ </div>
+ </div>
+ <el-empty v-if="!route.processList || route.processList.length === 0"
+ description="鏆傛棤宸ュ簭"
+ :image-size="80" />
+ </div>
+ </div>
+ </div>
+ <!-- 宸ヨ壓璺嚎鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="routeDialogVisible"
+ :title="isRouteEdit ? '缂栬緫宸ヨ壓璺嚎' : '鏂板宸ヨ壓璺嚎'"
+ width="500px">
+ <el-form :model="routeForm"
+ :rules="routeRules"
+ ref="routeFormRef"
+ label-width="120px">
+ <el-form-item label="璺嚎缂栫爜"
+ prop="routeCode">
+ <el-input v-model="routeForm.routeCode"
+ placeholder="璇疯緭鍏ヨ矾绾跨紪鐮�" />
</el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery">鎼滅储</el-button>
+ <el-form-item label="璺嚎鍚嶇О"
+ prop="routeName">
+ <el-input v-model="routeForm.routeName"
+ placeholder="璇疯緭鍏ヨ矾绾垮悕绉�" />
+ </el-form-item>
+ <el-form-item label="璺嚎鎻忚堪"
+ prop="routeDesc">
+ <el-input v-model="routeForm.routeDesc"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ヨ矾绾挎弿杩�" />
+ </el-form-item>
+ <!-- <el-form-item label="鐘舵��"
+ prop="status">
+ <el-radio-group v-model="routeForm.status">
+ <el-radio label="1">鍚敤</el-radio>
+ <el-radio label="0">鍋滅敤</el-radio>
+ </el-radio-group>
+ </el-form-item> -->
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="routeDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleRouteSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 宸ュ簭鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="processDialogVisible"
+ :title="isProcessEdit ? '缂栬緫宸ュ簭' : '鏂板宸ュ簭'"
+ width="500px">
+ <el-form :model="processForm"
+ :rules="processRules"
+ ref="processFormRef"
+ label-width="120px">
+ <el-form-item label="宸ュ簭缂栫爜"
+ prop="processCode">
+ <el-input v-model="processForm.processCode"
+ placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />
+ </el-form-item>
+ <el-form-item label="宸ュ簭鍚嶇О"
+ prop="processName">
+ <el-input v-model="processForm.processName"
+ placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+ </el-form-item>
+ <el-form-item label="宸ュ簭鎻忚堪"
+ prop="processDesc">
+ <el-input v-model="processForm.processDesc"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ュ伐搴忔弿杩�" />
+ </el-form-item>
+ <el-form-item label="鐘舵��"
+ prop="status">
+ <el-radio-group v-model="processForm.status">
+ <el-radio label="1">鍚敤</el-radio>
+ <el-radio label="0">鍋滅敤</el-radio>
+ </el-radio-group>
</el-form-item>
</el-form>
- </div>
- <div class="table_list">
- <div style="text-align: right" class="mb10">
- <el-button type="primary" @click="showNewModal">鏂板宸ヨ壓璺嚎</el-button>
- <el-button type="danger" @click="handleDelete" :disabled="selectedRows.length === 0" plain>鍒犻櫎宸ヨ壓璺嚎</el-button>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="processDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleProcessSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 閫夋嫨宸ュ簭瀵硅瘽妗� -->
+ <el-dialog v-model="selectProcessDialogVisible"
+ title="閫夋嫨宸ュ簭"
+ width="1000px">
+ <div class="process-select-container">
+ <!-- 宸︿晶宸ュ簭鍒楄〃 -->
+ <div class="process-list-area">
+ <div class="area-title">鍙�夊伐搴�</div>
+ <div class="search-box">
+ <el-input v-model="processSearchKeyword"
+ placeholder="璇疯緭鍏ュ伐搴忓悕绉版悳绱�"
+ clearable
+ size="small"
+ @input="handleProcessSearch">
+ <template #prefix>
+ <el-icon>
+ <Search />
+ </el-icon>
+ </template>
+ </el-input>
+ </div>
+ <el-table :data="filteredProcessList"
+ height="360"
+ border
+ highlight-current-row
+ @current-change="handleProcessSelect">
+ <el-table-column prop="processCode"
+ label="宸ュ簭缂栧彿"
+ width="100" />
+ <el-table-column prop="processName"
+ label="宸ュ簭鍚嶇О" />
+ <el-table-column prop="processDesc"
+ label="宸ュ簭鎻忚堪" />
+ <el-table-column prop="status"
+ label="鐘舵��"
+ width="80">
+ <template #default="scope">
+ <el-tag size="small"
+ :type="scope.row.status === '1' ? 'success' : 'info'">
+ {{ scope.row.status === '1' ? '鍚敤' : '鍋滅敤' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <!-- 鍙充晶宸ュ簭璇︽儏 -->
+ <div class="process-detail-area">
+ <div class="area-title">宸ュ簭璇︽儏</div>
+ <el-form v-if="selectedProcessItem"
+ :model="selectedProcessItem"
+ label-width="100px"
+ class="process-detail-form">
+ <el-form-item label="宸ュ簭缂栧彿">
+ <span class="detail-text">{{ selectedProcessItem.processCode }}</span>
+ </el-form-item>
+ <el-form-item label="宸ュ簭鍚嶇О">
+ <span class="detail-text">{{ selectedProcessItem.processName }}</span>
+ </el-form-item>
+ <el-form-item label="宸ュ簭鎻忚堪">
+ <span class="detail-text">{{ selectedProcessItem.processDesc || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鐘舵��">
+ <el-tag size="small"
+ :type="selectedProcessItem.status === '1' ? 'success' : 'info'">
+ {{ selectedProcessItem.status === '1' ? '鍚敤' : '鍋滅敤' }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟鏁伴噺">
+ <span class="detail-text">{{ selectedProcessItem.paramCount || 0 }}涓�</span>
+ </el-form-item>
+ </el-form>
+ <el-empty v-else
+ description="璇蜂粠宸︿晶閫夋嫨宸ュ簭" />
+ </div>
</div>
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"
- />
- </div>
- <new-process
- v-if="isShowNewModal"
- v-model:visible="isShowNewModal"
- @completed="getList"
- />
-
- <edit-process
- v-if="isShowEditModal"
- v-model:visible="isShowEditModal"
- :record="record"
- @completed="getList"
- />
-
- <route-item-form
- v-if="isShowItemModal"
- v-model:visible="isShowItemModal"
- :record="record"
- @completed="getList"
- />
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="selectProcessDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ :disabled="!selectedProcessItem"
+ @click="handleProcessSelectSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 鍙傛暟鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="paramDialogVisible"
+ :title="isParamEdit ? '缂栬緫鍙傛暟' : '鏂板鍙傛暟'"
+ width="500px">
+ <el-form :model="paramForm"
+ :rules="paramRules"
+ ref="paramFormRef"
+ label-width="120px">
+ <el-form-item label="鍙傛暟缂栧彿"
+ prop="parameterCode">
+ <el-input v-model="paramForm.parameterCode"
+ placeholder="璇疯緭鍏ュ弬鏁扮紪鍙�" />
+ </el-form-item>
+ <el-form-item label="鍙傛暟鍚嶇О"
+ prop="parameterName">
+ <el-input v-model="paramForm.parameterName"
+ placeholder="璇疯緭鍏ュ弬鏁板悕绉�" />
+ </el-form-item>
+ <el-form-item label="鍙傛暟妯″紡"
+ prop="parameterType2">
+ <el-select v-model="paramForm.parameterType2"
+ placeholder="璇烽�夋嫨鍙傛暟妯″紡">
+ <el-option label="鍗曞��"
+ value="1" />
+ <el-option label="鍖洪棿"
+ value="2" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷"
+ prop="parameterType">
+ <el-select v-model="paramForm.parameterType"
+ @change="handleParamTypeChange"
+ placeholder="璇烽�夋嫨鍙傛暟绫诲瀷">
+ <el-option label="鏁板�兼牸寮�"
+ value="鏁板�兼牸寮�" />
+ <el-option label="鏂囨湰鏍煎紡"
+ value="鏂囨湰鏍煎紡" />
+ <el-option label="涓嬫媺閫夐」"
+ value="涓嬫媺閫夐」" />
+ <el-option label="鏃堕棿鏍煎紡"
+ value="鏃堕棿鏍煎紡" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="paramForm.parameterType === '涓嬫媺閫夐」'"
+ label="鏁版嵁瀛楀吀"
+ prop="parameterFormat">
+ <el-select v-model="paramForm.parameterFormat"
+ placeholder="璇烽�夋嫨鏁版嵁瀛楀吀">
+ <el-option v-for="item in dictTypes"
+ :key="item.dictType"
+ :label="item.dictName"
+ :value="item.dictType" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-else-if="paramForm.parameterType === '鏃堕棿鏍煎紡'"
+ label="鏃堕棿鏍煎紡"
+ prop="parameterFormat">
+ <el-select v-model="paramForm.parameterFormat"
+ placeholder="璇烽�夋嫨鏃堕棿鏍煎紡">
+ <el-option label="YYYY-MM-DD HH:mm:ss"
+ value="YYYY-MM-DD HH:mm:ss" />
+ <el-option label="YYYY-MM-DD"
+ value="YYYY-MM-DD" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-else
+ label="鍙傛暟鏍煎紡"
+ prop="parameterFormat">
+ <el-input v-model="paramForm.parameterFormat"
+ placeholder="璇疯緭鍏ュ弬鏁版牸寮�" />
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�"
+ prop="standardValue">
+ <el-input v-model="paramForm.standardValue"
+ placeholder="璇疯緭鍏ユ爣鍑嗗��" />
+ </el-form-item>
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="paramForm.unit"
+ placeholder="璇疯緭鍏ュ崟浣�" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="paramDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleParamSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
-import {onMounted, ref} from "vue";
-import NewProcess from "@/views/productionManagement/processRoute/New.vue";
-import EditProcess from "@/views/productionManagement/processRoute/Edit.vue";
-import RouteItemForm from "@/views/productionManagement/processRoute/ItemsForm.vue";
-import {listPage, del} from "@/api/productionManagement/processRoute.js";
-import { useRouter } from 'vue-router'
+ import { ref, reactive } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import {
+ Plus,
+ Edit,
+ Delete,
+ ArrowUp,
+ ArrowDown,
+ Right,
+ Search,
+ Check,
+ Close,
+ } from "@element-plus/icons-vue";
+ import { listType } from "@/api/system/dict/type";
-const router = useRouter()
-const data = reactive({
- searchForm: {
- model: "",
- },
-});
-const { searchForm } = toRefs(data);
-const tableColumn = ref([
- {
- label: "宸ヨ壓璺嚎缂栧彿",
- prop: "processRouteCode",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- },
- {
- label: "瑙勬牸鍚嶇О",
- prop: "model",
- },
- {
- label: "BOM缂栧彿",
- prop: "bomNo",
- },
- {
- label: "鎻忚堪",
- prop: "description",
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
- operation: [
+ // 宸ヨ壓璺嚎鍒楄〃
+ const routeList = ref([]);
+ const dictTypes = ref([]);
+
+ // 宸ヨ壓璺嚎瀵硅瘽妗�
+ const routeDialogVisible = ref(false);
+ const isRouteEdit = ref(false);
+ const routeFormRef = ref(null);
+ const routeForm = reactive({
+ id: null,
+ routeCode: "",
+ routeName: "",
+ routeDesc: "",
+ status: "1",
+ });
+ const routeRules = {
+ routeCode: [{ required: true, message: "璇疯緭鍏ヨ矾绾跨紪鐮�", trigger: "blur" }],
+ routeName: [{ required: true, message: "璇疯緭鍏ヨ矾绾垮悕绉�", trigger: "blur" }],
+ };
+
+ // 宸ュ簭瀵硅瘽妗�
+ const processDialogVisible = ref(false);
+ const isProcessEdit = ref(false);
+ const processFormRef = ref(null);
+ const currentRouteId = ref(null);
+ const processForm = reactive({
+ id: null,
+ processCode: "",
+ processName: "",
+ processDesc: "",
+ status: "1",
+ });
+ const processRules = {
+ processCode: [{ required: true, message: "璇疯緭鍏ュ伐搴忕紪鐮�", trigger: "blur" }],
+ processName: [{ required: true, message: "璇疯緭鍏ュ伐搴忓悕绉�", trigger: "blur" }],
+ };
+
+ // 閫夋嫨宸ュ簭瀵硅瘽妗�
+ const selectProcessDialogVisible = ref(false);
+ const availableProcessList = ref([]);
+ const filteredProcessList = ref([]);
+ const selectedProcessItem = ref(null);
+ const processSearchKeyword = ref("");
+ const currentRouteIndex = ref(null);
+
+ // 鍙傛暟瀵硅瘽妗�
+ const paramDialogVisible = ref(false);
+ const isParamEdit = ref(false);
+ const paramFormRef = ref(null);
+ const currentProcessId = ref(null);
+ const paramForm = reactive({
+ id: null,
+ parameterCode: "",
+ parameterName: "",
+ parameterType2: "1",
+ parameterType: "",
+ parameterFormat: "",
+ standardValue: "",
+ unit: "",
+ });
+ const paramRules = {
+ parameterCode: [
+ { required: true, message: "璇疯緭鍏ュ弬鏁扮紪鍙�", trigger: "blur" },
+ ],
+ parameterName: [
+ { required: true, message: "璇疯緭鍏ュ弬鏁板悕绉�", trigger: "blur" },
+ ],
+ parameterType: [
+ { required: true, message: "璇烽�夋嫨鍙傛暟绫诲瀷", trigger: "change" },
+ ],
+ };
+
+ // 鎷栨嫿鐩稿叧
+ const draggedItem = ref(null);
+ const draggedRouteId = ref(null);
+
+ // 鑾峰彇宸ヨ壓璺嚎鍒楄〃
+ const getRouteList = () => {
+ routeList.value = [
{
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- showEditModal(row);
- }
+ id: 1,
+ routeCode: "ROUTE001",
+ routeName: "鏍囧噯鐮屽潡鐢熶骇绾�",
+ routeDesc: "鏍囧噯鐮屽潡鐢熶骇娴佺▼",
+ status: "1",
+ expanded: false,
+ processList: [
+ {
+ id: 1,
+ processCode: "PROC001",
+ processName: "鍘熸枡閰嶆瘮",
+ processDesc: "鍘熸潗鏂欓厤姣斿伐搴�",
+ status: "1",
+ expanded: false,
+ paramList: [
+ {
+ id: 1,
+ parameterCode: "P001",
+ parameterName: "姘存偿姣斾緥",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "30",
+ unit: "%",
+ },
+ {
+ id: 2,
+ parameterCode: "P002",
+ parameterName: "鐮傛瘮渚�",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "60",
+ unit: "%",
+ },
+ ],
+ },
+ {
+ id: 2,
+ processCode: "PROC002",
+ processName: "鎼呮媽娣峰悎",
+ processDesc: "鎼呮媽娣峰悎宸ュ簭",
+ status: "1",
+ expanded: false,
+ paramList: [
+ {
+ id: 3,
+ parameterCode: "P003",
+ parameterName: "鎼呮媽鏃堕棿",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "5",
+ unit: "鍒嗛挓",
+ },
+ ],
+ },
+ {
+ id: 3,
+ processCode: "PROC003",
+ processName: "娴囩瓚鎴愬瀷",
+ processDesc: "娴囩瓚鎴愬瀷宸ュ簭",
+ status: "1",
+ expanded: false,
+ paramList: [],
+ },
+ ],
},
{
- name: "璺嚎椤圭洰",
- type: "text",
- clickFun: (row) => {
- showItemModal(row);
- }
+ id: 2,
+ routeCode: "ROUTE002",
+ routeName: "鏉挎潗鐢熶骇绾�",
+ routeDesc: "鏉挎潗鐢熶骇娴佺▼",
+ status: "1",
+ expanded: false,
+ processList: [
+ {
+ id: 4,
+ processCode: "PROC004",
+ processName: "鍒囧壊鍔犲伐",
+ processDesc: "鍒囧壊鍔犲伐宸ュ簭",
+ status: "1",
+ expanded: false,
+ paramList: [
+ {
+ id: 4,
+ parameterCode: "P004",
+ parameterName: "鍒囧壊灏哄",
+ parameterType2: "1",
+ parameterType: "鏂囨湰鏍煎紡",
+ parameterFormat: "",
+ standardValue: "600x200x100",
+ unit: "mm",
+ },
+ ],
+ },
+ ],
+ },
+ ];
+ };
+
+ // 灞曞紑/鏀惰捣宸ヨ壓璺嚎
+ const toggleExpand = route => {
+ route.expanded = !route.expanded;
+ };
+
+ // 灞曞紑/鏀惰捣宸ュ簭鍙傛暟
+ const toggleProcessParams = process => {
+ process.expanded = !process.expanded;
+ };
+
+ // 宸ヨ壓璺嚎鎿嶄綔
+ const handleAddRoute = () => {
+ isRouteEdit.value = false;
+ routeForm.id = null;
+ routeForm.routeCode = "";
+ routeForm.routeName = "";
+ routeForm.routeDesc = "";
+ routeForm.status = "1";
+ routeDialogVisible.value = true;
+ };
+
+ const handleEditRoute = route => {
+ isRouteEdit.value = true;
+ routeForm.id = route.id;
+ routeForm.routeCode = route.routeCode;
+ routeForm.routeName = route.routeName;
+ routeForm.routeDesc = route.routeDesc;
+ routeForm.status = route.status;
+ routeDialogVisible.value = true;
+ };
+
+ const handleDeleteRoute = route => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ宸ヨ壓璺嚎鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getRouteList();
+ });
+ };
+
+ const handleRouteSubmit = () => {
+ routeFormRef.value.validate(valid => {
+ if (valid) {
+ ElMessage.success(isRouteEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ routeDialogVisible.value = false;
+ getRouteList();
}
- ]
- }
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const isShowNewModal = ref(false);
-const isShowEditModal = ref(false);
-const isShowItemModal = ref(false);
-const record = ref({});
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-const { proxy } = getCurrentInstance()
+ });
+ };
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
+ const handleApproveRoute = route => {
+ ElMessageBox.confirm("纭畾瑕佹壒鍑嗚宸ヨ壓璺嚎鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "info",
+ }).then(() => {
+ route.status = "2";
+ ElMessage.success("鎵瑰噯鎴愬姛");
+ });
+ };
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined
- listPage(params).then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records.map(item => ({
- ...item,
- }));
- page.total = res.data.total;
- }).catch(err => {
- tableLoading.value = false;
- })
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
+ const handleRevokeApproveRoute = route => {
+ ElMessageBox.confirm("纭畾瑕佹挙閿�鎵瑰噯璇ュ伐鑹鸿矾绾垮悧锛�", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ route.status = "1";
+ ElMessage.success("鎾ら攢鎵瑰噯鎴愬姛");
+ });
+ };
-// 鎵撳紑鏂板寮规
-const showNewModal = () => {
- isShowNewModal.value = true
-};
+ // 宸ュ簭鎿嶄綔
+ const handleSelectProcess = (route, index) => {
+ currentRouteId.value = route.id;
+ currentRouteIndex.value = index;
+ // 鑾峰彇鍙�夊伐搴忓垪琛紙鍋囨暟鎹級
+ availableProcessList.value = [
+ {
+ id: 1,
+ processCode: "PROC001",
+ processName: "鍘熸枡閰嶆瘮",
+ processDesc: "鍘熸潗鏂欓厤姣斿伐搴�",
+ status: "1",
+ paramCount: 3,
+ },
+ {
+ id: 2,
+ processCode: "PROC002",
+ processName: "鎼呮媽娣峰悎",
+ processDesc: "鎼呮媽娣峰悎宸ュ簭",
+ status: "1",
+ paramCount: 2,
+ },
+ {
+ id: 3,
+ processCode: "PROC003",
+ processName: "娴囩瓚鎴愬瀷",
+ processDesc: "娴囩瓚鎴愬瀷宸ュ簭",
+ status: "1",
+ paramCount: 4,
+ },
+ {
+ id: 4,
+ processCode: "PROC004",
+ processName: "钂稿帇鍏绘姢",
+ processDesc: "钂稿帇鍏绘姢宸ュ簭",
+ status: "0",
+ paramCount: 2,
+ },
+ {
+ id: 5,
+ processCode: "PROC005",
+ processName: "鍒囧壊鍔犲伐",
+ processDesc: "鍒囧壊鍔犲伐宸ュ簭",
+ status: "1",
+ paramCount: 3,
+ },
+ ];
+ filteredProcessList.value = availableProcessList.value;
+ processSearchKeyword.value = "";
+ selectedProcessItem.value = null;
+ selectProcessDialogVisible.value = true;
+ };
-const showEditModal = (row) => {
- isShowEditModal.value = true
- record.value = row
-};
+ const handleEditProcess = (routeId, process) => {
+ currentRouteId.value = routeId;
+ isProcessEdit.value = true;
+ processForm.id = process.id;
+ processForm.processCode = process.processCode;
+ processForm.processName = process.processName;
+ processForm.processDesc = process.processDesc;
+ processForm.status = process.status;
+ processDialogVisible.value = true;
+ };
-const showItemModal = (row) => {
- router.push({
- path: '/productionManagement/processRouteItem',
- query: {
- id: row.id,
- processRouteCode: row.processRouteCode || '',
- productName: row.productName || '',
- model: row.model || '',
- bomNo: row.bomNo || '',
- description: row.description || '',
- type: 'route',
+ const handleDeleteProcess = (routeId, process) => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ宸ュ簭鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getRouteList();
+ });
+ };
+
+ const handleProcessSubmit = () => {
+ processFormRef.value.validate(valid => {
+ if (valid) {
+ ElMessage.success(isProcessEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ processDialogVisible.value = false;
+ getRouteList();
+ }
+ });
+ };
+
+ // 閫夋嫨宸ュ簭鐩稿叧鏂规硶
+ const handleProcessSearch = () => {
+ const keyword = processSearchKeyword.value.trim().toLowerCase();
+ if (!keyword) {
+ filteredProcessList.value = availableProcessList.value;
+ } else {
+ filteredProcessList.value = availableProcessList.value.filter(item =>
+ item.processName.toLowerCase().includes(keyword)
+ );
}
- })
-};
+ };
-// 鍒犻櫎
-function handleDelete() {
- const ids = selectedRows.value.map((item) => item.id);
- proxy.$modal
- .confirm('鏄惁纭鍒犻櫎宸插嬀閫夌殑鏁版嵁椤癸紵')
- .then(function () {
- return del(ids);
- })
- .then(() => {
- getList();
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- })
- .catch(() => {});
-}
+ const handleProcessSelect = row => {
+ selectedProcessItem.value = row;
+ };
-onMounted(() => {
- getList();
-});
+ const handleProcessSelectSubmit = () => {
+ if (!selectedProcessItem.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓伐搴�");
+ return;
+ }
+
+ // 妫�鏌ュ伐搴忔槸鍚﹀凡瀛樺湪
+ const route = routeList.value[currentRouteIndex.value];
+ const exists = route.processList.some(
+ p => p.id === selectedProcessItem.value.id
+ );
+ if (exists) {
+ ElMessage.warning("璇ュ伐搴忓凡瀛樺湪浜庡伐鑹鸿矾绾夸腑");
+ return;
+ }
+
+ // 娣诲姞宸ュ簭鍒板伐鑹鸿矾绾�
+ const newProcess = {
+ id: Date.now(),
+ processCode: selectedProcessItem.value.processCode,
+ processName: selectedProcessItem.value.processName,
+ processDesc: selectedProcessItem.value.processDesc,
+ status: selectedProcessItem.value.status,
+ paramList: [],
+ expanded: false,
+ };
+
+ route.processList.push(newProcess);
+ ElMessage.success("娣诲姞宸ュ簭鎴愬姛");
+ selectProcessDialogVisible.value = false;
+ };
+
+ // 鍙傛暟鎿嶄綔
+ const handleAddParam = (routeId, process) => {
+ currentRouteId.value = routeId;
+ currentProcessId.value = process.id;
+ isParamEdit.value = false;
+ paramForm.id = null;
+ paramForm.parameterCode = "";
+ paramForm.parameterName = "";
+ paramForm.parameterType2 = "1";
+ paramForm.parameterType = "";
+ paramForm.parameterFormat = "";
+ paramForm.standardValue = "";
+ paramForm.unit = "";
+ paramDialogVisible.value = true;
+ };
+
+ const handleEditParam = (routeId, process, param) => {
+ currentRouteId.value = routeId;
+ currentProcessId.value = process.id;
+ isParamEdit.value = true;
+ paramForm.id = param.id;
+ paramForm.parameterCode = param.parameterCode;
+ paramForm.parameterName = param.parameterName;
+ paramForm.parameterType2 = param.parameterType2 || "1";
+ paramForm.parameterType = param.parameterType;
+ paramForm.parameterFormat = param.parameterFormat;
+ paramForm.standardValue = param.standardValue;
+ paramForm.unit = param.unit;
+ paramDialogVisible.value = true;
+ };
+
+ const handleDeleteParam = (routeId, process, param) => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ鍙傛暟鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getRouteList();
+ });
+ };
+
+ const handleParamSubmit = () => {
+ paramFormRef.value.validate(valid => {
+ if (valid) {
+ ElMessage.success(isParamEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ paramDialogVisible.value = false;
+ getRouteList();
+ }
+ });
+ };
+
+ const handleParamTypeChange = () => {
+ if (paramForm.parameterType === "鏁板�兼牸寮�") {
+ paramForm.parameterFormat = "#.0000";
+ } else if (paramForm.parameterType === "鏃堕棿鏍煎紡") {
+ paramForm.parameterFormat = "YYYY-MM-DD HH:mm:ss";
+ } else {
+ paramForm.parameterFormat = "";
+ }
+ };
+
+ const getParamTypeTag = type => {
+ const typeMap = {
+ 鏁板�兼牸寮�: "primary",
+ 鏂囨湰鏍煎紡: "info",
+ 涓嬫媺閫夐」: "warning",
+ 鏃堕棿鏍煎紡: "success",
+ };
+ return typeMap[type] || "default";
+ };
+
+ // 鎷栨嫿鎺掑簭
+ const handleDragStart = (event, index, routeId) => {
+ draggedItem.value = index;
+ draggedRouteId.value = routeId;
+ event.dataTransfer.effectAllowed = "move";
+ };
+
+ const handleDragOver = event => {
+ event.preventDefault();
+ event.dataTransfer.dropEffect = "move";
+ };
+
+ const handleDrop = (event, dropIndex, routeId) => {
+ event.preventDefault();
+ if (draggedItem.value === null || draggedItem.value === dropIndex) return;
+
+ const route = routeList.value.find(r => r.id === routeId);
+ if (route && route.processList) {
+ const draggedProcess = route.processList[draggedItem.value];
+ route.processList.splice(draggedItem.value, 1);
+ route.processList.splice(dropIndex, 0, draggedProcess);
+ ElMessage.success("鎺掑簭鎴愬姛");
+ }
+ };
+
+ const handleDragEnd = () => {
+ draggedItem.value = null;
+ draggedRouteId.value = null;
+ };
+
+ // 鑾峰彇鏁版嵁瀛楀吀
+ const getDictTypes = () => {
+ listType({ pageNum: 1, pageSize: 1000 }).then(res => {
+ dictTypes.value = res.rows || [];
+ });
+ };
+
+ getRouteList();
+ getDictTypes();
</script>
-<style scoped></style>
+<style scoped lang="scss">
+ .app-container {
+ padding: 20px;
+ background-color: #f0f2f5;
+ min-height: calc(100vh - 84px);
+ }
+
+ .route-header {
+ margin-bottom: 20px;
+
+ .add-route-btn {
+ width: 100%;
+ display: inline-flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ min-width: 120px;
+ height: 100px;
+ border: 2px dashed #dcdfe6;
+ border-radius: 12px;
+ background: #fafafa;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ color: #909399;
+ padding: 0 20px;
+
+ .el-icon {
+ font-size: 24px;
+ margin-bottom: 8px;
+ }
+
+ span {
+ font-size: 13px;
+ }
+
+ &:hover {
+ border-color: #409eff;
+ background: #ecf5ff;
+ color: #409eff;
+ }
+ }
+ }
+
+ .route-card-list {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ }
+
+ .route-card {
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+
+ .card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20px 40px;
+ border-bottom: 1px solid #ebeef5;
+ background: #f8f9fa;
+
+ .route-info {
+ display: flex;
+ // flex-direction: column;
+ // justify-content: center;
+ // items-align: center;
+ gap: 4px;
+
+ .route-code {
+ font-size: 12px;
+ color: #909399;
+ font-family: "Courier New", monospace;
+ line-height: 30px;
+ }
+
+ .route-name {
+ font-size: 18px;
+ font-weight: 600;
+ color: #303133;
+ display: flex;
+ align-items: center;
+ }
+ }
+
+ .route-actions {
+ display: flex;
+ gap: 8px;
+
+ // .el-button {
+ // color: #409eff;
+ // }
+ }
+ }
+
+ .card-body {
+ padding: 16px 40px;
+
+ .route-desc {
+ font-size: 14px;
+ color: #606266;
+ margin-bottom: 12px;
+ }
+
+ .expand-icon {
+ margin-left: 4px;
+ }
+ }
+
+ .process-route {
+ padding: 0 20px 20px;
+ background: #f5f7fa;
+ border-top: 1px solid #ebeef5;
+
+ .process-flow {
+ display: flex;
+ align-items: flex-start;
+ gap: 8px;
+ padding: 20px 0;
+ overflow-x: auto;
+ overflow-y: hidden;
+
+ .process-flow-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+
+ .process-node {
+ background: #fff;
+ border-radius: 12px;
+ padding: 16px;
+ border: 2px solid #ebeef5;
+ cursor: move;
+ transition: all 0.3s ease;
+ // min-width: 180px;
+ // max-width: 220px;
+ width: 300px;
+
+ &.expanded {
+ width: 400px;
+ }
+
+ &:hover {
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ transform: translateY(-2px);
+ border-color: #409eff;
+ }
+
+ &:active {
+ cursor: grabbing;
+ }
+
+ .process-node-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 12px;
+
+ .process-number {
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ background: #409eff;
+ color: #ffffff;
+ font-size: 12px;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .process-actions {
+ display: flex;
+ gap: 4px;
+ }
+ }
+
+ .process-node-body {
+ text-align: center;
+ margin-bottom: 12px;
+
+ .process-code {
+ font-size: 11px;
+ color: #909399;
+ font-family: "Courier New", monospace;
+ margin-bottom: 4px;
+ }
+
+ .process-name {
+ font-size: 15px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 6px;
+ }
+
+ .process-desc {
+ font-size: 12px;
+ color: #606266;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ }
+ }
+
+ .process-node-footer {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ padding-top: 10px;
+ border-top: 1px solid #ebeef5;
+ }
+
+ .process-params-section {
+ margin-top: 12px;
+ padding-top: 12px;
+ border-top: 1px solid #ebeef5;
+
+ .params-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+ font-size: 13px;
+ font-weight: 600;
+ color: #303133;
+ }
+
+ .params-list {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ max-height: 200px;
+ overflow-y: auto;
+
+ .param-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 6px 8px;
+ background: #fafafa;
+ border-radius: 4px;
+ border-left: 2px solid #409eff;
+ font-size: 12px;
+
+ .param-info {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 6px;
+ flex: 1;
+ min-width: 0;
+
+ .param-code {
+ font-size: 11px;
+ color: #e6a23c;
+ font-family: "Courier New", monospace;
+ margin-right: 20px;
+ }
+
+ .param-name {
+ font-size: 12px;
+ color: #303133;
+ font-weight: 500;
+ margin-right: 20px;
+ }
+
+ .param-value {
+ font-size: 11px;
+ color: #606266;
+ }
+ }
+
+ .param-actions {
+ display: flex;
+ gap: 4px;
+ flex-shrink: 0;
+ }
+ }
+ }
+ }
+ }
+
+ .flow-arrow {
+ display: flex;
+ align-items: center;
+ color: #c0c4cc;
+ font-size: 24px;
+ padding: 0 4px;
+
+ .el-icon {
+ font-size: 20px;
+ }
+ }
+ }
+
+ .add-process-node {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ min-width: 100px;
+ height: 175px;
+ border: 2px dashed #dcdfe6;
+ border-radius: 12px;
+ background: #fafafa;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ color: #909399;
+ // margin-left: 10px;
+
+ .el-icon {
+ font-size: 24px;
+ margin-bottom: 8px;
+ }
+
+ span {
+ font-size: 13px;
+ }
+
+ &:hover {
+ border-color: #409eff;
+ background: #ecf5ff;
+ color: #409eff;
+ }
+ }
+ }
+ }
+ }
+
+ // 鎷栨嫿鏃剁殑鏍峰紡
+ .process-flow-item.dragging {
+ opacity: 0.5;
+ transform: scale(0.98);
+ }
+
+ // 閫夋嫨宸ュ簭瀵硅瘽妗嗘牱寮�
+ .process-select-container {
+ display: flex;
+ gap: 20px;
+ height: 450px;
+
+ .process-list-area {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .search-box {
+ margin-bottom: 12px;
+
+ .el-input {
+ width: 100%;
+ }
+ }
+ }
+
+ .process-detail-area {
+ width: 380px;
+ display: flex;
+ flex-direction: column;
+ background: #f5f7fa;
+ border-radius: 8px;
+ padding: 16px;
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 16px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .process-detail-form {
+ .el-form-item {
+ margin-bottom: 12px;
+
+ .el-form-item__label {
+ color: #606266;
+ font-weight: 500;
+ }
+ }
+
+ .detail-text {
+ color: #303133;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+</style>
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
deleted file mode 100644
index 3aecfa0..0000000
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ /dev/null
@@ -1,896 +0,0 @@
-<template>
- <div class="app-container">
- <PageHeader content="宸ヨ壓璺嚎椤圭洰" />
-
- <!-- 宸ヨ壓璺嚎淇℃伅灞曠ず -->
- <el-card v-if="routeInfo.processRouteCode" class="route-info-card" shadow="hover">
- <div class="route-info">
- <div class="info-item">
- <div class="info-label-wrapper">
- <span class="info-label">宸ヨ壓璺嚎缂栧彿</span>
- </div>
- <div class="info-value-wrapper">
- <span class="info-value">{{ routeInfo.processRouteCode }}</span>
- </div>
- </div>
- <div class="info-item">
- <div class="info-label-wrapper">
- <span class="info-label">浜у搧鍚嶇О</span>
- </div>
- <div class="info-value-wrapper">
- <span class="info-value">{{ routeInfo.productName || '-' }}</span>
- </div>
- </div>
- <div class="info-item">
- <div class="info-label-wrapper">
- <span class="info-label">瑙勬牸鍚嶇О</span>
- </div>
- <div class="info-value-wrapper">
- <span class="info-value">{{ routeInfo.model || '-' }}</span>
- </div>
- </div>
- <div class="info-item">
- <div class="info-label-wrapper">
- <span class="info-label">BOM缂栧彿</span>
- </div>
- <div class="info-value-wrapper">
- <span class="info-value">{{ routeInfo.bomNo || '-' }}</span>
- </div>
- </div>
- <div class="info-item full-width" v-if="routeInfo.description">
- <div class="info-label-wrapper">
- <span class="info-label">鎻忚堪</span>
- </div>
- <div class="info-value-wrapper">
- <span class="info-value">{{ routeInfo.description }}</span>
- </div>
- </div>
- </div>
- </el-card>
-
- <!-- 琛ㄦ牸瑙嗗浘 -->
- <div v-if="viewMode === 'table'" class="section-header">
- <div class="section-title">宸ヨ壓璺嚎椤圭洰鍒楄〃</div>
- <div class="section-actions">
- <el-button
- icon="Grid"
- @click="toggleView"
- style="margin-right: 10px;"
- >
- 鍗$墖瑙嗗浘
- </el-button>
- <el-button type="primary" @click="handleAdd">鏂板</el-button>
- </div>
- </div>
- <el-table
- v-if="viewMode === 'table'"
- ref="tableRef"
- v-loading="tableLoading"
- border
- :data="tableData"
- :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
- row-key="id"
- tooltip-effect="dark"
- class="lims-table"
- >
- <el-table-column align="center" label="搴忓彿" width="60" type="index" />
- <el-table-column label="宸ュ簭鍚嶇О" prop="processId" width="200">
- <template #default="scope">
- {{ getProcessName(scope.row.processId) || '-' }}
- </template>
- </el-table-column>
- <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="160" />
- <el-table-column label="瑙勬牸鍚嶇О" prop="model" min-width="140" />
- <el-table-column label="鍗曚綅" prop="unit" width="100" />
- <el-table-column label="鏄惁璐ㄦ" prop="isQuality" width="100">
- <template #default="scope">
- {{scope.row.isQuality ? "鏄�" : "鍚�"}}
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔" align="center" fixed="right" width="150">
- <template #default="scope">
- <el-button type="primary" link size="small" @click="handleEdit(scope.row)" :disabled="scope.row.isComplete">缂栬緫</el-button>
- <el-button type="danger" link size="small" @click="handleDelete(scope.row)" :disabled="scope.row.isComplete">鍒犻櫎</el-button>
- </template>
- </el-table-column>
- </el-table>
-
- <!-- 鍗$墖瑙嗗浘 -->
- <template v-else>
- <div class="section-header">
- <div class="section-title">宸ヨ壓璺嚎椤圭洰鍒楄〃</div>
- <div class="section-actions">
- <el-button
- icon="Menu"
- @click="toggleView"
- style="margin-right: 10px;"
- >
- 琛ㄦ牸瑙嗗浘
- </el-button>
- <el-button type="primary" @click="handleAdd">鏂板</el-button>
- </div>
- </div>
- <div v-loading="tableLoading" class="card-container">
- <div
- ref="cardsContainer"
- class="cards-wrapper"
- >
- <div
- v-for="(item, index) in tableData"
- :key="item.id || index"
- class="process-card"
- :data-index="index"
- >
- <!-- 搴忓彿鍦嗗湀 -->
- <div class="card-header">
- <div class="card-number">{{ index + 1 }}</div>
- <div class="card-process-name">{{ getProcessName(item.processId) || '-' }}</div>
- </div>
-
- <!-- 浜у搧淇℃伅 -->
- <div class="card-content">
- <div v-if="item.productName" class="product-info">
- <div class="product-name">{{ item.productName }}</div>
- <div v-if="item.model" class="product-model">
- {{ item.model }}
- <!-- <span v-if="item.unit" class="product-unit">{{ item.unit }}</span> -->
- </div>
- <el-tag type="primary" class="product-tag" v-if="item.isQuality">璐ㄦ</el-tag>
- </div>
- <div v-else class="product-info empty">鏆傛棤浜у搧淇℃伅</div>
- </div>
-
- <!-- 鎿嶄綔鎸夐挳 -->
- <div class="card-footer">
- <el-button type="primary" link size="small" @click="handleEdit(item)" :disabled="item.isComplete">缂栬緫</el-button>
- <el-button type="danger" link size="small" @click="handleDelete(item)" :disabled="item.isComplete">鍒犻櫎</el-button>
- </div>
- </div>
- </div>
- </div>
- </template>
-
- <!-- 鏂板/缂栬緫寮圭獥 -->
- <el-dialog
- v-model="dialogVisible"
- :title="operationType === 'add' ? '鏂板宸ヨ壓璺嚎椤圭洰' : '缂栬緫宸ヨ壓璺嚎椤圭洰'"
- width="500px"
- @close="closeDialog"
- >
- <el-form
- ref="formRef"
- :model="form"
- :rules="rules"
- label-width="120px"
- >
- <el-form-item label="宸ュ簭" prop="processId">
- <el-select
- v-model="form.processId"
- placeholder="璇烽�夋嫨宸ュ簭"
- clearable
- style="width: 100%"
- >
- <el-option
- v-for="process in processOptions"
- :key="process.id"
- :label="process.name"
- :value="process.id"
- />
- </el-select>
- </el-form-item>
-
- <el-form-item label="浜у搧鍚嶇О" prop="productModelId">
- <el-button type="primary" @click="showProductSelectDialog = true">
- {{ form.productName && form.model
- ? `${form.productName} - ${form.model}`
- : '閫夋嫨浜у搧' }}
- </el-button>
- </el-form-item>
-
- <el-form-item label="鍗曚綅" prop="unit">
- <el-input
- v-model="form.unit"
- :placeholder="form.productModelId ? '鏍规嵁閫夋嫨鐨勪骇鍝佽嚜鍔ㄥ甫鍑�' : '璇峰厛閫夋嫨浜у搧'"
- clearable
- :disabled="true"
- />
- </el-form-item>
-
- <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
- <el-switch v-model="form.isQuality" :active-value="true" inactive-value="false"/>
- </el-form-item>
- </el-form>
-
- <template #footer>
- <el-button @click="closeDialog">鍙栨秷</el-button>
- <el-button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</el-button>
- </template>
- </el-dialog>
-
- <!-- 浜у搧閫夋嫨瀵硅瘽妗� -->
- <ProductSelectDialog
- v-model="showProductSelectDialog"
- @confirm="handleProductSelect"
- single
- />
- </div>
-</template>
-
-<script setup>
-import { ref, computed, getCurrentInstance, onMounted, onUnmounted, nextTick } from "vue";
-import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-import { findProcessRouteItemList, addOrUpdateProcessRouteItem, sortProcessRouteItem, batchDeleteProcessRouteItem } from "@/api/productionManagement/processRouteItem.js";
-import { findProductProcessRouteItemList, deleteRouteItem, addRouteItem, addOrUpdateProductProcessRouteItem, sortRouteItem } from "@/api/productionManagement/productProcessRoute.js";
-import { processList } from "@/api/productionManagement/productionProcess.js";
-import { useRoute } from 'vue-router'
-import { ElMessageBox } from 'element-plus'
-import Sortable from 'sortablejs'
-
-const route = useRoute()
-const { proxy } = getCurrentInstance() || {};
-
-const routeId = computed(() => route.query.id);
-const orderId = computed(() => route.query.orderId);
-const pageType = computed(() => route.query.type);
-
-const tableLoading = ref(false);
-const tableData = ref([]);
-const dialogVisible = ref(false);
-const operationType = ref('add'); // add | edit
-const formRef = ref(null);
-const submitLoading = ref(false);
-const cardsContainer = ref(null);
-const tableRef = ref(null);
-const viewMode = ref('table'); // table | card
-const routeInfo = ref({
- processRouteCode: '',
- productName: '',
- model: '',
- bomNo: '',
- description: ''
-});
-
-const processOptions = ref([]);
-const showProductSelectDialog = ref(false);
-let tableSortable = null;
-let cardSortable = null;
-
-// 鍒囨崲瑙嗗浘
-const toggleView = () => {
- viewMode.value = viewMode.value === 'table' ? 'card' : 'table';
- // 鍒囨崲瑙嗗浘鍚庨噸鏂板垵濮嬪寲鎷栨嫿鎺掑簭
- nextTick(() => {
- initSortable();
- });
-};
-
-const form = ref({
- id: undefined,
- routeId: routeId.value,
- processId: undefined,
- productModelId: undefined,
- productName: "",
- model: "",
- unit: "",
- isQuality: false,
-});
-
-const rules = {
- processId: [{ required: true, message: '璇烽�夋嫨宸ュ簭', trigger: 'change' }],
- productModelId: [{ required: true, message: '璇烽�夋嫨浜у搧', trigger: 'change' }],
-};
-
-// 鏍规嵁宸ュ簭ID鑾峰彇宸ュ簭鍚嶇О
-const getProcessName = (processId) => {
- if (!processId) return '';
- const process = processOptions.value.find(p => p.id === processId);
- return process ? process.name : '';
-};
-
-// 鑾峰彇鍒楄〃
-const getList = () => {
- tableLoading.value = true;
- const listPromise =
- pageType.value === "order"
- ? findProductProcessRouteItemList({ orderId: orderId.value })
- : findProcessRouteItemList({ routeId: routeId.value });
-
- listPromise
- .then(res => {
- tableData.value = res.data || [];
- tableLoading.value = false;
- // 鍒楄〃鍔犺浇瀹屾垚鍚庡垵濮嬪寲鎷栨嫿鎺掑簭
- nextTick(() => {
- initSortable();
- });
- })
- .catch(err => {
- tableLoading.value = false;
- console.error("鑾峰彇鍒楄〃澶辫触锛�", err);
- proxy?.$modal?.msgError("鑾峰彇鍒楄〃澶辫触");
- });
-};
-
-// 鑾峰彇宸ュ簭鍒楄〃
-const getProcessList = () => {
- processList({})
- .then(res => {
- processOptions.value = res.data || [];
- })
- .catch(err => {
- console.error("鑾峰彇宸ュ簭澶辫触锛�", err);
- });
-};
-
-// 鑾峰彇宸ヨ壓璺嚎璇︽儏锛堜粠璺敱鍙傛暟鑾峰彇锛�
-const getRouteInfo = () => {
- routeInfo.value = {
- processRouteCode: route.query.processRouteCode || '',
- productName: route.query.productName || '',
- model: route.query.model || '',
- bomNo: route.query.bomNo || '',
- description: route.query.description || ''
- };
-};
-
-// 鏂板
-const handleAdd = () => {
- operationType.value = 'add';
- resetForm();
- dialogVisible.value = true;
-};
-
-// 缂栬緫
-const handleEdit = (row) => {
- operationType.value = 'edit';
- form.value = {
- id: row.id,
- routeId: routeId.value,
- processId: row.processId,
- productModelId: row.productModelId,
- productName: row.productName || "",
- model: row.model || "",
- unit: row.unit || "",
- isQuality: row.isQuality,
- };
- dialogVisible.value = true;
-};
-
-// 鍒犻櫎
-const handleDelete = (row) => {
- ElMessageBox.confirm('纭鍒犻櫎璇ュ伐鑹鸿矾绾块」鐩紵', '鎻愮ず', {
- confirmButtonText: '纭',
- cancelButtonText: '鍙栨秷',
- type: 'warning'
- })
- .then(() => {
- // 鐢熶骇璁㈠崟涓嬩娇鐢� productProcessRoute 鐨勫垹闄ゆ帴鍙o紙璺敱鍚庢嫾鎺� id锛夛紝鍏跺畠鎯呭喌浣跨敤宸ヨ壓璺嚎椤圭洰鎵归噺鍒犻櫎鎺ュ彛
- const deletePromise =
- pageType.value === 'order'
- ? deleteRouteItem(row.id)
- : batchDeleteProcessRouteItem([row.id]);
-
- deletePromise
- .then(() => {
- proxy?.$modal?.msgSuccess('鍒犻櫎鎴愬姛');
- getList();
- })
- .catch(() => {
- proxy?.$modal?.msgError('鍒犻櫎澶辫触');
- });
- })
- .catch(() => {});
-};
-
-// 浜у搧閫夋嫨
-const handleProductSelect = (products) => {
- if (products && products.length > 0) {
- const product = products[0];
- form.value.productModelId = product.id;
- form.value.productName = product.productName;
- form.value.model = product.model;
- form.value.unit = product.unit || "";
- showProductSelectDialog.value = false;
- // 瑙﹀彂琛ㄥ崟楠岃瘉
- formRef.value?.validateField('productModelId');
- }
-};
-
-// 鎻愪氦
-const handleSubmit = () => {
- formRef.value.validate((valid) => {
- if (valid) {
- submitLoading.value = true;
-
- if (operationType.value === 'add') {
- // 鏂板锛氫紶鍗曚釜瀵硅薄锛屽寘鍚玠ragSort瀛楁
- // dragSort = 褰撳墠鍒楄〃闀垮害 + 1锛岃〃绀烘柊澧炶褰曟帓鍦ㄦ渶鍚�
- const dragSort = tableData.value.length + 1;
- const isOrderPage = pageType.value === 'order';
-
- const addPromise = isOrderPage
- ? addRouteItem({
- productOrderId: orderId.value,
- productRouteId: routeId.value,
- processId: form.value.processId,
- productModelId: form.value.productModelId,
- isQuality: form.value.isQuality,
- dragSort,
- })
- : addOrUpdateProcessRouteItem({
- routeId: routeId.value,
- processId: form.value.processId,
- productModelId: form.value.productModelId,
- isQuality: form.value.isQuality,
- dragSort,
- });
-
- addPromise
- .then(() => {
- proxy?.$modal?.msgSuccess('鏂板鎴愬姛');
- closeDialog();
- getList();
- })
- .catch(() => {
- proxy?.$modal?.msgError('鏂板澶辫触');
- })
- .finally(() => {
- submitLoading.value = false;
- });
- } else {
- // 缂栬緫锛氱敓浜ц鍗曚笅浣跨敤 productProcessRoute/updateRouteItem锛屽叾瀹冩儏鍐典娇鐢ㄥ伐鑹鸿矾绾块」鐩洿鏂版帴鍙�
- const isOrderPage = pageType.value === 'order';
-
- const updatePromise = isOrderPage
- ? addOrUpdateProductProcessRouteItem({
- id: form.value.id,
- processId: form.value.processId,
- productModelId: form.value.productModelId,
- isQuality: form.value.isQuality,
- })
- : addOrUpdateProcessRouteItem({
- routeId: routeId.value,
- processId: form.value.processId,
- productModelId: form.value.productModelId,
- id: form.value.id,
- isQuality: form.value.isQuality,
- });
-
- updatePromise
- .then(() => {
- proxy?.$modal?.msgSuccess('淇敼鎴愬姛');
- closeDialog();
- getList();
- })
- .catch(() => {
- proxy?.$modal?.msgError('淇敼澶辫触');
- })
- .finally(() => {
- submitLoading.value = false;
- });
- }
- }
- });
-};
-
-// 閲嶇疆琛ㄥ崟
-const resetForm = () => {
- form.value = {
- id: undefined,
- routeId: routeId.value,
- processId: undefined,
- productModelId: undefined,
- productName: "",
- model: "",
- unit: "",
- };
- formRef.value?.resetFields();
-};
-
-// 鍏抽棴寮圭獥
-const closeDialog = () => {
- dialogVisible.value = false;
- resetForm();
-};
-
-// 鍒濆鍖栨嫋鎷芥帓搴�
-const initSortable = () => {
- destroySortable();
-
- if (viewMode.value === 'table') {
- // 琛ㄦ牸瑙嗗浘鐨勬嫋鎷芥帓搴�
- if (!tableRef.value) return;
-
- const tbody = tableRef.value.$el.querySelector('.el-table__body tbody') ||
- tableRef.value.$el.querySelector('.el-table__body-wrapper > table > tbody');
-
- if (!tbody) return;
-
- tableSortable = new Sortable(tbody, {
- animation: 150,
- ghostClass: 'sortable-ghost',
- handle: '.el-table__row',
- filter: '.el-button, .el-select',
- onEnd: (evt) => {
- if (evt.oldIndex === evt.newIndex || !tableData.value[evt.oldIndex]) return;
-
- // 閲嶆柊鎺掑簭鏁扮粍
- const moveItem = tableData.value.splice(evt.oldIndex, 1)[0];
- tableData.value.splice(evt.newIndex, 0, moveItem);
-
- // 璁$畻鏂扮殑搴忓彿锛坉ragSort浠�1寮�濮嬶級
- const newIndex = evt.newIndex;
- const dragSort = newIndex + 1;
-
- // 璋冪敤鎺掑簭鎺ュ彛
- if (moveItem.id) {
- const isOrderPage = pageType.value === 'order';
- const sortPromise = isOrderPage
- ? sortRouteItem({
- id: moveItem.id,
- dragSort: dragSort
- })
- : sortProcessRouteItem({
- id: moveItem.id,
- dragSort: dragSort
- });
-
- sortPromise
- .then(() => {
- // 鏇存柊鎵�鏈夎鐨刣ragSort
- tableData.value.forEach((item, index) => {
- if (item.id) {
- item.dragSort = index + 1;
- }
- });
- proxy?.$modal?.msgSuccess('鎺掑簭鎴愬姛');
- })
- .catch((err) => {
- // 鎺掑簭澶辫触锛屾仮澶嶅師鏁扮粍
- tableData.value.splice(newIndex, 1);
- tableData.value.splice(evt.oldIndex, 0, moveItem);
- proxy?.$modal?.msgError('鎺掑簭澶辫触');
- console.error("鎺掑簭澶辫触锛�", err);
- });
- }
- }
- });
- } else {
- // 鍗$墖瑙嗗浘鐨勬嫋鎷芥帓搴�
- if (!cardsContainer.value) return;
-
- cardSortable = new Sortable(cardsContainer.value, {
- animation: 150,
- ghostClass: 'sortable-ghost',
- handle: '.process-card',
- filter: '.el-button',
- onEnd: (evt) => {
- if (evt.oldIndex === evt.newIndex || !tableData.value[evt.oldIndex]) return;
-
- // 閲嶆柊鎺掑簭鏁扮粍
- const moveItem = tableData.value.splice(evt.oldIndex, 1)[0];
- tableData.value.splice(evt.newIndex, 0, moveItem);
-
- // 璁$畻鏂扮殑搴忓彿锛坉ragSort浠�1寮�濮嬶級
- const newIndex = evt.newIndex;
- const dragSort = newIndex + 1;
-
- // 璋冪敤鎺掑簭鎺ュ彛
- if (moveItem.id) {
- const isOrderPage = pageType.value === 'order';
- const sortPromise = isOrderPage
- ? sortRouteItem({
- id: moveItem.id,
- dragSort: dragSort
- })
- : sortProcessRouteItem({
- id: moveItem.id,
- dragSort: dragSort
- });
-
- sortPromise
- .then(() => {
- // 鏇存柊鎵�鏈夎鐨刣ragSort
- tableData.value.forEach((item, index) => {
- if (item.id) {
- item.dragSort = index + 1;
- }
- });
- proxy?.$modal?.msgSuccess('鎺掑簭鎴愬姛');
- })
- .catch((err) => {
- // 鎺掑簭澶辫触锛屾仮澶嶅師鏁扮粍
- tableData.value.splice(newIndex, 1);
- tableData.value.splice(evt.oldIndex, 0, moveItem);
- proxy?.$modal?.msgError('鎺掑簭澶辫触');
- console.error("鎺掑簭澶辫触锛�", err);
- });
- }
- }
- });
- }
-};
-
-// 閿�姣佹嫋鎷芥帓搴�
-const destroySortable = () => {
- if (tableSortable) {
- tableSortable.destroy();
- tableSortable = null;
- }
- if (cardSortable) {
- cardSortable.destroy();
- cardSortable = null;
- }
-};
-
-onMounted(() => {
- getRouteInfo();
- getList();
- getProcessList();
-});
-
-onUnmounted(() => {
- destroySortable();
-});
-</script>
-
-<style scoped>
-.card-container {
- padding: 20px 0;
-}
-
-.cards-wrapper {
- display: flex;
- gap: 16px;
- overflow-x: auto;
- padding: 10px 0;
- min-height: 200px;
-}
-
-.cards-wrapper::-webkit-scrollbar {
- height: 8px;
-}
-
-.cards-wrapper::-webkit-scrollbar-track {
- background: #f1f1f1;
- border-radius: 4px;
-}
-
-.cards-wrapper::-webkit-scrollbar-thumb {
- background: #c1c1c1;
- border-radius: 4px;
-}
-
-.cards-wrapper::-webkit-scrollbar-thumb:hover {
- background: #a8a8a8;
-}
-
-.process-card {
- flex-shrink: 0;
- width: 220px;
- background: #fff;
- border-radius: 8px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- padding: 16px;
- display: flex;
- flex-direction: column;
- cursor: move;
- transition: all 0.3s;
-}
-
-.process-card:hover {
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
- transform: translateY(-2px);
-}
-
-.card-header {
- text-align: center;
- margin-bottom: 12px;
-}
-
-.card-number {
- width: 36px;
- height: 36px;
- line-height: 36px;
- border-radius: 50%;
- background: #409eff;
- color: #fff;
- font-weight: bold;
- font-size: 16px;
- margin: 0 auto 8px;
-}
-
-.card-process-name {
- font-size: 14px;
- color: #333;
- font-weight: 500;
- word-break: break-all;
-}
-
-.card-content {
- flex: 1;
- margin-bottom: 12px;
- min-height: 60px;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.product-info {
- font-size: 13px;
- color: #666;
- text-align: center;
- width: 100%;
-}
-
-.product-info.empty {
- color: #999;
- text-align: center;
- padding: 20px 0;
-}
-
-.product-name {
- margin-bottom: 6px;
- word-break: break-all;
- line-height: 1.5;
- text-align: center;
-}
-
-.product-model {
- color: #909399;
- font-size: 12px;
- word-break: break-all;
- line-height: 1.5;
- text-align: center;
-}
-
-.product-unit {
- margin-left: 4px;
- color: #409eff;
-}
-
-.product-tag {
- margin: 10px 0;
-}
-
-.card-footer {
- display: flex;
- justify-content: space-around;
- padding-top: 12px;
- border-top: 1px solid #f0f0f0;
-}
-
-.card-footer .el-button {
- padding: 0;
- font-size: 12px;
-}
-
-:deep(.sortable-ghost) {
- opacity: 0.5;
- background-color: #f5f7fa !important;
-}
-
-:deep(.sortable-drag) {
- opacity: 0.8;
-}
-
-/* 琛ㄦ牸瑙嗗浘鏍峰紡 */
-:deep(.el-table__row) {
- transition: background-color 0.2s;
- cursor: move;
-}
-
-:deep(.el-table__row:hover) {
- background-color: #f9fafc !important;
-}
-
-/* 鍖哄煙鏍囬鏍峰紡 */
-.section-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 12px;
-}
-
-.section-title {
- font-size: 16px;
- font-weight: 600;
- color: #303133;
- padding-left: 12px;
- position: relative;
- margin-bottom: 0;
-}
-
-.section-title::before {
- content: '';
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
- width: 3px;
- height: 16px;
- background: #409eff;
- border-radius: 2px;
-}
-
-.section-actions {
- display: flex;
- align-items: center;
-}
-
-/* 宸ヨ壓璺嚎淇℃伅鍗$墖鏍峰紡 */
-.route-info-card {
- margin-bottom: 20px;
- border: 1px solid #e4e7ed;
- background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
- border-radius: 8px;
- overflow: hidden;
-}
-
-.route-info {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
- gap: 16px;
- padding: 4px;
-}
-
-.info-item {
- display: flex;
- flex-direction: column;
- background: #ffffff;
- border-radius: 6px;
- padding: 14px 16px;
- border: 1px solid #f0f2f5;
- transition: all 0.3s ease;
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
-}
-
-.info-item:hover {
- border-color: #409eff;
- box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
- transform: translateY(-1px);
-}
-
-.info-item.full-width {
- grid-column: 1 / -1;
-}
-
-.info-label-wrapper {
- margin-bottom: 8px;
-}
-
-.info-label {
- display: inline-block;
- color: #909399;
- font-size: 12px;
- font-weight: 500;
- text-transform: uppercase;
- letter-spacing: 0.5px;
- padding: 2px 0;
- position: relative;
-}
-
-.info-label::after {
- content: '';
- position: absolute;
- left: 0;
- bottom: 0;
- width: 20px;
- height: 2px;
- background: linear-gradient(90deg, #409eff, transparent);
- border-radius: 1px;
-}
-
-.info-value-wrapper {
- flex: 1;
-}
-
-.info-value {
- display: block;
- color: #303133;
- font-size: 15px;
- font-weight: 500;
- line-height: 1.5;
- word-break: break-all;
-}
-</style>
diff --git a/src/views/productionManagement/productionProcess/Edit.vue b/src/views/productionManagement/productionProcess/Edit.vue
deleted file mode 100644
index 8e92403..0000000
--- a/src/views/productionManagement/productionProcess/Edit.vue
+++ /dev/null
@@ -1,138 +0,0 @@
-<template>
- <div>
- <el-dialog
- v-model="isShow"
- title="缂栬緫宸ュ簭"
- width="400"
- @close="closeModal"
- >
- <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
- <el-form-item
- label="宸ュ簭鍚嶇О锛�"
- prop="name"
- :rules="[
- {
- required: true,
- message: '璇疯緭鍏ュ伐搴忓悕绉�',
- },
- {
- max: 100,
- message: '鏈�澶�100涓瓧绗�',
- }
- ]">
- <el-input v-model="formState.name" />
- </el-form-item>
- <el-form-item label="宸ュ簭缂栧彿" prop="no">
- <el-input v-model="formState.no" />
- </el-form-item>
- <el-form-item label="宸ヨ祫瀹氶" prop="salaryQuota">
- <el-input v-model="formState.salaryQuota" type="number" :step="0.001" />
- </el-form-item>
- <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
- <el-switch v-model="formState.isQuality" :active-value="true" inactive-value="false"/>
- </el-form-item>
- <el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="formState.remark" type="textarea" />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="handleSubmit">纭</el-button>
- <el-button @click="closeModal">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import { ref, computed, getCurrentInstance, watch } from "vue";
-import {update} from "@/api/productionManagement/productionProcess.js";
-
-const props = defineProps({
- visible: {
- type: Boolean,
- required: true,
- },
-
- record: {
- type: Object,
- required: true,
- }
-});
-
-const emit = defineEmits(['update:visible', 'completed']);
-
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
-const formState = ref({
- id: props.record.id,
- name: props.record.name,
- no: props.record.no,
- remark: props.record.remark,
- salaryQuota: props.record.salaryQuota,
- isQuality: props.record.isQuality,
-});
-
-const isShow = computed({
- get() {
- return props.visible;
- },
- set(val) {
- emit('update:visible', val);
- },
-});
-
-// 鐩戝惉 record 鍙樺寲锛屾洿鏂拌〃鍗曟暟鎹�
-watch(() => props.record, (newRecord) => {
- if (newRecord && isShow.value) {
- formState.value = {
- id: newRecord.id,
- name: newRecord.name || '',
- no: newRecord.no || '',
- remark: newRecord.remark || '',
- salaryQuota: newRecord.salaryQuota || '',
- isQuality: props.record.isQuality,
- };
- }
-}, { immediate: true, deep: true });
-
-// 鐩戝惉寮圭獥鎵撳紑锛岄噸鏂板垵濮嬪寲琛ㄥ崟鏁版嵁
-watch(() => props.visible, (visible) => {
- if (visible && props.record) {
- formState.value = {
- id: props.record.id,
- name: props.record.name || '',
- no: props.record.no || '',
- remark: props.record.remark || '',
- salaryQuota: props.record.salaryQuota || '',
- isQuality: props.record.isQuality,
- };
- }
-});
-
-let { proxy } = getCurrentInstance()
-
-const closeModal = () => {
- isShow.value = false;
-};
-
-const handleSubmit = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- update(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- })
- }
- })
-};
-
-defineExpose({
- closeModal,
- handleSubmit,
- isShow,
-});
-</script>
diff --git a/src/views/productionManagement/productionProcess/New.vue b/src/views/productionManagement/productionProcess/New.vue
deleted file mode 100644
index 001e3b1..0000000
--- a/src/views/productionManagement/productionProcess/New.vue
+++ /dev/null
@@ -1,105 +0,0 @@
-<template>
- <div>
- <el-dialog
- v-model="isShow"
- title="鏂板宸ュ簭"
- width="400"
- @close="closeModal"
- >
- <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
- <el-form-item
- label="宸ュ簭鍚嶇О锛�"
- prop="name"
- :rules="[
- {
- required: true,
- message: '璇疯緭鍏ュ伐搴忓悕绉�',
- },
- {
- max: 100,
- message: '鏈�澶�100涓瓧绗�',
- }
- ]">
- <el-input v-model="formState.name" />
- </el-form-item>
- <el-form-item label="宸ュ簭缂栧彿" prop="no">
- <el-input v-model="formState.no" />
- </el-form-item>
- <el-form-item label="宸ヨ祫瀹氶" prop="salaryQuota">
- <el-input v-model="formState.salaryQuota" type="number" :step="0.001">
- <template #append>鍏�</template>
- </el-input>
- </el-form-item>
- <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
- <el-switch v-model="formState.isQuality" :active-value="true" inactive-value="false"/>
- </el-form-item>
- <el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="formState.remark" type="textarea" />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="handleSubmit">纭</el-button>
- <el-button @click="closeModal">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import { ref, computed, getCurrentInstance } from "vue";
-import {add} from "@/api/productionManagement/productionProcess.js";
-
-const props = defineProps({
- visible: {
- type: Boolean,
- required: true,
- },
-});
-
-const emit = defineEmits(['update:visible', 'completed']);
-
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
-const formState = ref({
- name: '',
- remark: '',
- salaryQuota: '',
- isQuality: false,
-});
-
-const isShow = computed({
- get() {
- return props.visible;
- },
- set(val) {
- emit('update:visible', val);
- },
-});
-
-let { proxy } = getCurrentInstance()
-
-const closeModal = () => {
- isShow.value = false;
-};
-
-const handleSubmit = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- add(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- })
- }
- })
-};
-
-defineExpose({
- closeModal,
- handleSubmit,
- isShow,
-});
-</script>
diff --git a/src/views/productionManagement/productionProcess/index.vue b/src/views/productionManagement/productionProcess/index.vue
index 4f3f3ef..5ecb747 100644
--- a/src/views/productionManagement/productionProcess/index.vue
+++ b/src/views/productionManagement/productionProcess/index.vue
@@ -1,314 +1,997 @@
<template>
<div class="app-container">
- <div class="search_form">
- <el-form :model="searchForm"
- :inline="true">
- <el-form-item label="宸ュ簭鍚嶇О:">
- <el-input v-model="searchForm.name"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- style="width: 200px;"
- @change="handleQuery" />
- </el-form-item>
- <el-form-item label="宸ュ簭缂栧彿:">
- <el-input v-model="searchForm.no"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- style="width: 200px;"
- @change="handleQuery" />
- </el-form-item>
- <el-form-item>
+ <div class="process-config-container">
+ <!-- 宸︿晶宸ュ簭鍒楄〃 -->
+ <div class="process-list-section">
+ <div class="section-header">
+ <h3 class="section-title">宸ュ簭鍒楄〃</h3>
<el-button type="primary"
- @click="handleQuery">鎼滅储</el-button>
+ size="small"
+ @click="handleAddProcess">
+ <el-icon>
+ <Plus />
+ </el-icon>鏂板宸ュ簭
+ </el-button>
+ </div>
+ <div class="process-card-list">
+ <div v-for="process in processList"
+ :key="process.id"
+ class="process-card"
+ :class="{ active: selectedProcess?.id === process.id }"
+ @click="selectProcess(process)">
+ <div class="card-header">
+ <span class="process-code">{{ process.processCode }}</span>
+ <div class="card-actions">
+ <el-button link
+ type="primary"
+ @click.stop="handleEditProcess(process)">
+ <el-icon>
+ <Edit />
+ </el-icon>
+ 缂栬緫
+ </el-button>
+ <el-button link
+ type="danger"
+ @click.stop="handleDeleteProcess(process)">
+ <el-icon>
+ <Delete />
+ </el-icon>
+ 鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ <div class="card-body">
+ <div class="process-name">{{ process.processName }}</div>
+ <div class="process-desc">{{ process.processDesc || '鏆傛棤鎻忚堪' }}</div>
+ </div>
+ <div class="card-footer">
+ <el-tag size="small"
+ :type="process.status === '1' ? 'success' : 'info'">
+ {{ process.status === '1' ? '鍚敤' : '鍋滅敤' }}
+ </el-tag>
+ <span class="param-count">鍙傛暟: {{ process.paramCount || 0 }}涓�</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- 鍙充晶鍙傛暟鍒楄〃 -->
+ <div class="param-list-section">
+ <div class="section-header">
+ <h3 class="section-title">
+ {{ selectedProcess ? selectedProcess.processName + ' - 鍙傛暟閰嶇疆' : '璇烽�夋嫨宸ュ簭' }}
+ </h3>
+ <el-button type="primary"
+ size="small"
+ :disabled="!selectedProcess"
+ @click="handleSelectParam">
+ <el-icon>
+ <Plus />
+ </el-icon>閫夋嫨鍙傛暟
+ </el-button>
+ </div>
+ <div class="param-table-wrapper">
+ <PIMTable v-if="selectedProcess"
+ rowKey="id"
+ :column="paramColumn"
+ :tableData="paramList"
+ :page="paramPage"
+ height="calc(100vh - 280px)"
+ :tableLoading="paramLoading"
+ :isSelection="false"
+ @pagination="handleParamPagination" />
+ <div v-else
+ class="empty-tip">
+ <el-empty description="璇蜂粠宸︿晶閫夋嫨涓�涓伐搴�" />
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- 宸ュ簭鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="processDialogVisible"
+ :title="isProcessEdit ? '缂栬緫宸ュ簭' : '鏂板宸ュ簭'"
+ width="500px">
+ <el-form :model="processForm"
+ :rules="processRules"
+ ref="processFormRef"
+ label-width="100px">
+ <el-form-item label="宸ュ簭缂栫爜"
+ prop="processCode">
+ <el-input v-model="processForm.processCode"
+ placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />
+ </el-form-item>
+ <el-form-item label="宸ュ簭鍚嶇О"
+ prop="processName">
+ <el-input v-model="processForm.processName"
+ placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+ </el-form-item>
+ <el-form-item label="宸ュ簭鎻忚堪"
+ prop="processDesc">
+ <el-input v-model="processForm.processDesc"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ュ伐搴忔弿杩�" />
+ </el-form-item>
+ <el-form-item label="鐘舵��"
+ prop="status">
+ <el-radio-group v-model="processForm.status">
+ <el-radio label="1">鍚敤</el-radio>
+ <el-radio label="0">鍋滅敤</el-radio>
+ </el-radio-group>
</el-form-item>
</el-form>
- </div>
- <div class="table_list">
- <div style="text-align: right"
- class="mb10">
- <el-button type="primary"
- @click="showNewModal">鏂板宸ュ簭</el-button>
- <el-button type="info"
- plain
- @click="handleImport">瀵煎叆</el-button>
- <el-button type="danger"
- @click="handleDelete"
- :disabled="selectedRows.length === 0"
- plain>鍒犻櫎宸ュ簭</el-button>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="processDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleProcessSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 閫夋嫨鍙傛暟瀵硅瘽妗� -->
+ <el-dialog v-model="paramDialogVisible"
+ title="閫夋嫨鍙傛暟"
+ width="1000px">
+ <div class="param-select-container">
+ <!-- 宸︿晶鍙傛暟鍒楄〃 -->
+ <div class="param-list-area">
+ <div class="area-title">鍙�夊弬鏁�</div>
+ <div class="search-box">
+ <el-input v-model="paramSearchKeyword"
+ placeholder="璇疯緭鍏ュ弬鏁板悕绉版悳绱�"
+ clearable
+ size="small"
+ @input="handleParamSearch">
+ <template #prefix>
+ <el-icon>
+ <Search />
+ </el-icon>
+ </template>
+ </el-input>
+ </div>
+ <el-table :data="filteredParamList"
+ height="360"
+ border
+ highlight-current-row
+ @current-change="handleParamSelect">
+ <el-table-column prop="parameterCode"
+ label="鍙傛暟缂栧彿"
+ width="100" />
+ <el-table-column prop="parameterName"
+ label="鍙傛暟鍚嶇О" />
+ <el-table-column prop="parameterType"
+ label="鍙傛暟绫诲瀷"
+ width="100">
+ <template #default="scope">
+ <el-tag size="small"
+ :type="getParamTypeTag(scope.row.parameterType)">
+ {{ scope.row.parameterType }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <!-- 鍙充晶鍙傛暟璇︽儏 -->
+ <div class="param-detail-area">
+ <div class="area-title">鍙傛暟璇︽儏</div>
+ <el-form v-if="selectedParam"
+ :model="selectedParam"
+ label-width="100px"
+ class="param-detail-form">
+ <el-form-item label="鍙傛暟缂栧彿">
+ <span class="detail-text">{{ selectedParam.parameterCode }}</span>
+ </el-form-item>
+ <el-form-item label="鍙傛暟鍚嶇О">
+ <span class="detail-text">{{ selectedParam.parameterName }}</span>
+ </el-form-item>
+ <el-form-item label="鍙傛暟妯″紡">
+ <el-tag size="small"
+ :type="selectedParam.parameterType2 === '1' ? 'success' : 'warning'">
+ {{ selectedParam.parameterType2 === '1' ? '鍗曞��' : '鍖洪棿' }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷">
+ <el-tag size="small"
+ :type="getParamTypeTag(selectedParam.parameterType)">
+ {{ selectedParam.parameterType }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟鏍煎紡">
+ <span class="detail-text">{{ selectedParam.parameterFormat || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�">
+ <span class="detail-text">{{ selectedParam.standardValue }}</span>
+ </el-form-item>
+ <el-form-item label="鍗曚綅">
+ <span class="detail-text">{{ selectedParam.unit || '-' }}</span>
+ </el-form-item>
+ </el-form>
+ <el-empty v-else
+ description="璇蜂粠宸︿晶閫夋嫨鍙傛暟" />
+ </div>
</div>
- <PIMTable rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"></PIMTable>
- </div>
- <new-process v-if="isShowNewModal"
- v-model:visible="isShowNewModal"
- @completed="getList" />
- <edit-process v-if="isShowEditModal"
- v-model:visible="isShowEditModal"
- :record="record"
- @completed="getList" />
- <ImportDialog ref="importDialogRef"
- v-model="importDialogVisible"
- title="瀵煎叆宸ュ簭"
- :action="importAction"
- :headers="importHeaders"
- :auto-upload="false"
- :on-success="handleImportSuccess"
- :on-error="handleImportError"
- @confirm="handleImportConfirm"
- @download-template="handleDownloadTemplate"
- @close="handleImportClose" />
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="paramDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ :disabled="!selectedParam"
+ @click="handleParamSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
- import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
- import NewProcess from "@/views/productionManagement/productionProcess/New.vue";
- import EditProcess from "@/views/productionManagement/productionProcess/Edit.vue";
- import ImportDialog from "@/components/Dialog/ImportDialog.vue";
- import {
- listPage,
- del,
- importData,
- downloadTemplate,
- } from "@/api/productionManagement/productionProcess.js";
- import { getToken } from "@/utils/auth";
+ import { ref, reactive, onMounted } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import { Plus, Edit, Delete, Search } from "@element-plus/icons-vue";
+ import PIMTable from "@/components/PIMTable/PIMTable.vue";
+ import { listType } from "@/api/system/dict/type";
- const data = reactive({
- searchForm: {
- name: "",
- no: "",
- },
+ // 宸ュ簭鍒楄〃鏁版嵁
+ const processList = ref([]);
+ const selectedProcess = ref(null);
+ const processLoading = ref(false);
+
+ // 鍙傛暟鍒楄〃鏁版嵁
+ const paramList = ref([]);
+ const paramLoading = ref(false);
+ const paramPage = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
});
- const { searchForm } = toRefs(data);
- const tableColumn = ref([
+
+ // 鏁版嵁瀛楀吀
+ const dictTypes = ref([]);
+
+ // 宸ュ簭瀵硅瘽妗�
+ const processDialogVisible = ref(false);
+ const isProcessEdit = ref(false);
+ const processFormRef = ref(null);
+ const processForm = reactive({
+ id: null,
+ processCode: "",
+ processName: "",
+ processDesc: "",
+ status: "1",
+ });
+ const processRules = {
+ processCode: [{ required: true, message: "璇疯緭鍏ュ伐搴忕紪鐮�", trigger: "blur" }],
+ processName: [{ required: true, message: "璇疯緭鍏ュ伐搴忓悕绉�", trigger: "blur" }],
+ };
+
+ // 鍙傛暟瀵硅瘽妗�
+ const paramDialogVisible = ref(false);
+ const availableParamList = ref([]);
+ const filteredParamList = ref([]);
+ const selectedParam = ref(null);
+ const paramSearchKeyword = ref("");
+
+ // 鍙傛暟琛ㄦ牸鍒楅厤缃�
+ const paramColumn = ref([
{
- label: "宸ュ簭缂栧彿",
- prop: "no",
+ label: "鍙傛暟缂栧彿",
+ prop: "parameterCode",
+ className: "code-cell",
},
{
- label: "宸ュ簭鍚嶇О",
- prop: "name",
+ label: "鍙傛暟鍚嶇О",
+ prop: "parameterName",
},
{
- label: "宸ヨ祫瀹氶",
- prop: "salaryQuota",
+ label: "鍙傛暟妯″紡",
+ prop: "parameterType2",
+ dataType: "tag",
+ formatType: row => (row.parameterType2 === "1" ? "success" : "warning"),
+ formatData: row => (row.parameterType2 === "1" ? "鍗曞��" : "鍖洪棿"),
},
{
- label: "鏄惁璐ㄦ",
- prop: "isQuality",
- formatData: (params) => {
- return params ? "鏄�" : "鍚�";
+ label: "鍙傛暟绫诲瀷",
+ prop: "parameterType",
+ dataType: "tag",
+ formatType: row => {
+ const typeMap = {
+ 鏁板�兼牸寮�: "primary",
+ 鏂囨湰鏍煎紡: "info",
+ 涓嬫媺閫夐」: "warning",
+ 鏃堕棿鏍煎紡: "success",
+ };
+ return typeMap[row.parameterType] || "default";
},
},
{
- label: "澶囨敞",
- prop: "remark",
+ label: "鍙傛暟鏍煎紡",
+ prop: "parameterFormat",
},
{
- label: "鏇存柊鏃堕棿",
- prop: "updateTime",
+ label: "鏍囧噯鍊�",
+ prop: "standardValue",
+ className: row => (row.parameterType === "鏁板�兼牸寮�" ? "quantity-cell" : ""),
},
{
- dataType: "action",
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
+ dataType: "action",
+ width: "100",
operation: [
{
- name: "缂栬緫",
- type: "text",
- clickFun: row => {
- showEditModal(row);
- },
+ name: "鍒犻櫎",
+ clickFun: row => handleDeleteParam(row),
},
],
},
]);
- const tableData = ref([]);
- const selectedRows = ref([]);
- const tableLoading = ref(false);
- const isShowNewModal = ref(false);
- const isShowEditModal = ref(false);
- const record = ref({});
- const importDialogVisible = ref(false);
- const importDialogRef = ref(null);
- const page = reactive({
- current: 1,
- size: 100,
- total: 0,
- });
- const { proxy } = getCurrentInstance();
- // 瀵煎叆鐩稿叧閰嶇疆
- const importAction =
- import.meta.env.VITE_APP_BASE_API + "/productProcess/importData";
- const importHeaders = { Authorization: "Bearer " + getToken() };
-
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- page.current = 1;
- getList();
+ // 鑾峰彇宸ュ簭鍒楄〃
+ const getProcessList = () => {
+ // 鍋囨暟鎹�
+ processList.value = [
+ {
+ id: 1,
+ processCode: "PROC001",
+ processName: "鍘熸枡閰嶆瘮",
+ processDesc: "鍘熸潗鏂欓厤姣斿伐搴�",
+ status: "1",
+ paramCount: 3,
+ },
+ {
+ id: 2,
+ processCode: "PROC002",
+ processName: "鎼呮媽娣峰悎",
+ processDesc: "鎼呮媽娣峰悎宸ュ簭",
+ status: "1",
+ paramCount: 2,
+ },
+ {
+ id: 3,
+ processCode: "PROC003",
+ processName: "娴囩瓚鎴愬瀷",
+ processDesc: "娴囩瓚鎴愬瀷宸ュ簭",
+ status: "1",
+ paramCount: 4,
+ },
+ {
+ id: 4,
+ processCode: "PROC004",
+ processName: "钂稿帇鍏绘姢",
+ processDesc: "钂稿帇鍏绘姢宸ュ簭",
+ status: "0",
+ paramCount: 2,
+ },
+ {
+ id: 5,
+ processCode: "PROC005",
+ processName: "鍒囧壊鍔犲伐",
+ processDesc: "鍒囧壊鍔犲伐宸ュ簭",
+ status: "1",
+ paramCount: 3,
+ },
+ ];
};
- const pagination = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined;
- listPage(params)
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records.map(item => ({
- ...item,
- }));
- page.total = res.data.total;
- })
- .catch(err => {
- tableLoading.value = false;
- });
- };
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
+ // 鑾峰彇鍙傛暟鍒楄〃
+ const getParamList = processId => {
+ paramLoading.value = true;
+ // 鍋囨暟鎹�
+ setTimeout(() => {
+ paramLoading.value = false;
+ const mockData = {
+ 1: [
+ {
+ id: 1,
+ parameterCode: "P001",
+ parameterName: "姘存偿姣斾緥",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "30",
+ unit: "%",
+ },
+ {
+ id: 2,
+ parameterCode: "P002",
+ parameterName: "鐮傛瘮渚�",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "60",
+ unit: "%",
+ },
+ {
+ id: 3,
+ parameterCode: "P003",
+ parameterName: "姘存瘮渚�",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "10",
+ unit: "%",
+ },
+ ],
+ 2: [
+ {
+ id: 4,
+ parameterCode: "P004",
+ parameterName: "鎼呮媽鏃堕棿",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "5",
+ unit: "鍒嗛挓",
+ },
+ {
+ id: 5,
+ parameterCode: "P005",
+ parameterName: "鎼呮媽閫熷害",
+ parameterType2: "2",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "100-200",
+ unit: "rpm",
+ },
+ ],
+ 3: [
+ {
+ id: 6,
+ parameterCode: "P006",
+ parameterName: "娴囩瓚娓╁害",
+ parameterType2: "2",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "20-30",
+ unit: "鈩�",
+ },
+ {
+ id: 7,
+ parameterCode: "P007",
+ parameterName: "娴囩瓚鍘嬪姏",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "0.5",
+ unit: "MPa",
+ },
+ {
+ id: 8,
+ parameterCode: "P008",
+ parameterName: "鎴愬瀷鐘舵��",
+ parameterType2: "1",
+ parameterType: "涓嬫媺閫夐」",
+ parameterFormat: "status",
+ standardValue: "姝e父",
+ unit: "",
+ },
+ {
+ id: 9,
+ parameterCode: "P009",
+ parameterName: "鎴愬瀷鏃堕棿",
+ parameterType2: "1",
+ parameterType: "鏃堕棿鏍煎紡",
+ parameterFormat: "YYYY-MM-DD HH:mm:ss",
+ standardValue: "2024-01-01 08:00:00",
+ unit: "",
+ },
+ ],
+ 4: [
+ {
+ id: 10,
+ parameterCode: "P010",
+ parameterName: "钂稿帇娓╁害",
+ parameterType2: "2",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "180-200",
+ unit: "鈩�",
+ },
+ {
+ id: 11,
+ parameterCode: "P011",
+ parameterName: "钂稿帇鍘嬪姏",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "1.2",
+ unit: "MPa",
+ },
+ ],
+ 5: [
+ {
+ id: 12,
+ parameterCode: "P012",
+ parameterName: "鍒囧壊灏哄",
+ parameterType2: "1",
+ parameterType: "鏂囨湰鏍煎紡",
+ parameterFormat: "",
+ standardValue: "600x200x100",
+ unit: "mm",
+ },
+ {
+ id: 13,
+ parameterCode: "P013",
+ parameterName: "鍒囧壊绮惧害",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "卤1",
+ unit: "mm",
+ },
+ {
+ id: 14,
+ parameterCode: "P014",
+ parameterName: "鍒囧壊閫熷害",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "2",
+ unit: "m/min",
+ },
+ ],
+ };
+ paramList.value = mockData[processId] || [];
+ paramPage.total = paramList.value.length;
+ }, 300);
};
- // 鎵撳紑鏂板寮规
- const showNewModal = () => {
- isShowNewModal.value = true;
+ // 閫夋嫨宸ュ簭
+ const selectProcess = process => {
+ selectedProcess.value = process;
+ getParamList(process.id);
};
- const showEditModal = row => {
- isShowEditModal.value = true;
- record.value = row;
+ // 宸ュ簭鎿嶄綔
+ const handleAddProcess = () => {
+ isProcessEdit.value = false;
+ processForm.id = null;
+ processForm.processCode = "";
+ processForm.processName = "";
+ processForm.processDesc = "";
+ processForm.status = "1";
+ processDialogVisible.value = true;
};
- // 鍒犻櫎
- function handleDelete() {
- const no = selectedRows.value.map(item => item.no);
- const ids = selectedRows.value.map(item => item.id);
- if (no.length > 2) {
- proxy.$modal
- .confirm(
- '鏄惁纭鍒犻櫎宸ュ簭缂栧彿涓�"' +
- no[0] +
- "銆�" +
- no[1] +
- '"绛�' +
- no.length +
- "鏉℃暟鎹」锛�"
- )
- .then(function () {
- return del(ids);
- })
- .then(() => {
- getList();
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- })
- .catch(() => {});
- } else {
- proxy.$modal
- .confirm('鏄惁纭鍒犻櫎宸ュ簭缂栧彿涓�"' + no + '"鐨勬暟鎹」锛�')
- .then(function () {
- return del(ids);
- })
- .then(() => {
- getList();
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- })
- .catch(() => {});
- }
- }
-
- // 瀵煎叆
- const handleImport = () => {
- importDialogVisible.value = true;
+ const handleEditProcess = process => {
+ isProcessEdit.value = true;
+ processForm.id = process.id;
+ processForm.processCode = process.processCode;
+ processForm.processName = process.processName;
+ processForm.processDesc = process.processDesc;
+ processForm.status = process.status;
+ processDialogVisible.value = true;
};
- // 纭瀵煎叆
- const handleImportConfirm = () => {
- if (importDialogRef.value) {
- importDialogRef.value.submit();
- }
- };
-
- // 瀵煎叆鎴愬姛
- const handleImportSuccess = response => {
- if (response.code === 200) {
- proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
- importDialogVisible.value = false;
- if (importDialogRef.value) {
- importDialogRef.value.clearFiles();
+ const handleDeleteProcess = process => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ宸ュ簭鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getProcessList();
+ if (selectedProcess.value?.id === process.id) {
+ selectedProcess.value = null;
+ paramList.value = [];
}
- getList();
+ });
+ };
+
+ const handleProcessSubmit = () => {
+ processFormRef.value.validate(valid => {
+ if (valid) {
+ ElMessage.success(isProcessEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ processDialogVisible.value = false;
+ getProcessList();
+ }
+ });
+ };
+
+ // 鍙傛暟鎿嶄綔
+ const handleSelectParam = () => {
+ if (!selectedProcess.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓伐搴�");
+ return;
+ }
+ // 鑾峰彇鍙�夊弬鏁板垪琛紙鍋囨暟鎹級
+ availableParamList.value = [
+ {
+ id: 101,
+ parameterCode: "P101",
+ parameterName: "娓╁害",
+ parameterType2: "2",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "20-30",
+ unit: "鈩�",
+ },
+ {
+ id: 102,
+ parameterCode: "P102",
+ parameterName: "鍘嬪姏",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "0.5",
+ unit: "MPa",
+ },
+ {
+ id: 103,
+ parameterCode: "P103",
+ parameterName: "婀垮害",
+ parameterType2: "2",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "40-60",
+ unit: "%",
+ },
+ {
+ id: 104,
+ parameterCode: "P104",
+ parameterName: "閫熷害",
+ parameterType2: "1",
+ parameterType: "鏁板�兼牸寮�",
+ parameterFormat: "",
+ standardValue: "100",
+ unit: "m/min",
+ },
+ {
+ id: 105,
+ parameterCode: "P105",
+ parameterName: "鐘舵��",
+ parameterType2: "1",
+ parameterType: "涓嬫媺閫夐」",
+ parameterFormat: "status",
+ standardValue: "姝e父",
+ unit: "",
+ },
+ {
+ id: 106,
+ parameterCode: "P106",
+ parameterName: "璁板綍鏃堕棿",
+ parameterType2: "1",
+ parameterType: "鏃堕棿鏍煎紡",
+ parameterFormat: "YYYY-MM-DD HH:mm:ss",
+ standardValue: "2024-01-01 08:00:00",
+ unit: "",
+ },
+ {
+ id: 107,
+ parameterCode: "P107",
+ parameterName: "澶囨敞",
+ parameterType2: "1",
+ parameterType: "鏂囨湰鏍煎紡",
+ parameterFormat: "",
+ standardValue: "鏃�",
+ unit: "",
+ },
+ ];
+ filteredParamList.value = availableParamList.value;
+ paramSearchKeyword.value = "";
+ selectedParam.value = null;
+ paramDialogVisible.value = true;
+ };
+
+ const handleParamSelect = row => {
+ selectedParam.value = row;
+ };
+
+ const handleParamSearch = () => {
+ const keyword = paramSearchKeyword.value.trim().toLowerCase();
+ if (!keyword) {
+ filteredParamList.value = availableParamList.value;
} else {
- proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
+ filteredParamList.value = availableParamList.value.filter(item =>
+ item.parameterName.toLowerCase().includes(keyword)
+ );
}
};
- // 瀵煎叆澶辫触
- const handleImportError = error => {
- proxy.$modal.msgError("瀵煎叆澶辫触锛�" + (error.message || "鏈煡閿欒"));
+ const getParamTypeTag = type => {
+ const typeMap = {
+ 鏁板�兼牸寮�: "primary",
+ 鏂囨湰鏍煎紡: "info",
+ 涓嬫媺閫夐」: "warning",
+ 鏃堕棿鏍煎紡: "success",
+ };
+ return typeMap[type] || "default";
};
- // 鍏抽棴瀵煎叆寮圭獥
- const handleImportClose = () => {
- if (importDialogRef.value) {
- importDialogRef.value.clearFiles();
+ const handleDeleteParam = row => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ鍙傛暟鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getParamList(selectedProcess.value.id);
+ });
+ };
+
+ const handleParamSubmit = () => {
+ if (!selectedParam.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓弬鏁�");
+ return;
}
+ ElMessage.success("娣诲姞鎴愬姛");
+ paramDialogVisible.value = false;
+ getParamList(selectedProcess.value.id);
};
- // 涓嬭浇妯℃澘
- const handleDownloadTemplate = async () => {
- try {
- const res = await downloadTemplate();
- const blob = new Blob([res], {
- type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
- });
- const url = window.URL.createObjectURL(blob);
- const link = document.createElement("a");
- link.href = url;
- link.download = "宸ュ簭瀵煎叆妯℃澘.xlsx";
- link.click();
- window.URL.revokeObjectURL(url);
- proxy.$modal.msgSuccess("妯℃澘涓嬭浇鎴愬姛");
- } catch (error) {
- proxy.$modal.msgError("妯℃澘涓嬭浇澶辫触");
- }
+ const handleParamPagination = obj => {
+ paramPage.current = obj.page;
+ paramPage.size = obj.limit;
+ getParamList(selectedProcess.value.id);
};
- // 瀵煎嚭
- // const handleOut = () => {
- // ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- // confirmButtonText: "纭",
- // cancelButtonText: "鍙栨秷",
- // type: "warning",
- // })
- // .then(() => {
- // proxy.download("/salesLedger/scheduling/exportTwo", {}, "宸ュ簭鎺掍骇.xlsx");
- // })
- // .catch(() => {
- // proxy.$modal.msg("宸插彇娑�");
- // });
- // };
+ // 鑾峰彇鏁版嵁瀛楀吀
+ const getDictTypes = () => {
+ listType({ pageNum: 1, pageSize: 1000 }).then(res => {
+ dictTypes.value = res.rows || [];
+ });
+ };
onMounted(() => {
- getList();
+ getProcessList();
+ getDictTypes();
});
</script>
-<style scoped></style>
+<style scoped lang="scss">
+ .app-container {
+ padding: 20px;
+ background-color: #f0f2f5;
+ min-height: calc(100vh - 84px);
+ }
+
+ .process-config-container {
+ display: flex;
+ gap: 20px;
+ height: calc(100vh - 124px);
+ }
+
+ // 宸︿晶宸ュ簭鍒楄〃
+ .process-list-section {
+ width: 370px;
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ display: flex;
+ flex-direction: column;
+ }
+
+ .section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 16px 20px;
+ border-bottom: 1px solid #ebeef5;
+
+ .section-title {
+ margin: 0;
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ .process-card-list {
+ flex: 1;
+ overflow-y: auto;
+ padding: 16px;
+ }
+
+ .process-card {
+ background: #fff;
+ border: 1px solid #ebeef5;
+ border-radius: 8px;
+ padding: 16px;
+ margin-bottom: 12px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+
+ &:hover {
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ transform: translateY(-2px);
+ }
+
+ &.active {
+ border-color: #409eff;
+ background: #f5f7fa;
+ box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
+ }
+
+ .card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+
+ .process-code {
+ font-size: 12px;
+ color: #909399;
+ font-family: "Courier New", monospace;
+ }
+
+ .card-actions {
+ display: flex;
+ gap: 4px;
+
+ .el-button {
+ padding: 4px;
+ }
+ }
+ }
+
+ .card-body {
+ margin-bottom: 12px;
+
+ .process-name {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+ }
+
+ .process-desc {
+ font-size: 12px;
+ color: #909399;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ }
+
+ .card-footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .param-count {
+ font-size: 12px;
+ color: #606266;
+ }
+ }
+ }
+
+ // 鍙充晶鍙傛暟鍒楄〃
+ .param-list-section {
+ flex: 1;
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ display: flex;
+ flex-direction: column;
+ }
+
+ .param-table-wrapper {
+ flex: 1;
+ padding: 0 20px 20px;
+ overflow: hidden;
+ }
+
+ .empty-tip {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ // 琛ㄦ牸鏍峰紡
+ :deep(.el-table) {
+ border: none;
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-table__header-wrapper {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+
+ th {
+ background: transparent;
+ font-weight: 600;
+ color: #ffffff;
+ border-bottom: none;
+ padding: 16px 0;
+ }
+ }
+
+ .el-table__body-wrapper {
+ tr {
+ transition: all 0.3s ease;
+
+ &:hover {
+ background: linear-gradient(
+ 90deg,
+ rgba(102, 126, 234, 0.05) 0%,
+ rgba(118, 75, 162, 0.05) 100%
+ );
+ }
+
+ td {
+ border-bottom: 1px solid #f0f0f0;
+ padding: 14px 0;
+ color: #303133;
+ }
+ }
+ }
+ }
+
+ // 缂栫爜鍗曞厓鏍兼牱寮�
+ :deep(.code-cell) {
+ color: #e6a23c;
+ font-family: "Courier New", monospace;
+ font-weight: 500;
+ }
+
+ // 鏁板�煎崟鍏冩牸鏍峰紡
+ :deep(.quantity-cell) {
+ font-weight: 600;
+ color: #409eff;
+ font-family: "Courier New", monospace;
+ }
+
+ // 閫夋嫨鍙傛暟瀵硅瘽妗嗘牱寮�
+ .param-select-container {
+ display: flex;
+ gap: 20px;
+ height: 450px;
+
+ .param-list-area {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .search-box {
+ margin-bottom: 12px;
+
+ .el-input {
+ width: 100%;
+ }
+ }
+ }
+
+ .param-detail-area {
+ width: 380px;
+ display: flex;
+ flex-direction: column;
+ background: #f5f7fa;
+ border-radius: 8px;
+ padding: 16px;
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 16px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .param-detail-form {
+ .el-form-item {
+ margin-bottom: 12px;
+
+ .el-form-item__label {
+ color: #606266;
+ font-weight: 500;
+ }
+ }
+
+ .detail-text {
+ color: #303133;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+</style>
--
Gitblit v1.9.3