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/index.vue |  252 ++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 201 insertions(+), 51 deletions(-)

diff --git a/rsf-design/src/views/orders/transfer/index.vue b/rsf-design/src/views/orders/transfer/index.vue
index 3de4a1d..f57b73c 100644
--- a/rsf-design/src/views/orders/transfer/index.vue
+++ b/rsf-design/src/views/orders/transfer/index.vue
@@ -12,7 +12,9 @@
       <ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData">
         <template #left>
           <ElSpace wrap>
-            <ElButton v-if="canCreate" type="primary" @click="showDialog('add')" v-ripple>{{ t('pages.orders.transfer.actions.add') }}</ElButton>
+            <ElButton v-if="canCreate" type="primary" @click="showDialog('add')" v-ripple>{{
+              t('pages.orders.transfer.actions.add')
+            }}</ElButton>
             <ElButton
               v-if="canDelete"
               type="danger"
@@ -57,6 +59,7 @@
         :transfer-data="currentTransferData"
         :type-options="typeOptions"
         :area-options="areaOptions"
+        :field-definitions="fieldDefinitions"
         :submit-loading="dialogSubmitting"
         @submit="handleDialogSubmit"
       />
@@ -68,6 +71,7 @@
         :detail="detailData"
         :order-rows="detailOrderRows"
         :order-pagination="detailOrderPagination"
+        :on-order-view="handleViewRelatedOrder"
         @size-change="handleDetailSizeChange"
         @current-change="handleDetailCurrentChange"
       />
@@ -90,16 +94,18 @@
   import { guardRequestWithMessage } from '@/utils/sys/requestGuard'
   import { fetchDictDataPage } from '@/api/system-manage'
   import { fetchWarehouseAreasList } from '@/api/warehouse-areas'
+  import { fetchTransferItemList } from '@/api/transfer-item'
   import {
     fetchDeleteTransfer,
+    fetchEnabledTransferFields,
     fetchExportTransferReport,
     fetchTransferDetail,
     fetchTransferMany,
+    fetchSaveTransferItems,
     fetchTransferOrdersPage,
     fetchTransferPage,
     fetchTransferPubOutStock,
-    fetchSaveTransfer,
-    fetchUpdateTransfer
+    fetchUpdateTransferItems
   } from '@/api/transfer'
   import TransferDialog from './modules/transfer-dialog.vue'
   import TransferDetailDrawer from './modules/transfer-detail-drawer.vue'
