| rsf-design/src/views/basic-info/matnr-group/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/src/views/basic-info/matnr-group/matnrGroupTable.columns.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/src/views/basic-info/warehouse-areas/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/src/views/basic-info/wh-mat/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/java/com/vincent/rsf/server/common/domain/BaseParam.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/BasStationController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CompanysController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/BasStationOptionVo.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/CompanysOptionVo.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
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: '正常', 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> 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 }, { 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> 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> 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); } 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; } } 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; } } rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/BasStationOptionVo.java
New file @@ -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; } rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/vo/CompanysOptionVo.java
New file @@ -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; }