From 1553782fd262f97a336fecc8b38f8f309fc08ae6 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期三, 01 四月 2026 11:07:31 +0800
Subject: [PATCH] #前端

---
 rsf-design/src/views/basic-info/matnr-group/index.vue                                         |  430 +++++++++++----------------------
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CompanysController.java    |   18 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/BasStationOptionVo.java |   21 +
 rsf-design/src/views/basic-info/matnr-group/matnrGroupTable.columns.js                        |   81 -----
 rsf-server/src/main/java/com/vincent/rsf/server/common/domain/BaseParam.java                  |   24 
 rsf-design/src/views/basic-info/warehouse-areas/index.vue                                     |   68 +++-
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/CompanysOptionVo.java   |   24 +
 rsf-design/src/views/basic-info/wh-mat/index.vue                                              |   94 +++++-
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java  |   20 +
 9 files changed, 363 insertions(+), 417 deletions(-)

diff --git a/rsf-design/src/views/basic-info/matnr-group/index.vue b/rsf-design/src/views/basic-info/matnr-group/index.vue
index dadb999..8475421 100644
--- a/rsf-design/src/views/basic-info/matnr-group/index.vue
+++ b/rsf-design/src/views/basic-info/matnr-group/index.vue
@@ -1,141 +1,99 @@
 <template>
-  <div class="matnr-group-page art-full-height flex flex-col gap-4 xl:flex-row">
-    <ElCard class="w-full shrink-0 xl:w-[320px]">
-      <div class="mb-3 flex items-center justify-between gap-3">
-        <div>
-          <div class="text-base font-medium text-[var(--art-text-primary)]">鐗╂枡鍒嗙粍</div>
-          <div class="text-xs text-[var(--art-text-secondary)]">
-            {{ selectedGroupLabel }}
-          </div>
-        </div>
-        <ElButton text @click="handleResetGroup">鍏ㄩ儴</ElButton>
-      </div>
+  <div class="matnr-group-page art-full-height">
+    <ArtSearchBar
+      v-model="searchForm"
+      :items="searchItems"
+      :show-expand="false"
+      @search="handleSearch"
+      @reset="handleReset"
+    />
 
-      <div class="mb-3 flex items-center gap-2">
-        <ElInput
-          v-model.trim="groupSearch"
-          clearable
-          placeholder="鎼滅储鐗╂枡鍒嗙粍"
-          @clear="handleGroupSearch"
-          @keyup.enter="handleGroupSearch"
-        />
-        <ElButton @click="handleGroupSearch">鎼滅储</ElButton>
-      </div>
+    <ElCard class="art-table-card">
+      <ArtTableHeader
+        :loading="loading"
+        :show-zebra="false"
+        v-model:columns="columnChecks"
+        @refresh="handleRefresh"
+      >
+        <template #left>
+          <ElSpace wrap>
+            <ElButton v-auth="'add'" @click="showDialog('add')" v-ripple>鏂板鍒嗙粍</ElButton>
+            <ElButton
+              v-auth="'delete'"
+              type="danger"
+              :disabled="selectedRows.length === 0"
+              @click="handleBatchDelete"
+              v-ripple
+            >
+              鎵归噺鍒犻櫎
+            </ElButton>
+            <ElButton @click="toggleExpand" v-ripple>
+              {{ isExpanded ? '鏀惰捣' : '灞曞紑' }}
+            </ElButton>
+            <ListExportPrint
+              class="inline-flex"
+              :preview-visible="previewVisible"
+              @update:previewVisible="handlePreviewVisibleChange"
+              :report-title="reportTitle"
+              :selected-rows="selectedRows"
+              :query-params="reportQueryParams"
+              :columns="columns"
+              :preview-rows="previewRows"
+              :preview-meta="resolvedPreviewMeta"
+              :total="flattenedTableRows.length"
+              :disabled="loading"
+              @export="handleExport"
+              @print="handlePrint"
+            />
+          </ElSpace>
+        </template>
+      </ArtTableHeader>
 
-      <ElScrollbar class="h-[calc(100vh-260px)] pr-1">
-        <div v-if="groupTreeLoading" class="py-6">
-          <ElSkeleton :rows="10" animated />
-        </div>
-        <ElEmpty v-else-if="!groupTreeData.length" description="鏆傛棤鐗╂枡鍒嗙粍" />
-        <ElTree
-          v-else
-          :data="groupTreeData"
-          :props="treeProps"
-          node-key="id"
-          highlight-current
-          default-expand-all
-          :current-node-key="selectedGroupId"
-          @node-click="handleGroupNodeClick"
-        >
-          <template #default="{ data }">
-            <div class="flex items-center gap-2">
-              <span class="font-medium">{{ data.name || '--' }}</span>
-              <span class="text-xs text-[var(--art-text-secondary)]">{{ data.code || '--' }}</span>
-            </div>
-          </template>
-        </ElTree>
-      </ElScrollbar>
-    </ElCard>
-
-    <div class="min-w-0 flex-1 space-y-4">
-      <ArtSearchBar
-        v-model="searchForm"
-        :items="searchItems"
-        :showExpand="true"
-        @search="handleSearch"
-        @reset="handleReset"
+      <ArtTable
+        ref="tableRef"
+        rowKey="id"
+        :loading="loading"
+        :columns="columns"
+        :data="tableData"
+        :stripe="false"
+        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
+        :default-expand-all="true"
+        @selection-change="handleSelectionChange"
       />
 
