From d4e039545c9e97347223eb415fbba85ee01bc263 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期六, 11 四月 2026 10:10:14 +0800
Subject: [PATCH] #页面优化

---
 rsf-design/src/views/orders/transfer/modules/transfer-dialog.vue |  342 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 286 insertions(+), 56 deletions(-)

diff --git a/rsf-design/src/views/orders/transfer/modules/transfer-dialog.vue b/rsf-design/src/views/orders/transfer/modules/transfer-dialog.vue
index 43e6a52..a799a82 100644
--- a/rsf-design/src/views/orders/transfer/modules/transfer-dialog.vue
+++ b/rsf-design/src/views/orders/transfer/modules/transfer-dialog.vue
@@ -1,36 +1,226 @@
+<template>
+  <ElDialog
+    :model-value="visible"
+    :title="dialogTitle"
+    width="92%"
+    top="4vh"
+    destroy-on-close
+    @update:model-value="handleVisibleChange"
+    @closed="handleClosed"
+  >
+    <div class="flex flex-col gap-4">
+      <ArtForm
+        ref="formRef"
+        v-model="form"
+        :items="formItems"
+        :rules="rules"
+        :span="8"
+        :gutter="20"
+        label-width="110px"
+        :show-reset="false"
+        :show-submit="false"
+      />
+
+      <div class="flex flex-wrap items-center justify-between gap-3">
+        <ElSpace wrap>
+          <ElButton type="primary" @click="handleOpenMaterialDialog">
+            {{ t('pages.orders.transfer.dialog.addMaterial') }}
+          </ElButton>
+          <ElButton
+            type="danger"
+            plain
+            :disabled="isEdit || selectedItemKeys.length === 0"
+            @click="handleBatchRemove"
+          >
+            {{ t('pages.orders.transfer.dialog.deleteSelected') }}
+          </ElButton>
+        </ElSpace>
+        <div class="text-xs text-[var(--art-gray-600)]">
+          {{ t('pages.orders.transfer.dialog.itemCount', { count: itemRows.length }) }}
+        </div>
+      </div>
+
+      <ElTable
+        :data="itemRows"
+        row-key="__rowKey"
+        border
+        size="small"
+        max-height="420"
+        @selection-change="handleItemSelectionChange"
+      >
+        <ElTableColumn type="selection" width="48" align="center" />
+        <ElTableColumn type="index" :label="t('table.index')" width="72" align="center" />
+        <ElTableColumn
+          prop="matnrCode"
+          :label="t('table.materialCode')"
+          min-width="140"
+          show-overflow-tooltip
+        />
+        <ElTableColumn
+          prop="maktx"
+          :label="t('table.materialName')"
+          min-width="220"
+          show-overflow-tooltip
+        />
+        <ElTableColumn
+          prop="spec"
+          :label="t('pages.orders.transferItem.table.spec')"
+          min-width="140"
+          show-overflow-tooltip
+        />
+        <ElTableColumn
+          prop="model"
+          :label="t('pages.orders.transferItem.table.model')"
+          min-width="140"
+          show-overflow-tooltip
+        />
+        <ElTableColumn :label="t('table.quantity')" width="150" align="right">
+          <template #default="{ row }">
+            <ElInputNumber
+              v-model="row.anfme"
+              :min="0"
+              :precision="2"
+              controls-position="right"
+              class="w-full"
+            />
+          </template>
+        </ElTableColumn>
+        <ElTableColumn
+          :label="t('pages.orders.transfer.dialog.supplierCode')"
+          min-width="150"
+          show-overflow-tooltip
+        >
+          <template #default="{ row }">
+            <ElInput v-model="row.splrCode" clearable />
+          </template>
+        </ElTableColumn>
+        <ElTableColumn
+          :label="t('pages.orders.transfer.dialog.supplierName')"
+          min-width="180"
+          show-overflow-tooltip
+        >
+          <template #default="{ row }">
+            <ElInput v-model="row.splrName" clearable />
+          </template>
+        </ElTableColumn>
+        <ElTableColumn :label="t('table.batch')" min-width="140" show-overflow-tooltip>
+          <template #default="{ row }">
+            <ElInput v-model="row.batch" clearable />
+          </template>
+        </ElTableColumn>
+        <ElTableColumn :label="t('table.unit')" width="120" align="center">
+          <template #default="{ row }">
+            <ElInput v-model="row.unit" clearable />
+          </template>
+        </ElTableColumn>
+        <ElTableColumn
+          v-for="field in fieldDefinitions"
+          :key="field.fields"
+          :label="field.fieldsAlise || field.fields"
+          min-width="140"
+        >
+          <template #default="{ row }">
+            <ElInput v-model="row[field.fields]" clearable />
+          </template>
+        </ElTableColumn>
+        <ElTableColumn :label="t('table.operation')" fixed="right" width="88" align="center">
+          <template #default="{ row }">
+            <ElButton link type="danger" :disabled="isEdit" @click="handleRemoveRow(row)">
+              {{ t('pages.orders.transfer.actions.delete') }}
+            </ElButton>
+          </template>
+        </ElTableColumn>
+      </ElTable>
+    </div>
+
+    <template #footer>
+      <ElSpace>
+        <ElButton @click="handleVisibleChange(false)">{{ t('common.cancel') }}</ElButton>
+        <ElButton type="primary" :loading="submitLoading" @click="handleSubmit">
+          {{ t('common.confirm') }}
+        </ElButton>
+      </ElSpace>
+    </template>
+
+    <TransferMaterialDialog
+      v-model:visible="materialDialogVisible"
+      :org-area-id="form.orgAreaId"
+      :field-definitions="fieldDefinitions"
+      :selected-matnr-ids="selectedMatnrIds"
+      @confirm="handleMaterialConfirm"
+    />
+  </ElDialog>
+</template>
+
 <script setup>
   import { computed, nextTick, reactive, ref, watch } from 'vue'
