diff --git a/src/pages/product/ProductStockSkuList.vue b/src/pages/product/ProductStockSkuList.vue index 64c6d44..090edd4 100644 --- a/src/pages/product/ProductStockSkuList.vue +++ b/src/pages/product/ProductStockSkuList.vue @@ -21,16 +21,43 @@ - + + + + + + + + + + + - - 库存 - - + + 库存 + + - 可用 - - + 可用 + + - 预占 - - + 预占 + + @@ -70,8 +97,9 @@ import { useUserStore } from "timi-web-api"; import ProductAPI from "@/api/ProductAPI"; import { useNavBarStore } from "@/store/navBarStore"; -import type { Product, ProductStock } from "@/types/Product"; +import type { Product, ProductSkuUnit, ProductStock } from "@/types/Product"; import { getErrorMessage } from "@/utils/error"; +import { convertBaseQuantityToPackageQuantity } from "@/utils/package"; import { getProductPhotoURL, getProductQuantityText } from "@/utils/product"; import { Message } from "@/utils/message"; import { permissionCodes } from "@/utils/permission"; @@ -90,6 +118,7 @@ const total = ref(0); const isLoading = ref(false); const isRefreshing = ref(false); const isNoMore = ref(false); +const selectedUnitIdMap = ref>({}); const productId = computed(() => { const value = route.params.productId; return Array.isArray(value) ? String(value[0] || "") : String(value || ""); @@ -108,6 +137,52 @@ function getSkuPhotoURL(item: ProductStock): string { return item.sku ? getProductPhotoURL(item.sku) : ""; } +function getStockKey(item: ProductStock): string { + return item.skuId || item.sku?.id || item.id || ""; +} + +function getUnitList(item: ProductStock): ProductSkuUnit[] { + if (item.sku?.unitList?.length) { + return item.sku.unitList.filter(unit => !!unit.id); + } + return product.value?.skuList?.find(sku => sku.id === item.skuId)?.unitList?.filter(unit => !!unit.id) || []; +} + +function getSelectedUnit(item: ProductStock): ProductSkuUnit | undefined { + const unitList = getUnitList(item); + const selectedUnitId = selectedUnitIdMap.value[getStockKey(item)]; + return unitList.find(unit => unit.id === selectedUnitId) || unitList.find(unit => unit.isBase) || unitList[0]; +} + +function getSelectedUnitName(item: ProductStock): string { + return getSelectedUnit(item)?.name || "基础单位"; +} + +function getStockQuantityText(item: ProductStock, value?: number | string): string { + const quantity = convertBaseQuantityToPackageQuantity(value ?? "0", getSelectedUnit(item)?.baseQuantityPerUnit ?? "1"); + return getProductQuantityText(quantity); +} + +function selectUnit(item: ProductStock, unitId: string): void { + const stockKey = getStockKey(item); + if (!stockKey || !getUnitList(item).some(unit => unit.id === unitId)) { + return; + } + selectedUnitIdMap.value = { ...selectedUnitIdMap.value, [stockKey]: unitId }; +} + +function initializeSelectedUnits(list: ProductStock[]): void { + const nextSelectedUnitIdMap = { ...selectedUnitIdMap.value }; + for (const item of list) { + const stockKey = getStockKey(item); + const selectedUnit = getSelectedUnit(item); + if (stockKey && selectedUnit?.id) { + nextSelectedUnitIdMap[stockKey] = selectedUnit.id; + } + } + selectedUnitIdMap.value = nextSelectedUnitIdMap; +} + let keywordTimer: number | undefined; let requestToken = 0; let suppressKeywordFetch = false; @@ -130,6 +205,7 @@ async function fetch(reset = false): Promise { if (reset) { pageIndex.value = 0; skuStockList.value = []; + selectedUnitIdMap.value = {}; total.value = 0; isNoMore.value = false; } @@ -148,6 +224,7 @@ async function fetch(reset = false): Promise { } const list = result.list || []; skuStockList.value = reset ? list : skuStockList.value.concat(list); + initializeSelectedUnits(list); total.value = result.total || 0; pageIndex.value += 1; isNoMore.value = list.length < pageSize || skuStockList.value.length === total.value || total.value < skuStockList.value.length; @@ -167,7 +244,8 @@ async function loadCurrent(): Promise { return; } try { - await Promise.all([loadProduct(), fetch(true)]); + await loadProduct(); + await fetch(true); } catch (error) { Message.error(getErrorMessage(error, "SKU 列表加载失败")); } @@ -175,7 +253,8 @@ async function loadCurrent(): Promise { async function refresh(): Promise { try { - await Promise.all([loadProduct(), fetch(true)]); + await loadProduct(); + await fetch(true); } catch (error) { Message.error(getErrorMessage(error, "SKU 列表加载失败")); } finally { @@ -273,6 +352,16 @@ onUnmounted(() => { .item { padding: 10px; + :deep(.t-cell__title) { + min-width: 0; + width: 0; + } + + :deep(.t-cell__title-text) { + min-width: 0; + width: 100%; + } + .avatar { width: 3.5rem; height: 3.5rem; @@ -292,6 +381,7 @@ onUnmounted(() => { .title { gap: .5rem; min-width: 0; + max-width: 100%; flex: 1; display: flex; align-items: center; @@ -303,6 +393,19 @@ onUnmounted(() => { white-space: nowrap; text-overflow: ellipsis; } + + .unit-options { + gap: .25rem; + max-width: 55%; + display: flex; + flex-shrink: 0; + overflow-x: auto; + + :deep(.t-button) { + --td-button-border-radius: .5rem; + flex-shrink: 0; + } + } } .sku-spec {