-      <ElCard class="art-table-card">
-        <ArtTableHeader :loading="loading" v-model:columns="columnChecks" @refresh="refreshData">
-          <template #left>
-            <ElSpace wrap>
-              <ElButton v-auth="'add'" @click="showDialog('add')" v-ripple>鏂板鍒嗙粍</ElButton>
-              <ElButton
-                v-auth="'delete'"
-                type="danger"
-                :disabled="selectedRows.length === 0"
-                @click="handleBatchDelete"
-                v-ripple
-              >
-                鎵归噺鍒犻櫎
-              </ElButton>
-              <ListExportPrint
-                class="inline-flex"
-                :preview-visible="previewVisible"
-                @update:previewVisible="handlePreviewVisibleChange"
-                :report-title="reportTitle"
-                :selected-rows="selectedRows"
-                :query-params="reportQueryParams"
-                :columns="columns"
-                :preview-rows="previewRows"
-                :preview-meta="resolvedPreviewMeta"
-                :total="pagination.total"
-                :disabled="loading"
-                @export="handleExport"
-                @print="handlePrint"
-              />
-            </ElSpace>
-          </template>
-        </ArtTableHeader>
+      <MatnrGroupDialog
+        v-model:visible="dialogVisible"
+        :dialog-type="dialogType"
+        :group-data="currentGroupData"
+        :parent-group-options="parentGroupOptions"
+        :resolve-parent-code="resolveGroupCode"
+        @submit="handleDialogSubmit"
+      />
 
-        <ArtTable
-          :loading="loading"
-          :data="data"
-          :columns="columns"
-          :pagination="pagination"
-          @selection-change="handleSelectionChange"
-          @pagination:size-change="handleSizeChange"
-          @pagination:current-change="handleCurrentChange"
-        />
-
-        <MatnrGroupDialog
-          v-model:visible="dialogVisible"
-          :dialog-type="dialogType"
-          :group-data="currentGroupData"
-          :parent-group-options="parentGroupOptions"
-          :resolve-parent-code="resolveGroupCode"
-          @submit="handleDialogSubmit"
-        />
-
-        <MatnrGroupDetailDrawer
-          v-model:visible="detailDrawerVisible"
-          :loading="detailLoading"
-          :detail="detailData"
-        />
-      </ElCard>
-    </div>
+      <MatnrGroupDetailDrawer
+        v-model:visible="detailDrawerVisible"
+        :loading="detailLoading"
+        :detail="detailData"
+      />
+    </ElCard>
   </div>
 </template>
 
 <script setup>
+  import { computed, nextTick, onMounted, reactive, ref } from 'vue'
   import { ElMessage } from 'element-plus'
-  import { computed, onMounted, ref } from 'vue'
   import { useUserStore } from '@/store/modules/user'
   import { useAuth } from '@/hooks/core/useAuth'
-  import { useTable } from '@/hooks/core/useTable'
   import { useTableColumns } from '@/hooks/core/useTableColumns'
   import { useCrudPage } from '@/views/system/common/useCrudPage'
   import { usePrintExportPage } from '@/views/system/common/usePrintExportPage'
   import ListExportPrint from '@/components/biz/list-export-print/index.vue'
-  import { defaultResponseAdapter } from '@/utils/table/tableUtils'
   import { guardRequestWithMessage } from '@/utils/sys/requestGuard'
   import {
     fetchDeleteMatnrGroup,
     fetchExportMatnrGroupReport,
     fetchGetMatnrGroupDetail,
     fetchGetMatnrGroupMany,
-    fetchMatnrGroupPage,
     fetchMatnrGroupTree,
     fetchSaveMatnrGroup,
     fetchUpdateMatnrGroup
@@ -147,7 +105,6 @@
     MATNR_GROUP_REPORT_STYLE,
     MATNR_GROUP_REPORT_TITLE,
     buildMatnrGroupDialogModel,
-    buildMatnrGroupPageQueryParams,
     buildMatnrGroupPrintRows,
     buildMatnrGroupReportMeta,
     buildMatnrGroupSavePayload,
@@ -155,11 +112,8 @@
     buildMatnrGroupTreeQueryParams,
     createMatnrGroupSearchState,
     createMatnrGroupTreeSelectOptions,
-    getMatnrGroupPaginationKey,
     normalizeMatnrGroupDetailRecord,
-    normalizeMatnrGroupListRow,
-    normalizeMatnrGroupTreeRows,
-    resolveMatnrGroupTreeNodeLabel
+    normalizeMatnrGroupTreeRows
   } from './matnrGroupPage.helpers'
 
   defineOptions({ name: 'MatnrGroup' })
@@ -167,31 +121,23 @@
   const { hasAuth } = useAuth()
   const userStore = useUserStore()
 
