From 6738e8f5a78431e41fed28e6b795e70c2396070a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期四, 03 九月 2026 17:27:23 +0800
Subject: [PATCH] refactor(mes): 优化工艺路线配置与工单表单功能
---
src/views/mes/process-design/route/modules/form.vue | 146 +++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 124 insertions(+), 22 deletions(-)
diff --git a/src/views/mes/process-design/route/modules/form.vue b/src/views/mes/process-design/route/modules/form.vue
index 8c0c230..cf73e0e 100644
--- a/src/views/mes/process-design/route/modules/form.vue
+++ b/src/views/mes/process-design/route/modules/form.vue
@@ -2,24 +2,28 @@
import type { FormType } from '../data';
import type { MesProRouteApi } from '#/api/mes/pro/route';
+import type { MesProRouteProductApi } from '#/api/mes/pro/route/product';
import { computed, ref } from 'vue';
-import { useVbenModal } from '@vben/common-ui';
+import { confirm, useVbenModal } from '@vben/common-ui';
-import { message, TabPane, Tabs } from 'ant-design-vue';
+import { Button, Divider, message, Select } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { createRoute, getRoute, updateRoute } from '#/api/mes/pro/route';
+import {
+ deleteRouteProduct,
+ getRouteProductListByRoute,
+} from '#/api/mes/pro/route/product';
import { $t } from '#/locales';
import { useFormSchema } from '../data';
-import ProcessList from './process-list.vue';
-import ProductList from './product-list.vue';
+import ProductForm from './product-form.vue';
+import Workbench from './workbench.vue';
const emit = defineEmits(['success']);
const formType = ref<FormType>('create'); // 琛ㄥ崟妯″紡
-const subTab = ref('process'); // 褰撳墠婵�娲荤殑瀛愯〃 Tab
const formData = ref<MesProRouteApi.Route>();
const isDetail = computed(() => formType.value === 'detail'); // 鏄惁鏌ョ湅妯″紡
@@ -32,6 +36,72 @@
: $t('ui.actionTitle.create', ['宸ヨ壓璺嚎']);
});
+// ==================== 浜у搧缁戝畾 ====================
+const products = ref<MesProRouteProductApi.RouteProduct[]>([]); // 鍏宠仈浜у搧鍒楄〃
+const selectedProductItemId = ref<number>(); // 褰撳墠閫変腑鐨勪骇鍝佺墿鏂欑紪鍙�
+const selectedProduct = computed(() =>
+ products.value.find((item) => item.itemId === selectedProductItemId.value),
+);
+const productOptions = computed(() =>
+ products.value.map((item) => ({ label: item.itemName, value: item.itemId })),
+);
+
+async function loadProducts() {
+ const routeId = formData.value?.id;
+ if (!routeId) {
+ products.value = [];
+ return;
+ }
+ products.value = (await getRouteProductListByRoute(routeId)) || [];
+ if (
+ !products.value.some((item) => item.itemId === selectedProductItemId.value)
+ ) {
+ selectedProductItemId.value = products.value[0]?.itemId;
+ }
+}
+
+const [ProductFormModal, productFormModalApi] = useVbenModal({
+ connectedComponent: ProductForm,
+ destroyOnClose: true,
+});
+
+/** 鎵撳紑浜у搧寮圭獥锛堢粦瀹� / 缂栬緫锛� */
+function openProductForm(row?: MesProRouteProductApi.RouteProduct) {
+ if (!formData.value?.id) {
+ return;
+ }
+ productFormModalApi
+ .setData(
+ row
+ ? { id: row.id, routeId: formData.value.id }
+ : {
+ routeId: formData.value.id,
+ boundItemIds: products.value
+ .map((item) => item.itemId)
+ .filter((id): id is number => id != null),
+ },
+ )
+ .open();
+}
+
+/** 绉婚櫎浜у搧锛堜細绾ц仈鍒犻櫎璇ヤ骇鍝佺殑鎶曞叆鐗╂枡閰嶇疆锛� */
+async function handleRemoveProduct() {
+ if (!selectedProduct.value?.id) {
+ return;
+ }
+ try {
+ await confirm(
+ `纭灏嗕骇鍝併��${selectedProduct.value.itemName}銆嶄粠璇ュ伐鑹鸿矾绾跨Щ闄わ紵鍏跺叏閮ㄦ姇鍏ョ墿鏂欓厤缃皢涓�骞跺垹闄ゃ�俙,
+ );
+ } catch {
+ return;
+ }
+ await deleteRouteProduct(selectedProduct.value.id);
+ message.success($t('ui.actionMessage.operationSuccess'));
+ await loadProducts();
+}
+
+// ==================== 鍩烘湰淇℃伅琛ㄥ崟 ====================
const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: { class: 'w-full' },
@@ -59,11 +129,12 @@
const data = (await formApi.getValues()) as MesProRouteApi.Route;
try {
if (formType.value === 'create') {
- // 鏂板鎴愬姛鍚庡垏鍒扮紪杈戞ā寮忥紝鏂逛究缁х画缁存姢缁勬垚宸ュ簭銆佸叧鑱斾骇鍝�
+ // 鏂板鎴愬姛鍚庡垏鍒扮紪杈戞ā寮忥紝杩涘叆銆屼骇鍝佷笌宸ュ簭閰嶇疆銆嶅伐浣滃彴
const id = await createRoute(data);
formData.value = { ...data, id };
await formApi.setFieldValue('id', id);
formType.value = 'update';
+ await loadProducts();
} else {
await updateRoute(data);
formData.value = { ...formData.value, ...data };
@@ -82,10 +153,11 @@
async onOpenChange(isOpen: boolean) {
if (!isOpen) {
formData.value = undefined;
+ products.value = [];
+ selectedProductItemId.value = undefined;
return;
}
formApi.setState({ schema: useFormSchema(formApi) });
- subTab.value = 'process';
// 鍔犺浇鏁版嵁
const data = modalApi.getData<{ formType: FormType; id?: number }>();
formType.value = data.formType;
@@ -99,6 +171,7 @@
formData.value = await getRoute(data.id);
// 璁剧疆鍒� values
await formApi.setValues(formData.value);
+ await loadProducts();
} finally {
modalApi.unlock();
}
@@ -107,20 +180,49 @@
</script>
<template>
- <Modal :title="getTitle" class="w-4/5">
+ <Modal :title="getTitle" class="w-11/12">
<Form class="mx-4" />
- <!-- 缂栬緫/璇︽儏妯″紡涓嬪睍绀哄瓙琛� Tab锛屾柊澧炴ā寮忎笅闅愯棌 -->
- <Tabs
- v-if="formType !== 'create' && formData?.id"
- v-model:active-key="subTab"
- class="mx-4 mt-4"
- >
- <TabPane key="process" tab="缁勬垚宸ュ簭">
- <ProcessList :form-type="formType" :route-id="formData.id" />
- </TabPane>
- <TabPane key="product" tab="鍏宠仈浜у搧">
- <ProductList :form-type="formType" :route-id="formData.id" />
- </TabPane>
- </Tabs>
+ <!-- 缂栬緫/璇︽儏妯″紡涓嬪睍绀恒�屼骇鍝佷笌宸ュ簭閰嶇疆銆嶅伐浣滃彴锛屾柊澧炴ā寮忎笅闅愯棌 -->
+ <template v-if="formData?.id">
+ <div class="mx-4 mt-4">
+ <Divider class="!my-2" orientation="left">
+ <span class="text-sm">浜у搧涓庡伐搴忛厤缃�</span>
+ </Divider>
+ <div class="flex flex-wrap items-center gap-3">
+ <span class="shrink-0 text-sm font-medium">鐢熶骇浜у搧</span>
+ <Select
+ v-model:value="selectedProductItemId"
+ class="!w-64"
+ allow-clear
+ :disabled="isDetail"
+ placeholder="璇烽�夋嫨鎴栫粦瀹氫骇鍝�"
+ :options="productOptions"
+ />
+ <template v-if="!isDetail">
+ <Button type="primary" @click="openProductForm()"> 缁戝畾浜у搧 </Button>
+ <Button
+ :disabled="!selectedProduct"
+ @click="openProductForm(selectedProduct)"
+ >
+ 缂栬緫浜у搧
+ </Button>
+ <Button danger :disabled="!selectedProduct" @click="handleRemoveProduct">
+ 绉婚櫎浜у搧
+ </Button>
+ </template>
+ </div>
+ <p v-if="products.length === 0" class="mt-2 text-xs text-gray-400">
+ 鍏堢粦瀹氳鐢熶骇鐨勭墿鏂欙紝鍐嶄负姣忛亾宸ュ簭閰嶇疆銆屾姇鍏� + 浜у嚭銆�
+ </p>
+ <div class="mt-3">
+ <Workbench
+ :form-type="formType"
+ :product="selectedProduct"
+ :route-id="formData.id"
+ />
+ </div>
+ </div>
+ </template>
</Modal>
-</template>
+ <ProductFormModal @success="loadProducts" />
+</template>
\ No newline at end of file
--
Gitblit v1.9.3