diff --git a/src/modules/warehouse-resources/locations/pages/LocationsView.test.ts b/src/modules/warehouse-resources/locations/pages/LocationsView.test.ts index fa4c1c76..131ecf67 100644 --- a/src/modules/warehouse-resources/locations/pages/LocationsView.test.ts +++ b/src/modules/warehouse-resources/locations/pages/LocationsView.test.ts @@ -200,7 +200,12 @@ describe('LocationsView', () => { const wrapper = await mountView() await selectScope(wrapper) - expect(wrapper.find('.table-panel .panel-heading').exists()).toBe(false) + const panelHeading = wrapper.find('.table-panel .panel-heading') + expect(panelHeading.exists()).toBe(true) + expect(panelHeading.text()).toContain('库位列表') + expect(panelHeading.text()).toContain('共 2 个库位') + expect(panelHeading.text()).toContain('新增库位') + expect(wrapper.findComponent(QueryToolbar).text()).not.toContain('新增库位') expect(listPlatformWarehouses).toHaveBeenCalledWith(undefined, 1, 200) expect(listPlatformLocations).toHaveBeenLastCalledWith({ page: 1, @@ -220,7 +225,7 @@ describe('LocationsView', () => { it('opens creation without a list filter and requires the warehouse inside the form', async () => { const wrapper = await mountView() - const createButton = wrapper.findAll('button').find((button) => button.text().trim() === '新增库位') + const createButton = wrapper.find('.table-panel .panel-heading').findAll('button').find((button) => button.text().trim() === '新增库位') expect(createButton?.attributes('disabled')).toBeUndefined() await createButton!.trigger('click') diff --git a/src/modules/warehouse-resources/locations/pages/LocationsView.vue b/src/modules/warehouse-resources/locations/pages/LocationsView.vue index c1a17422..d1ed0bfa 100644 --- a/src/modules/warehouse-resources/locations/pages/LocationsView.vue +++ b/src/modules/warehouse-resources/locations/pages/LocationsView.vue @@ -495,15 +495,7 @@ onMounted(() => { ariaLabel="库位筛选" :fields="queryFields" @search="applyFilters" - > - - 新增库位 - - + /> 所属企业列表加载失败 @@ -527,7 +519,15 @@ onMounted(() => { 重新查询 - + + + 库位列表共 {{ total }} 个库位 + 新增库位 + { }) }) + it('groups the pallet editor into clear ownership and specification sections', async () => { + const wrapper = await mountView() + const createButton = wrapper.findAll('button').find((button) => button.text().trim() === '新增托盘') + await createButton?.trigger('click') + await flushPromises() + + expect(document.body.querySelector('.pallet-editor-header')?.textContent).toContain('新增托盘') + expect(document.body.querySelector('.pallet-editor-header')?.textContent).toContain('录入归属仓库与基础规格') + const editorDialog = document.body.querySelector('.pallet-editor-drawer[role="dialog"]') + const labelledBy = editorDialog?.getAttribute('aria-labelledby') + expect(labelledBy).toBeTruthy() + expect(document.getElementById(labelledBy || '')?.textContent).toBe('新增托盘') + expect(document.body.querySelectorAll('.editor-section')).toHaveLength(2) + expect(document.body.querySelector('#pallet-ownership-heading')?.textContent).toBe('归属仓库') + expect(document.body.querySelector('#pallet-spec-heading')?.textContent).toBe('托盘规格') + expect(document.body.querySelector('.pallet-editor-footer')?.textContent).toContain('为必填项') + }) + it('hides all write actions without write permissions', async () => { const wrapper = await mountView(['platform:pallet:list']) diff --git a/src/modules/warehouse-resources/pallets/pages/PalletsView.vue b/src/modules/warehouse-resources/pallets/pages/PalletsView.vue index b2d2efbe..af9eee7b 100644 --- a/src/modules/warehouse-resources/pallets/pages/PalletsView.vue +++ b/src/modules/warehouse-resources/pallets/pages/PalletsView.vue @@ -450,47 +450,73 @@ onMounted(() => { 关闭 - - - - {{ editorWarehouse?.warehouseName || '当前仓库' }}({{ editorWarehouse?.warehouseCode || form.warehouseId }})客户 {{ customerLabel(form.customerId) }} · 托盘保存后不可跨仓移动 - + + + + + + {{ editorTitle }} + {{ form.id ? '调整托盘规格与现场识别信息' : '录入归属仓库与基础规格,创建后即可用于仓储作业' }} + + + - - - - - - - - - - - - - - - - 用于服务端按总体积计算所需托盘数量;请输入托盘实际可用容积。 - - - - + + + + 归属仓库托盘创建后固定归属于所选仓库,不支持跨仓移动。 + + + {{ editorWarehouse?.warehouseName || '当前仓库' }}{{ editorWarehouse?.warehouseCode || form.warehouseId }} · 客户 {{ customerLabel(form.customerId) }} + + + + + + + + + + + + 托盘规格完善编码、类型与实际可用容积。 + + + + + + + + + + + + + + 用于服务端按总体积计算所需托盘数量,请填写托盘实际可用容积。 + + + + + - + @@ -518,20 +544,45 @@ onMounted(() => { .detail-hero p { margin-top: 4px; color: var(--cc-muted); font-size: 13px; } .detail-section-title { margin: 20px 0 8px; color: var(--cc-text); font-size: 14px; } .detail-section-title:first-of-type { margin-top: 0; } -.editor-context { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; padding: 12px; border: 1px solid var(--el-color-primary-light-7); border-radius: 8px; background: var(--el-color-primary-light-9); color: var(--cc-primary); } -.editor-context div { display: grid; gap: 2px; } -.editor-context span { color: var(--cc-muted); font-size: 12px; } +.pallet-editor-header { display: flex; min-width: 0; align-items: center; gap: 12px; } +.pallet-editor-header > span { display: grid; width: 38px; height: 38px; flex: 0 0 auto; place-items: center; border-radius: 8px; background: var(--el-color-primary-light-9); color: var(--cc-primary); } +.pallet-editor-header h2 { margin: 0; color: #172033; font-size: 17px; line-height: 1.4; } +.pallet-editor-header p { margin: 3px 0 0; color: var(--cc-muted); font-size: 12px; line-height: 1.5; } +.editor-form { padding: 4px 24px 28px; } +.editor-section { padding: 20px 0 4px; border-bottom: 1px solid var(--cc-border); } +.editor-section:last-child { padding-bottom: 0; border-bottom: 0; } +.editor-section-heading { display: flex; align-items: flex-start; gap: 9px; margin-bottom: 18px; } +.editor-section-heading > svg { margin-top: 1px; flex: 0 0 auto; color: var(--cc-primary); } +.editor-section-heading h3 { margin: 0; color: #172033; font-size: 14px; line-height: 1.4; } +.editor-section-heading p { margin: 3px 0 0; color: var(--cc-muted); font-size: 11px; line-height: 1.5; } +.editor-field-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; } +.editor-context { margin-bottom: 18px; padding: 12px 14px; border-radius: 6px; background: #f8fafc; } +.editor-context div { display: grid; gap: 3px; } +.editor-context strong { color: #172033; font-size: 13px; } +.editor-context span { color: var(--cc-muted); font-size: 11px; } .editor-form :deep(.el-input-number), .editor-form :deep(.el-select) { width: 100%; } +.editor-form :deep(.el-form-item) { margin-bottom: 18px; } +.editor-form :deep(.el-form-item__label) { padding-bottom: 7px; color: #344054; font-size: 12px; font-weight: 650; line-height: 1.4; } +.editor-remark-field { margin-bottom: 0 !important; } .field-help { margin: 6px 0 0; color: var(--cc-muted); font-size: 12px; line-height: 1.5; } .drawer-footer { display: flex; justify-content: flex-end; gap: 8px; } .drawer-footer :deep(.el-button + .el-button) { margin-left: 0; } +.pallet-editor-footer { align-items: center; justify-content: space-between; } +.pallet-editor-footer > span { color: var(--cc-muted); font-size: 11px; } +.pallet-editor-footer > span i { color: var(--el-color-danger); font-style: normal; } +.pallet-editor-footer > div { display: flex; gap: 8px; } +.pallet-editor-footer > div :deep(.el-button + .el-button) { margin-left: 0; } @media (max-width: 720px) { .panel-heading { align-items: stretch; flex-direction: column; } .panel-heading > .el-button { width: 100%; min-height: 44px; } .pallet-row-actions :deep(.el-button) { min-height: 36px; padding-inline: 5px; } - .drawer-footer { display: grid; grid-template-columns: 1fr 1fr; } - .drawer-footer :deep(.el-button) { min-height: 44px; margin-left: 0; } + .editor-form { padding-right: 16px; padding-left: 16px; } + .editor-field-grid { grid-template-columns: 1fr; } + .pallet-editor-footer { display: block; } + .pallet-editor-footer > span { display: none; } + .pallet-editor-footer > div { display: grid; grid-template-columns: 1fr 1fr; } + .pallet-editor-footer :deep(.el-button) { min-height: 44px; margin-left: 0; } } @media (max-width: 768px) { .pallet-filter-toolbar :deep(.query-toolbar__filters) { width: 100%; flex-direction: column; }
共 {{ total }} 个库位
{{ form.id ? '调整托盘规格与现场识别信息' : '录入归属仓库与基础规格,创建后即可用于仓储作业' }}
用于服务端按总体积计算所需托盘数量;请输入托盘实际可用容积。
托盘创建后固定归属于所选仓库,不支持跨仓移动。
完善编码、类型与实际可用容积。
用于服务端按总体积计算所需托盘数量,请填写托盘实际可用容积。