-  const searchForm = ref(createMatnrGroupSearchState())
-  const groupSearch = ref('')
-  const groupTreeLoading = ref(false)
-  const groupTreeData = ref([])
-  const selectedGroupId = ref(null)
+  const loading = ref(false)
+  const isExpanded = ref(true)
+  const tableRef = ref()
   const detailDrawerVisible = ref(false)
   const detailLoading = ref(false)
   const detailData = ref({})
+  const tableData = ref([])
   let handleDeleteAction = null
 
   const reportTitle = MATNR_GROUP_REPORT_TITLE
-  const reportQueryParams = computed(() =>
-    buildMatnrGroupPageQueryParams({
-      ...searchForm.value,
-      parentId: selectedGroupId.value ?? ''
-    })
-  )
+  const initialSearchState = createMatnrGroupSearchState()
+  const searchForm = reactive({ ...initialSearchState })
 
-  const groupLookupMap = computed(() => buildMatnrGroupTreeLookupMap(groupTreeData.value))
-  const parentGroupOptions = computed(() => createMatnrGroupTreeSelectOptions(groupTreeData.value))
-
-  const treeProps = {
-    label: 'displayLabel',
-    children: 'children'
-  }
+  const reportQueryParams = computed(() => buildMatnrGroupTreeQueryParams(searchForm))
+  const groupLookupMap = computed(() => buildMatnrGroupTreeLookupMap(tableData.value))
+  const parentGroupOptions = computed(() => createMatnrGroupTreeSelectOptions(tableData.value))
+  const flattenedTableRows = computed(() => flattenMatnrGroupRows(tableData.value))
 
   const searchItems = computed(() => [
     {
@@ -202,56 +148,16 @@
         clearable: true,
         placeholder: '璇疯緭鍏ュ垎缁勭紪鐮�/鍚嶇О/澶囨敞'
       }
-    },
-    {
-      label: '鍒嗙粍缂栫爜',
-      key: 'code',
-      type: 'input',
-      props: {
-        clearable: true,
-        placeholder: '璇疯緭鍏ュ垎缁勭紪鐮�'
-      }
-    },
-    {
-      label: '鍒嗙粍鍚嶇О',
-      key: 'name',
-      type: 'input',
-      props: {
-        clearable: true,
-        placeholder: '璇疯緭鍏ュ垎缁勫悕绉�'
-      }
-    },
-    {
-      label: '涓婄骇缂栫爜',
-      key: 'parCode',
-      type: 'input',
-      props: {
-        clearable: true,
-        placeholder: '璇疯緭鍏ヤ笂绾х紪鐮�'
-      }
-    },
-    {
-      label: '鐘舵��',
-      key: 'status',
-      type: 'select',
-      props: {
-        clearable: true,
-        options: [
-          { label: '姝e父', value: 1 },
-          { label: '鍐荤粨', value: 0 }
-        ]
-      }
-    },
-    {
-      label: '澶囨敞',
-      key: 'memo',
-      type: 'input',
-      props: {
-        clearable: true,
-        placeholder: '璇疯緭鍏ュ娉�'
-      }
     }
   ])
+
+  function flattenMatnrGroupRows(records = []) {
+    if (!Array.isArray(records)) {
+      return []
+    }
+
+    return records.flatMap((item) => [item, ...flattenMatnrGroupRows(item?.children || [])])
+  }
 
   function resolveGroupCode(id) {
     return groupLookupMap.value.get(Number(id))?.code || ''
@@ -262,51 +168,53 @@
     if (!node) {
       return ''
     }
-    return node.displayLabel || resolveMatnrGroupTreeNodeLabel(node)
+    return node.displayLabel || node.label || [node.name, node.code].filter(Boolean).join(' 路 ')
   }
 
-  const selectedGroupLabel = computed(() => {
-    if (selectedGroupId.value === null || selectedGroupId.value === undefined) {
-      return '鍏ㄩ儴鍒嗙粍'
-    }
-    return resolveGroupLabel(selectedGroupId.value) || '鍏ㄩ儴鍒嗙粍'
-  })
+  const { columnChecks, columns } = useTableColumns(() =>
+    createMatnrGroupTableColumns({
+      handleView: openDetail,
+      handleEdit: hasAuth('update') ? openEditDialog : null,
+      handleDelete: hasAuth('delete') ? (row) => handleDeleteAction?.(row) : null,
+      canEdit: hasAuth('update'),
+      canDelete: hasAuth('delete')
+    })
+  )
 
