fix(selfop): enable visible turnover rate sorting and formula help

This commit is contained in:
2026-10-15 14:31:24 +08:00
parent 5e8c17c82f
commit 68284ad2bf
4 changed files with 40 additions and 6 deletions
@@ -91,7 +91,7 @@ const columns = computed<DataTableColumn[]>(() => [
{ prop: 'transitQuantity', label: '在途', slotName: 'transitQuantity', minWidth: 125 },
...([7, 15, 30] as const).map(n => ({ prop: `outbound${n}`, label: `${n}日出库`, slotName: `outbound${n}`, minWidth: 160 })),
{ prop: 'averageDailyOutboundQuantity', label: `${applied.value?.baseWindowDays ?? 30}日日均`, slotName: 'daily', minWidth: 110 },
{ prop: 'quantityTurnoverRate', label: '期间周转率', slotName: 'turnoverRate', minWidth: 145 },
{ prop: 'quantityTurnoverRate', label: '期间周转率', slotName: 'turnoverRate', minWidth: 180 },
...(ownerMode.value ? [{ prop: 'noOutboundInWindow', label: '无出库SKU / 实物', slotName: 'noOutbound', minWidth: 190 }, { prop: 'slowCoverage', label: '慢消化SKU / 待判断', slotName: 'slow', minWidth: 175 }] : [{ prop: 'inventoryCoverageDays', label: '预计可售天数', slotName: 'coverage', minWidth: 150 }]),
...(expanded.value ? [{ prop: 'frozenQuantity', label: '冻结件数', slotName: 'frozenQuantity', minWidth: 125 }, { prop: 'defectiveQuantity', label: '次品实物', slotName: 'defectiveQuantity', minWidth: 125 }, { prop: 'averagePhysicalQuantity', label: '期间平均实物', slotName: 'averageStock', minWidth: 145 }, { prop: 'quantityTurnoverCount', label: '期间件数周转', slotName: 'turnover', minWidth: 145 }, { prop: 'lastObservedOutboundDate', label: '最近已观测出库日', slotName: 'lastDate', minWidth: 180 }] : []),
].map(column => ({ ...column, headerSlotName: turnoverSortColumns[column.prop] ? 'sortHeader' : undefined })))
@@ -279,10 +279,22 @@ onUnmounted(() => { exportController?.abort(); fence.cancel(); runtimeFence.canc
<p v-if="inputError" role="alert">{{ inputError }}</p><p v-if="notice" role="status">{{ notice }}</p>
<DataTable :data="data?.rows ?? []" :columns="columns" :loading="loading" :total="data?.total ?? 0" :page="page" :page-size="size" appearance="integrated" :empty-text="!warehouses.length ? '暂无可用仓库' : error ? '读取失败,请重试' : '暂无符合条件的数据'" @update:page="page = $event; load()" @update:page-size="size = $event; search()">
<template #sortHeader="{ column }">
<span class="turnover-sort-heading">
<button type="button" class="turnover-sort" :data-column="column.property" :disabled="loading" :aria-label="`${column.label}:${columnSortDirection(column.property) === 'ASC' ? '当前升序,' : columnSortDirection(column.property) === 'DESC' ? '当前降序,' : ''}点击${columnSortDirection(column.property) === 'DESC' ? '升序' : '降序'}排列`" @click.stop="sortColumn(column.property)">
{{ column.label }}
<span class="turnover-sort-arrows" aria-hidden="true"><span :class="{ active: columnSortDirection(column.property) === 'ASC' }">▲</span><span :class="{ active: columnSortDirection(column.property) === 'DESC' }">▼</span></span>
</button>
<el-popover v-if="column.property === 'quantityTurnoverRate'" title="期间周转率计算说明" trigger="click" placement="bottom" :width="380" teleported>
<template #reference><el-button link aria-label="期间周转率计算说明" title="查看计算公式" @click.stop><Info :size="14" /></el-button></template>
<div class="turnover-rules">
<p>期间周转率=所选 {{ applied?.baseWindowDays ?? 30 }} 天完整出库量 ÷ 同期平均实物库存 × 100%。</p>
<p>平均实物库存=同期每日末实物库存之和 ÷ 天数。历史库存由流水还原并核对;包含冻结、次品实物,不含在途。</p>
<p>货主汇总使用汇总出库量 ÷ 汇总平均实物库存,不取各 SKU 百分比的平均值。</p>
<p>缺少完整销量、合格历史库存或平均库存为 0 时显示“—”;当前库存不代替历史平均库存。100% 表示所选期间出库量相当于平均库存周转一次。</p>
<p>点击列名切换从高到低/从低到高,对全部匹配记录排序,“—”排在最后。</p>
</div>
</el-popover>
</span>
</template>
<template #toolbar-start><slot name="view-tabs"><h2 class="turnover-title">库存周转<span>销量 · 库存 · 周转效率</span></h2></slot></template>
<template #toolbar-actions><el-button :disabled="loading || !data || exporting" title="导出当前查询的全部记录与当前显示列(CSV)" @click="exportRows">{{ exporting ? `导出中 ${exportProgress} 条` : '导出' }}</el-button><el-button v-if="exporting" @click="exportController?.abort()">取消导出</el-button><el-button @click="router.push('/self-operated/collection')">数据采集</el-button><el-button @click="page = 1; load(true)">整体刷新</el-button><el-button @click="expanded = !expanded">{{ expanded ? '收起扩展列' : '扩展列' }}</el-button><el-popover title="统计说明" trigger="click" placement="bottom-end" :width="460" teleported><template #reference><el-button aria-label="库存周转统计说明" title="统计说明"><Info :size="16" /></el-button></template><div class="turnover-rules"><p>7/15/30天均为截至所选日期的完整滚动窗口。日均仅使用完整窗口;预计可售天数使用查询时固定的当前正品可售库存,不是库龄。</p><p>期间件数周转次数=同期完整出库÷流水还原并经库存锚点核对的每日末实物库存均值。缺日、缺商品或单位异常不补零;当前库存不代替历史平均库存。件数不是占用空间,快慢标签仅供人工复核。</p><p>货主视图按“含此类SKU的货主”筛选;未知数量保留已知小计,不平均SKU可售天数。库存过期不抹去有完整证据的历史销量与周转。</p>
@@ -391,6 +403,7 @@ onUnmounted(() => { exportController?.abort(); fence.cancel(); runtimeFence.canc
</AdminPage>
</template>
<style scoped>
.turnover-sort-heading { display: inline-flex; align-items: center; gap: var(--admin-space-1); }
.turnover-sort { display: inline-flex; align-items: center; gap: 6px; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; cursor: pointer; }
.turnover-sort:disabled { cursor: wait; }
.turnover-sort:focus-visible { outline: 2px solid var(--el-color-primary); outline-offset: 3px; }