From f12d684876ffbe90fa95c3113b1e6c4308ae4615 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期一, 20 四月 2026 16:55:33 +0800
Subject: [PATCH] 参数和工序部分
---
src/views/productionManagement/productionProcess/index.vue | 1277 ++++++++++--
/dev/null | 121 -
src/api/productionManagement/processRouteItem.js | 31
src/api/productionManagement/productStructure.js | 28
src/api/productionManagement/productionProcess.js | 64
src/views/productionManagement/processRoute/processRouteItem/index.vue | 2031 +++++++++++++-------
src/api/basicData/parameterMaintenance.js | 81
src/components/ProcessParamListDialog.vue | 656 ++++++
src/views/basicData/parameterMaintenance/index.vue | 790 +++++++
src/components/PIMTable/PIMTable.vue | 854 ++++----
src/api/productionManagement/productProcessRoute.js | 31
11 files changed, 4,416 insertions(+), 1,548 deletions(-)
diff --git a/src/api/basicData/parameterMaintenance.js b/src/api/basicData/parameterMaintenance.js
new file mode 100644
index 0000000..86d889e
--- /dev/null
+++ b/src/api/basicData/parameterMaintenance.js
@@ -0,0 +1,81 @@
+// 鍙傛暟缁存姢椤甸潰鎺ュ彛
+import request from "@/utils/request";
+
+// 鏌ヨ鍙傛暟鍒楄〃
+export function parameterListPage(query) {
+ return request({
+ url: "/basic/parameter/listPage",
+ method: "get",
+ params: query,
+ });
+}
+
+// 鏂板鍙傛暟
+export function addParameter(data) {
+ return request({
+ url: "/basic/parameter/add",
+ method: "post",
+ data: data,
+ });
+}
+
+// 缂栬緫鍙傛暟
+export function updateParameter(data) {
+ return request({
+ url: "/basic/parameter/update",
+ method: "put",
+ data: data,
+ });
+}
+
+// 鍒犻櫎鍙傛暟
+export function delParameter(ids) {
+ return request({
+ url: "/basic/parameter/del",
+ method: "delete",
+ data: Array.isArray(ids) ? ids : [ids],
+ });
+}
+
+// 鑾峰彇浜у搧绫诲瀷鍒楄〃
+export function getProductTypes() {
+ return request({
+ url: "/basic/product/typeList",
+ method: "get",
+ });
+}
+
+// 鏂板鍩虹鍙傛暟
+export function addBaseParam(data) {
+ return request({
+ url: "/technologyParam/add",
+ method: "post",
+ data: data,
+ });
+}
+
+// 缂栬緫鍩虹鍙傛暟
+export function editBaseParam(data) {
+ return request({
+ url: "/technologyParam/edit",
+ method: "put",
+ data: data,
+ });
+}
+
+// 鏌ヨ鍩虹鍙傛暟鍒楄〃
+export function getBaseParamList(query) {
+ return request({
+ url: "/technologyParam/list",
+ method: "get",
+ params: query,
+ });
+}
+
+// 鍒犻櫎鍩虹鍙傛暟
+export function removeBaseParam(ids) {
+ return request({
+ url: `/technologyParam/remove/` + ids,
+ method: "delete",
+ });
+}
diff --git a/src/api/productionManagement/processRouteItem.js b/src/api/productionManagement/processRouteItem.js
index 9e81406..7b66f8f 100644
--- a/src/api/productionManagement/processRouteItem.js
+++ b/src/api/productionManagement/processRouteItem.js
@@ -36,3 +36,34 @@
method: "delete",
});
}
+// 鑾峰彇宸ュ簭鍙傛暟鍒楄〃
+export function getProcessParamList(query) {
+ return request({
+ url: `/ProcessRouteItemParam/pageList`,
+ method: "get",
+ params: query,
+ });
+}
+// 宸ヨ壓璺嚎鍙傛暟鏂板
+export function addProcessRouteItemParam(data) {
+ return request({
+ url: "/ProcessRouteItemParam/save",
+ method: "post",
+ data: data,
+ });
+}
+// 宸ヨ壓璺嚎鍙傛暟淇敼
+export function editProcessRouteItemParam(data) {
+ return request({
+ url: "/ProcessRouteItemParam/edit",
+ method: "put",
+ data: data,
+ });
+}
+// 宸ヨ壓璺嚎鍙傛暟鍒犻櫎
+export function delProcessRouteItemParam(id) {
+ return request({
+ url: `/ProcessRouteItemParam/remove/${id}`,
+ method: "delete",
+ });
+}
diff --git a/src/api/productionManagement/productProcessRoute.js b/src/api/productionManagement/productProcessRoute.js
index e8d5da5..9d13c61 100644
--- a/src/api/productionManagement/productProcessRoute.js
+++ b/src/api/productionManagement/productProcessRoute.js
@@ -52,3 +52,34 @@
data,
});
}
+// 鑾峰彇宸ュ簭鍙傛暟鍒楄〃-鐢熶骇璁㈠崟
+export function findProcessParamListOrder(query) {
+ return request({
+ url: `/productionOrderRouteItemParam/list`,
+ method: "get",
+ params: query,
+ });
+}
+// 宸ヨ壓璺嚎鍙傛暟鏂板-鐢熶骇璁㈠崟
+export function addProcessRouteItemParamOrder(data) {
+ return request({
+ url: "/productionOrderRouteItemParam/add",
+ method: "post",
+ data: data,
+ });
+}
+// 宸ヨ壓璺嚎鍙傛暟淇敼-鐢熶骇璁㈠崟
+export function editProcessRouteItemParamOrder(data) {
+ return request({
+ url: "/productionOrderRouteItemParam/update",
+ method: "put",
+ data: data,
+ });
+}
+// 宸ヨ壓璺嚎鍙傛暟鍒犻櫎-鐢熶骇璁㈠崟
+export function delProcessRouteItemParamOrder(id) {
+ return request({
+ url: `/productionOrderRouteItemParam/delete/${id}`,
+ method: "delete",
+ });
+}
diff --git a/src/api/productionManagement/productStructure.js b/src/api/productionManagement/productStructure.js
index e69e14a..5062e04 100644
--- a/src/api/productionManagement/productStructure.js
+++ b/src/api/productionManagement/productStructure.js
@@ -8,11 +8,33 @@
method: "get",
});
}
-
export function add(data) {
return request({
- url: "/productStructure",
+ url: "/productStructure/" + data.bomId,
method: "post",
- data: data,
+ data: data.children,
+ });
+}
+
+// export function add(data) {
+// return request({
+// url: "/productStructure",
+// method: "post",
+// data: data,
+// });
+// }
+// 鍒嗛〉鏌ヨ-浜у搧璁㈠崟
+export function queryList2(id) {
+ return request({
+ url: "/productionOrderStructure/getBomStructs/" + id,
+ method: "get",
+ });
+}
+
+export function add2(data) {
+ return request({
+ url: "/productionOrderStructure/addOrUpdateBomStructs/" + data.orderId,
+ method: "put",
+ data: data.children,
});
}
diff --git a/src/api/productionManagement/productionProcess.js b/src/api/productionManagement/productionProcess.js
index d3a453c..50f756e 100644
--- a/src/api/productionManagement/productionProcess.js
+++ b/src/api/productionManagement/productionProcess.js
@@ -12,7 +12,7 @@
export function processList(query) {
return request({
- url: "/productProcess/list",
+ url: "/technologyOperation/listPage",
method: "get",
params: query,
});
@@ -20,7 +20,7 @@
export function add(data) {
return request({
- url: "/productProcess",
+ url: "/technologyOperation/",
method: "post",
data: data,
});
@@ -28,26 +28,27 @@
export function del(data) {
return request({
- url: '/productProcess/batchDelete',
- method: 'delete',
+ url: "/technologyOperation/batchDelete",
+ method: "delete",
data: data,
- })
+ });
}
export function update(data) {
return request({
- url: '/productProcess/update',
- method: 'put',
+ url: "/technologyOperation/update",
+ method: "put",
data: data,
- })
+ });
}
// 宸ュ簭鏌ヨ
-export function list() {
- return request({
- url: "/productProcess/list",
- method: "get",
- });
+export function list(query) {
+ return request({
+ url: "/technologyOperation/listPage",
+ method: "get",
+ params: query,
+ });
}
// 瀵煎叆鏁版嵁
@@ -66,4 +67,39 @@
method: "post",
responseType: "blob",
});
-}
\ No newline at end of file
+}
+
+// 鑾峰彇宸ュ簭鍙傛暟鍒楄〃
+export function getProcessParamList(processId, params) {
+ return request({
+ url: `/productProcessParam/list/${processId}`,
+ method: "get",
+ params,
+ });
+}
+
+// 娣诲姞宸ュ簭鍙傛暟
+export function addProcessParam(data) {
+ return request({
+ url: "/productProcessParam/add",
+ method: "post",
+ data: data,
+ });
+}
+
+// 缂栬緫宸ュ簭鍙傛暟
+export function editProcessParam(data) {
+ return request({
+ url: "/productProcessParam/edit",
+ method: "put",
+ data: data,
+ });
+}
+
+// 鍒犻櫎宸ュ簭鍙傛暟
+export function deleteProcessParam(id) {
+ return request({
+ url: `/productProcessParam/${id}`,
+ method: "delete",
+ });
+}
diff --git a/src/components/PIMTable/PIMTable.vue b/src/components/PIMTable/PIMTable.vue
index 2b65817..61df179 100644
--- a/src/components/PIMTable/PIMTable.vue
+++ b/src/components/PIMTable/PIMTable.vue
@@ -1,83 +1,75 @@
<template>
- <el-table
- ref="multipleTable"
- v-loading="tableLoading"
- :border="border"
- :data="tableData"
- :header-cell-style="mergedHeaderCellStyle"
- :height="height"
- :highlight-current-row="highlightCurrentRow"
- :row-class-name="rowClassName"
- :row-style="rowStyle"
- :row-key="rowKey"
- :style="tableStyle"
- tooltip-effect="dark"
- :expand-row-keys="expandRowKeys"
- :show-summary="isShowSummary"
- :summary-method="summaryMethod"
- @row-click="rowClick"
- @current-change="currentChange"
- @selection-change="handleSelectionChange"
- @expand-change="expandChange"
- class="lims-table"
- >
- <el-table-column
- align="center"
- type="selection"
- width="55"
- v-if="isSelection"
- />
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-
- <el-table-column
- v-for="(item, index) in column"
- :key="index"
- :column-key="item.columnKey"
- :filter-method="item.filterHandler"
- :filter-multiple="item.filterMultiple"
- :filtered-value="item.filteredValue"
- :filters="item.filters"
- :fixed="item.fixed"
- :label="item.label"
- :prop="item.prop"
- :show-overflow-tooltip="item.dataType !== 'action' && item.dataType !== 'slot'"
- :align="item.align"
- :sortable="!!item.sortable"
- :type="item.type"
- :width="item.width"
- :minWidth="item.minWidth"
- >
+ <el-table ref="multipleTable"
+ v-loading="tableLoading"
+ :border="border"
+ :data="tableData"
+ :header-cell-style="mergedHeaderCellStyle"
+ :height="height"
+ :highlight-current-row="highlightCurrentRow"
+ :row-class-name="rowClassName"
+ :row-style="rowStyle"
+ :row-key="rowKey"
+ :style="tableStyle"
+ tooltip-effect="dark"
+ :expand-row-keys="expandRowKeys"
+ :show-summary="isShowSummary"
+ :summary-method="summaryMethod"
+ @row-click="rowClick"
+ @current-change="currentChange"
+ @selection-change="handleSelectionChange"
+ @expand-change="expandChange"
+ class="lims-table">
+ <el-table-column align="center"
+ type="selection"
+ width="55"
+ v-if="isSelection" />
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column v-for="(item, index) in column"
+ :key="index"
+ :column-key="item.columnKey"
+ :filter-method="item.filterHandler"
+ :filter-multiple="item.filterMultiple"
+ :filtered-value="item.filteredValue"
+ :filters="item.filters"
+ :fixed="item.fixed"
+ :label="item.label"
+ :prop="item.prop"
+ :show-overflow-tooltip="item.dataType !== 'action' && item.dataType !== 'slot'"
+ :align="item.align"
+ :sortable="!!item.sortable"
+ :type="item.type"
+ :width="item.width"
+ :minWidth="item.minWidth">
<template #header="scope">
- <div class="pim-table-header-cell" :class="{ 'has-extra': item.headerSlot }">
+ <div class="pim-table-header-cell"
+ :class="{ 'has-extra': item.headerSlot }">
<div class="pim-table-header-title">
{{ item.label }}
</div>
- <div v-if="item.headerSlot" class="pim-table-header-extra">
- <slot :name="item.headerSlot" :column="scope.column" />
+ <div v-if="item.headerSlot"
+ class="pim-table-header-extra">
+ <slot :name="item.headerSlot"
+ :column="scope.column" />
</div>
</div>
</template>
- <template
- v-if="item.hasOwnProperty('colunmTemplate')"
- #[item.colunmTemplate]="scope"
- >
- <slot
- v-if="item.theadSlot"
- :name="item.theadSlot"
- :index="scope.$index"
- :row="scope.row"
- />
+ <template v-if="item.hasOwnProperty('colunmTemplate')"
+ #[item.colunmTemplate]="scope">
+ <slot v-if="item.theadSlot"
+ :name="item.theadSlot"
+ :index="scope.$index"
+ :row="scope.row" />
</template>
-
<template #default="scope">
<!-- 鎻掓Ы -->
<div v-if="item.dataType == 'slot'">
- <slot
- v-if="item.slot"
- :index="scope.$index"
- :name="item.slot"
- :row="scope.row"
- />
+ <slot v-if="item.slot"
+ :index="scope.$index"
+ :name="item.slot"
+ :row="scope.row" />
</div>
<!-- 杩涘害鏉� -->
<div v-else-if="item.dataType == 'progress'">
@@ -85,128 +77,111 @@
</div>
<!-- 鍥剧墖 -->
<div v-else-if="item.dataType == 'image'">
- <img
- :src="javaApi + '/img/' + scope.row[item.prop]"
- alt=""
- style="width: 40px; height: 40px; margin-top: 10px"
- />
+ <img :src="javaApi + '/img/' + scope.row[item.prop]"
+ alt=""
+ style="width: 40px; height: 40px; margin-top: 10px" />
</div>
-
<!-- tag -->
<div v-else-if="item.dataType == 'tag'">
- <el-tag
- v-if="
+ <el-tag v-if="
typeof dataTypeFn(scope.row[item.prop], item.formatData) ===
'string'
"
- :title="formatters(scope.row[item.prop], item.formatData)"
- :type="formatType(scope.row[item.prop], item.formatType)"
- >
+ :title="formatters(scope.row[item.prop], item.formatData)"
+ :type="formatType(scope.row[item.prop], item.formatType)">
{{ formatters(scope.row[item.prop], item.formatData) }}
</el-tag>
-
- <el-tag
- v-for="(tag, index) in dataTypeFn(
+ <el-tag v-for="(tag, index) in dataTypeFn(
scope.row[item.prop],
item.formatData
)"
- v-else-if="
+ v-else-if="
typeof dataTypeFn(scope.row[item.prop], item.formatData) ===
'object'
"
- :key="index"
- :title="formatters(scope.row[item.prop], item.formatData)"
- :type="formatType(tag, item.formatType)"
- >
+ :key="index"
+ :title="formatters(scope.row[item.prop], item.formatData)"
+ :type="formatType(tag, item.formatType)">
{{ item.tagGroup ? tag[item.tagGroup.label] ?? tag : tag }}
</el-tag>
-
- <el-tag
- v-else
- :title="formatters(scope.row[item.prop], item.formatData)"
- :type="formatType(scope.row[item.prop], item.formatType)"
- >
+ <el-tag v-else
+ :title="formatters(scope.row[item.prop], item.formatData)"
+ :type="formatType(scope.row[item.prop], item.formatType)">
{{ formatters(scope.row[item.prop], item.formatData) }}
</el-tag>
</div>
-
<!-- 鎸夐挳 -->
- <div v-else-if="item.dataType == 'action'" @click.stop>
- <template v-for="(o, key) in item.operation" :key="key">
- <el-button
- v-show="o.type != 'upload'"
- v-if="o.showHide ? o.showHide(scope.row) : true"
- :disabled="isOperationDisabled(o, scope.row)"
- :plain="o.plain"
- type="primary"
- :style="{
+ <div v-else-if="item.dataType == 'action'"
+ @click.stop>
+ <template v-for="(o, key) in item.operation"
+ :key="key">
+ <el-button v-show="o.type != 'upload'"
+ v-if="o.showHide ? o.showHide(scope.row) : true"
+ :disabled="isOperationDisabled(o, scope.row)"
+ :plain="o.plain"
+ type="primary"
+ :style="{
color: getOperationColor(o, scope.row),
fontWeight: 'bold',
}"
- link
- @click.stop="o.clickFun(scope.row)"
- :key="key"
- >
+ link
+ @click.stop="o.clickFun(scope.row)"
+ :key="key">
{{ o.name }}
</el-button>
- <el-upload
- :action="
+ <el-upload :action="
javaApi +
o.url +
'?id=' +
(o.uploadIdFun ? o.uploadIdFun(scope.row) : scope.row.id)
"
- ref="uploadRef"
- :multiple="o.multiple ? o.multiple : false"
- :limit="1"
- :disabled="isOperationDisabled(o, scope.row)"
- :accept="
+ ref="uploadRef"
+ :multiple="o.multiple ? o.multiple : false"
+ :limit="1"
+ :disabled="isOperationDisabled(o, scope.row)"
+ :accept="
o.accept
? o.accept
: '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
"
- v-if="o.type == 'upload'"
- style="display: inline-block; width: 50px"
- v-show="o.showHide ? o.showHide(scope.row) : true"
- :headers="uploadHeader"
- :before-upload="(file) => beforeUpload(file, scope.$index)"
- :on-change="
+ v-if="o.type == 'upload'"
+ style="display: inline-block; width: 50px"
+ v-show="o.showHide ? o.showHide(scope.row) : true"
+ :headers="uploadHeader"
+ :before-upload="(file) => beforeUpload(file, scope.$index)"
+ :on-change="
(file, fileList) => handleChange(file, fileList, scope.$index)
"
- :on-error="
+ :on-error="
(error, file, fileList) =>
onError(error, file, fileList, scope.$index)
"
- :on-success="
+ :on-success="
(response, file, fileList) =>
handleSuccessUp(response, file, fileList, scope.$index)
"
- :on-exceed="onExceed"
- :show-file-list="false"
- >
- <el-button
- link
- type="primary"
- :disabled="isOperationDisabled(o, scope.row)"
- :style="{
+ :on-exceed="onExceed"
+ :show-file-list="false">
+ <el-button link
+ type="primary"
+ :disabled="isOperationDisabled(o, scope.row)"
+ :style="{
color: getOperationColor(o, scope.row),
- }"
- >{{ o.name }}</el-button
- >
+ }">{{ o.name }}</el-button>
</el-upload>
</template>
</div>
<!-- 鍙偣鍑荤殑鏂囧瓧 -->
- <div
- v-else-if="item.dataType == 'link'"
- class="cell link"
- style="width: 100%"
- @click="goLink(scope.row, item.linkMethod)"
- >
+ <div v-else-if="item.dataType == 'link'"
+ class="cell link"
+ style="width: 100%"
+ @click="goLink(scope.row, item.linkMethod)">
<span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
</div>
<!-- 榛樿绾睍绀烘暟鎹� -->
- <div v-else class="cell" style="width: 100%">
+ <div v-else
+ class="cell"
+ style="width: 100%">
<span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
<span v-else>{{
formatters(scope.row[item.prop], item.formatData)
@@ -215,326 +190,333 @@
</template>
</el-table-column>
</el-table>
- <pagination
- v-if="isShowPagination"
- :total="page.total"
- :layout="page.layout"
- :page="page.current"
- :limit="page.size"
- @pagination="paginationSearch"
- />
+ <pagination v-if="isShowPagination"
+ :total="page.total"
+ :layout="page.layout"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationSearch" />
</template>
<script setup>
-import pagination from "./Pagination.vue";
-import { computed, ref, inject, getCurrentInstance } from "vue";
-import { ElMessage } from "element-plus";
+ import pagination from "./Pagination.vue";
+ import { computed, ref, inject, getCurrentInstance } from "vue";
+ import { ElMessage } from "element-plus";
-// 鑾峰彇鍏ㄥ眬鐨� uploadHeader
-const { proxy } = getCurrentInstance();
-const uploadHeader = proxy.uploadHeader;
-const javaApi = proxy.javaApi;
+ // 鑾峰彇鍏ㄥ眬鐨� uploadHeader
+ const { proxy } = getCurrentInstance();
+ const uploadHeader = proxy.uploadHeader;
+ const javaApi = proxy.javaApi;
-const emit = defineEmits(["pagination", "expand-change", "selection-change", "row-click"]);
+ const emit = defineEmits([
+ "pagination",
+ "expand-change",
+ "selection-change",
+ "row-click",
+ ]);
-// Filters
-const typeFn = (val, row) => {
- return typeof val === "function" ? val(row) : val;
-};
+ // Filters
+ const typeFn = (val, row) => {
+ return typeof val === "function" ? val(row) : val;
+ };
-const formatters = (val, format) => {
- return typeof format === "function" ? format(val) : val;
-};
+ const formatters = (val, format) => {
+ return typeof format === "function" ? format(val) : val;
+ };
-// Props锛堜娇鐢� defineProps 鐨勯潪 TS 褰㈠紡锛�
-const props = defineProps({
- tableLoading: {
- type: Boolean,
- default: false,
- },
- height: {
- type: [Number, String],
- default: "calc(100vh - 22em)",
- },
- expandRowKeys: {
- type: Array,
- default: () => [],
- },
- summaryMethod: {
- type: Function,
- default: () => {},
- },
- rowClick: {
- type: Function,
- default: () => {},
- },
- currentChange: {
- type: Function,
- default: () => {},
- },
- border: {
- type: Boolean,
- default: true,
- },
- isSelection: {
- type: Boolean,
- default: false,
- },
- isShowPagination: {
- type: Boolean,
- default: true,
- },
- isShowSummary: {
- type: Boolean,
- default: false,
- },
- highlightCurrentRow: {
- type: Boolean,
- default: false,
- },
- headerCellStyle: {
- type: Object,
- default: () => ({}),
- },
- column: {
- type: Array,
- default: () => [],
- },
- rowClassName: {
- type: Function,
- default: () => "",
- },
- rowStyle: {
- type: [Object, Function],
- default: () => ({}),
- },
- tableData: {
- type: Array,
- default: () => [],
- },
- rowKey: {
- type: String,
- default: 'id',
- },
- page: {
- type: Object,
- default: () => ({
- total: 0,
- current: 0,
- size: 10,
- layout: "total, sizes, prev, pager, next, jumper",
- }),
- },
- total: {
- type: Number,
- default: 0,
- },
- tableStyle: {
- type: [String, Object],
- default: () => ({ width: "100%" }),
- },
-});
+ // Props锛堜娇鐢� defineProps 鐨勯潪 TS 褰㈠紡锛�
+ const props = defineProps({
+ tableLoading: {
+ type: Boolean,
+ default: false,
+ },
+ height: {
+ type: [Number, String],
+ default: "calc(100vh - 22em)",
+ },
+ expandRowKeys: {
+ type: Array,
+ default: () => [],
+ },
+ summaryMethod: {
+ type: Function,
+ default: () => {},
+ },
+ rowClick: {
+ type: Function,
+ default: () => {},
+ },
+ currentChange: {
+ type: Function,
+ default: () => {},
+ },
+ border: {
+ type: Boolean,
+ default: true,
+ },
+ isSelection: {
+ type: Boolean,
+ default: false,
+ },
+ isShowPagination: {
+ type: Boolean,
+ default: true,
+ },
+ isShowSummary: {
+ type: Boolean,
+ default: false,
+ },
+ highlightCurrentRow: {
+ type: Boolean,
+ default: false,
+ },
+ headerCellStyle: {
+ type: Object,
+ default: () => ({}),
+ },
+ column: {
+ type: Array,
+ default: () => [],
+ },
+ rowClassName: {
+ type: Function,
+ default: () => "",
+ },
+ rowStyle: {
+ type: [Object, Function],
+ default: () => ({}),
+ },
+ tableData: {
+ type: Array,
+ default: () => [],
+ },
+ rowKey: {
+ type: String,
+ default: "id",
+ },
+ page: {
+ type: Object,
+ default: () => ({
+ total: 0,
+ current: 0,
+ size: 10,
+ layout: "total, sizes, prev, pager, next, jumper",
+ }),
+ },
+ total: {
+ type: Number,
+ default: 0,
+ },
+ tableStyle: {
+ type: [String, Object],
+ default: () => ({ width: "100%" }),
+ },
+ });
-const mergedHeaderCellStyle = computed(() => ({
- background: "var(--surface-soft)",
- color: "var(--text-secondary)",
- fontWeight: 600,
- ...props.headerCellStyle,
-}));
+ const mergedHeaderCellStyle = computed(() => ({
+ background: "var(--surface-soft)",
+ color: "var(--text-secondary)",
+ fontWeight: 600,
+ ...props.headerCellStyle,
+ }));
-// Data
-const uploadRefs = ref([]);
-const currentFiles = ref({});
-const uploadKeys = ref({});
+ // Data
+ const uploadRefs = ref([]);
+ const currentFiles = ref({});
+ const uploadKeys = ref({});
-const indexMethod = (index) => {
- return (props.page.current - 1) * props.page.size + index + 1;
-};
+ const indexMethod = index => {
+ return (props.page.current - 1) * props.page.size + index + 1;
+ };
-// 鐐瑰嚮 link 浜嬩欢
-const goLink = (row, linkMethod) => {
- if (!linkMethod) {
- return ElMessage.warning("璇烽厤缃� link 浜嬩欢");
- }
- const parentMethod = getParentMethod(linkMethod);
- if (typeof parentMethod === "function") {
- parentMethod(row);
- } else {
- console.warn(`鐖剁粍浠朵腑鏈壘鍒版柟娉�: ${linkMethod}`);
- }
-};
-
-// 鑾峰彇鐖剁粍浠舵柟娉曪紙绀轰緥瀹炵幇锛�
-const getParentMethod = (methodName) => {
- const parentMethods = inject("parentMethods", {});
- return parentMethods[methodName];
-};
-
-const dataTypeFn = (val, format) => {
- if (typeof format === "function") {
- return format(val);
- } else return val;
-};
-const validTagTypes = ["primary", "success", "info", "warning", "danger"];
-
-const formatType = (val, format) => {
- const type = typeof format === "function" ? format(val) : undefined;
- return validTagTypes.includes(type) ? type : undefined;
-};
-
-const isOperationDisabled = (operation, row) => {
- if (!operation?.disabled) return false;
- return typeof operation.disabled === "function"
- ? !!operation.disabled(row)
- : !!operation.disabled;
-};
-
-const parseHexToRgb = (hex) => {
- const normalized = String(hex || "").trim().replace("#", "");
- if (normalized.length === 3) {
- const r = parseInt(normalized[0] + normalized[0], 16);
- const g = parseInt(normalized[1] + normalized[1], 16);
- const b = parseInt(normalized[2] + normalized[2], 16);
- if ([r, g, b].some((n) => Number.isNaN(n))) return null;
- return { r, g, b };
- }
- if (normalized.length === 6 || normalized.length === 8) {
- const r = parseInt(normalized.slice(0, 2), 16);
- const g = parseInt(normalized.slice(2, 4), 16);
- const b = parseInt(normalized.slice(4, 6), 16);
- if ([r, g, b].some((n) => Number.isNaN(n))) return null;
- return { r, g, b };
- }
- return null;
-};
-
-const fadeColor = (color, alpha = 0.35) => {
- const c = String(color || "").trim();
- if (!c) return undefined;
- if (c.startsWith("#")) {
- const rgb = parseHexToRgb(c);
- if (!rgb) return c;
- return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
- }
- const rgbMatch = c.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*[\d.]+\s*)?\)$/i);
- if (rgbMatch) {
- const r = Number(rgbMatch[1]);
- const g = Number(rgbMatch[2]);
- const b = Number(rgbMatch[3]);
- if ([r, g, b].some((n) => Number.isNaN(n))) return c;
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
- }
- if (c.includes("--el-color-primary")) {
- return "var(--el-color-primary-light-5)";
- }
- if (c.includes("--el-color-danger")) {
- return "var(--el-color-danger-light-5)";
- }
- return "var(--el-text-color-disabled)";
-};
-
-const getOperationColor = (operation, row) => {
- const baseColor =
- operation?.name === "鍒犻櫎" || operation?.name === "delete"
- ? "#D93025"
- : operation?.name === "璇︽儏"
- ? "#67C23A"
- : operation?.color || "var(--el-color-primary)";
-
- if (isOperationDisabled(operation, row)) {
- return fadeColor(baseColor, 0.35);
- }
- return baseColor;
-};
-
-// 鏂囦欢鍙樺寲澶勭悊
-const handleChange = (file, fileList, index) => {
- if (fileList.length > 1) {
- const earliestFile = fileList[0];
- uploadRefs.value[index]?.handleRemove(earliestFile);
- }
- currentFiles.value[index] = file;
-};
-
-// 鏂囦欢涓婁紶鍓嶆牎楠�
-const beforeUpload = (rawFile, index) => {
- currentFiles.value[index] = {};
- if (rawfile.size > 1024 * 1024 * 10 * 10) {
- ElMessage.error("涓婁紶鏂囦欢涓嶈秴杩�10M");
- return false;
- }
- return true;
-};
-
-// 涓婁紶鎴愬姛
-const handleSuccessUp = (response, file, fileList, index) => {
- if (response.code == 200) {
- if (uploadRefs[index]) {
- uploadRefs[index].clearFiles();
+ // 鐐瑰嚮 link 浜嬩欢
+ const goLink = (row, linkMethod) => {
+ if (!linkMethod) {
+ return ElMessage.warning("璇烽厤缃� link 浜嬩欢");
}
- currentFiles[index] = file;
- ElMessage.success("涓婁紶鎴愬姛");
- resetUploadComponent(index);
- } else {
- ElMessage.error(response.message);
- }
-};
+ const parentMethod = getParentMethod(linkMethod);
+ if (typeof parentMethod === "function") {
+ parentMethod(row);
+ } else {
+ console.warn(`鐖剁粍浠朵腑鏈壘鍒版柟娉�: ${linkMethod}`);
+ }
+ };
-const resetUploadComponent = (index) => {
- uploadKeys[index] = Date.now();
-};
+ // 鑾峰彇鐖剁粍浠舵柟娉曪紙绀轰緥瀹炵幇锛�
+ const getParentMethod = methodName => {
+ const parentMethods = inject("parentMethods", {});
+ return parentMethods[methodName];
+ };
-// 涓婁紶澶辫触
-const onError = (error, file, fileList, index) => {
- ElMessage.error("鏂囦欢涓婁紶澶辫触锛岃閲嶈瘯");
- if (uploadRefs.value[index]) {
- uploadRefs.value[index].clearFiles();
- }
-};
+ const dataTypeFn = (val, format) => {
+ if (typeof format === "function") {
+ return format(val);
+ } else return val;
+ };
+ const validTagTypes = ["primary", "success", "info", "warning", "danger"];
-// 鏂囦欢鏁伴噺瓒呴檺鎻愮ず
-const onExceed = () => {
- ElMessage.warning("瓒呭嚭鏂囦欢涓暟");
-};
+ const formatType = (val, format) => {
+ const type = typeof format === "function" ? format(val) : undefined;
+ return validTagTypes.includes(type) ? type : undefined;
+ };
-const paginationSearch = ({ page, limit }) => {
- emit("pagination", { page: page, limit: limit });
-};
+ const isOperationDisabled = (operation, row) => {
+ if (!operation?.disabled) return false;
+ return typeof operation.disabled === "function"
+ ? !!operation.disabled(row)
+ : !!operation.disabled;
+ };
-const rowClick = (row) => {
- emit("row-click", row);
-};
+ const parseHexToRgb = hex => {
+ const normalized = String(hex || "")
+ .trim()
+ .replace("#", "");
+ if (normalized.length === 3) {
+ const r = parseInt(normalized[0] + normalized[0], 16);
+ const g = parseInt(normalized[1] + normalized[1], 16);
+ const b = parseInt(normalized[2] + normalized[2], 16);
+ if ([r, g, b].some(n => Number.isNaN(n))) return null;
+ return { r, g, b };
+ }
+ if (normalized.length === 6 || normalized.length === 8) {
+ const r = parseInt(normalized.slice(0, 2), 16);
+ const g = parseInt(normalized.slice(2, 4), 16);
+ const b = parseInt(normalized.slice(4, 6), 16);
+ if ([r, g, b].some(n => Number.isNaN(n))) return null;
+ return { r, g, b };
+ }
+ return null;
+ };
-const expandChange = (row, expandedRows) => {
- emit("expand-change", row, expandedRows);
-};
+ const fadeColor = (color, alpha = 0.35) => {
+ const c = String(color || "").trim();
+ if (!c) return undefined;
+ if (c.startsWith("#")) {
+ const rgb = parseHexToRgb(c);
+ if (!rgb) return c;
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
+ }
+ const rgbMatch = c.match(
+ /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*[\d.]+\s*)?\)$/i
+ );
+ if (rgbMatch) {
+ const r = Number(rgbMatch[1]);
+ const g = Number(rgbMatch[2]);
+ const b = Number(rgbMatch[3]);
+ if ([r, g, b].some(n => Number.isNaN(n))) return c;
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
+ }
+ if (c.includes("--el-color-primary")) {
+ return "var(--el-color-primary-light-5)";
+ }
+ if (c.includes("--el-color-danger")) {
+ return "var(--el-color-danger-light-5)";
+ }
+ return "var(--el-text-color-disabled)";
+ };
-const handleSelectionChange = (newSelection) => {
- emit("selection-change", newSelection);
-};
+ const getOperationColor = (operation, row) => {
+ const baseColor =
+ operation?.name === "鍒犻櫎" || operation?.name === "delete"
+ ? "#D93025"
+ : operation?.name === "璇︽儏"
+ ? "#67C23A"
+ : operation?.color || "var(--el-color-primary)";
+
+ if (isOperationDisabled(operation, row)) {
+ return fadeColor(baseColor, 0.35);
+ }
+ return baseColor;
+ };
+
+ // 鏂囦欢鍙樺寲澶勭悊
+ const handleChange = (file, fileList, index) => {
+ if (fileList.length > 1) {
+ const earliestFile = fileList[0];
+ uploadRefs.value[index]?.handleRemove(earliestFile);
+ }
+ currentFiles.value[index] = file;
+ };
+
+ // 鏂囦欢涓婁紶鍓嶆牎楠�
+ const beforeUpload = (rawFile, index) => {
+ currentFiles.value[index] = {};
+ if (rawfile.size > 1024 * 1024 * 10 * 10) {
+ ElMessage.error("涓婁紶鏂囦欢涓嶈秴杩�10M");
+ return false;
+ }
+ return true;
+ };
+
+ // 涓婁紶鎴愬姛
+ const handleSuccessUp = (response, file, fileList, index) => {
+ if (response.code == 200) {
+ if (uploadRefs[index]) {
+ uploadRefs[index].clearFiles();
+ }
+ currentFiles[index] = file;
+ ElMessage.success("涓婁紶鎴愬姛");
+ resetUploadComponent(index);
+ } else {
+ ElMessage.error(response.message);
+ }
+ };
+
+ const resetUploadComponent = index => {
+ uploadKeys[index] = Date.now();
+ };
+
+ // 涓婁紶澶辫触
+ const onError = (error, file, fileList, index) => {
+ ElMessage.error("鏂囦欢涓婁紶澶辫触锛岃閲嶈瘯");
+ if (uploadRefs.value[index]) {
+ uploadRefs.value[index].clearFiles();
+ }
+ };
+
+ // 鏂囦欢鏁伴噺瓒呴檺鎻愮ず
+ const onExceed = () => {
+ ElMessage.warning("瓒呭嚭鏂囦欢涓暟");
+ };
+
+ const paginationSearch = ({ page, limit }) => {
+ emit("pagination", { page: page, limit: limit });
+ };
+
+ const rowClick = row => {
+ emit("row-click", row);
+ };
+
+ const expandChange = (row, expandedRows) => {
+ emit("expand-change", row, expandedRows);
+ };
+
+ const handleSelectionChange = newSelection => {
+ emit("selection-change", newSelection);
+ };
</script>
<style scoped lang="scss">
-.lims-table {
- border: 1px solid var(--surface-border);
- border-radius: 18px;
- background: rgba(255, 255, 255, 0.9);
-}
+ .lims-table {
+ border: 1px solid var(--surface-border);
+ border-radius: 18px;
+ background: rgba(255, 255, 255, 0.9);
+ }
-.cell {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- padding-right: 0 !important;
- padding-left: 0 !important;
-}
+ .cell {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ padding-right: 0 !important;
+ padding-left: 0 !important;
+ }
-.pim-table-header-extra :deep(.el-input),
-.pim-table-header-extra :deep(.el-select) {
- width: 100%;
-}
+ .pim-table-header-extra :deep(.el-input),
+ .pim-table-header-extra :deep(.el-select) {
+ width: 100%;
+ }
-.pim-table-header-title {
- font-weight: 600;
-}
+ .pim-table-header-title {
+ font-weight: 600;
+ }
</style>
diff --git a/src/components/ProcessParamListDialog.vue b/src/components/ProcessParamListDialog.vue
new file mode 100644
index 0000000..c835f29
--- /dev/null
+++ b/src/components/ProcessParamListDialog.vue
@@ -0,0 +1,656 @@
+<template>
+ <el-dialog v-model="visible"
+ :title="title"
+ width="800px"
+ destroy-on-close>
+ <div class="param-list-container">
+ <div class="params-header">
+ <span>鍙傛暟鍒楄〃</span>
+ <el-button v-if="editable"
+ type="primary"
+ link
+ size="small"
+ @click="handleAddParam">
+ <el-icon>
+ <Plus />
+ </el-icon>鏂板
+ </el-button>
+ </div>
+ <div class="params-list">
+ <div v-for="param in paramList"
+ :key="param.id"
+ class="param-item">
+ <div class="param-info">
+ <span class="param-code">{{ param.paramName }}</span>
+ <span class="param-value">
+ 鏍囧噯鍊硷細{{ param.standardValue || "-" }} {{ param.unit }}
+ </span>
+ </div>
+ <div class="param-actions">
+ <el-button v-if="editable"
+ link
+ type="primary"
+ size="small"
+ @click="handleEditParam(param)">
+ 缂栬緫
+ </el-button>
+ <el-button v-if="editable"
+ link
+ type="danger"
+ size="small"
+ @click="handleDeleteParam(param)">
+ 鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ <el-empty v-if="!paramList || paramList.length === 0"
+ description="鏆傛棤鍙傛暟"
+ :image-size="50" />
+ </div>
+ </div>
+ <!-- 閫夋嫨鍙傛暟瀵硅瘽妗� -->
+ <el-dialog v-model="selectParamDialogVisible"
+ 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="getBaseParamListData">
+ <template #prefix>
+ <el-icon>
+ <Search />
+ </el-icon>
+ </template>
+ </el-input>
+ </div>
+ <el-table :data="filteredParamList"
+ height="400"
+ border
+ highlight-current-row
+ @current-change="handleSelectParam">
+ <el-table-column prop="paramName"
+ label="鍙傛暟鍚嶇О" />
+ <el-table-column prop="paramType"
+ label="鍙傛暟绫诲瀷">
+ <template #default="scope">
+ <el-tag size="small"
+ :type="getParamTypeTag(scope.row.paramType)">{{ getParamTypeText(scope.row.paramType) }}</el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ <!-- 鍒嗛〉鎺т欢 -->
+ <div class="pagination-container"
+ style="margin-top: 10px;">
+ <el-pagination v-model:current-page="paramPage.current"
+ v-model:page-size="paramPage.size"
+ :page-sizes="[10, 20, 50, 100]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="paramPage.total"
+ @size-change="getBaseParamListData"
+ @current-change="getBaseParamListData"
+ size="small" />
+ </div>
+ </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.paramName }}</span>
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷">
+ <el-tag size="small"
+ :type="getParamTypeTag(selectedParam.paramType)">{{ getParamTypeText(selectedParam.paramType) }}</el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟鏍煎紡">
+ <span class="detail-text">{{ selectedParam.paramFormat || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鍗曚綅">
+ <span class="detail-text">{{ selectedParam.unit || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�"
+ v-if="selectedParam.paramType == '1'">
+ <el-input v-model="selectedParam.standardValue"
+ type="number"
+ placeholder="璇疯緭鍏ラ粯璁ゅ��" />
+ </el-form-item>
+ <el-form-item label="鎺掑簭">
+ <el-input v-model="selectedParam.sort"
+ type="number"
+ placeholder="璇疯緭鍏ユ帓搴�" />
+ </el-form-item>
+ <el-form-item label="鏄惁蹇呭~">
+ <el-switch :active-value="true"
+ :inactive-value="false"
+ v-model="selectedParam.isRequired" />
+ </el-form-item>
+ </el-form>
+ <el-empty v-else
+ description="璇蜂粠宸︿晶閫夋嫨鍙傛暟"
+ :image-size="100" />
+ </div>
+ </div>
+ <template #footer>
+ <el-button @click="selectParamDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleParamSelectSubmit">纭畾</el-button>
+ </template>
+ </el-dialog>
+ <!-- 缂栬緫鍙傛暟瀵硅瘽妗� -->
+ <el-dialog v-model="editParamDialogVisible"
+ title="缂栬緫鍙傛暟"
+ width="600px">
+ <el-form :model="editParamForm"
+ :rules="editParamRules"
+ ref="editParamFormRef"
+ label-width="120px">
+ <el-form-item label="鍙傛暟鍚嶇О">
+ <span class="detail-text">{{ editParamForm.paramName }}</span>
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷">
+ <el-tag size="small"
+ :type="getParamTypeTag(editParamForm.paramType)">
+ {{ getParamTypeText(editParamForm.paramType) }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟鏍煎紡">
+ <span class="detail-text">{{ editParamForm.paramFormat || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鍗曚綅">
+ <span class="detail-text">{{ editParamForm.unit || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�"
+ v-if="editParamForm.paramType == '1'"
+ prop="standardValue">
+ <el-input v-model="editParamForm.standardValue"
+ type="number"
+ placeholder="璇疯緭鍏ユ爣鍑嗗��" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <el-button @click="editParamDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleEditParamSubmit">纭畾</el-button>
+ </template>
+ </el-dialog>
+ </el-dialog>
+</template>
+
+<script setup>
+ import { ref, computed, watch } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import { Plus, Search } from "@element-plus/icons-vue";
+ import {
+ delProcessRouteItemParam,
+ editProcessRouteItemParam,
+ addProcessRouteItemParam,
+ } from "@/api/productionManagement/processRouteItem.js";
+ import {
+ addProcessRouteItemParamOrder,
+ delProcessRouteItemParamOrder,
+ editProcessRouteItemParamOrder,
+ } from "@/api/productionManagement/productProcessRoute.js";
+
+ import { getBaseParamList } from "@/api/basicData/parameterMaintenance.js";
+
+ const props = defineProps({
+ modelValue: {
+ type: Boolean,
+ default: false,
+ },
+ title: {
+ type: String,
+ default: "鍙傛暟鍒楄〃",
+ },
+ routeId: {
+ type: Number,
+ default: 0,
+ },
+ process: {
+ type: Object,
+ default: () => ({}),
+ },
+ paramList: {
+ type: Array,
+ default: () => [],
+ },
+ editable: {
+ type: Boolean,
+ default: true,
+ },
+ orderId: {
+ type: Number,
+ default: 0,
+ },
+ pageType: {
+ type: String,
+ default: "route",
+ },
+ });
+
+ const emit = defineEmits(["update:modelValue", "refresh"]);
+
+ const visible = computed({
+ get: () => props.modelValue,
+ set: value => emit("update:modelValue", value),
+ });
+
+ // 鍝嶅簲寮忔暟鎹�
+ const selectParamDialogVisible = ref(false);
+ const editParamDialogVisible = ref(false);
+ const paramSearchKeyword = ref("");
+ const selectedParam = ref(null);
+ const filteredParamList = ref([]);
+ const paramPage = ref({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+ const editParamForm = ref({
+ id: null,
+ processId: null,
+ paramId: null,
+ paramName: "",
+ standardValue: null,
+ sort: 1,
+ isRequired: false,
+ paramType: null,
+ paramFormat: "",
+ unit: "",
+ });
+ const editParamRules = ref({
+ standardValue: [{ required: true, message: "璇疯緭鍏ユ爣鍑嗗��", trigger: "blur" }],
+ });
+ const editParamFormRef = ref(null);
+
+ // 鏂板鍙傛暟
+ const handleAddParam = () => {
+ selectedParam.value = null;
+ paramSearchKeyword.value = "";
+ paramPage.current = 1;
+ // 鑾峰彇鍙�夊弬鏁板垪琛�
+ getBaseParamListData();
+ selectParamDialogVisible.value = true;
+ };
+
+ // 缂栬緫鍙傛暟
+ const handleEditParam = param => {
+ editParamForm.value = {
+ id: param.id,
+ processId: props.process.id,
+ paramId: param.paramId,
+ paramName: param.parameterName || param.paramName,
+ standardValue: param.standardValue,
+ sort: param.sort || 1,
+ isRequired: param.isRequired || false,
+ paramType: param.parameterType || param.paramType,
+ paramFormat: param.parameterFormat || param.paramFormat,
+ unit: param.unit || param.unit,
+ };
+ editParamDialogVisible.value = true;
+ };
+
+ // 鍒犻櫎鍙傛暟
+ const handleDeleteParam = param => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ鍙傛暟鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ // 璋冪敤API鍒犻櫎鍙傛暟
+ if (props.pageType === "order") {
+ delProcessRouteItemParamOrder(param.id)
+ .then(res => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ emit("refresh");
+ })
+ .catch(err => {
+ ElMessage.error("鍒犻櫎鍙傛暟澶辫触");
+ console.error("鍒犻櫎鍙傛暟澶辫触锛�", err);
+ });
+ } else {
+ delProcessRouteItemParam(param.id)
+ .then(res => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ emit("refresh");
+ })
+ .catch(err => {
+ ElMessage.error("鍒犻櫎鍙傛暟澶辫触");
+ console.error("鍒犻櫎鍙傛暟澶辫触锛�", err);
+ });
+ }
+ })
+ .catch(() => {});
+ };
+
+ // 鑾峰彇鍙�夊弬鏁板垪琛�
+ const getBaseParamListData = () => {
+ getBaseParamList({
+ paramName: paramSearchKeyword.value,
+ current: paramPage.current,
+ size: paramPage.size,
+ }).then(res => {
+ if (res.code === 200) {
+ filteredParamList.value = res.data?.records || [];
+ paramPage.total = res.data?.total || 0;
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ });
+ };
+
+ // 閫夋嫨鍙傛暟
+ const handleSelectParam = param => {
+ selectedParam.value = param;
+ };
+
+ // 鎻愪氦閫夋嫨鍙傛暟
+ const handleParamSelectSubmit = () => {
+ if (!selectedParam.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓弬鏁�");
+ return;
+ }
+
+ if (!props.process || !props.process.id) {
+ ElMessage.error("宸ヨ壓璺嚎椤圭洰淇℃伅涓嶅畬鏁�");
+ return;
+ }
+
+ // 鍒ゆ柇鍙傛暟绫诲瀷锛屽彧鏈夋暟鍊肩被鍨嬫墠浼犳爣鍑嗗�笺�佹渶澶у�煎拰鏈�灏忓��
+ const isNumericMode = selectedParam.value.paramType == 1;
+ console.log(isNumericMode, "isNumericMode");
+ // 璋冪敤API鏂板鍙傛暟
+ if (props.pageType === "order") {
+ addProcessRouteItemParamOrder({
+ orderId: Number(props.orderId),
+ // processId: props.process.id,
+ routeItemId: props.process.id,
+ // routeItemId: Number(props.routeId),
+ paramId: selectedParam.value.id,
+ standardValue: isNumericMode
+ ? selectedParam.value.standardValue || ""
+ : "",
+ isRequired: selectedParam.value.isRequired || false,
+ sort: selectedParam.value.sort || 1,
+ })
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("娣诲姞鍙傛暟鎴愬姛");
+ selectParamDialogVisible.value = false;
+ emit("refresh");
+ } else {
+ ElMessage.error(res.msg || "娣诲姞鍙傛暟澶辫触");
+ }
+ })
+ .catch(err => {
+ ElMessage.error("娣诲姞鍙傛暟澶辫触");
+ console.error("娣诲姞鍙傛暟澶辫触锛�", err);
+ });
+ } else {
+ addProcessRouteItemParam({
+ routeItemId: props.process.id,
+ paramId: selectedParam.value.id,
+ standardValue: isNumericMode
+ ? selectedParam.value.standardValue || ""
+ : "",
+ isRequired: selectedParam.value.isRequired || false,
+ sort: selectedParam.value.sort || 1,
+ })
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("娣诲姞鍙傛暟鎴愬姛");
+ selectParamDialogVisible.value = false;
+ emit("refresh");
+ } else {
+ ElMessage.error(res.msg || "娣诲姞鍙傛暟澶辫触");
+ }
+ })
+ .catch(err => {
+ ElMessage.error("娣诲姞鍙傛暟澶辫触");
+ console.error("娣诲姞鍙傛暟澶辫触锛�", err);
+ });
+ }
+ };
+
+ // 鎻愪氦缂栬緫鍙傛暟
+ const handleEditParamSubmit = () => {
+ if (!editParamFormRef.value) return;
+ editParamFormRef.value.validate(valid => {
+ if (valid) {
+ // 鍒ゆ柇鍙傛暟绫诲瀷锛屽彧鏈夋暟鍊肩被鍨嬫墠浼犳爣鍑嗗�笺�佹渶澶у�煎拰鏈�灏忓��
+ const isNumericMode = editParamForm.value.paramType == 1;
+ console.log(isNumericMode, "isNumericMode");
+ if (props.pageType === "order") {
+ editProcessRouteItemParamOrder({
+ id: editParamForm.value.id,
+ // routeItemId: props.process.id,
+ // paramId: editParamForm.value.paramId,
+ standardValue: isNumericMode
+ ? editParamForm.value.standardValue || ""
+ : "",
+ isRequired: editParamForm.value.isRequired || false,
+ })
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("缂栬緫鎴愬姛");
+ editParamDialogVisible.value = false;
+ emit("refresh");
+ } else {
+ ElMessage.error(res.msg || "缂栬緫澶辫触");
+ }
+ })
+ .catch(err => {
+ ElMessage.error("缂栬緫鍙傛暟澶辫触");
+ console.error("缂栬緫鍙傛暟澶辫触锛�", err);
+ });
+ } else {
+ // 璋冪敤API淇敼鍙傛暟
+ editProcessRouteItemParam({
+ id: editParamForm.value.id,
+ routeItemId: props.process.id,
+ paramId: editParamForm.value.paramId,
+ standardValue: isNumericMode
+ ? editParamForm.value.standardValue || ""
+ : "",
+ isRequired: editParamForm.value.isRequired || false,
+ })
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("缂栬緫鎴愬姛");
+ editParamDialogVisible.value = false;
+ emit("refresh");
+ } else {
+ ElMessage.error(res.msg || "缂栬緫澶辫触");
+ }
+ })
+ .catch(err => {
+ ElMessage.error("缂栬緫鍙傛暟澶辫触");
+ console.error("缂栬緫鍙傛暟澶辫触锛�", err);
+ });
+ }
+ }
+ });
+ };
+
+ // 鑾峰彇鍙傛暟绫诲瀷鏍囩
+ const getParamTypeTag = type => {
+ const typeMap = {
+ 1: "primary",
+ 2: "info",
+ 3: "warning",
+ 4: "success",
+ };
+ return typeMap[type] || "default";
+ };
+
+ // 鑾峰彇鍙傛暟绫诲瀷鏂囨湰
+ const getParamTypeText = type => {
+ const typeMap = {
+ 1: "鏁板�兼牸寮�",
+ 2: "鏂囨湰鏍煎紡",
+ 3: "涓嬫媺閫夐」",
+ 4: "鏃堕棿鏍煎紡",
+ };
+ return typeMap[type] || type;
+ };
+
+ watch(
+ () => props.modelValue,
+ newVal => {
+ if (!newVal) {
+ // 寮圭獥鍏抽棴鏃堕噸缃暟鎹�
+ selectParamDialogVisible.value = false;
+ editParamDialogVisible.value = false;
+ selectedParam.value = null;
+ paramSearchKeyword.value = "";
+ paramPage.current = 1;
+ filteredParamList.value = [];
+ editParamForm.value = {
+ id: null,
+ processId: null,
+ paramId: null,
+ paramName: "",
+ standardValue: null,
+ sort: 1,
+ isRequired: false,
+ paramType: null,
+ paramFormat: "",
+ unit: "",
+ };
+ }
+ }
+ );
+</script>
+
+<style scoped>
+ .param-list-container {
+ padding: 10px 0;
+ }
+
+ .params-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #e4e7ed;
+ }
+
+ .params-header span {
+ font-size: 16px;
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .params-list {
+ max-height: 400px;
+ overflow-y: auto;
+ }
+
+ .param-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 12px 16px;
+ margin-bottom: 8px;
+ background-color: #f9f9f9;
+ border-radius: 4px;
+ transition: all 0.3s ease;
+ }
+
+ .param-item:hover {
+ background-color: #ecf5ff;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ }
+
+ .param-info {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ flex: 1;
+ }
+
+ .param-code {
+ font-weight: 500;
+ color: #303133;
+ min-width: 120px;
+ }
+
+ .param-value {
+ color: #606266;
+ font-size: 14px;
+ }
+
+ .param-actions {
+ display: flex;
+ gap: 10px;
+ }
+
+ /* 婊氬姩鏉℃牱寮� */
+ .params-list::-webkit-scrollbar {
+ width: 6px;
+ }
+
+ .params-list::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 3px;
+ }
+
+ .params-list::-webkit-scrollbar-thumb {
+ background: #c1c1c1;
+ border-radius: 3px;
+ }
+
+ .params-list::-webkit-scrollbar-thumb:hover {
+ background: #a8a8a8;
+ }
+
+ /* 閫夋嫨鍙傛暟瀵硅瘽妗嗘牱寮� */
+ .param-select-container {
+ display: flex;
+ gap: 20px;
+ }
+
+ .param-list-area {
+ flex: 1;
+ min-width: 400px;
+ }
+
+ .param-detail-area {
+ flex: 1;
+ min-width: 300px;
+ }
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 500;
+ margin-bottom: 10px;
+ color: #303133;
+ }
+
+ .search-box {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 10px;
+ }
+
+ .param-detail-form {
+ background: #f9f9f9;
+ padding: 15px;
+ border-radius: 4px;
+ }
+
+ .detail-text {
+ font-weight: 500;
+ }
+</style>
\ No newline at end of file
diff --git a/src/views/basicData/parameterMaintenance/index.vue b/src/views/basicData/parameterMaintenance/index.vue
new file mode 100644
index 0000000..63b52e9
--- /dev/null
+++ b/src/views/basicData/parameterMaintenance/index.vue
@@ -0,0 +1,790 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title ml10">鍙傛暟鍚嶇О锛�</span>
+ <el-input v-model="searchForm.paramName"
+ style="width: 200px"
+ placeholder="璇疯緭鍏ュ弬鏁板悕绉�"
+ clearable />
+ <!-- 鍏宠仈浜у搧绫诲瀷鎼滅储 -->
+ <!-- <span class="search_title ml10">鍏宠仈浜у搧绫诲瀷锛�</span>
+ <el-input v-model="searchForm.productName"
+ style="width: 200px"d
+ placeholder="璇疯緭鍏ュ叧鑱斾骇鍝佺被鍨�"
+ clearable /> -->
+ <el-button type="primary"
+ @click="handleQuery"
+ style="margin-left: 10px">鎼滅储</el-button>
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ <el-button type="primary"
+ @click="handleAdd"
+ style="margin-left: 10px">鏂板鍙傛暟</el-button>
+ <!-- 浜у搧绫诲瀷缁存姢鎸夐挳 -->
+ <!-- <el-button type="primary"
+ @click="handleProductTypeMaintenance"
+ style="margin-left: 10px">浜у搧绫诲瀷缁存姢</el-button> -->
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable rowKey="paramName"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ height="calc(100vh - 320px)"
+ :tableLoading="tableLoading"
+ :isSelection="false"
+ :isShowPagination="true"
+ @pagination="pagination">
+ </PIMTable>
+ </div>
+ <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="dialogVisible"
+ :title="dialogTitle"
+ width="500px">
+ <el-form :model="formData"
+ :rules="rules"
+ ref="formRef"
+ label-width="120px">
+ <el-form-item label="鍙傛暟缂栫爜"
+ prop="paramCode">
+ <el-input v-model="formData.paramCode"
+ disabled
+ placeholder="鑷姩鐢熸垚" />
+ </el-form-item>
+ <el-form-item label="鍙傛暟鍚嶇О"
+ prop="paramName">
+ <el-input v-model="formData.paramName"
+ placeholder="璇疯緭鍏ュ弬鏁板悕绉�" />
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷"
+ prop="paramType">
+ <el-select v-model="formData.paramType"
+ @change="handleParamTypeChange"
+ placeholder="璇烽�夋嫨鍙傛暟绫诲瀷">
+ <el-option label="鏁板�兼牸寮�"
+ :value="1" />
+ <el-option label="鏂囨湰鏍煎紡"
+ :value="2" />
+ <el-option label="涓嬫媺閫夐」"
+ :value="3" />
+ <el-option label="鏃堕棿鏍煎紡"
+ :value="4" />
+ </el-select>
+ </el-form-item>
+ <!-- <el-form-item label="鍙栧�兼ā寮�"
+ prop="valueMode">
+ <el-select v-model="formData.valueMode"
+ placeholder="璇烽�夋嫨鍙栧�兼ā寮�">
+ <el-option label="鍗曞��"
+ value="1" />
+ <el-option label="鍖洪棿"
+ value="2" />
+ </el-select>
+ </el-form-item> -->
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="formData.unit"
+ placeholder="璇疯緭鍏ュ崟浣�" />
+ </el-form-item>
+ <el-form-item label="鍙栧�兼牸寮�"
+ v-if="formData.paramType == 1 || formData.paramType == 2"
+ prop="paramFormat">
+ <el-input v-model="formData.paramFormat"
+ placeholder="璇疯緭鍏ュ彇鍊兼牸寮�" />
+ <!-- <el-select v-model="formData.paramFormat"
+ placeholder="璇烽�夋嫨鍙栧�兼ā寮�">
+ <el-option label="#.00000"
+ value="#.00000" />
+ <el-option label="#.0000"
+ value="#.0000" />
+ <el-option label="#.000"
+ value="#.000" />
+ <el-option label="#.00"
+ value="#.00" />
+ </el-select> -->
+ </el-form-item>
+ <el-form-item label="涓嬫媺瀛楀吀"
+ v-else-if="formData.paramType == 3"
+ prop="paramFormat">
+ <el-select v-model="formData.paramFormat"
+ 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 label="鏃堕棿鏍煎紡"
+ v-else-if="formData.paramType == 4"
+ prop="paramFormat">
+ <el-select v-model="formData.paramFormat"
+ placeholder="璇烽�夋嫨鍙栧�兼ā寮�">
+ <el-option label="YYYY-MM-DD"
+ value="YYYY-MM-DD" />
+ <el-option label="YYYY-MM-DD HH:mm:ss"
+ value="YYYY-MM-DD HH:mm:ss" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏄惁蹇呭~"
+ prop="isRequired">
+ <el-switch v-model="formData.isRequired"
+ :active-value="1"
+ :inactive-value="0" />
+ </el-form-item>
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="formData.remark"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ュ娉�" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 浜у搧绫诲瀷缁存姢瀵硅瘽妗� -->
+ <!-- <el-dialog v-model="productTypeDialogVisible"
+ title="浜у搧绫诲瀷缁存姢"
+ width="600px">
+ <div class="product-type-header">
+ <el-button type="primary"
+ @click="handleAddProductType">鏂板浜у搧绫诲瀷</el-button>
+ </div>
+ <el-table :data="productTypeList"
+ border
+ style="width: 100%; margin-top: 10px; margin-bottom: 20px">
+ <el-table-column prop="typeCode"
+ label="绫诲瀷缂栫爜"
+ width="150" />
+ <el-table-column prop="typeName"
+ label="绫诲瀷鍚嶇О" />
+ <el-table-column label="鎿嶄綔"
+ width="150">
+ <template #default="scope">
+ <el-button link
+ type="primary"
+ @click="handleEditProductType(scope.row)">缂栬緫</el-button>
+ <el-button link
+ type="danger"
+ @click="handleDeleteProductType(scope.row)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-dialog> -->
+ <!-- 鏂板/缂栬緫浜у搧绫诲瀷瀵硅瘽妗� -->
+ <!-- <el-dialog v-model="productTypeFormVisible"
+ :title="productTypeDialogTitle"
+ width="400px">
+ <el-form :model="productTypeForm"
+ :rules="productTypeRules"
+ ref="productTypeFormRef"
+ label-width="100px">
+ <el-form-item label="绫诲瀷缂栫爜"
+ prop="typeCode">
+ <el-input v-model="productTypeForm.typeCode"
+ placeholder="璇疯緭鍏ョ被鍨嬬紪鐮�" />
+ </el-form-item>
+ <el-form-item label="绫诲瀷鍚嶇О"
+ prop="typeName">
+ <el-input v-model="productTypeForm.typeName"
+ placeholder="璇疯緭鍏ョ被鍨嬪悕绉�" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="productTypeFormVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleProductTypeSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog> -->
+ </div>
+</template>
+
+<script setup>
+ import { onMounted, ref, reactive } from "vue";
+ import {
+ parameterListPage,
+ addParameter,
+ updateParameter,
+ delParameter,
+ addBaseParam,
+ editBaseParam,
+ getBaseParamList,
+ removeBaseParam,
+ // getProductTypes as getProductTypesApi,
+ } from "@/api/basicData/parameterMaintenance.js";
+ import { listType } from "@/api/system/dict/type";
+ import { deptTreeSelect } from "@/api/system/user.js";
+ import PIMTable from "@/components/PIMTable/PIMTable.vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+
+ const tableColumn = ref([
+ {
+ label: "鍙傛暟缂栫爜",
+ prop: "paramCode",
+ },
+ {
+ label: "鍙傛暟鍚嶇О",
+ prop: "paramName",
+ },
+ {
+ label: "鍙傛暟绫诲瀷",
+ prop: "paramType",
+ dataType: "tag",
+ formatType: params => {
+ const typeMap = {
+ 1: "primary",
+ 2: "info",
+ 3: "warning",
+ 4: "success",
+ };
+ return typeMap[params] || "default";
+ },
+ formatData: val => {
+ const labelMap = {
+ 1: "鏁板�兼牸寮�",
+ 2: "鏂囨湰鏍煎紡",
+ 3: "涓嬫媺閫夐」",
+ 4: "鏃堕棿鏍煎紡",
+ };
+ return labelMap[val] || val;
+ },
+ },
+ // {
+ // label: "鍙栧�兼ā寮�",
+ // prop: "valueMode",
+ // dataType: "tag",
+ // formatType: params => {
+ // return params === 2 ? "warning" : "success";
+ // },
+ // formatData: val => {
+ // return val === 2 ? "鍖洪棿" : "鍗曞��";
+ // },
+ // },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鍙栧�兼牸寮�",
+ prop: "paramFormat",
+ },
+ {
+ label: "鏄惁蹇呭~",
+ prop: "isRequired",
+ dataType: "tag",
+ formatType: val => {
+ return val === 1 ? "success" : "info";
+ },
+ formatData: val => {
+ return val === 1 ? "鏄�" : "鍚�";
+ },
+ },
+ {
+ label: "澶囨敞",
+ prop: "remark",
+ },
+ {
+ label: "鍒涘缓鏃堕棿",
+ prop: "createTime",
+ },
+ {
+ label: "鎿嶄綔",
+ dataType: "action",
+ width: "150",
+ operation: [
+ {
+ name: "缂栬緫",
+ clickFun: row => {
+ handleEdit(row);
+ },
+ },
+ {
+ name: "鍒犻櫎",
+ clickFun: row => {
+ handleDelete(row);
+ },
+ },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+ // 鎼滅储琛ㄥ崟
+ const searchForm = reactive({
+ paramName: "",
+ productName: "",
+ });
+
+ // 瀵硅瘽妗嗙浉鍏�
+ const dialogVisible = ref(false);
+ const dialogTitle = ref("");
+ const formRef = ref(null);
+ const formData = reactive({
+ id: null,
+ paramCode: "",
+ paramName: "",
+ paramType: "",
+ // valueMode: "1",
+ unit: "",
+ remark: "",
+ isRequired: 0,
+ paramFormat: "",
+ });
+ const rules = reactive({
+ paramName: [{ required: true, message: "璇疯緭鍏ュ弬鏁板悕绉�", trigger: "blur" }],
+ paramType: [{ required: true, message: "璇烽�夋嫨鍙傛暟绫诲瀷", trigger: "change" }],
+ // valueMode: [{ required: true, message: "璇烽�夋嫨鍙栧�兼ā寮�", trigger: "change" }],
+ unit: [
+ {
+ required: false,
+ message: "璇疯緭鍏ュ崟浣�",
+ trigger: "blur",
+ validator: (rule, value, callback) => {
+ if (formData.paramType === 1 && !value) {
+ callback(new Error("鏁板�肩被鍨嬪繀椤诲~鍐欏崟浣�"));
+ } else {
+ callback();
+ }
+ },
+ },
+ ],
+ });
+ // 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 handleParamTypeChange = () => {
+ if (formData.paramType === 1) {
+ formData.paramFormat = "#.00000";
+ } else if (formData.paramType === 4) {
+ formData.paramFormat = "YYYY-MM-DD HH:mm:ss";
+ } else {
+ formData.paramFormat = "";
+ }
+ // 瑙﹀彂鍗曚綅瀛楁楠岃瘉
+ if (formRef.value) {
+ formRef.value.validateField("unit");
+ }
+ };
+ // 浜у搧绫诲瀷缁存姢鎸夐挳鐐瑰嚮浜嬩欢 - 宸叉敞閲�
+ // 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 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 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 handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+
+ /** 閲嶇疆鎸夐挳鎿嶄綔 */
+ const handleReset = () => {
+ searchForm.paramName = "";
+ searchForm.productName = "";
+ page.current = 1;
+ getList();
+ };
+ const pagination = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+
+ const getList = () => {
+ tableLoading.value = true;
+ // 璋冪敤鏂版帴鍙� /baseParam/list
+ getBaseParamList({
+ paramName: searchForm.paramName,
+ current: page.current,
+ size: page.size,
+ })
+ .then(res => {
+ tableLoading.value = false;
+ if (res.code === 200) {
+ tableData.value = res.data.records || [];
+ page.total = res.data.total || 0;
+ console.log(tableData.value, "tableData.value");
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ ElMessage.error("鏌ヨ澶辫触");
+ });
+ };
+
+ // 鑾峰彇浜у搧绫诲瀷鍒楄〃 - 宸叉敞閲�
+ // const getProductTypes = () => {
+ // productTypes.value = [
+ // { label: "3.5鐮屽潡", value: "type1" },
+ // { label: "5.0鐮屽潡", value: "type2" },
+ // { label: "鏉挎潗", value: "type3" },
+ // ];
+ // };
+
+ // 鏂板鎸夐挳鐐瑰嚮浜嬩欢
+ const handleAdd = () => {
+ isEdit.value = false;
+ dialogTitle.value = "鏂板鍙傛暟";
+ // 閲嶇疆琛ㄥ崟
+ formData.id = null;
+ formData.paramCode = "";
+ formData.paramName = "";
+ formData.paramType = "";
+ // formData.valueMode = "1";
+ formData.unit = "";
+ formData.remark = "";
+ formData.isRequired = 0;
+ dialogVisible.value = true;
+ };
+
+ // 缂栬緫鎸夐挳鐐瑰嚮浜嬩欢
+ const handleEdit = row => {
+ isEdit.value = true;
+ dialogTitle.value = "缂栬緫鍙傛暟";
+ // 濉厖琛ㄥ崟鏁版嵁
+ formData.id = row.id;
+ formData.paramCode = row.paramCode || "";
+ formData.paramName = row.paramName || "";
+ formData.paramType = row.paramType !== undefined ? row.paramType : null;
+ // formData.valueMode =
+ // row.valueMode !== undefined ? String(row.valueMode) : "1";
+ formData.unit = row.unit || "";
+ formData.remark = row.remark || "";
+ formData.paramFormat = row.paramFormat || "";
+ formData.isRequired = row.isRequired || 0;
+ dialogVisible.value = true;
+ };
+
+ // 鍒犻櫎鎸夐挳鐐瑰嚮浜嬩欢
+ const handleDelete = row => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ繖鏉℃暟鎹悧锛�", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ // 璋冪敤鏂版帴鍙� /baseParam/remove/{id}
+ removeBaseParam([row.id])
+ .then(res => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ })
+ .catch(() => {
+ // 鍙栨秷鍒犻櫎
+ });
+ };
+
+ // 鎻愪氦琛ㄥ崟
+ const handleSubmit = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ if (formData.id) {
+ // 缂栬緫浣跨敤鏂版帴鍙� /technologyParam/edit
+ editBaseParam(formData)
+ .then(res => {
+ ElMessage.success("缂栬緫鎴愬姛");
+ dialogVisible.value = false;
+ getList();
+ })
+ .catch(() => {
+ // ElMessage.error("缂栬緫澶辫触");
+ });
+ } else {
+ // 鏂板浣跨敤鏂版帴鍙� /technologyParam/add
+ addBaseParam(formData)
+ .then(res => {
+ ElMessage.success("鏂板鎴愬姛");
+ dialogVisible.value = false;
+ getList();
+ })
+ .catch(() => {
+ ElMessage.error("鏂板澶辫触");
+ });
+ }
+ } else {
+ return false;
+ }
+ });
+ };
+ const dictTypes = ref([]);
+ const getDictTypes = () => {
+ listType({ pageNum: 1, pageSize: 1000 }).then(res => {
+ dictTypes.value = res.rows || [];
+ });
+ };
+
+ onMounted(() => {
+ getDictTypes();
+ getList();
+ // getProductTypes();
+ });
+</script>
+
+<style scoped lang="scss">
+ .app-container {
+ padding: 24px;
+ background-color: #f0f2f5;
+ min-height: calc(100vh - 48px);
+ }
+
+ .search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+ padding: 20px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ transition: all 0.3s ease;
+
+ &:hover {
+ box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08);
+ }
+
+ .search_title {
+ color: #606266;
+ font-size: 14px;
+ font-weight: 500;
+ }
+
+ .ml10 {
+ margin-left: 10px;
+ }
+ }
+
+ .table_list {
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ overflow: hidden;
+ height: calc(100vh - 230px);
+ }
+
+ :deep(.el-table) {
+ border: none;
+ border-radius: 6px;
+ overflow: hidden;
+ box-shadow: 0 4px 16px rgba(102, 126, 234, 0.1);
+
+ .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;
+ letter-spacing: 0.5px;
+ }
+ }
+
+ .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%
+ );
+ transform: scale(1.002);
+ box-shadow: 0 2px 8px rgba(102, 126, 234, 0.1);
+ }
+
+ td {
+ border-bottom: 1px solid #f0f0f0;
+ padding: 14px 0;
+ color: #303133;
+ }
+ }
+
+ tr.current-row {
+ background: linear-gradient(
+ 90deg,
+ rgba(102, 126, 234, 0.08) 0%,
+ rgba(118, 75, 162, 0.08) 100%
+ );
+ }
+
+ // 鏁板�煎瓧娈垫牱寮�
+ .quantity-cell,
+ .volume-cell,
+ .dimension-cell {
+ font-weight: 600;
+ color: #409eff;
+ font-family: "Courier New", monospace;
+ text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2);
+ }
+
+ // 瑙勬牸瀛楁鏍峰紡
+ .spec-cell {
+ color: #67c23a;
+ font-weight: 500;
+ padding: 4px 8px;
+ border-radius: 4px;
+ }
+
+ // 缂栫爜瀛楁鏍峰紡
+ .code-cell {
+ color: #e6a23c;
+ font-family: "Courier New", monospace;
+ font-weight: 500;
+ padding: 4px 8px;
+ border-radius: 4px;
+ }
+
+ // 鏃ユ湡瀛楁鏍峰紡
+ .date-cell {
+ color: #909399;
+ font-style: italic;
+ }
+ }
+
+ .el-table__empty-block {
+ padding: 60px 0;
+ background-color: #fafafa;
+ }
+ }
+
+ .pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ padding: 16px 20px;
+ background-color: #ffffff;
+ border-top: 1px solid #ebeef5;
+ border-radius: 0 0 12px 12px;
+ }
+
+ :deep(.el-button) {
+ transition: all 0.3s ease;
+
+ &:hover {
+ transform: translateY(-1px);
+ }
+ }
+
+ @media (max-width: 768px) {
+ .app-container {
+ padding: 16px;
+ }
+
+ .search_form {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+
+ .el-form {
+ width: 100%;
+
+ .el-form-item {
+ width: 100%;
+ }
+ }
+
+ .el-button {
+ margin-right: 12px;
+ }
+ }
+
+ :deep(.el-table) {
+ th,
+ td {
+ padding: 10px 0;
+ font-size: 12px;
+ }
+ }
+ }
+</style>
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index c1c490c..be7138d 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -1,9 +1,10 @@
<template>
<div class="app-container">
<PageHeader content="宸ヨ壓璺嚎椤圭洰" />
-
<!-- 宸ヨ壓璺嚎淇℃伅灞曠ず -->
- <el-card v-if="routeInfo.processRouteCode" class="route-info-card" shadow="hover">
+ <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">
@@ -37,7 +38,8 @@
<span class="info-value">{{ routeInfo.bomNo || '-' }}</span>
</div>
</div>
- <div class="info-item full-width" v-if="routeInfo.description">
+ <div class="info-item full-width"
+ v-if="routeInfo.description">
<div class="info-label-wrapper">
<span class="info-label">鎻忚堪</span>
</div>
@@ -47,435 +49,469 @@
</div>
</div>
</el-card>
-
<!-- 琛ㄦ牸瑙嗗浘 -->
- <div v-if="viewMode === 'table'" class="section-header">
+ <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 icon="Grid"
+ @click="toggleView"
+ style="margin-right: 10px;">
鍗$墖瑙嗗浘
</el-button>
- <el-button type="primary" @click="handleAdd">鏂板</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">
+ <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">
+ <el-table-column label="鍙傛暟鍒楄〃"
+ min-width="160">
+ <template #default="scope">
+ <el-button type="primary"
+ link
+ size="small"
+ @click="handleViewParams(scope.row)">鍙傛暟鍒楄〃</el-button>
+ </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">
+ <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>
+ <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 icon="Menu"
+ @click="toggleView"
+ style="margin-right: 10px;">
琛ㄦ牸瑙嗗浘
</el-button>
- <el-button type="primary" @click="handleAdd">鏂板</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 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 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 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="info"
+ link
+ size="small"
+ @click="handleViewParams(item)">鍙傛暟鍒楄〃</el-button>
+ <el-button type="danger"
+ link
+ size="small"
+ @click="handleDelete(item)"
+ :disabled="item.isComplete">鍒犻櫎</el-button>
+ </div>
</div>
</div>
- </div>
</div>
</template>
-
+ <div class="section-BOM">
+ <div class="section-header">
+ <div class="section-title">BOM</div>
+ <div class="section-actions">
+ <el-button type="primary"
+ @click="toggleBomEdit">
+ {{ bomDataValue.isEdit ? '鍙栨秷' : '缂栬緫' }}
+ </el-button>
+ <el-button v-if=" bomDataValue.isEdit"
+ type="success"
+ @click="saveBomChanges">淇濆瓨</el-button>
+ </div>
+ </div>
+ <div>
+ <!-- BOM琛ㄦ牸 -->
+ <el-table :data="bomTableData"
+ border
+ :preserve-expanded-content="false"
+ :default-expand-all="true"
+ style="width: 100%">
+ <el-table-column type="expand">
+ <template #default="props">
+ <el-form ref="bomFormRef"
+ :model="bomDataValue">
+ <el-table :data="props.row.bomList"
+ row-key="tempId"
+ default-expand-all
+ :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+ style="width: 100%">
+ <el-table-column prop="productName"
+ label="浜у搧" />
+ <el-table-column prop="model"
+ label="瑙勬牸">
+ <template #default="{ row }">
+ <el-form-item v-if="bomDataValue.isEdit"
+ :rules="[{ required: true, message: '璇烽�夋嫨瑙勬牸', trigger: ['blur','change'] }]"
+ style="margin: 0">
+ <el-select v-model="row.model"
+ placeholder="璇烽�夋嫨瑙勬牸"
+ clearable
+ :disabled="!bomDataValue.isEdit"
+ style="width: 100%"
+ @visible-change="(v) => { if (v) openBomProductDialog(row.tempId) }">
+ <el-option v-if="row.model"
+ :label="row.model"
+ :value="row.model" />
+ </el-select>
+ </el-form-item>
+ <span v-else>{{ row.model }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="processName"
+ label="娑堣�楀伐搴�">
+ <template #default="{ row }">
+ <el-form-item v-if="bomDataValue.isEdit"
+ :rules="[{ required: true, message: '璇烽�夋嫨娑堣�楀伐搴�', trigger: 'change' }]"
+ style="margin: 0">
+ <el-select v-model="row.processId"
+ placeholder="璇烽�夋嫨"
+ filterable
+ clearable
+ :disabled="!bomDataValue.isEdit"
+ style="width: 100%">
+ <el-option v-for="process in processOptions"
+ :key="process.id"
+ :label="process.name"
+ :value="process.id" />
+ </el-select>
+ </el-form-item>
+ <span v-else>{{ row.processName }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="unitQuantity"
+ label="鍗曚綅浜у嚭鎵�闇�鏁伴噺">
+ <template #default="{ row }">
+ <el-form-item v-if="bomDataValue.isEdit"
+ :rules="[{ required: true, message: '璇疯緭鍏ュ崟浣嶄骇鍑烘墍闇�鏁伴噺', trigger: ['blur','change'] }]"
+ style="margin: 0">
+ <el-input-number v-model="row.unitQuantity"
+ :min="0"
+ :precision="2"
+ :step="1"
+ controls-position="right"
+ style="width: 100%"
+ :disabled="!bomDataValue.isEdit" />
+ </el-form-item>
+ <span v-else>{{ row.unitQuantity }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column v-if="pageType === 'order'"
+ prop="demandedQuantity"
+ label="闇�姹傛�婚噺">
+ <template #default="{ row }">
+ <el-form-item v-if="bomDataValue.isEdit"
+ :rules="[{ required: true, message: '璇疯緭鍏ラ渶姹傛�婚噺', trigger: ['blur','change'] }]"
+ style="margin: 0">
+ <el-input-number v-model="row.demandedQuantity"
+ :min="0"
+ :precision="2"
+ :step="1"
+ controls-position="right"
+ style="width: 100%"
+ :disabled="!bomDataValue.isEdit" />
+ </el-form-item>
+ <span v-else>{{ row.demandedQuantity }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="unit"
+ label="鍗曚綅">
+ <template #default="{ row }">
+ <el-form-item v-if="bomDataValue.isEdit"
+ :rules="[{ required: true, message: '璇疯緭鍏ュ崟浣�', trigger: ['blur','change'] }]"
+ style="margin: 0">
+ <el-input v-model="row.unit"
+ placeholder="璇疯緭鍏ュ崟浣�"
+ clearable
+ :disabled="!bomDataValue.isEdit" />
+ </el-form-item>
+ <span v-else>{{ row.unit }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔"
+ fixed="right"
+ width="180">
+ <template #default="{ row }">
+ <el-button v-if="bomDataValue.isEdit"
+ type="danger"
+ text
+ size="small"
+ @click="removeBomItem(row.tempId)">鍒犻櫎</el-button>
+ <el-button v-if="bomDataValue.isEdit"
+ type="primary"
+ text
+ size="small"
+ @click="addBomItem2(row.tempId)">娣诲姞瀛愰」</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-form>
+ </template>
+ </el-table-column>
+ <el-table-column label="BOM缂栧彿"
+ prop="bomNo" />
+ <el-table-column label="浜у搧鍚嶇О"
+ prop="productName" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="model" />
+ </el-table>
+ <!-- <div v-if="bomDataValue.isEdit"
+ style="text-align: center;border: 1px solid #e4e7ed;padding: 10px;transition: all 0.3s ease;cursor: pointer;"
+ :class="{'hover-effect': bomDataValue.isEdit}">
+ <el-button type="primary"
+ text
+ @click="addBomItem">
+ <el-icon style="vertical-align: middle;margin-right: 5px;">
+ <Plus />
+ </el-icon>
+ 娣诲姞
+ </el-button>
+ </div> -->
+ </div>
+ </div>
<!-- 鏂板/缂栬緫寮圭獥 -->
- <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-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">
+ <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 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 label="鏄惁璐ㄦ"
+ prop="isQuality">
+ <el-switch v-model="form.isQuality"
+ :active-value="true"
+ inactive-value="false" />
</el-form-item>
</el-form>
-
<template #footer>
- <el-button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</el-button>
+ <el-button type="primary"
+ @click="handleSubmit"
+ :loading="submitLoading">纭畾</el-button>
<el-button @click="closeDialog">鍙栨秷</el-button>
</template>
</el-dialog>
-
<!-- 浜у搧閫夋嫨瀵硅瘽妗� -->
- <ProductSelectDialog
- v-model="showProductSelectDialog"
- @confirm="handleProductSelect"
- single
- />
+ <ProductSelectDialog v-model="showProductSelectDialog"
+ @confirm="handleProductSelect"
+ single />
+ <!-- BOM浜у搧閫夋嫨瀵硅瘽妗� -->
+ <ProductSelectDialog v-model="bomDataValue.showProductDialog"
+ @confirm="handleBomProductSelect"
+ single />
+ <!-- 鍙傛暟鍒楄〃瀵硅瘽妗� -->
+ <!-- :editable="!routeInfo.status" -->
+ <ProcessParamListDialog v-model="showParamListDialog"
+ :title="`${currentProcess ? (currentProcess.processName || getProcessName(currentProcess.processId)) : ''} - 鍙傛暟鍒楄〃`"
+ :route-id="routeId"
+ :order-id="orderId"
+ :process="currentProcess"
+ :page-type="pageType"
+ :param-list="paramList"
+ @refresh="refreshParamList" />
</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'
+ import {
+ ref,
+ computed,
+ getCurrentInstance,
+ onMounted,
+ onUnmounted,
+ nextTick,
+ } from "vue";
+ import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+ import ProcessParamListDialog from "@/components/ProcessParamListDialog.vue";
+ import {
+ findProcessRouteItemList,
+ addOrUpdateProcessRouteItem,
+ sortProcessRouteItem,
+ batchDeleteProcessRouteItem,
+ getProcessParamList,
+ } from "@/api/productionManagement/processRouteItem.js";
+ import {
+ findProductProcessRouteItemList,
+ deleteRouteItem,
+ addRouteItem,
+ findProcessParamListOrder,
+ addOrUpdateProductProcessRouteItem,
+ sortRouteItem,
+ } from "@/api/productionManagement/productProcessRoute.js";
+ import { processList } from "@/api/productionManagement/productionProcess.js";
+ import {
+ queryList2,
+ queryList,
+ add2,
+ } from "@/api/productionManagement/productStructure.js";
+ import { useRoute } from "vue-router";
+ import { ElMessageBox, ElMessage } from "element-plus";
+ import Sortable from "sortablejs";
-const route = useRoute()
-const { proxy } = getCurrentInstance() || {};
+ 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 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 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("card"); // table | card
+ const routeInfo = ref({
+ processRouteCode: "",
+ productName: "",
+ model: "",
+ bomNo: "",
+ description: "",
});
-};
-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 processOptions = ref([]);
+ const showProductSelectDialog = ref(false);
+ const showParamListDialog = ref(false);
+ const currentProcess = ref(null);
+ const paramList = ref([]);
+ const bomTableData = ref([]);
+ const bomFormRef = ref(null);
+ const bomDataValue = ref({
+ dataList: [],
+ showProductDialog: false,
+ currentRowName: null,
+ loading: false,
+ isEdit: false,
});
-};
+ let tableSortable = null;
+ let cardSortable = null;
-// 閲嶇疆琛ㄥ崟
-const resetForm = () => {
- form.value = {
+ // 鍒囨崲瑙嗗浘
+ const toggleView = () => {
+ viewMode.value = viewMode.value === "table" ? "card" : "table";
+ // 鍒囨崲瑙嗗浘鍚庨噸鏂板垵濮嬪寲鎷栨嫿鎺掑簭
+ nextTick(() => {
+ initSortable();
+ });
+ };
+
+ const form = ref({
id: undefined,
routeId: routeId.value,
processId: undefined,
@@ -483,414 +519,967 @@
productName: "",
model: "",
unit: "",
+ isQuality: false,
+ });
+
+ const rules = {
+ processId: [{ required: true, message: "璇烽�夋嫨宸ュ簭", trigger: "change" }],
+ productModelId: [
+ { required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" },
+ ],
};
- formRef.value?.resetFields();
-};
-// 鍏抽棴寮圭獥
-const closeDialog = () => {
- dialogVisible.value = false;
- resetForm();
-};
+ // 鏍规嵁宸ュ簭ID鑾峰彇宸ュ簭鍚嶇О
+ const getProcessName = processId => {
+ if (!processId) return "";
+ const process = processOptions.value.find(p => p.id === processId);
+ return process ? process.name : "";
+ };
-// 鍒濆鍖栨嫋鎷芥帓搴�
-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;
+ // 鑾峰彇鍒楄〃
+ const getList = () => {
+ tableLoading.value = true;
+ const listPromise =
+ pageType.value === "order"
+ ? findProductProcessRouteItemList({ orderId: orderId.value })
+ : findProcessRouteItemList({ routeId: routeId.value });
- 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;
+ listPromise
+ .then(res => {
+ tableData.value = res.data || [];
+ tableLoading.value = false;
+ // 鍒楄〃鍔犺浇瀹屾垚鍚庡垵濮嬪寲鎷栨嫿鎺掑簭
+ nextTick(() => {
+ initSortable();
+ });
+ })
+ .catch(err => {
+ tableLoading.value = false;
+ console.error("鑾峰彇鍒楄〃澶辫触锛�", err);
+ proxy?.$modal?.msgError("鑾峰彇鍒楄〃澶辫触");
+ });
+ };
- // 閲嶆柊鎺掑簭鏁扮粍
- 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
- });
+ // 鑾峰彇宸ュ簭鍒楄〃
+ const getProcessList = () => {
+ processList({})
+ .then(res => {
+ processOptions.value = res.data || [];
+ })
+ .catch(err => {
+ console.error("鑾峰彇宸ュ簭澶辫触锛�", err);
+ });
+ };
- sortPromise
- .then(() => {
- // 鏇存柊鎵�鏈夎鐨刣ragSort
- tableData.value.forEach((item, index) => {
- if (item.id) {
- item.dragSort = index + 1;
+ // 鑾峰彇宸ヨ壓璺嚎璇︽儏锛堜粠璺敱鍙傛暟鑾峰彇锛�
+ const getRouteInfo = () => {
+ routeInfo.value = {
+ processRouteCode: route.query.processRouteCode || "",
+ productName: route.query.productName || "",
+ model: route.query.model || "",
+ bomNo: route.query.bomNo || "",
+ description: route.query.description || "",
+ status: !(route.query.status == 1 || route.query.status === "false"),
+ };
+ if (pageType.value === "order") {
+ queryList2(route.query.orderId)
+ .then(res => {
+ if (res.data) {
+ // 涓築OM鏁版嵁璁剧疆tempId
+ const setTempIdRecursively = items => {
+ items.forEach(item => {
+ item.tempId = item.id || new Date().getTime();
+ if (item.children && item.children.length > 0) {
+ setTempIdRecursively(item.children);
}
});
- proxy?.$modal?.msgSuccess('鎺掑簭鎴愬姛');
+ };
+ setTempIdRecursively(res.data);
+
+ bomTableData.value = [
+ {
+ bomNo: routeInfo.value.bomNo,
+ dictLabel: routeInfo.value.dictLabel,
+ productCode: "",
+ productName: routeInfo.value.productName,
+ model: routeInfo.value.model,
+ bomList: res.data,
+ },
+ ];
+
+ // 淇濆瓨鍘熷BOM鏁版嵁
+ bomDataValue.value.dataList = res.data;
+ }
+ })
+ .catch(err => {
+ console.error("鑾峰彇BOM鏁版嵁澶辫触锛�", err);
+ });
+ } else {
+ queryList(Number(route.query.bomId))
+ .then(res => {
+ if (res.data) {
+ // 涓築OM鏁版嵁璁剧疆tempId
+ const setTempIdRecursively = items => {
+ items.forEach(item => {
+ item.tempId = item.id || new Date().getTime();
+ if (item.children && item.children.length > 0) {
+ setTempIdRecursively(item.children);
+ }
+ });
+ };
+ setTempIdRecursively(res.data);
+
+ bomTableData.value = [
+ {
+ bomNo: routeInfo.value.bomNo,
+ dictLabel: routeInfo.value.dictLabel,
+ productCode: "",
+ productName: routeInfo.value.productName,
+ model: routeInfo.value.model,
+ bomList: res.data,
+ },
+ ];
+
+ // 淇濆瓨鍘熷BOM鏁版嵁
+ bomDataValue.value.dataList = res.data;
+ }
+ })
+ .catch(err => {
+ console.error("鑾峰彇BOM鏁版嵁澶辫触锛�", err);
+ });
+ }
+ };
+
+ // 鏂板
+ 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((err) => {
- // 鎺掑簭澶辫触锛屾仮澶嶅師鏁扮粍
- tableData.value.splice(newIndex, 1);
- tableData.value.splice(evt.oldIndex, 0, moveItem);
- proxy?.$modal?.msgError('鎺掑簭澶辫触');
- console.error("鎺掑簭澶辫触锛�", err);
+ .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;
});
}
}
});
- } 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 resetForm = () => {
+ form.value = {
+ id: undefined,
+ routeId: routeId.value,
+ processId: undefined,
+ productModelId: undefined,
+ productName: "",
+ model: "",
+ unit: "",
+ };
+ formRef.value?.resetFields();
+ };
- // 閲嶆柊鎺掑簭鏁扮粍
- 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
- });
+ // 鍏抽棴寮圭獥
+ const closeDialog = () => {
+ dialogVisible.value = false;
+ resetForm();
+ };
- 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 handleViewParams = row => {
+ currentProcess.value = row;
+ const query = {
+ routeItemId: row.id,
+ orderId: orderId.value,
+ };
+
+ const apiPromise =
+ pageType.value === "order"
+ ? findProcessParamListOrder(query)
+ : getProcessParamList(query);
+
+ apiPromise
+ .then(res => {
+ paramList.value = res.data || [];
+ showParamListDialog.value = true;
+ })
+ .catch(err => {
+ console.error("鑾峰彇鍙傛暟鍒楄〃澶辫触锛�", err);
+ proxy?.$modal?.msgError("鑾峰彇鍙傛暟鍒楄〃澶辫触");
+ });
+ };
+
+ // 鍒锋柊鍙傛暟鍒楄〃
+ const refreshParamList = () => {
+ if (currentProcess.value) {
+ handleViewParams(currentProcess.value);
+ }
+ };
+
+ // BOM鐩稿叧鏂规硶
+ // 鍒囨崲BOM缂栬緫妯″紡
+ const toggleBomEdit = () => {
+ bomDataValue.value.isEdit = !bomDataValue.value.isEdit;
+ if (!bomDataValue.value.isEdit) {
+ // 鍙栨秷缂栬緫鏃堕噸鏂板姞杞芥暟鎹�
+ getRouteInfo();
+ }
+ };
+
+ // 娣诲姞BOM椤�
+ const addBomItem = () => {
+ if (bomTableData.value.length > 0) {
+ const newItem = {
+ parentId: "",
+ parentTempId: "",
+ productName: "",
+ productId: "",
+ model: undefined,
+ productModelId: undefined,
+ processId: "",
+ processName: "",
+ unitQuantity: 0,
+ demandedQuantity: 0,
+ unit: "",
+ children: [],
+ tempId: new Date().getTime(),
+ };
+ bomTableData.value[0].bomList.push(newItem);
+ }
+ };
+
+ // 娣诲姞BOM瀛愰」
+ const addBomItem2 = tempId => {
+ const addChildItem = (items, tempId) => {
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ if (item.tempId === tempId) {
+ if (!item.children) {
+ item.children = [];
+ }
+ item.children.push({
+ parentId: item.id || "",
+ parentTempId: item.tempId || "",
+ productName: "",
+ productId: "",
+ model: undefined,
+ productModelId: undefined,
+ processId: "",
+ processName: "",
+ unitQuantity: 0,
+ demandedQuantity: 0,
+ unit: "",
+ children: [],
+ tempId: new Date().getTime(),
+ });
+ return true;
+ }
+ if (item.children && item.children.length > 0) {
+ if (addChildItem(item.children, tempId)) {
+ return true;
+ }
}
}
- });
- }
-};
+ return false;
+ };
-// 閿�姣佹嫋鎷芥帓搴�
-const destroySortable = () => {
- if (tableSortable) {
- tableSortable.destroy();
- tableSortable = null;
- }
- if (cardSortable) {
- cardSortable.destroy();
- cardSortable = null;
- }
-};
+ if (bomTableData.value.length > 0) {
+ addChildItem(bomTableData.value[0].bomList, tempId);
+ }
+ };
-onMounted(() => {
- getRouteInfo();
- getList();
- getProcessList();
-});
+ // 鍒犻櫎BOM椤�
+ const removeBomItem = tempId => {
+ if (bomTableData.value.length > 0) {
+ const removeFromList = (items, tempId) => {
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ if (item.tempId === tempId) {
+ items.splice(i, 1);
+ return true;
+ }
+ if (item.children && item.children.length > 0) {
+ if (removeFromList(item.children, tempId)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+ removeFromList(bomTableData.value[0].bomList, tempId);
+ }
+ };
-onUnmounted(() => {
- destroySortable();
-});
+ // 鎵撳紑BOM浜у搧閫夋嫨瀵硅瘽妗�
+ const openBomProductDialog = tempId => {
+ bomDataValue.value.currentRowName = tempId;
+ bomDataValue.value.showProductDialog = true;
+ };
+
+ // 澶勭悊BOM浜у搧閫夋嫨
+ const handleBomProductSelect = products => {
+ if (products && products.length > 0) {
+ const product = products[0];
+ const updateProductInfo = (items, tempId, productData) => {
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ if (item.tempId === tempId) {
+ item.productName = productData.productName;
+ item.model = productData.model;
+ item.productModelId = productData.id;
+ item.unit = productData.unit || "";
+ return true;
+ }
+ if (item.children && item.children.length > 0) {
+ if (updateProductInfo(item.children, tempId, productData)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ if (bomTableData.value.length > 0) {
+ updateProductInfo(
+ bomTableData.value[0].bomList,
+ bomDataValue.value.currentRowName,
+ product
+ );
+ }
+ bomDataValue.value.showProductDialog = false;
+ }
+ };
+
+ // 淇濆瓨BOM鏇存敼
+ const saveBomChanges = () => {
+ const validateBomData = (items, isTopLevel = false) => {
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ if (!item.productModelId) {
+ ElMessage.error("璇烽�夋嫨浜у搧");
+ return false;
+ }
+ if (!isTopLevel && !item.processId) {
+ ElMessage.error("璇烽�夋嫨娑堣�楀伐搴�");
+ return false;
+ }
+ if (
+ item.unitQuantity === undefined ||
+ item.unitQuantity === null ||
+ item.unitQuantity === 0
+ ) {
+ ElMessage.error("璇峰~鍐欏崟浣嶄骇鍑烘墍闇�鏁伴噺");
+ return false;
+ }
+ if (
+ pageType.value === "order" &&
+ (item.demandedQuantity === undefined ||
+ item.demandedQuantity === null ||
+ item.demandedQuantity === 0)
+ ) {
+ ElMessage.error("璇疯緭鍏ラ渶姹傛�婚噺");
+ return false;
+ }
+ if (item.children && item.children.length > 0) {
+ if (!validateBomData(item.children, false)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ if (bomTableData.value.length > 0) {
+ if (!validateBomData(bomTableData.value[0].bomList, true)) {
+ return;
+ }
+ }
+
+ const processBomItem = (item, parentId = null, parentTempId = null) => {
+ const cleanItem = {
+ id: item.id || null,
+ orderId: Number(orderId.value) || null,
+ parentId: parentId,
+ parentTempId: parentTempId || null,
+ productModelId: item.productModelId || null,
+ processId: item.processId || null,
+ unitQuantity: item.unitQuantity || 0,
+ demandedQuantity: item.demandedQuantity || 0,
+ unit: item.unit || "",
+ tempId: item.tempId || new Date().getTime(),
+ bomId: Number(route.query.bomId) || null,
+ children: [],
+ };
+
+ if (item.children && item.children.length > 0) {
+ cleanItem.children = item.children.map(child =>
+ processBomItem(child, item.id, item.tempId)
+ );
+ }
+
+ return cleanItem;
+ };
+
+ const saveData = {
+ orderId: Number(orderId.value),
+ bomId: Number(route.query.bomId),
+ children: bomTableData.value[0].bomList.map(item => processBomItem(item)),
+ };
+
+ const savePromise =
+ pageType.value === "order" ? add2(saveData) : add(saveData);
+
+ savePromise
+ .then(() => {
+ proxy?.$modal?.msgSuccess("淇濆瓨鎴愬姛");
+ bomDataValue.value.isEdit = false;
+ getRouteInfo();
+ })
+ .catch(err => {
+ console.error("淇濆瓨BOM澶辫触锛�", err);
+ proxy?.$modal?.msgError("淇濆瓨澶辫触");
+ });
+ };
+
+ // 鍒濆鍖栨嫋鎷芥帓搴�
+ 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;
-}
+ .card-container {
+ padding: 20px 0;
+ }
-.cards-wrapper {
- display: flex;
- gap: 16px;
- overflow-x: auto;
- padding: 10px 0;
- min-height: 200px;
-}
+ .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 {
+ height: 8px;
+ }
-.cards-wrapper::-webkit-scrollbar-track {
- background: #f1f1f1;
- border-radius: 4px;
-}
+ .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 {
+ background: #c1c1c1;
+ border-radius: 4px;
+ }
-.cards-wrapper::-webkit-scrollbar-thumb:hover {
- background: #a8a8a8;
-}
+ .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 {
+ 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);
-}
+ .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-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-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-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;
-}
+ .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 {
+ font-size: 13px;
+ color: #666;
+ text-align: center;
+ width: 100%;
+ }
-.product-info.empty {
- color: #999;
- text-align: center;
- padding: 20px 0;
-}
+ .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-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-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-unit {
+ margin-left: 4px;
+ color: #409eff;
+ }
-.product-tag {
- margin: 10px 0;
-}
+ .product-tag {
+ margin: 10px 0;
+ }
-.card-footer {
- display: flex;
- justify-content: space-around;
- padding-top: 12px;
- border-top: 1px solid #f0f0f0;
-}
+ .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;
-}
+ .card-footer .el-button {
+ padding: 0;
+ font-size: 12px;
+ }
-:deep(.sortable-ghost) {
- opacity: 0.5;
- background-color: #f5f7fa !important;
-}
+ :deep(.sortable-ghost) {
+ opacity: 0.5;
+ background-color: #f5f7fa !important;
+ }
-:deep(.sortable-drag) {
- opacity: 0.8;
-}
+ :deep(.sortable-drag) {
+ opacity: 0.8;
+ }
-/* 琛ㄦ牸瑙嗗浘鏍峰紡 */
-:deep(.el-table__row) {
- transition: background-color 0.2s;
- cursor: move;
-}
+ /* 琛ㄦ牸瑙嗗浘鏍峰紡 */
+ :deep(.el-table__row) {
+ transition: background-color 0.2s;
+ cursor: move;
+ }
-:deep(.el-table__row:hover) {
- background-color: #f9fafc !important;
-}
+ :deep(.el-table__row:hover) {
+ background-color: #f9fafc !important;
+ }
-/* 鍖哄煙鏍囬鏍峰紡 */
-.section-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 12px;
-}
+ /* 鍖哄煙鏍囬鏍峰紡 */
+ .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 {
+ 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-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;
-}
+ .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-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;
-}
+ .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 {
+ 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: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-item.full-width {
+ grid-column: 1 / -1;
+ }
-.info-label-wrapper {
- margin-bottom: 8px;
-}
+ .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 {
+ 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-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-wrapper {
+ flex: 1;
+ }
-.info-value {
- display: block;
- color: #303133;
- font-size: 15px;
- font-weight: 500;
- line-height: 1.5;
- word-break: break-all;
-}
+ .info-value {
+ display: block;
+ color: #303133;
+ font-size: 15px;
+ font-weight: 500;
+ line-height: 1.5;
+ word-break: break-all;
+ }
+
+ .section-BOM {
+ margin-top: 20px;
+ }
+
+ .hover-effect:hover {
+ border-color: #409eff;
+ background-color: #ecf5ff;
+ transform: translateY(-2px);
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ }
</style>
diff --git a/src/views/productionManagement/productionProcess/Edit.vue b/src/views/productionManagement/productionProcess/Edit.vue
deleted file mode 100644
index fb0ee74..0000000
--- a/src/views/productionManagement/productionProcess/Edit.vue
+++ /dev/null
@@ -1,156 +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="type"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨宸ュ簭绫诲瀷',
- }
- ]"
- >
- <el-select v-model="formState.type" placeholder="璇烽�夋嫨宸ュ簭绫诲瀷">
- <el-option label="璁℃椂" :value="0" />
- <el-option label="璁′欢" :value="1" />
- </el-select>
- </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,
- type: props.record.type,
- 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 || '',
- type: newRecord.type,
- 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 || '',
- type: props.record.type,
- 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 a5f00aa..0000000
--- a/src/views/productionManagement/productionProcess/New.vue
+++ /dev/null
@@ -1,121 +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="type"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨宸ュ簭绫诲瀷',
- }
- ]"
- >
- <el-select v-model="formState.type" placeholder="璇烽�夋嫨宸ュ簭绫诲瀷">
- <el-option label="璁℃椂" :value="0" />
- <el-option label="璁′欢" :value="1" />
- </el-select>
- </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: '',
- type: undefined,
- 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 ffe13fc..c52fa65 100644
--- a/src/views/productionManagement/productionProcess/index.vue
+++ b/src/views/productionManagement/productionProcess/index.vue
@@ -1,319 +1,1090 @@
<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"
+ v-loading="processLoading">
+ <div v-for="process in processValueList"
+ :key="process.id"
+ class="process-card"
+ :class="{ active: selectedProcess?.id === process.id }"
+ @click="selectProcess(process)">
+ <div class="card-header">
+ <div class="process-name">{{ process.name }} <span class="process-code">{{ process.no }}</span></div>
+ <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.name }}</div> -->
+ <div class="process-desc">{{ process.remark || '鏆傛棤鎻忚堪' }}</div>
+ <div class="process-device">鍏宠仈璁惧: {{ process.deviceName || '鏈叧鑱�' }}</div>
+ </div>
+ <div class="card-footer">
+ <div class="status-tag"> <el-tag size="small"
+ :type="process.status ? 'success' : 'info'">
+ {{ process.status ? '鍚敤' : '鍋滅敤' }}
+ </el-tag>
+ <el-tag size="small"
+ :type="process.isQuality ? 'warning' : 'info'"
+ style="margin-left: 8px">
+ {{ process.isQuality ? '璐ㄦ' : '闈炶川妫�' }}
+ </el-tag>
+ <el-tag v-if="process.type !== null && process.type !== undefined"
+ size="small"
+ :type="process.type == 1 ? 'primary' : 'success'"
+ style="margin-left: 8px">
+ {{ process.type == 0 ? '璁℃椂' : '璁′欢' }}
+ </el-tag>
+ </div>
+ <span class="param-count">宸ヨ祫瀹氶: 楼{{ process.salaryQuota || 0 }}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- 鍙充晶鍙傛暟鍒楄〃 -->
+ <div class="param-list-section">
+ <div class="section-header">
+ <h3 class="section-title">
+ {{ selectedProcess ? selectedProcess.name + ' - 鍙傛暟閰嶇疆' : '璇烽�夋嫨宸ュ簭' }}
+ </h3>
+ <el-button type="primary"
+ size="small"
+ :disabled="!selectedProcess"
+ @click="openParamDialog">
+ <el-icon>
+ <Plus />
+ </el-icon>閫夋嫨鍙傛暟
+ </el-button>
+ </div>
+ <div class="param-table-wrapper">
+ <PIMTable v-if="selectedProcess"
+ rowKey="id"
+ :column="paramColumn"
+ :tableData="paramList"
+ :page="paramPage2"
+ height="calc(100vh - 280px)"
+ :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="no">
+ <el-input v-model="processForm.no"
+ placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />
+ </el-form-item>
+ <el-form-item label="宸ュ簭鍚嶇О"
+ prop="name">
+ <el-input v-model="processForm.name"
+ placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+ </el-form-item>
+ <el-form-item label="宸ヨ祫瀹氶"
+ prop="salaryQuota">
+ <el-input v-model="processForm.salaryQuota"
+ type="number"
+ :step="0.001" />
+ </el-form-item>
+ <el-form-item label="鏄惁璐ㄦ"
+ prop="isQuality">
+ <el-switch v-model="processForm.isQuality" />
+ </el-form-item>
+ <el-form-item label="璁¤垂绫诲瀷"
+ prop="type">
+ <el-radio-group v-model="processForm.type">
+ <el-radio :label="0">璁℃椂</el-radio>
+ <el-radio :label="1">璁′欢</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="鍏宠仈璁惧"
+ prop="deviceLedgerId">
+ <el-select v-model="processForm.deviceLedgerId"
+ placeholder="璇烽�夋嫨璁惧"
+ clearable
+ filterable
+ style="width: 100%">
+ <el-option v-for="item in deviceOptions"
+ :key="item.id"
+ :label="item.deviceName"
+ :value="item.id" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="宸ュ簭鎻忚堪"
+ prop="remark">
+ <el-input v-model="processForm.remark"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ュ伐搴忔弿杩�" />
+ </el-form-item>
+ <el-form-item label="鐘舵��"
+ prop="status">
+ <el-radio-group v-model="processForm.status">
+ <el-radio :label="true">鍚敤</el-radio>
+ <el-radio :label="false">鍋滅敤</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="handleSelectParam">
+ <template #prefix>
+ <el-icon>
+ <Search />
+ </el-icon>
+ </template>
+ </el-input>
+ </div>
+ <el-table :data="filteredParamList"
+ height="300"
+ border
+ highlight-current-row
+ @current-change="handleParamSelect">
+ <el-table-column prop="paramName"
+ label="鍙傛暟鍚嶇О" />
+ <el-table-column prop="paramType"
+ label="鍙傛暟绫诲瀷">
+ <template #default="scope">
+ <el-tag size="small"
+ :type="getParamTypeTag(scope.row.paramType)">
+ {{ getParamTypeText(scope.row.paramType) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ <!-- 鍒嗛〉鎺т欢 -->
+ <div class="pagination-container"
+ style="margin-top: 10px;">
+ <el-pagination v-model:current-page="paramPage.current"
+ v-model:page-size="paramPage.size"
+ :page-sizes="[10, 20, 50, 100]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="paramPage.total"
+ @size-change="handleParamSizeChange"
+ @current-change="handleParamCurrentChange"
+ size="small" />
+ </div>
+ </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.paramName }}</span>
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷">
+ <el-tag size="small"
+ :type="getParamTypeTag(selectedParam.paramType)">
+ {{ getParamTypeText(selectedParam.paramType) }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟鏍煎紡">
+ <span class="detail-text">{{ selectedParam.paramFormat || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鍗曚綅">
+ <span class="detail-text">{{ selectedParam.unit || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�">
+ <el-input v-model="selectedParam.standardValue"
+ type="number"
+ placeholder="璇疯緭鍏ラ粯璁ゅ��" />
+ </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>
+ <!-- 缂栬緫鍙傛暟瀵硅瘽妗� -->
+ <el-dialog v-model="editParamDialogVisible"
+ title="缂栬緫鍙傛暟"
+ width="600px">
+ <el-form :model="editParamForm"
+ :rules="editParamRules"
+ ref="editParamFormRef"
+ label-width="120px">
+ <el-form-item label="鍙傛暟鍚嶇О">
+ <span class="detail-text">{{ editParamForm.paramName }}</span>
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�"
+ prop="standardValue">
+ <el-input v-model="editParamForm.standardValue"
+ type="number"
+ placeholder="璇疯緭鍏ユ爣鍑嗗��" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="editParamDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleEditParamSubmit">纭畾</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 { 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";
import {
- listPage,
+ add,
+ update,
del,
- importData,
- downloadTemplate,
+ list as getProcessListApi,
+ processList,
+ getProcessParamList,
+ addProcessParam,
+ editProcessParam,
+ deleteProcessParam,
} from "@/api/productionManagement/productionProcess.js";
- import { getToken } from "@/utils/auth";
+ import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
+ import { getBaseParamList } from "@/api/basicData/parameterMaintenance.js";
- const data = reactive({
- searchForm: {
- name: "",
- no: "",
- },
+ // 宸ュ簭鍒楄〃鏁版嵁
+ const processValueList = ref([]);
+ const selectedProcess = ref(null);
+ const processLoading = ref(false);
+ const deviceOptions = ref([]);
+
+ // 鍙傛暟鍒楄〃鏁版嵁
+ const paramList = ref([]);
+ const paramLoading = ref(false);
+
+ // 鏁版嵁瀛楀吀
+ const dictTypes = ref([]);
+
+ // 宸ュ簭瀵硅瘽妗�
+ const processDialogVisible = ref(false);
+ const isProcessEdit = ref(false);
+ const processFormRef = ref(null);
+ const processForm = reactive({
+ id: null,
+ no: "",
+ name: "",
+ salaryQuota: null,
+ isQuality: false,
+ remark: "",
+ status: true,
+ deviceLedgerId: null,
+ type: 0,
});
- const { searchForm } = toRefs(data);
- const tableColumn = ref([
+ const processRules = {
+ no: [{ required: true, message: "璇疯緭鍏ュ伐搴忕紪鐮�", trigger: "blur" }],
+ name: [{ required: true, message: "璇疯緭鍏ュ伐搴忓悕绉�", trigger: "blur" }],
+ salaryQuota: [
+ {
+ required: false,
+ message: "璇疯緭鍏ュ伐璧勫畾棰�",
+ trigger: "blur",
+ validator: (rule, value, callback) => {
+ if (isNaN(value) || value < 0) {
+ callback(new Error("宸ヨ祫瀹氶蹇呴』鏄潪璐熸暟瀛�"));
+ } else {
+ callback();
+ }
+ },
+ },
+ ],
+ deviceLedgerId: [
+ { required: false, message: "璇烽�夋嫨璁惧", trigger: "change" },
+ ],
+ type: [{ required: false, message: "璇烽�夋嫨璁¤垂绫诲瀷", trigger: "change" }],
+ };
+
+ // 鍙傛暟瀵硅瘽妗�
+ const paramDialogVisible = ref(false);
+ const availableParamList = ref([]);
+ const filteredParamList = ref([]);
+ const selectedParam = ref(null);
+ const paramSearchKeyword = ref("");
+
+ // 鍙�夊弬鏁板垎椤�
+ const paramPage = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ // 缂栬緫鍙傛暟瀵硅瘽妗�
+ const editParamDialogVisible = ref(false);
+ const editParamFormRef = ref(null);
+ const editParamForm = reactive({
+ id: null,
+ processId: null,
+ paramId: null,
+ paramName: "",
+ standardValue: null,
+ tenantId: 1,
+ });
+ const editParamRules = {
+ standardValue: [
+ {
+ required: true,
+ message: "璇疯緭鍏ユ爣鍑嗗��",
+ trigger: "blur",
+ validator: (rule, value, callback) => {
+ if (value === null || value === undefined || value === "") {
+ callback(new Error("璇疯緭鍏ユ爣鍑嗗��"));
+ } else {
+ callback();
+ }
+ },
+ },
+ ],
+ };
+
+ // 鍙傛暟琛ㄦ牸鍒楅厤缃�
+ const paramColumn = ref([
{
- label: "宸ュ簭缂栧彿",
- prop: "no",
+ label: "鍙傛暟鍚嶇О",
+ prop: "paramName",
},
{
- label: "宸ュ簭鍚嶇О",
- prop: "name",
- },
- {
- label: "宸ュ簭绫诲瀷",
- prop: "typeText",
- },
- {
- label: "宸ヨ祫瀹氶",
- prop: "salaryQuota",
- },
- {
- label: "鏄惁璐ㄦ",
- prop: "isQuality",
- formatData: (params) => {
- return params ? "鏄�" : "鍚�";
+ label: "鍙傛暟绫诲瀷",
+ prop: "paramType",
+ dataType: "tag",
+ formatType: params => {
+ const typeMap = {
+ 1: "primary",
+ 2: "info",
+ 3: "warning",
+ 4: "success",
+ };
+ return typeMap[params] || "default";
+ },
+ formatData: val => {
+ const labelMap = {
+ 1: "鏁板�兼牸寮�",
+ 2: "鏂囨湰鏍煎紡",
+ 3: "涓嬫媺閫夐」",
+ 4: "鏃堕棿鏍煎紡",
+ };
+ return labelMap[val] || val;
},
},
{
- label: "澶囨敞",
- prop: "remark",
+ label: "鍙栧�兼牸寮�",
+ prop: "paramFormat",
+ formatData: (val, row) => {
+ if (row.paramType == "3") {
+ const dict = dictTypes.value.find(item => item.dictType === val);
+ return dict ? "瀛楀吀:" + dict.dictName : val;
+ }
+ return val;
+ },
},
{
- label: "鏇存柊鏃堕棿",
- prop: "updateTime",
+ label: "鏍囧噯鍊�",
+ prop: "standardValue",
},
{
- dataType: "action",
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
+ dataType: "action",
+ width: "150",
operation: [
{
name: "缂栬緫",
- type: "text",
- clickFun: row => {
- showEditModal(row);
- },
+ clickFun: row => handleEditParam(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({
+
+ // 鑾峰彇宸ュ簭鍒楄〃
+ const getProcessList = () => {
+ processLoading.value = true;
+ getProcessListApi()
+ .then(res => {
+ processValueList.value = res.data.records || [];
+ })
+ .catch(() => {
+ ElMessage.error("鑾峰彇宸ュ簭鍒楄〃澶辫触");
+ })
+ .finally(() => {
+ processLoading.value = false;
+ });
+ };
+
+ const loadDeviceName = async () => {
+ try {
+ const { data } = await getDeviceLedger();
+ deviceOptions.value = data || [];
+ } catch (error) {
+ console.error("鍔犺浇璁惧鍒楄〃澶辫触", error);
+ }
+ };
+
+ const paramPage2 = ref({
current: 1,
- size: 100,
+ size: 10,
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 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)
+ // 鑾峰彇鍙傛暟鍒楄〃
+ const getParamList = processId => {
+ paramLoading.value = true;
+ console.log(paramPage2.value, "paramPage2.value");
+ getProcessParamList(processId, {
+ current: paramPage2.value.current,
+ size: paramPage2.value.size,
+ })
.then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records.map(item => ({
- ...item,
- typeText: item.type !== undefined && item.type !== null ? (item.type === 0 ? "璁℃椂" : "璁′欢") : "",
- }));
- page.total = res.data.total;
+ paramList.value = res.data.records || [];
+ paramPage2.value.total = res.data.total;
})
- .catch(err => {
- tableLoading.value = false;
+ .catch(() => {
+ ElMessage.error("鑾峰彇鍙傛暟鍒楄〃澶辫触");
+ })
+ .finally(() => {
+ paramLoading.value = false;
});
};
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- selectedRows.value = selection;
+
+ // 閫夋嫨宸ュ簭
+ const selectProcess = process => {
+ selectedProcess.value = process;
+ getParamList(process.id);
};
- // 鎵撳紑鏂板寮规
- const showNewModal = () => {
- isShowNewModal.value = true;
+ // 宸ュ簭鎿嶄綔
+ const handleAddProcess = () => {
+ isProcessEdit.value = false;
+ processForm.id = null;
+ processForm.no = "";
+ processForm.name = "";
+ processForm.salaryQuota = null;
+ processForm.isQuality = false;
+ processForm.remark = "";
+ processForm.status = true;
+ processForm.deviceLedgerId = null;
+ processForm.type = 0;
+ loadDeviceName();
+ processDialogVisible.value = true;
};
- const showEditModal = row => {
- isShowEditModal.value = true;
- record.value = row;
+ const handleEditProcess = async process => {
+ isProcessEdit.value = true;
+ await loadDeviceName(); // Ensure deviceOptions is loaded before setting deviceLedgerId
+ processForm.id = process.id;
+ processForm.no = process.no;
+ processForm.name = process.name;
+ processForm.salaryQuota = process.salaryQuota;
+ processForm.isQuality = !!process.isQuality;
+ processForm.remark = process.remark || "";
+ processForm.status = process.status;
+ processForm.deviceLedgerId = Number(process.deviceLedgerId);
+ processForm.type = process.type;
+ 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);
- })
+ const handleDeleteProcess = process => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ宸ュ簭鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ del([process.id])
.then(() => {
- getList();
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getProcessList();
+ if (selectedProcess.value?.id === process.id) {
+ selectedProcess.value = null;
+ paramList.value = [];
+ }
})
- .catch(() => {});
- } else {
- proxy.$modal
- .confirm('鏄惁纭鍒犻櫎宸ュ簭缂栧彿涓�"' + no + '"鐨勬暟鎹」锛�')
- .then(function () {
- return del(ids);
- })
- .then(() => {
- getList();
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- })
- .catch(() => {});
- }
- }
-
- // 瀵煎叆
- const handleImport = () => {
- importDialogVisible.value = true;
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
};
- // 纭瀵煎叆
- 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 handleProcessSubmit = () => {
+ processFormRef.value.validate(valid => {
+ if (valid) {
+ if (processForm.id) {
+ update(processForm)
+ .then(() => {
+ ElMessage.success("缂栬緫鎴愬姛");
+ processDialogVisible.value = false;
+ getProcessList();
+ })
+ .catch(() => {
+ ElMessage.error("缂栬緫澶辫触");
+ });
+ } else {
+ add(processForm)
+ .then(() => {
+ ElMessage.success("鏂板鎴愬姛");
+ processDialogVisible.value = false;
+ getProcessList();
+ })
+ .catch(() => {
+ ElMessage.error("鏂板澶辫触");
+ });
+ }
}
- getList();
- } else {
- proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
+ });
+ };
+ const openParamDialog = () => {
+ paramSearchKeyword.value = "";
+ if (!selectedProcess.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓伐搴�");
+ return;
}
+ // 鑾峰彇鍙�夊弬鏁板垪琛�
+ getBaseParamList({
+ paramName: paramSearchKeyword.value,
+ current: paramPage.current,
+ size: paramPage.size,
+ }).then(res => {
+ if (res.code === 200) {
+ filteredParamList.value = res.data?.records || [];
+ paramPage.total = res.data?.total || 0;
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ });
+ console.log(filteredParamList.value, "鍙�夊弬鏁板垪琛�");
+ selectedParam.value = null;
+ paramDialogVisible.value = true;
};
- // 瀵煎叆澶辫触
- const handleImportError = error => {
- proxy.$modal.msgError("瀵煎叆澶辫触锛�" + (error.message || "鏈煡閿欒"));
- };
-
- // 鍏抽棴瀵煎叆寮圭獥
- const handleImportClose = () => {
- if (importDialogRef.value) {
- importDialogRef.value.clearFiles();
+ // 鍙傛暟鎿嶄綔
+ const handleSelectParam = () => {
+ if (!selectedProcess.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓伐搴�");
+ return;
}
+ // 鑾峰彇鍙�夊弬鏁板垪琛�
+ getBaseParamList({
+ paramName: paramSearchKeyword.value,
+ current: paramPage.current,
+ size: paramPage.size,
+ }).then(res => {
+ if (res.code === 200) {
+ filteredParamList.value = res.data?.records || [];
+ paramPage.total = res.data?.total || 0;
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ });
+ console.log(filteredParamList.value, "鍙�夊弬鏁板垪琛�");
+ selectedParam.value = null;
+ paramDialogVisible.value = true;
};
- // 涓嬭浇妯℃澘
- const handleDownloadTemplate = async () => {
- try {
- const res = await downloadTemplate();
- const blob = new Blob([res], {
- type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ const handleParamSelect = row => {
+ selectedParam.value = row;
+ };
+
+ const handleParamSearch = () => {
+ // 閲嶇疆鍒嗛〉
+ paramPage.current = 1;
+ // 閲嶆柊鍔犺浇鏁版嵁
+ handleSelectParam();
+ };
+
+ // 澶勭悊鍒嗛〉澶у皬鍙樺寲
+ const handleParamSizeChange = size => {
+ paramPage.size = size;
+ handleSelectParam();
+ };
+
+ // 澶勭悊褰撳墠椤电爜鍙樺寲
+ const handleParamCurrentChange = current => {
+ paramPage.current = current;
+ handleSelectParam();
+ };
+ const getParamTypeText = type => {
+ const typeMap = {
+ 1: "鏁板�兼牸寮�",
+ 2: "鏂囨湰鏍煎紡",
+ 3: "涓嬫媺閫夐」",
+ 4: "鏃堕棿鏍煎紡",
+ };
+ return typeMap[type] || "鏈煡鍙傛暟绫诲瀷";
+ };
+ const getParamTypeTag = type => {
+ const typeMap = {
+ 1: "primary",
+ 2: "info",
+ 3: "warning",
+ 4: "success",
+ };
+ return typeMap[type] || "default";
+ };
+
+ const handleDeleteParam = row => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ鍙傛暟鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ deleteProcessParam(row.id)
+ .then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getParamList(selectedProcess.value.id);
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
+ };
+
+ const handleEditParam = row => {
+ editParamForm.id = row.id;
+ editParamForm.processId = row.processId;
+ editParamForm.paramId = row.paramId;
+ editParamForm.paramName = row.paramName;
+ editParamForm.standardValue = row.standardValue;
+ editParamForm.tenantId = 1;
+ editParamDialogVisible.value = true;
+ };
+
+ const handleEditParamSubmit = () => {
+ editParamFormRef.value.validate(valid => {
+ if (valid) {
+ editProcessParam(editParamForm)
+ .then(() => {
+ ElMessage.success("缂栬緫鎴愬姛");
+ editParamDialogVisible.value = false;
+ getParamList(selectedProcess.value.id);
+ })
+ .catch(() => {
+ ElMessage.error("缂栬緫澶辫触");
+ });
+ }
+ });
+ };
+
+ const handleParamSubmit = () => {
+ if (!selectedParam.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓弬鏁�");
+ return;
+ }
+ addProcessParam({
+ processId: selectedProcess.value.id,
+ paramId: selectedParam.value.id,
+ standardValue: selectedParam.value.standardValue,
+ tenantId: 1,
+ })
+ .then(() => {
+ ElMessage.success("娣诲姞鎴愬姛");
+ paramDialogVisible.value = false;
+ getParamList(selectedProcess.value.id);
+ })
+ .catch(() => {
+ ElMessage.error("娣诲姞澶辫触");
});
- 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 handleOut = () => {
- // ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- // confirmButtonText: "纭",
- // cancelButtonText: "鍙栨秷",
- // type: "warning",
- // })
- // .then(() => {
- // proxy.download("/salesLedger/scheduling/exportTwo", {}, "宸ュ簭鎺掍骇.xlsx");
- // })
- // .catch(() => {
- // proxy.$modal.msg("宸插彇娑�");
- // });
- // };
+ const handleParamPagination = obj => {
+ console.log(obj, "obj");
+ paramPage2.value.current = obj.page;
+ paramPage2.value.size = obj.limit;
+ getParamList(selectedProcess.value.id);
+ };
+
+ // 鑾峰彇鏁版嵁瀛楀吀
+ 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;
+ min-width: 370px;
+ flex-shrink: 0;
+ 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;
+ color: #cb9b18;
+ 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;
+ margin-bottom: 4px;
+ }
+
+ .process-device {
+ font-size: 12px;
+ color: #606266;
+ 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;
+ min-width: 0;
+ }
+
+ .param-table-wrapper {
+ flex: 1;
+ padding: 0 20px 20px;
+ overflow: auto;
+ min-width: 100%;
+ }
+
+ /* 琛ㄦ牸妯悜婊氬姩 */
+ .param-table-wrapper :deep(.el-table) {
+ min-width: 100%;
+ }
+
+ .param-table-wrapper :deep(.el-table__body-wrapper) {
+ overflow-x: auto;
+ }
+
+ .pagination-container {
+ margin-top: 10px;
+ overflow-x: auto;
+ padding-bottom: 8px;
+ }
+
+ .pagination-container .el-pagination {
+ white-space: nowrap;
+ }
+
+ /* 鍝嶅簲寮忚皟鏁� */
+ @media screen and (max-width: 768px) {
+ .pagination-container {
+ font-size: 12px;
+ }
+
+ .pagination-container .el-pagination__sizes {
+ margin-right: 8px;
+ }
+
+ .pagination-container .el-pagination__jump {
+ margin-left: 8px;
+ }
+
+ .pagination-container .el-pagination__page-size {
+ font-size: 12px;
+ }
+ }
+
+ .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;
+ width: 380px;
+ 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;
+ flex: 1;
+ 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