-  async function applyTableFilters() {
-    replaceSearchParams(
-      buildMatnrGroupPageQueryParams({
-        ...searchForm.value,
-        parentId: selectedGroupId.value ?? ''
+  async function syncTreeExpandState() {
+    await nextTick()
+    if (!tableRef.value?.elTableRef) {
+      return
+    }
+
+    const toggleRows = (rows = []) => {
+      rows.forEach((row) => {
+        if (Array.isArray(row.children) && row.children.length) {
+          tableRef.value.elTableRef.toggleRowExpansion(row, isExpanded.value)
+          toggleRows(row.children)
+        }
       })
-    )
-    await getData()
+    }
+
+    toggleRows(tableData.value)
   }
 
   async function loadGroupTree() {
-    groupTreeLoading.value = true
-    let selectionCleared = false
+    loading.value = true
     try {
       const records = await guardRequestWithMessage(
-        fetchMatnrGroupTree(buildMatnrGroupTreeQueryParams({ condition: groupSearch.value })),
+        fetchMatnrGroupTree(buildMatnrGroupTreeQueryParams(searchForm)),
         [],
         { timeoutMessage: '鐗╂枡鍒嗙粍鍔犺浇瓒呮椂锛屽凡鍋滄绛夊緟' }
       )
-      const normalizedTree = normalizeMatnrGroupTreeRows(Array.isArray(records) ? records : [])
-      groupTreeData.value = normalizedTree
-      if (selectedGroupId.value && !groupLookupMap.value.get(Number(selectedGroupId.value))) {
-        selectedGroupId.value = null
-        selectionCleared = true
-      }
-      if (selectionCleared) {
-        await applyTableFilters()
-      }
+      tableData.value = normalizeMatnrGroupTreeRows(Array.isArray(records) ? records : [])
+      await syncTreeExpandState()
     } catch (error) {
-      groupTreeData.value = []
+      tableData.value = []
       ElMessage.error(error?.message || '鐗╂枡鍒嗙粍鍔犺浇澶辫触')
     } finally {
-      groupTreeLoading.value = false
+      loading.value = false
     }
-    return selectionCleared
   }
 
   async function loadGroupDetail(id) {
@@ -314,32 +222,6 @@
       timeoutMessage: '鐗╂枡鍒嗙粍璇︽儏鍔犺浇瓒呮椂锛屽凡鍋滄绛夊緟'
     })
   }
-
-  const { columns, columnChecks, data, loading, pagination, getData, replaceSearchParams, resetSearchParams, handleSizeChange, handleCurrentChange, refreshData, refreshCreate, refreshUpdate, refreshRemove } =
-    useTable({
-      core: {
-        apiFn: fetchMatnrGroupPage,
-        apiParams: buildMatnrGroupPageQueryParams(reportQueryParams.value),
-        paginationKey: getMatnrGroupPaginationKey(),
-        columnsFactory: () =>
-          createMatnrGroupTableColumns({
-            handleView: openDetail,
-            handleEdit: hasAuth('update') ? openEditDialog : null,
-            handleDelete: hasAuth('delete') ? (row) => handleDeleteAction?.(row) : null,
-            resolveParentLabel: resolveGroupLabel,
-            canEdit: hasAuth('update'),
-            canDelete: hasAuth('delete')
-          })
-      },
-      transform: {
-        dataTransformer: (records) => {
-          if (!Array.isArray(records)) {
-            return []
-          }
-          return records.map((item) => normalizeMatnrGroupListRow(item, resolveGroupLabel))
-        }
-      }
-    })
 
   const {
     dialogVisible,
@@ -354,8 +236,8 @@
   } = useCrudPage({
     createEmptyModel: () =>
       buildMatnrGroupDialogModel({}, {
-        parentId: selectedGroupId.value ?? 0,
-        parCode: resolveGroupCode(selectedGroupId.value ?? 0),
+        parentId: 0,
+        parCode: '',
         resolveParentCode: resolveGroupCode
       }),
     buildEditModel: (record) => buildMatnrGroupDialogModel(record, { resolveParentCode: resolveGroupCode }),
@@ -375,18 +257,11 @@
     deleteRequest: fetchDeleteMatnrGroup,
     entityName: '鐗╂枡鍒嗙粍',
     resolveRecordLabel: (record) => record?.name || record?.code || record?.id,
-    refreshCreate: refreshTreeAndTable,
-    refreshUpdate: refreshTreeAndTable,
-    refreshRemove: refreshTreeAndTable
+    refreshCreate: loadGroupTree,
+    refreshUpdate: loadGroupTree,
+    refreshRemove: loadGroupTree
   })
   handleDeleteAction = handleDelete
-
-  async function refreshTreeAndTable() {
-    const selectionCleared = await loadGroupTree()
-    if (!selectionCleared) {
-      await refreshData()
-    }
-  }
 
   const buildPreviewMeta = (rows) => {
     const now = new Date()
@@ -401,15 +276,9 @@
 
   const resolvePrintRecords = async (payload) => {
     if (Array.isArray(payload?.ids) && payload.ids.length > 0) {
-      return defaultResponseAdapter(await fetchGetMatnrGroupMany(payload.ids)).records
+      return await fetchGetMatnrGroupMany(payload.ids)
     }
-    return defaultResponseAdapter(
-      await fetchMatnrGroupPage({
-        ...reportQueryParams.value,
-        current: 1,
-        pageSize: Number(pagination.total) > 0 ? Number(pagination.total) : Number(payload?.pageSize) || 20
-      })
-    ).records
+    return flattenedTableRows.value
   }
 
   const {
@@ -440,34 +309,17 @@
     })
   )
 