@@ -107,11 +113,11 @@
   import {
     TRANSFER_REPORT_STYLE,
     buildTransferDetailOrderQueryParams,
-    buildTransferDialogModel,
+    buildTransferItemsSavePayload,
+    buildTransferManageDialogModel,
     buildTransferPageQueryParams,
     buildTransferPrintRows,
     buildTransferReportMeta,
-    buildTransferSavePayload,
     buildTransferSearchParams,
     createTransferFormState,
     createTransferSearchState,
@@ -138,6 +144,7 @@
   const searchForm = ref(createTransferSearchState())
   const typeOptions = ref([])
   const areaOptions = ref([])
+  const fieldDefinitions = ref([])
   const selectedRows = ref([])
   const detailDrawerVisible = ref(false)
   const detailLoading = ref(false)
@@ -159,8 +166,18 @@
 
   const reportQueryParams = computed(() => buildTransferSearchParams(searchForm.value))
   const searchItems = computed(() => [
-    { label: t('pages.orders.transfer.search.condition'), key: 'condition', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.condition') } },
-    { label: t('pages.orders.transfer.search.code'), key: 'code', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.code') } },
+    {
+      label: t('pages.orders.transfer.search.condition'),
+      key: 'condition',
+      type: 'input',
+      props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.condition') }
+    },
+    {
+      label: t('pages.orders.transfer.search.code'),
+      key: 'code',
+      type: 'input',
+      props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.code') }
+    },
     {
       label: t('pages.orders.transfer.search.type'),
       key: 'type',
@@ -179,17 +196,94 @@
       type: 'select',
       props: { clearable: true, options: getTransferExceStatusOptions(t) }
     },
-    { label: t('pages.orders.transfer.search.orgWareName'), key: 'orgWareName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgWareName') } },
-    { label: t('pages.orders.transfer.search.tarWareName'), key: 'tarWareName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarWareName') } },
-    { label: t('pages.orders.transfer.search.orgAreaName'), key: 'orgAreaName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgAreaName') } },
-    { label: t('pages.orders.transfer.search.tarAreaName'), key: 'tarAreaName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarAreaName') } },
+    {
+      label: t('pages.orders.transfer.search.timeStart'),
+      key: 'timeStart',
+      type: 'date',
+      props: { clearable: true, type: 'date', valueFormat: 'YYYY-MM-DD' }
+    },
+    {
+      label: t('pages.orders.transfer.search.timeEnd'),
+      key: 'timeEnd',
+      type: 'date',
+      props: { clearable: true, type: 'date', valueFormat: 'YYYY-MM-DD' }
+    },
+    {
+      label: t('pages.orders.transfer.search.orgWareId'),
+      key: 'orgWareId',
+      type: 'inputNumber',
+      props: {
+        clearable: true,
+        controlsPosition: 'right',
+        placeholder: t('pages.orders.transfer.placeholder.orgWareId')
+      }
+    },
+    {
+      label: t('pages.orders.transfer.search.orgWareName'),
+      key: 'orgWareName',
+      type: 'input',
+      props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgWareName') }
+    },
+    {
+      label: t('pages.orders.transfer.search.tarWareId'),
+      key: 'tarWareId',
+      type: 'inputNumber',
+      props: {
+        clearable: true,
+        controlsPosition: 'right',
+        placeholder: t('pages.orders.transfer.placeholder.tarWareId')
+      }
+    },
+    {
+      label: t('pages.orders.transfer.search.tarWareName'),
+      key: 'tarWareName',
+      type: 'input',
+      props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarWareName') }
+    },
+    {
+      label: t('pages.orders.transfer.search.orgAreaId'),
+      key: 'orgAreaId',
+      type: 'inputNumber',
+      props: {
+        clearable: true,
+        controlsPosition: 'right',
+        placeholder: t('pages.orders.transfer.placeholder.orgAreaId')
+      }
+    },
+    {
+      label: t('pages.orders.transfer.search.orgAreaName'),
+      key: 'orgAreaName',
+      type: 'input',
+      props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgAreaName') }
+    },
+    {
+      label: t('pages.orders.transfer.search.tarAreaId'),
+      key: 'tarAreaId',
+      type: 'inputNumber',
+      props: {
+        clearable: true,
+        controlsPosition: 'right',
+        placeholder: t('pages.orders.transfer.placeholder.tarAreaId')
+      }
+    },
+    {
+      label: t('pages.orders.transfer.search.tarAreaName'),
+      key: 'tarAreaName',
+      type: 'input',
+      props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarAreaName') }
+    },
     {
       label: t('pages.orders.transfer.search.status'),
       key: 'status',
       type: 'select',
       props: { clearable: true, options: getTransferStatusOptions(t) }
     },
-    { label: t('pages.orders.transfer.search.memo'), key: 'memo', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.memo') } }
+    {
+      label: t('pages.orders.transfer.search.memo'),
+      key: 'memo',
+      type: 'input',
+      props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.memo') }
+    }
   ])
 
   function handleSelectionChange(rows) {
@@ -211,24 +305,32 @@
     }
   }
 
