From f08a81f01bc4a4104dd9ef04e071bb0bd0eb8afe Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 23 七月 2026 10:50:19 +0800
Subject: [PATCH] Merge branch 'dev_pro2.0' of http://114.132.189.42:9002/r/mom-pro2-before into dev_pro2.0
---
src/views/mes/pro/workorder/modules/process-list.vue | 304 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 304 insertions(+), 0 deletions(-)
diff --git a/src/views/mes/pro/workorder/modules/process-list.vue b/src/views/mes/pro/workorder/modules/process-list.vue
new file mode 100644
index 0000000..35ac698
--- /dev/null
+++ b/src/views/mes/pro/workorder/modules/process-list.vue
@@ -0,0 +1,304 @@
+<script lang="ts" setup>
+import type { FormType } from '../data';
+
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { MesProWorkOrderApi } from '#/api/mes/pro/workorder';
+import type { MesProWorkOrderProcessApi } from '#/api/mes/pro/workorder/process';
+
+import { computed, nextTick, onUnmounted, ref, watch } from 'vue';
+
+import { useVbenModal } from '@vben/common-ui';
+import { MesProWorkOrderStatusEnum } from '@vben/constants';
+import { IconifyIcon } from '@vben/icons';
+
+import { useSortable } from '@vueuse/integrations/useSortable';
+import { message, Tag } from 'ant-design-vue';
+
+import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
+import {
+ deleteWorkOrderProcess,
+ getWorkOrderProcessListByWorkOrderId,
+} from '#/api/mes/pro/workorder/process';
+import { getRouteProcessListByProduct } from '#/api/mes/pro/route/process';
+import { $t } from '#/locales';
+
+import { useProcessGridColumns } from '../data';
+import ProcessForm from './process-form.vue';
+
+const props = defineProps<{
+ formType: FormType;
+ workOrder: MesProWorkOrderApi.WorkOrder;
+ workOrderId?: number;
+ productId?: number;
+}>();
+
+const emit = defineEmits<{
+ processListChange: [list: MesProWorkOrderProcessApi.WorkOrderProcess[]];
+}>();
+
+// 宸ュ簭鍒楄〃鏁版嵁
+const list = ref<MesProWorkOrderProcessApi.WorkOrderProcess[]>([]);
+
+const isEditable = computed(() =>
+ ['create', 'update'].includes(props.formType) &&
+ (props.workOrder?.status === MesProWorkOrderStatusEnum.PREPARE ||
+ props.formType === 'create'),
+);
+
+const isCreateMode = computed(() => props.formType === 'create');
+
+// 鎷栨嫿鎺掑簭
+const sortableInstance = ref<any>(null);
+
+const [ProcessFormModal, processFormModalApi] = useVbenModal({
+ connectedComponent: ProcessForm,
+ destroyOnClose: true,
+});
+
+const [Grid, gridApi] = useVbenVxeGrid({
+ gridOptions: {
+ autoResize: true,
+ border: true,
+ columns: useProcessGridColumns(isEditable.value),
+ data: [],
+ minHeight: 240,
+ pagerConfig: { enabled: false },
+ rowConfig: { isHover: true, keyField: 'processId' },
+ showOverflow: true,
+ toolbarConfig: { enabled: false },
+ } as VxeTableGridOptions<MesProWorkOrderProcessApi.WorkOrderProcess>,
+});
+
+/** 鍒濆鍖�/閿�姣佹嫋鎷芥帓搴� */
+async function initSortable() {
+ destroySortable();
+ if (!isEditable.value || list.value.length === 0) return;
+ await nextTick();
+ sortableInstance.value = useSortable(
+ '.workorder-process-list .vxe-table--body-wrapper:not(.fixed-right--wrapper) .vxe-table--body tbody',
+ list.value,
+ {
+ animation: 150,
+ draggable: '.vxe-body--row',
+ handle: '.drag-handle',
+ onEnd: ({ newDraggableIndex, oldDraggableIndex }) => {
+ if (
+ newDraggableIndex !== undefined &&
+ oldDraggableIndex !== undefined &&
+ oldDraggableIndex !== newDraggableIndex
+ ) {
+ // 閲嶆柊鎺掑簭鏁扮粍
+ list.value.splice(
+ newDraggableIndex,
+ 0,
+ list.value.splice(oldDraggableIndex, 1)[0]!,
+ );
+ // 鏇存柊 sort 瀛楁
+ list.value.forEach((item, index) => {
+ item.sort = index + 1;
+ });
+ gridApi.setGridOptions({ data: list.value });
+ emit('processListChange', list.value);
+ }
+ },
+ },
+ );
+}
+
+/** 閿�姣佹嫋鎷芥帓搴忓疄渚� */
+function destroySortable() {
+ if (sortableInstance.value) {
+ sortableInstance.value.stop?.();
+ sortableInstance.value = null;
+ }
+}
+
+/** 鍔犺浇宸ュ簭鍒楄〃 */
+async function getList() {
+ gridApi.setLoading(true);
+ try {
+ if (isCreateMode.value) {
+ // 鏂板妯″紡锛氫粠宸ヨ壓璺嚎鑾峰彇
+ if (!props.productId) {
+ list.value = [];
+ } else {
+ // 璋冪敤宸ヨ壓璺嚎鎺ュ彛鑾峰彇宸ュ簭鍒楄〃
+ const routeProcessList = await getRouteProcessListByProduct(props.productId);
+ // 杞崲涓哄伐鍗曞伐搴忔牸寮�
+ list.value = routeProcessList.map((item) => ({
+ processId: item.processId,
+ processCode: item.processCode,
+ processName: item.processName,
+ sort: item.sort,
+ nextProcessId: item.nextProcessId,
+ nextProcessName: item.nextProcessName,
+ linkType: item.linkType,
+ prepareTime: item.prepareTime,
+ waitTime: item.waitTime,
+ colorCode: item.colorCode,
+ keyFlag: item.keyFlag,
+ checkFlag: item.checkFlag,
+ backflushFlag: item.backflushFlag,
+ outputItemId: item.outputItemId,
+ outputItemCode: item.outputItemCode,
+ outputItemName: item.outputItemName,
+ remark: item.remark,
+ }));
+ }
+ } else {
+ // 缂栬緫妯″紡锛氫粠宸ュ崟宸ュ簭鑾峰彇
+ if (!props.workOrderId) {
+ list.value = [];
+ } else {
+ list.value = await getWorkOrderProcessListByWorkOrderId(props.workOrderId);
+ }
+ }
+ gridApi.setGridOptions({ data: list.value });
+ emit('processListChange', list.value);
+ // 鍒濆鍖栨嫋鎷芥帓搴�
+ initSortable();
+ } finally {
+ gridApi.setLoading(false);
+ }
+}
+
+/** 娣诲姞宸ュ簭 */
+function handleCreate() {
+ processFormModalApi
+ .setData({
+ workOrderId: props.workOrderId,
+ productId: props.productId || props.workOrder?.productId,
+ processList: list.value,
+ })
+ .open();
+}
+
+/** 缂栬緫宸ュ簭 */
+function handleEdit(row: MesProWorkOrderProcessApi.WorkOrderProcess) {
+ processFormModalApi
+ .setData({
+ id: row.id,
+ workOrderId: props.workOrderId,
+ productId: props.productId || props.workOrder?.productId,
+ row,
+ processList: list.value,
+ })
+ .open();
+}
+
+/** 鏂板/缂栬緫鎴愬姛鍥炶皟 */
+function handleFormSuccess(data: MesProWorkOrderProcessApi.WorkOrderProcess, isEdit: boolean) {
+ if (isCreateMode.value) {
+ if (isEdit) {
+ const index = list.value.findIndex((item) => item.processId === data.processId);
+ if (index > -1) {
+ list.value[index] = data;
+ }
+ } else {
+ list.value.push(data);
+ }
+ gridApi.setGridOptions({ data: list.value });
+ emit('processListChange', list.value);
+ initSortable();
+ } else {
+ getList();
+ }
+}
+
+/** 鍒犻櫎宸ュ簭 */
+function handleDelete(row: MesProWorkOrderProcessApi.WorkOrderProcess) {
+ if (isCreateMode.value) {
+ // 鏂板妯″紡锛氫粠鍒楄〃鍒犻櫎
+ const index = list.value.findIndex((item) => item.processId === row.processId);
+ if (index > -1) {
+ list.value.splice(index, 1);
+ // 鏇存柊 sort 瀛楁
+ list.value.forEach((item, idx) => {
+ item.sort = idx + 1;
+ });
+ gridApi.setGridOptions({ data: list.value });
+ emit('processListChange', list.value);
+ initSortable();
+ }
+ } else {
+ // 缂栬緫妯″紡锛氳皟鐢ㄦ帴鍙e垹闄�
+ deleteWorkOrderProcess(row.id!).then(() => {
+ message.success($t('ui.actionMessage.deleteSuccess', [row.processName]));
+ getList();
+ });
+ }
+}
+
+// 缁勪欢鍗歌浇鏃堕攢姣佹帓搴忓疄渚�
+onUnmounted(() => {
+ destroySortable();
+});
+
+// 鐩戝惉浜у搧/宸ュ崟鍙樺寲
+watch(
+ () => [props.productId, props.workOrderId],
+ () => {
+ getList();
+ },
+ { immediate: true },
+);
+</script>
+
+<template>
+ <div class="workorder-process-list">
+ <ProcessFormModal @success="handleFormSuccess" />
+ <div v-if="isEditable" class="mb-3 flex items-center justify-start">
+ <TableAction
+ :actions="[
+ {
+ label: '娣诲姞宸ュ簭',
+ type: 'primary',
+ onClick: handleCreate,
+ },
+ ]"
+ />
+ </div>
+ <Grid class="w-full" table-title="宸ュ簭">
+ <template #dragHandle>
+ <IconifyIcon
+ icon="ic:round-drag-indicator"
+ class="drag-handle cursor-move text-xl text-gray-400"
+ />
+ </template>
+ <template #keyFlag="{ row }">
+ <Tag v-if="row.keyFlag" color="red">鍏抽敭</Tag>
+ <span v-else>-</span>
+ </template>
+ <template #checkFlag="{ row }">
+ <Tag v-if="row.checkFlag" color="blue">璐ㄦ</Tag>
+ <span v-else>-</span>
+ </template>
+ <template #backflushFlag="{ row }">
+ <Tag v-if="row.backflushFlag" color="green">鏄�</Tag>
+ <Tag v-else color="default">鍚�</Tag>
+ </template>
+ <template #actions="{ row }">
+ <TableAction
+ :actions="[
+ {
+ label: $t('common.edit'),
+ type: 'link',
+ ifShow: isEditable,
+ onClick: handleEdit.bind(null, row),
+ },
+ {
+ label: $t('common.delete'),
+ type: 'link',
+ danger: true,
+ ifShow: isEditable,
+ popConfirm: {
+ title: $t('ui.actionMessage.deleteConfirm', [row.processName]),
+ confirm: handleDelete.bind(null, row),
+ },
+ },
+ ]"
+ />
+ </template>
+ </Grid>
+ </div>
+</template>
\ No newline at end of file
--
Gitblit v1.9.3