-  function handleSearch(params) {
-    replaceSearchParams(
-      buildMatnrGroupPageQueryParams({
-        ...params,
-        parentId: selectedGroupId.value ?? ''
-      })
-    )
-    getData()
+  function handleSearch() {
+    loadGroupTree()
   }
 
   function handleReset() {
-    Object.assign(searchForm.value, createMatnrGroupSearchState())
-    selectedGroupId.value = null
-    resetSearchParams()
+    Object.assign(searchForm, { ...initialSearchState })
+    loadGroupTree()
   }
 
-  async function handleGroupSearch() {
-    await loadGroupTree()
-  }
-
-  async function handleGroupNodeClick(node) {
-    selectedGroupId.value = Number(node?.id || 0) || null
-    await applyTableFilters()
-  }
-
-  async function handleResetGroup() {
-    selectedGroupId.value = null
-    await applyTableFilters()
+  function handleRefresh() {
+    loadGroupTree()
   }
 
   async function openDetail(row) {
@@ -494,8 +346,12 @@
     }
   }
 
-  onMounted(async () => {
-    await loadGroupTree()
-    await getData()
+  function toggleExpand() {
+    isExpanded.value = !isExpanded.value
+    syncTreeExpandState()
+  }
+
+  onMounted(() => {
+    loadGroupTree()
   })
 </script>
diff --git a/rsf-design/src/views/basic-info/matnr-group/matnrGroupTable.columns.js b/rsf-design/src/views/basic-info/matnr-group/matnrGroupTable.columns.js
index e878bba..8720615 100644
--- a/rsf-design/src/views/basic-info/matnr-group/matnrGroupTable.columns.js
+++ b/rsf-design/src/views/basic-info/matnr-group/matnrGroupTable.columns.js
@@ -1,13 +1,10 @@
 import { h } from 'vue'
-import { ElTag } from 'element-plus'
 import ArtButtonMore from '@/components/core/forms/art-button-more/index.vue'
-import { getMatnrGroupStatusMeta } from './matnrGroupPage.helpers'
 
 export function createMatnrGroupTableColumns({
   handleView,
   handleEdit,
   handleDelete,
-  resolveParentLabel,
   canEdit = true,
   canDelete = true
 }) {
@@ -28,88 +25,22 @@
       align: 'center'
     },
     {
-      type: 'globalIndex',
-      label: '搴忓彿',
-      width: 72,
-      align: 'center'
-    },
-    {
-      prop: 'name',
-      label: '鍒嗙粍鍚嶇О',
-      minWidth: 180,
-      showOverflowTooltip: true
-    },
-    {
       prop: 'code',
       label: '鍒嗙粍缂栫爜',
-      minWidth: 150,
-      showOverflowTooltip: true
-    },
-    {
-      prop: 'parentLabel',
-      label: '涓婄骇鍒嗙粍',
       minWidth: 160,
-      showOverflowTooltip: true,
-      formatter: (row) => {
-        if (typeof resolveParentLabel === 'function') {
-          const resolved = resolveParentLabel(row.parentId)
-          if (resolved) {
-            return resolved
-          }
-        }
-        return row.parentLabel || (Number(row.parentId) === 0 ? '椤剁骇鍒嗙粍' : '--')
-      }
+      showOverflowTooltip: true
     },
     {
       prop: 'parCode',
       label: '涓婄骇缂栫爜',
       minWidth: 160,
-      showOverflowTooltip: true
+      showOverflowTooltip: true,
+      formatter: (row) => row.parCode || '--'
     },
     {
-      prop: 'sort',
-      label: '鎺掑簭',
-      width: 90,
-      align: 'center'
-    },
-    {
-      prop: 'status',
-      label: '鐘舵��',
-      width: 100,
-      align: 'center',
-      formatter: (row) => {
-        const statusMeta = getMatnrGroupStatusMeta(row.statusBool ?? row.status)
-        return h(ElTag, { type: statusMeta.type, effect: 'light' }, () => statusMeta.text)
-      }
-    },
-    {
-      prop: 'memo',
-      label: '澶囨敞',
-      minWidth: 180,
-      showOverflowTooltip: true
-    },
-    {
-      prop: 'createByText',
-      label: '鍒涘缓浜�',
-      minWidth: 120,
-      showOverflowTooltip: true
-    },
-    {
-      prop: 'createTimeText',
-      label: '鍒涘缓鏃堕棿',
-      minWidth: 170,
-      showOverflowTooltip: true
-    },
-    {
-      prop: 'updateByText',
-      label: '鏇存柊浜�',
-      minWidth: 120,
-      showOverflowTooltip: true
-    },
-    {
-      prop: 'updateTimeText',
-      label: '鏇存柊鏃堕棿',
-      minWidth: 170,
+      prop: 'name',
+      label: '鍒嗙粍鍚嶇О',
+      minWidth: 240,
       showOverflowTooltip: true
     },
     {
diff --git a/rsf-design/src/views/basic-info/warehouse-areas/index.vue b/rsf-design/src/views/basic-info/warehouse-areas/index.vue
index 1043d16..6f6b31c 100644
--- a/rsf-design/src/views/basic-info/warehouse-areas/index.vue
+++ b/rsf-design/src/views/basic-info/warehouse-areas/index.vue
@@ -12,7 +12,7 @@
       <ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData">
         <template #left>
           <ElSpace wrap>
-            <ElButton v-auth="'add'" @click="showDialog('add')" v-ripple>鏂板搴撳尯</ElButton>
+            <ElButton v-auth="'add'" @click="openWarehouseAreasDialog('add')" v-ripple>鏂板搴撳尯</ElButton>
             <ElButton
               v-auth="'delete'"
               type="danger"
@@ -102,6 +102,8 @@
   const shipperOptions = ref([])
   const supplierOptions = ref([])
   const typeOptions = ref([])
+  const companyOptionsLoaded = ref(false)
+  const companyOptionsLoading = ref(null)
   let handleDeleteAction = null
 
   const searchItems = computed(() => [
@@ -182,6 +184,7 @@
 
   async function openEditDialog(row) {
     try {
+      await ensureCompanyOptions()
       const detail = await guardRequestWithMessage(fetchWarehouseAreasDetail(row.id), {}, {
         timeoutMessage: '搴撳尯璇︽儏鍔犺浇瓒呮椂锛屽凡鍋滄绛夊緟'
       })
@@ -189,6 +192,11 @@
     } catch (error) {
       ElMessage.error(error?.message || '鑾峰彇搴撳尯璇︽儏澶辫触')
     }
+  }
+
+  async function openWarehouseAreasDialog(type, record) {
+    await ensureCompanyOptions()
+    showDialog(type, record)
   }
 
   const { columns, columnChecks, data, loading, pagination, getData, replaceSearchParams, resetSearchParams, handleSizeChange, handleCurrentChange, refreshData, refreshCreate, refreshUpdate, refreshRemove } =
@@ -251,6 +259,43 @@
     resetSearchParams()
   }
 
+  async function ensureCompanyOptions() {
+    if (companyOptionsLoaded.value) {
+      return
+    }
+
+    if (companyOptionsLoading.value) {
+      await companyOptionsLoading.value
+      return
+    }
+
+    companyOptionsLoading.value = (async () => {
+      const records = await guardRequestWithMessage(fetchCompanysList(), [], {
+        timeoutMessage: '寰�鏉ヤ紒涓氶�夐」鍔犺浇瓒呮椂锛屽凡鍋滄绛夊緟'
+      })
+      const normalizedRecords = defaultResponseAdapter(records).records
+      shipperOptions.value = normalizedRecords
+        .filter((item) => item.type === 'shipper')
+        .map((item) => ({
+          label: item.name || item.code || `璐т富 ${item.id}`,
+          value: item.id
+        }))
+      supplierOptions.value = normalizedRecords
+        .filter((item) => item.type === 'supplier')
+        .map((item) => ({
+          label: item.name || item.code || `渚涘簲鍟� ${item.id}`,
+          value: item.id
+        }))
+      companyOptionsLoaded.value = true
+    })()
+
+    try {
+      await companyOptionsLoading.value
+    } finally {
+      companyOptionsLoading.value = null
+    }
+  }
+
   async function loadWarehouseOptions() {
     const records = await guardRequestWithMessage(fetchWarehouseList(), [], {
       timeoutMessage: '浠撳簱閫夐」鍔犺浇瓒呮椂锛屽凡鍋滄绛夊緟'
@@ -259,25 +304,6 @@
       label: item.name || item.code || `浠撳簱 ${item.id}`,
       value: item.id
     }))
-  }
-
-  async function loadCompanyOptions() {
-    const records = await guardRequestWithMessage(fetchCompanysList(), [], {
-      timeoutMessage: '寰�鏉ヤ紒涓氶�夐」鍔犺浇瓒呮椂锛屽凡鍋滄绛夊緟'
-    })
-    const normalizedRecords = defaultResponseAdapter(records).records
-    shipperOptions.value = normalizedRecords
-      .filter((item) => item.type === 'shipper')
-      .map((item) => ({
-        label: item.name || item.code || `璐т富 ${item.id}`,
-        value: item.id
-      }))
-    supplierOptions.value = normalizedRecords
-      .filter((item) => item.type === 'supplier')
-      .map((item) => ({
-        label: item.name || item.code || `渚涘簲鍟� ${item.id}`,
-        value: item.id
-      }))
   }
 
   async function loadTypeOptions() {
@@ -298,6 +324,6 @@
   }
 
   onMounted(async () => {
-    await Promise.all([loadWarehouseOptions(), loadCompanyOptions(), loadTypeOptions(), getData()])
+    await Promise.all([loadWarehouseOptions(), loadTypeOptions(), getData()])
   })
 </script>
diff --git a/rsf-design/src/views/basic-info/wh-mat/index.vue b/rsf-design/src/views/basic-info/wh-mat/index.vue
index 72d23c5..6533a23 100644
--- a/rsf-design/src/views/basic-info/wh-mat/index.vue
+++ b/rsf-design/src/views/basic-info/wh-mat/index.vue
@@ -1,6 +1,7 @@
 <template>
-  <div class="wh-mat-page art-full-height flex flex-col gap-4 xl:flex-row">
-    <ElCard class="w-full shrink-0 xl:w-[320px]">
+  <div class="wh-mat-page art-full-height">
+    <div class="wh-mat-page__sidebar">
+      <ElCard class="wh-mat-page__sidebar-card">
       <div class="mb-3 flex items-center justify-between gap-3">
         <div>
           <div class="text-base font-medium text-[var(--art-text-primary)]">鐗╂枡鍒嗙粍</div>
@@ -22,7 +23,7 @@
         <ElButton @click="handleGroupSearch">鎼滅储</ElButton>
       </div>
 
-      <ElScrollbar class="h-[calc(100vh-260px)] pr-1">
+      <ElScrollbar class="wh-mat-page__tree-scroll pr-1">
         <div v-if="groupTreeLoading" class="py-6">
           <ElSkeleton :rows="10" animated />
         </div>
@@ -45,9 +46,10 @@
           </template>
         </ElTree>
       </ElScrollbar>
-    </ElCard>
+      </ElCard>
+    </div>
 
-    <div class="min-w-0 flex-1 space-y-4">
+    <div class="wh-mat-page__content">
       <ArtSearchBar
         v-model="searchForm"
         :items="searchItems"
@@ -59,23 +61,23 @@
       <ElCard class="art-table-card">
         <ArtTableHeader :loading="loading" v-model:columns="columnChecks" @refresh="loadMatnrList" />
 
-      <ArtTable
-        :loading="loading"
-        :data="tableData"
-        :columns="columns"
-        :pagination="pagination"
-        @pagination:size-change="handleSizeChange"
-        @pagination:current-change="handleCurrentChange"
-      >
-        <template #action="{ row }">
-          <ArtButtonTable icon="ri:eye-line" @click="openDetailDrawer(row)" />
-        </template>
-      </ArtTable>
-    </ElCard>
+        <ArtTable
+          :loading="loading"
+          :data="tableData"
+          :columns="columns"
+          :pagination="pagination"
+          @pagination:size-change="handleSizeChange"
+          @pagination:current-change="handleCurrentChange"
+        >
+          <template #action="{ row }">
+            <ArtButtonTable icon="ri:eye-line" @click="openDetailDrawer(row)" />
+          </template>
+        </ArtTable>
+      </ElCard>
     </div>
-
-    <WhMatDetailDrawer v-model:visible="detailDrawerVisible" :loading="detailLoading" :detail="detailData" />
   </div>
+
+  <WhMatDetailDrawer v-model:visible="detailDrawerVisible" :loading="detailLoading" :detail="detailData" />
 </template>
 
 <script setup>
@@ -327,3 +329,55 @@
     await Promise.all([loadGroupTree(), loadMatnrList()])
   })
 </script>
+
+<style scoped>
+  .wh-mat-page {
+    display: flex;
+    align-items: flex-start;
+    gap: 16px;
+  }
+
+  .wh-mat-page__sidebar {
+    width: 320px;
+    flex: 0 0 320px;
+  }
+
+  .wh-mat-page__sidebar-card {
+    position: sticky;
+    top: 16px;
+  }
+
+  .wh-mat-page__tree-scroll {
+    height: calc(100vh - 320px);
+    min-height: 420px;
+  }
+
+  .wh-mat-page__content {
+    min-width: 0;
+    flex: 1 1 auto;
+  }
+
+  .wh-mat-page__content > * + * {
+    margin-top: 16px;
+  }
+
+  @media (max-width: 1024px) {
+    .wh-mat-page {
+      flex-direction: column;
+    }
+
+    .wh-mat-page__sidebar {
+      width: 100%;
+      flex-basis: auto;
+    }
+
+    .wh-mat-page__sidebar-card {
+      position: static;
+    }
+
+    .wh-mat-page__tree-scroll {
+      height: 320px;
+      min-height: 320px;
+    }
+  }
+</style>
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/BaseParam.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/BaseParam.java
index c8b0249..086dfd1 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/BaseParam.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/BaseParam.java
@@ -79,18 +79,18 @@
             map.remove("condition");
         }
 
-        FieldsService fieldsService = SpringUtils.getBean(FieldsService.class);
-        List<Fields> fields = fieldsService.list(new LambdaQueryWrapper<Fields>().eq(Fields::getFlagEnable, 1).eq(Fields::getStatus, 1));
-        if (!fields.isEmpty()) {
-            for (Fields fields1 : fields) {
-                if (null !=map.get(fields1.getFields())){
-                    this.fields.put(fields1.getFields(), map.get(fields1.getFields()));
-                    map.entrySet().removeIf(next -> next.getKey().equals(fields1.getFields())
-                    );
-                }
-            }
-
-        }
+//        FieldsService fieldsService = SpringUtils.getBean(FieldsService.class);
+//        List<Fields> fields = fieldsService.list(new LambdaQueryWrapper<Fields>().eq(Fields::getFlagEnable, 1).eq(Fields::getStatus, 1));
+//        if (!fields.isEmpty()) {
+//            for (Fields fields1 : fields) {
+//                if (null !=map.get(fields1.getFields())){
+//                    this.fields.put(fields1.getFields(), map.get(fields1.getFields()));
+//                    map.entrySet().removeIf(next -> next.getKey().equals(fields1.getFields())
+//                    );
+//                }
+//            }
+//
+//        }
 
         this.setMap(map);
     }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java
