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 +++++++++++++++++-----------------------------------
1 files changed, 143 insertions(+), 287 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>
--
Gitblit v1.9.1