-  async function loadTransferOrders(code) {
+  async function loadTransferOrders(transferId, code) {
     detailOrdersLoading.value = true
     try {
       const response = await guardRequestWithMessage(
         fetchTransferOrdersPage(
           buildTransferDetailOrderQueryParams({
+            id: transferId,
             code,
             current: detailOrderPagination.current,
             pageSize: detailOrderPagination.size
           })
         ),
-        { records: [], total: 0, current: detailOrderPagination.current, size: detailOrderPagination.size },
+        {
+          records: [],
+          total: 0,
+          current: detailOrderPagination.current,
+          size: detailOrderPagination.size
+        },
         { timeoutMessage: t('pages.orders.transfer.messages.ordersTimeout') }
       )
       const normalized = defaultResponseAdapter(response)
       detailOrderRows.value = normalized.records.map((item) => normalizeTransferOrderRow(item, t))
       detailOrderPagination.total = Number(normalized.total || 0)
-      detailOrderPagination.current = Number(normalized.current || detailOrderPagination.current || 1)
+      detailOrderPagination.current = Number(
+        normalized.current || detailOrderPagination.current || 1
+      )
       detailOrderPagination.size = Number(normalized.size || detailOrderPagination.size || 20)
     } catch (error) {
       detailOrderRows.value = []
@@ -249,7 +351,7 @@
     try {
       await loadTransferDetail(row.id)
       activeTransferCode.value = detailData.value.code || row.code || activeTransferCode.value
-      await loadTransferOrders(activeTransferCode.value)
+      await loadTransferOrders(row.id, activeTransferCode.value)
     } catch (error) {
       detailDrawerVisible.value = false
       detailData.value = {}
@@ -260,12 +362,23 @@
 
   async function openEditDialog(row) {
     try {
-      const detail = await guardRequestWithMessage(
-        fetchTransferDetail(row.id),
-        {},
-        { timeoutMessage: t('pages.orders.transfer.messages.detailTimeout') }
-      )
-      showDialog('edit', detail)
+      const [detail, itemResponse] = await Promise.all([
+        guardRequestWithMessage(
+          fetchTransferDetail(row.id),
+          {},
+          { timeoutMessage: t('pages.orders.transfer.messages.detailTimeout') }
+        ),
+        guardRequestWithMessage(fetchTransferItemList({ transferId: row.id }), [], {
+          timeoutMessage: t('pages.orders.transfer.messages.itemsTimeout')
+        })
+      ])
+      const itemRecords = Array.isArray(itemResponse)
+        ? itemResponse
+        : defaultResponseAdapter(itemResponse).records
+      showDialog('edit', {
+        transfer: detail,
+        items: itemRecords
+      })
     } catch (error) {
       ElMessage.error(error?.message || t('pages.orders.transfer.messages.detailLoadFailed'))
     }
@@ -273,21 +386,23 @@
 
   async function handlePublish(row) {
     try {
-      await ElMessageBox.confirm(t('pages.orders.transfer.messages.publishConfirm', { code: row.code || row.id }), t('pages.orders.transfer.messages.publishTitle'), {
-        confirmButtonText: t('common.confirm'),
-        cancelButtonText: t('common.cancel'),
-        type: 'warning'
-      })
-      const response = await fetchTransferPubOutStock({ id: row.id })
-      if (response?.code !== 200 && response?.success !== true) {
-        throw new Error(response?.message || t('pages.orders.transfer.messages.publishFailed'))
-      }
-      ElMessage.success(response?.message || t('pages.orders.transfer.messages.publishSuccess'))
+      await ElMessageBox.confirm(
+        t('pages.orders.transfer.messages.publishConfirm', { code: row.code || row.id }),
+        t('pages.orders.transfer.messages.publishTitle'),
+        {
+          confirmButtonText: t('common.confirm'),
+          cancelButtonText: t('common.cancel'),
+          type: 'warning'
+        }
+      )
+      await fetchTransferPubOutStock({ id: row.id })
+      ElMessage.success(t('pages.orders.transfer.messages.publishSuccess'))
       await refreshData()
       if (detailDrawerVisible.value && activeTransferId.value === row.id) {
         await loadTransferDetail(row.id)
-        await loadTransferOrders(row.code || activeTransferCode.value)
+        await loadTransferOrders(row.id, row.code || activeTransferCode.value)
       }
+      router.push('/orders/out-stock')
     } catch (error) {
       if (error === 'cancel' || error?.message === 'cancel') return
       ElMessage.error(error?.message || t('pages.orders.transfer.messages.publishFailed'))
@@ -346,10 +461,15 @@
       apiFn: fetchTransferPage,
       apiParams: buildTransferPageQueryParams(searchForm.value),
       paginationKey: getTransferPaginationKey(),
-      columnsFactory: () => createTransferTableColumns({ handleActionClick })
+      columnsFactory: () =>
+        createTransferTableColumns({
+          handleActionClick,
+          handleViewOrder: handleViewRelatedOrder
+        })
     },
     transform: {
-      dataTransformer: (records) => (Array.isArray(records) ? records.map((item) => normalizeTransferRow(item, t)) : [])
+      dataTransformer: (records) =>
+        Array.isArray(records) ? records.map((item) => normalizeTransferRow(item, t)) : []
     }
   })
 
@@ -357,18 +477,21 @@
     dialogVisible,
     dialogType,
     currentRecord: currentTransferData,
-    selectedRows: crudSelectedRows,
     handleSelectionChange: handleCrudSelectionChange,
     showDialog,
     handleDialogSubmit: handleCrudDialogSubmit,
     handleDelete,
     handleBatchDelete
   } = useCrudPage({
-    createEmptyModel: () => createTransferFormState(),
-    buildEditModel: (record) => buildTransferDialogModel(record),
-    buildSavePayload: (formData) => buildTransferSavePayload(formData, areaOptions.value),
-    saveRequest: fetchSaveTransfer,
-    updateRequest: fetchUpdateTransfer,
+    createEmptyModel: () => ({
+      transfer: createTransferFormState(),
+      items: []
+    }),
+    buildEditModel: (record) => buildTransferManageDialogModel(record, fieldDefinitions.value),
+    buildSavePayload: (formData) =>
+      buildTransferItemsSavePayload(formData, areaOptions.value, fieldDefinitions.value),
+    saveRequest: fetchSaveTransferItems,
+    updateRequest: fetchUpdateTransferItems,
     deleteRequest: fetchDeleteTransfer,
     entityName: t('pages.orders.transfer.entity'),
     resolveRecordLabel: (record) => record?.code || record?.id,
@@ -387,7 +510,12 @@
 
   async function loadTypeOptions() {
     const response = await guardRequestWithMessage(
-      fetchDictDataPage({ current: 1, pageSize: 200, dictTypeCode: 'sys_transfer_type', status: 1 }),
+      fetchDictDataPage({
+        current: 1,
+        pageSize: 200,
+        dictTypeCode: 'sys_transfer_type',
+        status: 1
+      }),
       { records: [] },
       { timeoutMessage: t('pages.orders.transfer.messages.typeOptionsTimeout') }
     )
@@ -403,6 +531,23 @@
     areaOptions.value = resolveTransferAreaOptions(defaultResponseAdapter(response).records)
   }
 
+  async function loadFieldDefinitions() {
+    const records = await guardRequestWithMessage(fetchEnabledTransferFields(), [], {
+      timeoutMessage: t('pages.orders.transfer.messages.fieldTimeout')
+    })
+    fieldDefinitions.value = Array.isArray(records) ? records : []
+  }
+
+  function handleViewRelatedOrder(row) {
+    if (row?.type === 'out') {
+      router.push('/orders/out-stock')
+      return
+    }
+    if (row?.type === 'in') {
+      router.push('/orders/asn-order')
+    }
+  }
+
   function handleSearch(params) {
     searchForm.value = { ...searchForm.value, ...params }
     replaceSearchParams(buildTransferSearchParams(searchForm.value))
@@ -416,13 +561,13 @@
 
   async function handleDetailCurrentChange(current) {
     detailOrderPagination.current = current
-    await loadTransferOrders(activeTransferCode.value)
+    await loadTransferOrders(activeTransferId.value, activeTransferCode.value)
   }
 
   async function handleDetailSizeChange(size) {
     detailOrderPagination.size = size
     detailOrderPagination.current = 1
-    await loadTransferOrders(activeTransferCode.value)
+    await loadTransferOrders(activeTransferId.value, activeTransferCode.value)
   }
 
   const resolvePrintRecords = async (payload) => {
@@ -433,7 +578,8 @@
       await fetchTransferPage({
         ...reportQueryParams.value,
         current: 1,
-        pageSize: Number(pagination.total) > 0 ? Number(pagination.total) : Number(payload?.pageSize) || 20
+        pageSize:
+          Number(pagination.total) > 0 ? Number(pagination.total) : Number(payload?.pageSize) || 20
       })
     ).records
   }
@@ -448,11 +594,14 @@
   } = usePrintExportPage({
     downloadFileName: 'transfer.xlsx',
     requestExport: (payload) =>
-      fetchExportTransferReport(Array.isArray(payload?.ids) && payload.ids.length > 0 ? reportQueryParams.value : payload, {
-        headers: {
-          Authorization: userStore.accessToken || ''
+      fetchExportTransferReport(
+        Array.isArray(payload?.ids) && payload.ids.length > 0 ? reportQueryParams.value : payload,
+        {
+          headers: {
+            Authorization: userStore.accessToken || ''
+          }
         }
-      }),
+      ),
     resolvePrintRecords,
     buildPreviewRows: (records) => buildTransferPrintRows(records, t),
     buildPreviewMeta: (rows) => {
@@ -478,12 +627,13 @@
     buildTransferReportMeta({
       previewMeta: rawPreviewMeta.value,
       count: previewRows.value.length,
-      orientation: rawPreviewMeta.value?.reportStyle?.orientation || TRANSFER_REPORT_STYLE.orientation,
+      orientation:
+        rawPreviewMeta.value?.reportStyle?.orientation || TRANSFER_REPORT_STYLE.orientation,
       t
     })
   )
 
   onMounted(async () => {
-    await Promise.allSettled([loadTypeOptions(), loadAreaOptions()])
+    await Promise.allSettled([loadTypeOptions(), loadAreaOptions(), loadFieldDefinitions()])
   })
 </script>

--
Gitblit v1.9.1