index 68e7977..cd540a0 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java
@@ -10,6 +10,8 @@
 import com.vincent.rsf.server.common.domain.BaseParam;
 import com.vincent.rsf.server.common.domain.KeyValVo;
 import com.vincent.rsf.server.common.domain.PageParam;
+import com.vincent.rsf.server.common.domain.PageResult;
+import com.vincent.rsf.server.manager.controller.vo.BasStationOptionVo;
 import com.vincent.rsf.server.manager.entity.BasStation;
 import com.vincent.rsf.server.manager.enums.LocStsType;
 import com.vincent.rsf.server.manager.service.BasStationService;
@@ -59,7 +61,15 @@
     public R pagev22(@RequestBody Map<String, Object> map) {
         BaseParam baseParam = buildParam(map, BaseParam.class);
         PageParam<BasStation, BaseParam> pageParam = new PageParam<>(baseParam, BasStation.class);
-        return R.ok().add(basStationService.page(pageParam, pageParam.buildWrapper(true)));
+        PageParam<BasStation, BaseParam> page = basStationService.page(
+                pageParam,
+                pageParam.buildWrapper(true).select("id", "station_name", "station_id")
+        );
+        PageResult<BasStationOptionVo> pageResult = new PageResult<>();
+        pageResult
+                .setTotal(page.getTotal())
+                .setRecords(page.getRecords().stream().map(this::buildOptionVo).collect(Collectors.toList()));
+        return R.ok().add(pageResult);
     }
 
     @PreAuthorize("hasAuthority('manager:basStation:list')")