+  import { ElMessage } from 'element-plus'
   import { useI18n } from 'vue-i18n'
   import ArtForm from '@/components/core/forms/art-form/index.vue'
   import {
-    buildTransferDialogModel,
-    createTransferFormState,
-    getTransferStatusOptions
+    buildTransferManageDialogModel,
+    createTransferEditableItemFromMaterial,
+    createTransferFormState
   } from '../transferPage.helpers.js'
+  import TransferMaterialDialog from './transfer-material-dialog.vue'
 
   const props = defineProps({
     visible: { type: Boolean, default: false },
     dialogType: { type: String, default: 'add' },
-    transferData: { type: Object, default: () => ({}) },
+    transferData: {
+      type: Object,
+      default: () => ({
+        transfer: {},
+        items: []
+      })
+    },
     typeOptions: { type: Array, default: () => [] },
     areaOptions: { type: Array, default: () => [] },
+    fieldDefinitions: { type: Array, default: () => [] },
     submitLoading: { type: Boolean, default: false }
   })
 
   const emit = defineEmits(['update:visible', 'submit'])
+  const { t } = useI18n()
+
   const formRef = ref()
   const form = reactive(createTransferFormState())
-  const { t } = useI18n()
+  const itemRows = ref([])
+  const selectedItemKeys = ref([])
+  const materialDialogVisible = ref(false)
 
   const isEdit = computed(() => props.dialogType === 'edit')
   const dialogTitle = computed(() =>
-    isEdit.value ? t('pages.orders.transfer.dialog.titleEdit') : t('pages.orders.transfer.dialog.titleAdd')
+    isEdit.value
+      ? t('pages.orders.transfer.dialog.titleEdit')
+      : t('pages.orders.transfer.dialog.titleAdd')
+  )
+  const selectedMatnrIds = computed(() =>
+    itemRows.value.map((item) => item.matnrId).filter((item) => item !== undefined && item !== null)
   )
 
   const rules = computed(() => ({
-    type: [{ required: true, message: t('pages.orders.transfer.dialog.validation.type'), trigger: 'change' }],
-    orgAreaId: [{ required: true, message: t('pages.orders.transfer.dialog.validation.orgAreaId'), trigger: 'change' }],
-    tarAreaId: [{ required: true, message: t('pages.orders.transfer.dialog.validation.tarAreaId'), trigger: 'change' }]
+    type: [
+      {
+        required: true,
+        message: t('pages.orders.transfer.dialog.validation.type'),
+        trigger: 'change'
+      }
+    ],
+    orgAreaId: [
+      {
+        required: true,
+        message: t('pages.orders.transfer.dialog.validation.orgAreaId'),
+        trigger: 'change'
+      }
+    ],
+    tarAreaId: [
+      {
+        required: true,
+        message: t('pages.orders.transfer.dialog.validation.tarAreaId'),
+        trigger: 'change'
+      }
+    ]
   }))
 
   const formItems = computed(() => [
@@ -84,7 +274,10 @@
       props: {
         placeholder: t('pages.orders.transfer.dialog.placeholderStatus'),
         clearable: true,
-        options: getTransferStatusOptions()
+        options: [
+          { label: t('pages.orders.transfer.status.normal'), value: 1 },
+          { label: t('pages.orders.transfer.status.frozen'), value: 0 }
+        ]
       }
     },
     {
@@ -101,38 +294,110 @@
     }
   ])
 
