fix(selfop): render inventory turnover cells and data status

This commit is contained in:
2026-10-14 09:23:29 +08:00
parent 3291d34fb8
commit 3f728cd0b2
7 changed files with 158 additions and 36 deletions
@@ -5,15 +5,22 @@ import InventoryView from './InventoryView.vue'
const mocks = vi.hoisted(() => ({ route: { query: {} as Record<string, string> }, push: vi.fn() }))
vi.mock('vue-router', () => ({ useRoute: () => mocks.route, useRouter: () => ({ push: mocks.push }) }))
const button = defineComponent({ emits: ['click'], setup(_, { slots, emit }) { return () => h('button', { onClick: () => emit('click') }, slots.default?.()) } })
const options = { global: { stubs: { AnalyticsView: true, InventoryTurnoverView: true, 'el-button': button } } }
const options = { global: { stubs: { AnalyticsView: defineComponent({ name: 'AnalyticsView', props: ['mode'], setup(_, { slots }) { return () => h('section', { class: 'search-region' }, slots['view-tabs']?.()) } }), InventoryTurnoverView: defineComponent({ name: 'InventoryTurnoverView', setup(_, { slots }) { return () => h('section', { class: 'search-region' }, slots['view-tabs']?.()) } }), 'el-button': button } } }
beforeEach(() => { mocks.route = reactive({ query: {} }); mocks.push.mockReset() })
describe('inventory view entry', () => {
it('defaults to turnover and switches to detail without reusing turnover filters', async () => {
mocks.route.query = { warehouseCode: 'US02', focus: 'FROZEN' }
const w = mount(InventoryView, options)
expect(w.findComponent({ name: 'InventoryTurnoverView' }).exists()).toBe(true)
expect(w.find('.search-region .inventory-views').exists()).toBe(true)
expect(w.find('button[aria-pressed="true"]').text()).toBe('库存周转')
await w.findAll('button').find(b => b.text() === '库存明细')!.trigger('click')
expect(mocks.push).toHaveBeenCalledWith({ path: '/self-operated/inventory', query: { view: 'DETAIL', warehouseCode: 'US02' } })
mocks.route.query = { view: 'DETAIL', warehouseCode: 'US02' }; await flushPromises()
expect(w.find('button[aria-pressed="true"]').text()).toBe('库存明细')
w.findComponent({ name: 'AnalyticsView' }).vm.$emit('warehouseSelected', 'US01')
await w.findAll('button').find(b => b.text() === '库存周转')!.trigger('click')
expect(mocks.push).toHaveBeenLastCalledWith({ path: '/self-operated/inventory', query: { view: 'TURNOVER', warehouseCode: 'US01' } })
w.unmount()
})
it('preserves original strict detail links and rejects contradictory parameters', async () => {
@@ -16,9 +16,19 @@ function switchView(view: 'TURNOVER' | 'DETAIL') {
}
</script>
<template>
<nav class="inventory-views" aria-label="库存分析视图"><el-button :type="selected.view === 'TURNOVER' ? 'primary' : undefined" @click="switchView('TURNOVER')">库存周转</el-button><el-button :type="selected.view === 'DETAIL' ? 'primary' : undefined" @click="switchView('DETAIL')">库存明细</el-button></nav>
<p v-if="selected.error" role="alert">{{ selected.error }}</p>
<AnalyticsView v-else-if="selected.view === 'DETAIL'" mode="inventory" />
<InventoryTurnoverView v-else @warehouse-selected="retainedWarehouse = $event" />
<component v-else :is="selected.view === 'DETAIL' ? AnalyticsView : InventoryTurnoverView" v-bind="selected.view === 'DETAIL' ? { mode: 'inventory' as const } : {}" @warehouse-selected="retainedWarehouse = $event">
<template #view-tabs>
<nav class="inventory-views" aria-label="库存分析视图">
<button type="button" :aria-pressed="selected.view === 'TURNOVER'" @click="switchView('TURNOVER')">库存周转</button>
<button type="button" :aria-pressed="selected.view === 'DETAIL'" @click="switchView('DETAIL')">库存明细</button>
</nav>
</template>
</component>
</template>
<style scoped>.inventory-views { display: flex; gap: 8px; padding: 16px 20px 0; }</style>
<style scoped>
.inventory-views { display: flex; align-items: center; gap: var(--admin-space-4); }
.inventory-views button { border: 0; border-bottom: 2px solid transparent; background: transparent; min-height: var(--admin-control-height); padding: var(--admin-space-1) var(--admin-space-2); color: var(--el-text-color-regular); font: inherit; cursor: pointer; white-space: nowrap; }
.inventory-views button[aria-pressed="true"] { color: var(--el-color-primary); border-bottom-color: var(--el-color-primary); font-weight: 600; }
.inventory-views button:focus-visible { outline: 2px solid var(--el-color-primary); outline-offset: 2px; }
</style>