@@ -189,4 +199,12 @@
         ExcelUtil.build(ExcelUtil.create(basStationService.list(), BasStation.class), response);
     }
 
+    private BasStationOptionVo buildOptionVo(BasStation station) {
+        BasStationOptionVo optionVo = new BasStationOptionVo();
+        optionVo.setId(station.getId());
+        optionVo.setStationName(station.getStationName());
+        optionVo.setStationId(station.getStationId());
+        return optionVo;
+    }
+
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CompanysController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CompanysController.java
index b802114..a628c94 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CompanysController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CompanysController.java
@@ -10,6 +10,7 @@
 import com.vincent.rsf.server.common.domain.BaseParam;
 import com.vincent.rsf.server.common.domain.KeyValVo;
 import com.vincent.rsf.server.common.domain.PageParam;
+import com.vincent.rsf.server.manager.controller.vo.CompanysOptionVo;
 import com.vincent.rsf.server.manager.entity.Companys;
 import com.vincent.rsf.server.manager.entity.Warehouse;
 import com.vincent.rsf.server.manager.service.CompanysService;
@@ -43,7 +44,13 @@
     @PreAuthorize("hasAuthority('manager:companys:list')")
     @PostMapping("/companys/list")
     public R list(@RequestBody Map<String, Object> map) {
-        return R.ok().add(companysService.list());
+        List<CompanysOptionVo> records = companysService
+                .list(new LambdaQueryWrapper<Companys>()
+                        .select(Companys::getId, Companys::getCode, Companys::getName, Companys::getType))
+                .stream()
+                .map(this::buildOptionVo)
+                .toList();
+        return R.ok().add(records);
     }
 
     @PreAuthorize("hasAuthority('manager:companys:list')")
