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