From 303e0cb5fa6816dc10b77a284195d36b9e3787db Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期四, 25 十二月 2025 14:13:55 +0800
Subject: [PATCH] 工艺路线项目页面
---
src/views/productionManagement/processRoute/ItemsForm.vue | 209 ++++++++++++++++++++++++++++++++++
src/views/productionManagement/processRoute/index.vue | 27 +++-
src/views/basicData/product/ProductSelectDialog.vue | 29 ++--
src/api/productionManagement/processRouteItem.js | 19 +++
src/api/productionManagement/processRoute.js | 2
src/api/productionManagement/productionProcess.js | 8 +
src/api/basicData/productModel.js | 9 +
7 files changed, 281 insertions(+), 22 deletions(-)
diff --git a/src/api/basicData/productModel.js b/src/api/basicData/productModel.js
new file mode 100644
index 0000000..f048f9e
--- /dev/null
+++ b/src/api/basicData/productModel.js
@@ -0,0 +1,9 @@
+import request from "@/utils/request.js";
+
+export function productModelList(query) {
+ return request({
+ url: '/basic/product/pageModel',
+ method: 'get',
+ params: query
+ })
+}
\ No newline at end of file
diff --git a/src/api/productionManagement/processRoute.js b/src/api/productionManagement/processRoute.js
index 4348465..4d16775 100644
--- a/src/api/productionManagement/processRoute.js
+++ b/src/api/productionManagement/processRoute.js
@@ -1,4 +1,4 @@
-// 宸ュ簭椤甸潰鎺ュ彛
+// 宸ヨ壓璺嚎椤甸潰鎺ュ彛
import request from "@/utils/request";
// 鍒嗛〉鏌ヨ
diff --git a/src/api/productionManagement/processRouteItem.js b/src/api/productionManagement/processRouteItem.js
new file mode 100644
index 0000000..ad4861c
--- /dev/null
+++ b/src/api/productionManagement/processRouteItem.js
@@ -0,0 +1,19 @@
+// 宸ヨ壓璺嚎椤圭洰椤甸潰鎺ュ彛
+import request from "@/utils/request";
+
+// 鍒楄〃鏌ヨ
+export function findProcessRouteItemList(query) {
+ return request({
+ url: "/processRouteItem/list",
+ method: "get",
+ params: query,
+ });
+}
+
+export function addOrUpdateProcessRouteItem(data) {
+ return request({
+ url: "/processRouteItem",
+ method: "post",
+ data: data,
+ });
+}
\ No newline at end of file
diff --git a/src/api/productionManagement/productionProcess.js b/src/api/productionManagement/productionProcess.js
index 28e268a..2c3f795 100644
--- a/src/api/productionManagement/productionProcess.js
+++ b/src/api/productionManagement/productionProcess.js
@@ -10,6 +10,14 @@
});
}
+export function processList(query) {
+ return request({
+ url: "/productProcess/list",
+ method: "get",
+ params: query,
+ });
+}
+
export function add(data) {
return request({
url: "/productProcess",
diff --git a/src/views/basicData/product/ProductSelectDialog.vue b/src/views/basicData/product/ProductSelectDialog.vue
index d4b0119..70d3f3e 100644
--- a/src/views/basicData/product/ProductSelectDialog.vue
+++ b/src/views/basicData/product/ProductSelectDialog.vue
@@ -37,8 +37,10 @@
:data="tableData"
height="420"
highlight-current-row
- @current-change="onCurrentChange"
+ row-key="id"
+ @selection-change="handleSelectionChange"
>
+ <el-table-column type="selection" width="55" />
<el-table-column type="index" label="#" width="60"/>
<el-table-column prop="productName" label="浜у搧澶х被" min-width="160"/>
<el-table-column prop="model" label="鍨嬪彿鍚嶇О" min-width="200"/>
@@ -60,7 +62,7 @@
<template #footer>
<el-button @click="close()">鍙栨秷</el-button>
- <el-button type="primary" :disabled="!selectedRow" @click="onConfirm">
+ <el-button type="primary" :disabled="multipleSelection.length === 0" @click="onConfirm">
纭畾
</el-button>
</template>
@@ -70,7 +72,7 @@
<script setup lang="ts">
import {computed, onMounted, reactive, ref, watch} from "vue";
import {ElMessage} from "element-plus";
-import {list} from '@/api/basicData/productModel'
+import {productModelList} from '@/api/basicData/productModel'
export type ProductRow = {
id: number;
@@ -83,10 +85,7 @@
modelValue: boolean;
}>();
-const emit = defineEmits<{
- (e: "update:modelValue", v: boolean): void;
- (e: "confirm", row: ProductRow): void; // 鎶婃暣琛屾暟鎹繑缁欑埗缁勪欢
-}>();
+const emit = defineEmits(['update:modelValue', 'confirm']);
const visible = computed({
get: () => props.modelValue,
@@ -106,14 +105,14 @@
const loading = ref(false);
const tableData = ref<ProductRow[]>([]);
const total = ref(0);
-const selectedRow = ref<ProductRow | null>(null);
+const multipleSelection = ref<ProductRow[]>([])
function close() {
visible.value = false;
}
-function onCurrentChange(row: ProductRow | null) {
- selectedRow.value = row;
+const handleSelectionChange = (val: ProductRow[]) => {
+ multipleSelection.value = val
}
function onSearch() {
@@ -133,25 +132,25 @@
}
function onConfirm() {
- if (!selectedRow.value) {
+ if (multipleSelection.value.length === 0) {
ElMessage.warning("璇烽�夋嫨涓�鏉′骇鍝�");
return;
}
- emit("confirm", selectedRow.value);
+ emit("confirm", multipleSelection.value);
close();
}
async function loadData() {
loading.value = true;
try {
- selectedRow.value = null; // 缈婚〉/鎼滅储鍚庢竻绌洪�夋嫨鏇寸鍚堥鏈�
- const res = await list({
+ multipleSelection.value = []; // 缈婚〉/鎼滅储鍚庢竻绌洪�夋嫨鏇寸鍚堥鏈�
+ const res = await productModelList({
productName: query.productName.trim(),
model: query.model.trim(),
pageNum: page.pageNum,
pageSize: page.pageSize,
});
- tableData.value = res.list;
+ tableData.value = res.records;
total.value = res.total;
} finally {
loading.value = false;
diff --git a/src/views/productionManagement/processRoute/ItemsForm.vue b/src/views/productionManagement/processRoute/ItemsForm.vue
new file mode 100644
index 0000000..7ac04f2
--- /dev/null
+++ b/src/views/productionManagement/processRoute/ItemsForm.vue
@@ -0,0 +1,209 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="isShow"
+ title="宸ヨ壓璺嚎椤圭洰"
+ width="800"
+ @close="closeModal"
+ >
+ <el-button type="primary" @click="isShowProductSelectDialog = true" class="mb5">閫夋嫨浜у搧</el-button>
+ <el-table
+ ref="multipleTable"
+ v-loading="tableLoading"
+ border
+ :data="routeItems"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ row-key="id"
+ tooltip-effect="dark"
+ class="lims-table"
+ >
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+
+ <el-table-column v-for="(item, index) in tableColumn" :key="index" :label="item.label" :width="item.width" show-overflow-tooltip>
+ <template #default="scope" v-if="item.dataType === 'action'">
+ <el-button
+ v-for="(op, opIndex) in item.operation"
+ :key="opIndex"
+ :type="op.type"
+ :link="op.link"
+ size="small"
+ @click="op.clickFun(scope.row)"
+ >
+ {{ op.name }}
+ </el-button>
+ </template>
+
+ <template #default="scope" v-else>
+ <template v-if="item.prop === 'processId'">
+ <el-select v-model="scope.row[item.prop]" style="width: 100%">
+ <el-option
+ v-for="process in processOptions"
+ :key="process.id"
+ :label="process.name"
+ :value="process.id"
+ />
+ </el-select>
+ </template>
+ <template v-else>
+ {{ scope.row[item.prop] }}
+ </template>
+ </template>
+
+ </el-table-column>
+ </el-table>
+
+ <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>
+
+ <ProductSelectDialog v-if="isShowProductSelectDialog" v-model:model-value="isShowProductSelectDialog" @confirm="handelSelectProducts" />
+</template>
+
+<script setup>
+import {ref, computed, getCurrentInstance, onMounted} from "vue";
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+import {findProcessRouteItemList, addOrUpdateProcessRouteItem} from "@/api/productionManagement/processRouteItem.js";
+import { processList } from "@/api/productionManagement/productionProcess.js";
+
+const props = defineProps({
+ visible: {
+ type: Boolean,
+ required: true,
+ },
+ record: {
+ type: Object,
+ required: true,
+ }
+});
+
+const emit = defineEmits(['update:visible', 'completed']);
+
+const processOptions = ref([]);
+
+const isShow = computed({
+ get() {
+ return props.visible;
+ },
+ set(val) {
+ emit('update:visible', val);
+ },
+});
+
+const tableColumn = ref([
+ {
+ label: "浜у搧鍚嶇О",
+ prop: "productName",
+ },
+ {
+ label: "瑙勬牸鍚嶇О",
+ prop: "model",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "宸ュ簭鍚嶇О",
+ prop: "processId",
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ operation: [
+ {
+ name: "鍒犻櫎",
+ type: "danger",
+ link: true,
+ clickFun: (row) => {
+ const index = routeItems.value.indexOf(row);
+ if (index !== -1) {
+ routeItems.value.splice(index, 1);
+ }
+ }
+ },
+ ]
+ }
+])
+
+const tableLoading = ref(false);
+
+const isShowProductSelectDialog = ref(false)
+const routeItems = ref([])
+
+let { proxy } = getCurrentInstance()
+
+const closeModal = () => {
+ isShow.value = false;
+};
+
+const handelSelectProducts = (products) => {
+ const data = products.map(({ id, ...product }) => ({
+ ...product,
+ productModelId: id,
+ routeId: props.record.id
+ }));
+
+ routeItems.value.push(...data);
+}
+
+const findProcessRouteItems = () => {
+ tableLoading.value = true;
+
+ findProcessRouteItemList({routeId: props.record.id}).then(res => {
+ tableLoading.value = false;
+ routeItems.value = res.data.map(item => ({
+ ...item,
+ processId: item.processId === 0 ? undefined : item.processId
+ }))
+ }).catch(err => {
+ tableLoading.value = false;
+ })
+};
+
+const findProcessList = () => {
+ processList({}).then(res => {
+ processOptions.value = res.data
+ })
+}
+
+const handleSubmit = () => {
+ if (routeItems.value.length === 0) {
+ proxy.$modal.msgError("璇锋坊鍔犺矾绾块」鐩�");
+ return;
+ }
+
+ // 鏄惁鏈夋湭閫夋嫨鐨勫伐搴�
+ const hasUnselectedProcess = routeItems.value.some(item => !item.processId);
+ if (hasUnselectedProcess) {
+ proxy.$modal.msgError("璇烽�夋嫨宸ュ簭");
+ return;
+ }
+
+ addOrUpdateProcessRouteItem({routeId: props.record.id, processRouteItem: routeItems.value}).then(res => {
+ // 鍏抽棴妯℃�佹
+ isShow.value = false;
+ // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
+ emit('completed');
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ })
+};
+
+
+defineExpose({
+ closeModal,
+ handleSubmit,
+ isShow,
+});
+
+onMounted(() => {
+ findProcessRouteItems()
+ findProcessList()
+})
+</script>
diff --git a/src/views/productionManagement/processRoute/index.vue b/src/views/productionManagement/processRoute/index.vue
index 06a798d..7b53dfd 100644
--- a/src/views/productionManagement/processRoute/index.vue
+++ b/src/views/productionManagement/processRoute/index.vue
@@ -2,8 +2,8 @@
<div class="app-container">
<div class="search_form">
<el-form :model="searchForm" :inline="true">
- <el-form-item label="闆朵欢鍚嶇О:">
- <el-input v-model="searchForm.speculativeTradingName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+ <el-form-item label="瑙勬牸鍚嶇О:">
+ <el-input v-model="searchForm.model" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
style="width: 200px;"
@change="handleQuery" />
</el-form-item>
@@ -27,7 +27,7 @@
:tableLoading="tableLoading"
@pagination="pagination"
:total="page.total"
- ></PIMTable>
+ />
</div>
<new-process
v-if="isShowNewModal"
@@ -41,6 +41,14 @@
:record="record"
@completed="getList"
/>
+
+ <route-item-form
+ v-if="isShowItemModal"
+ v-model:visible="isShowItemModal"
+ :record="record"
+ @completed="getList"
+ />
+ RouteItemForm
</div>
</template>
@@ -48,6 +56,7 @@
import {onMounted, ref} from "vue";
import NewProcess from "@/views/productionManagement/processRoute/New.vue";
import EditProcess from "@/views/productionManagement/processRoute/Edit.vue";
+import RouteItemForm from "@/views/productionManagement/processRoute/ItemsForm.vue";
import {listPage, del} from "@/api/productionManagement/processRoute.js";
const data = reactive({
@@ -73,17 +82,17 @@
width: 280,
operation: [
{
- name: "璇︽儏",
+ name: "缂栬緫",
type: "text",
clickFun: (row) => {
showEditModal(row);
}
},
{
- name: "缂栬緫",
+ name: "璺嚎椤圭洰",
type: "text",
clickFun: (row) => {
- showEditModal(row);
+ showItemModal(row);
}
}
]
@@ -94,6 +103,7 @@
const tableLoading = ref(false);
const isShowNewModal = ref(false);
const isShowEditModal = ref(false);
+const isShowItemModal = ref(false);
const record = ref({});
const page = reactive({
current: 1,
@@ -143,6 +153,11 @@
record.value = row
};
+const showItemModal = (row) => {
+ isShowItemModal.value = true
+ record.value = row
+};
+
// 鍒犻櫎
function handleDelete() {
const ids = selectedRows.value.map((item) => item.id);
--
Gitblit v1.9.3