@@ -158,4 +165,13 @@
         ExcelUtil.build(ExcelUtil.create(companies, Companys.class), response);
     }
 
+    private CompanysOptionVo buildOptionVo(Companys companys) {
+        CompanysOptionVo optionVo = new CompanysOptionVo();
+        optionVo.setId(companys.getId());
+        optionVo.setCode(companys.getCode());
+        optionVo.setName(companys.getName());
+        optionVo.setType(companys.getType());
+        return optionVo;
+    }
+
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/BasStationOptionVo.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/BasStationOptionVo.java
new file mode 100644
index 0000000..fa57973
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/BasStationOptionVo.java
@@ -0,0 +1,21 @@
+package com.vincent.rsf.server.manager.controller.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class BasStationOptionVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "绔欑偣缂栧彿")
+    private String stationName;
+
+    @ApiModelProperty(value = "绔欑偣鍚嶇О")
+    private String stationId;
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/CompanysOptionVo.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/CompanysOptionVo.java
new file mode 100644
index 0000000..ac3ba8a
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/CompanysOptionVo.java
@@ -0,0 +1,24 @@
+package com.vincent.rsf.server.manager.controller.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class CompanysOptionVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "ID")
+    private Long id;
+
+    @ApiModelProperty(value = "缂栧彿")
+    private String code;
+
+    @ApiModelProperty(value = "鍚嶇О")
+    private String name;
+
+    @ApiModelProperty(value = "甯愬彿绫诲瀷")
+    private String type;
+}

--
Gitblit v1.9.1