-  const loadFormData = () => {
-    Object.assign(form, buildTransferDialogModel(props.transferData))
+  function loadDialogData() {
+    const dialogData = buildTransferManageDialogModel(props.transferData, props.fieldDefinitions)
+    Object.assign(form, dialogData.transfer)
+    itemRows.value = dialogData.items
+    selectedItemKeys.value = []
   }
 
-  const resetForm = () => {
+  function resetDialogData() {
     Object.assign(form, createTransferFormState())
+    itemRows.value = []
+    selectedItemKeys.value = []
+    materialDialogVisible.value = false
     formRef.value?.clearValidate?.()
   }
 
-  const handleSubmit = async () => {
+  function handleItemSelectionChange(rows) {
+    selectedItemKeys.value = Array.isArray(rows) ? rows.map((item) => item.__rowKey) : []
+  }
+
+  function handleRemoveRow(row) {
+    itemRows.value = itemRows.value.filter((item) => item.__rowKey !== row.__rowKey)
+    selectedItemKeys.value = selectedItemKeys.value.filter((item) => item !== row.__rowKey)
+  }
+
+  function handleBatchRemove() {
+    if (!selectedItemKeys.value.length) return
+    const selectedKeySet = new Set(selectedItemKeys.value)
+    itemRows.value = itemRows.value.filter((item) => !selectedKeySet.has(item.__rowKey))
+    selectedItemKeys.value = []
+  }
+
+  function handleOpenMaterialDialog() {
+    if (!form.orgAreaId) {
+      ElMessage.warning(t('pages.orders.transfer.dialog.validation.orgAreaId'))
+      return
+    }
+    if (!form.tarAreaId) {
+      ElMessage.warning(t('pages.orders.transfer.dialog.validation.tarAreaId'))
+      return
+    }
+    materialDialogVisible.value = true
+  }
+
+  function handleMaterialConfirm(rows) {
+    const existingMatnrIds = new Set(selectedMatnrIds.value)
+    const nextRows = rows
+      .map((item) => createTransferEditableItemFromMaterial(item, props.fieldDefinitions))
+      .filter((item) => !existingMatnrIds.has(item.matnrId))
+
+    if (!nextRows.length) {
+      ElMessage.warning(t('pages.orders.transfer.dialog.materialDuplicate'))
+      return
+    }
+
+    itemRows.value = [...itemRows.value, ...nextRows]
+  }
+
+  function validateItems() {
+    if (!itemRows.value.length) {
+      ElMessage.warning(t('pages.orders.transfer.dialog.validation.items'))
+      return false
+    }
+
+    const invalidRow = itemRows.value.find((item) => Number(item.anfme) <= 0)
+    if (invalidRow) {
+      ElMessage.warning(t('pages.orders.transfer.dialog.validation.anfme'))
+      return false
+    }
+
+    return true
+  }
+
+  async function handleSubmit() {
     if (!formRef.value) return
+
     try {
       await formRef.value.validate()
-      emit('submit', { ...form })
     } catch {
       return
     }
+
+    if (!validateItems()) {
+      return
+    }
+
+    emit('submit', {
+      transfer: { ...form },
+      items: itemRows.value.map((item) => ({ ...item }))
+    })
   }
 
-  const handleCancel = () => {
-    emit('update:visible', false)
+  function handleVisibleChange(visible) {
+    emit('update:visible', visible)
   }
 
-  const handleClosed = () => {
-    resetForm()
+  function handleClosed() {
+    resetDialogData()
   }
 
   watch(
     () => props.visible,
     (visible) => {
       if (visible) {
-        loadFormData()
+        loadDialogData()
         nextTick(() => {
           formRef.value?.clearValidate?.()
         })
@@ -145,44 +410,9 @@
     () => props.transferData,
     () => {
       if (props.visible) {
-        loadFormData()
+        loadDialogData()
       }
     },
     { deep: true }
   )
 </script>
-
-<template>
-  <ElDialog
-    :title="dialogTitle"
-    :model-value="visible"
-    width="760px"
-    align-center
-    destroy-on-close
-    @update:model-value="handleCancel"
-    @closed="handleClosed"
-  >
-    <div class="mb-3 rounded-lg border border-[var(--art-border-color)] bg-[var(--art-bg-color)] px-3 py-2 text-xs text-[var(--art-text-gray-600)]">
-      {{ t('pages.orders.transfer.dialog.tip') }}
-    </div>
-
-    <ArtForm
-      ref="formRef"
-      v-model="form"
-      :items="formItems"
-      :rules="rules"
-      :span="12"
-      :gutter="20"
-      label-width="110px"
-      :show-reset="false"
-      :show-submit="false"
-    />
-
-    <template #footer>
-      <span class="dialog-footer">
-        <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton>
-        <ElButton type="primary" :loading="submitLoading" @click="handleSubmit">{{ t('common.confirm') }}</ElButton>
-      </span>
-    </template>
-  </ElDialog>
-</template>

--
Gitblit v1.9.1