fix ProductDetail.vue SKU Detail style
This commit is contained in:
@@ -83,38 +83,13 @@
|
|||||||
<bottom-popup
|
<bottom-popup
|
||||||
v-model="skuDetailVisible"
|
v-model="skuDetailVisible"
|
||||||
title="SKU 详情"
|
title="SKU 详情"
|
||||||
height="min(88vh, 48rem)"
|
height="min(80vh, 48rem)"
|
||||||
left-button-text="关闭"
|
left-button-text="关闭"
|
||||||
right-button-text=""
|
right-button-text=""
|
||||||
@left-button-click="closeSkuDetail"
|
@left-button-click="closeSkuDetail"
|
||||||
>
|
>
|
||||||
<div v-if="selectedSku" class="sku-popup">
|
<div v-if="selectedSku" class="sku-popup">
|
||||||
<div class="sku-popup-header">
|
<t-cell-group>
|
||||||
<div class="sku-heading">
|
|
||||||
<strong v-text="getSkuTitle(selectedSku)" />
|
|
||||||
<span class="code" v-text="selectedSku.code || '无 SKU 编码'" />
|
|
||||||
</div>
|
|
||||||
<t-tag
|
|
||||||
size="small"
|
|
||||||
variant="light-outline"
|
|
||||||
:theme="selectedSku.status === 'ACTIVE' ? 'success' : 'warning'"
|
|
||||||
:content="selectedSku.status === 'ACTIVE' ? '启用' : '停用'"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="sku-spec-panel">
|
|
||||||
<div class="section-title">
|
|
||||||
<strong>销售规格</strong>
|
|
||||||
<span v-if="selectedSku.specSummary" v-text="`摘要:${selectedSku.specSummary}`" />
|
|
||||||
</div>
|
|
||||||
<div v-if="skuSpecEntries.length" class="sku-spec-list">
|
|
||||||
<div v-for="entry in skuSpecEntries" :key="`${entry.specName}-${entry.valueName}`" class="sku-spec-item">
|
|
||||||
<span class="spec-name" v-text="entry.specName" />
|
|
||||||
<strong v-text="entry.valueName" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="sku-spec-empty" v-text="product?.specList?.length ? '暂无匹配的规格值' : '无多规格产品,使用默认 SKU'" />
|
|
||||||
</div>
|
|
||||||
<t-cell-group title="基本信息" theme="card">
|
|
||||||
<t-cell title="明细名称" :note="selectedSku.name || '未命名 SKU'" />
|
<t-cell title="明细名称" :note="selectedSku.name || '未命名 SKU'" />
|
||||||
<t-cell title="SKU 编码" :note="selectedSku.code || '无编码'" />
|
<t-cell title="SKU 编码" :note="selectedSku.code || '无编码'" />
|
||||||
<t-cell v-if="selectedSku.barcode" title="SKU 条码" :note="selectedSku.barcode" />
|
<t-cell v-if="selectedSku.barcode" title="SKU 条码" :note="selectedSku.barcode" />
|
||||||
@@ -123,6 +98,7 @@
|
|||||||
<t-cell v-if="selectedSku.stockEnabled" title="最低库存" :note="`${getProductQuantityText(selectedSku.minStockQuantity)} 基础单位`" />
|
<t-cell v-if="selectedSku.stockEnabled" title="最低库存" :note="`${getProductQuantityText(selectedSku.minStockQuantity)} 基础单位`" />
|
||||||
<t-cell v-if="selectedSku.remark" title="备注" :note="Text.display(selectedSku.remark)" />
|
<t-cell v-if="selectedSku.remark" title="备注" :note="Text.display(selectedSku.remark)" />
|
||||||
</t-cell-group>
|
</t-cell-group>
|
||||||
|
<div class="media-wrap">
|
||||||
<media-selector
|
<media-selector
|
||||||
v-if="skuPhotoItemList.length"
|
v-if="skuPhotoItemList.length"
|
||||||
:model-value="skuPhotoUrlList"
|
:model-value="skuPhotoUrlList"
|
||||||
@@ -132,22 +108,70 @@
|
|||||||
:show-remove="false"
|
:show-remove="false"
|
||||||
:show-viewer-actions="false"
|
:show-viewer-actions="false"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<div class="unit-section">
|
<div class="unit">
|
||||||
<div class="unit-heading">
|
<div class="header">
|
||||||
<strong>销售单位</strong>
|
<strong>销售单位</strong>
|
||||||
<span>采购、销售和库存操作共用</span>
|
<span>采购、销售和库存操作共用</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="selectedSku.unitList?.length" class="unit-list">
|
<t-cell-group
|
||||||
<div v-for="unit in selectedSku.unitList" :key="unit.id || unit.name" class="unit-item">
|
v-if="selectedSku.unitList?.length"
|
||||||
<div class="unit-name">
|
class="items empty-cell-title-margin"
|
||||||
|
theme="card"
|
||||||
|
>
|
||||||
|
<t-cell
|
||||||
|
class="item"
|
||||||
|
v-for="unit in selectedSku.unitList"
|
||||||
|
:key="unit.id || unit.name"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<div class="title">
|
||||||
<strong v-text="unit.name || '未命名单位'" />
|
<strong v-text="unit.name || '未命名单位'" />
|
||||||
<t-tag v-if="unit.isBase" size="small" theme="primary" variant="light-outline" content="基础" />
|
<div class="transfer" v-text="getUnitDescription(unit, selectedSku)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="unit-meta" v-text="getUnitSummary(unit)" />
|
</template>
|
||||||
|
<template #description>
|
||||||
|
<div class="description">
|
||||||
|
<t-tag
|
||||||
|
v-if="unit.isBase"
|
||||||
|
size="small"
|
||||||
|
theme="primary"
|
||||||
|
variant="light-outline"
|
||||||
|
content="基础"
|
||||||
|
/>
|
||||||
|
<t-tag
|
||||||
|
size="small"
|
||||||
|
variant="light-outline"
|
||||||
|
:theme="unit.allowSale ? 'success' : 'default'"
|
||||||
|
:content="unit.allowSale ? '可销售' : '停售'"
|
||||||
|
/>
|
||||||
|
<t-tag
|
||||||
|
size="small"
|
||||||
|
variant="light-outline"
|
||||||
|
:theme="unit.allowPurchase ? 'primary' : 'default'"
|
||||||
|
:content="unit.allowPurchase ? '可采购' : '禁采购'"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #note>
|
||||||
|
<div class="note">
|
||||||
|
<span
|
||||||
|
v-if="unit.salePrice !== null && unit.salePrice !== undefined"
|
||||||
|
class="price"
|
||||||
|
v-text="`¥${formatProductAmount(unit.salePrice)}`"
|
||||||
|
/>
|
||||||
|
<t-tag
|
||||||
|
v-else
|
||||||
|
size="small"
|
||||||
|
theme="warning"
|
||||||
|
variant="light-outline"
|
||||||
|
content="未定价"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="unit-empty" v-text="'暂无销售单位'" />
|
</template>
|
||||||
|
</t-cell>
|
||||||
|
</t-cell-group>
|
||||||
|
<div v-else class="center-tips" v-text="'暂无销售单位'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</bottom-popup>
|
</bottom-popup>
|
||||||
@@ -171,7 +195,6 @@ import {
|
|||||||
formatProductAmount,
|
formatProductAmount,
|
||||||
getProductPhotoURL,
|
getProductPhotoURL,
|
||||||
getProductQuantityText,
|
getProductQuantityText,
|
||||||
getProductSkuSpecEntries,
|
|
||||||
getProductStatusText
|
getProductStatusText
|
||||||
} from "@/utils/product";
|
} from "@/utils/product";
|
||||||
import { Message } from "@/utils/message";
|
import { Message } from "@/utils/message";
|
||||||
@@ -197,7 +220,6 @@ const attachmentItemList = computed<PhotoItem[]>(() => (product.value?.attachmen
|
|||||||
url: getAttachmentReadURL(item.id || "", 90)
|
url: getAttachmentReadURL(item.id || "", 90)
|
||||||
})));
|
})));
|
||||||
const attachmentUrlList = computed(() => attachmentItemList.value.map(item => item.url));
|
const attachmentUrlList = computed(() => attachmentItemList.value.map(item => item.url));
|
||||||
const skuSpecEntries = computed(() => getProductSkuSpecEntries(selectedSku.value || { specValueIdList: [] }, product.value?.specList || []));
|
|
||||||
const skuPhotoItemList = computed<PhotoItem[]>(() => (selectedSku.value?.attachmentList || [])
|
const skuPhotoItemList = computed<PhotoItem[]>(() => (selectedSku.value?.attachmentList || [])
|
||||||
.filter(item => !!item.id)
|
.filter(item => !!item.id)
|
||||||
.map(item => ({
|
.map(item => ({
|
||||||
@@ -264,12 +286,12 @@ function closeSkuDetail(): void {
|
|||||||
skuDetailVisible.value = false;
|
skuDetailVisible.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUnitSummary(unit: ProductSkuUnit): string {
|
function getUnitDescription(unit: ProductSkuUnit, sku: ProductSku): string {
|
||||||
const quantityText = unit.isBase ? "基础单位" : `1 ${unit.name || "单位"} = ${getProductQuantityText(unit.baseQuantityPerUnit)} 基础单位`;
|
if (unit.isBase) {
|
||||||
const priceText = unit.salePrice === null || unit.salePrice === undefined ? "未定价" : `¥${formatProductAmount(unit.salePrice)}`;
|
return "";
|
||||||
const saleText = unit.allowSale ? "可销售" : "停售";
|
}
|
||||||
const purchaseText = unit.allowPurchase ? "可采购" : "禁采购";
|
const baseUnitName = sku.unitList?.find(item => item.isBase)?.name || "基础单位";
|
||||||
return `${quantityText} · ${priceText} · ${saleText} · ${purchaseText}`;
|
return `1 ${unit.name || "单位"} = ${getProductQuantityText(unit.baseQuantityPerUnit)} ${baseUnitName}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentRouteDepth(): number {
|
function getCurrentRouteDepth(): number {
|
||||||
@@ -358,113 +380,19 @@ onUnmounted(() => navBarStore.clearRight());
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sku-popup {
|
.sku-popup {
|
||||||
max-height: 100%;
|
|
||||||
padding: 1rem 0 calc(1rem + env(safe-area-inset-bottom, 0px));
|
padding: 1rem 0 calc(1rem + env(safe-area-inset-bottom, 0px));
|
||||||
|
max-height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
.sku-popup-header {
|
.media-wrap {
|
||||||
gap: .75rem;
|
margin: 0 1rem;
|
||||||
display: flex;
|
|
||||||
padding: 0 1rem .75rem;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sku-heading {
|
.unit {
|
||||||
gap: .5rem;
|
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-size: 1.125rem;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code {
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sku-spec-panel {
|
|
||||||
margin: 0 .75rem .75rem;
|
|
||||||
padding: .75rem;
|
|
||||||
background: var(--td-bg-color-secondarycontainer);
|
|
||||||
border-radius: .875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
gap: .5rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sku-spec-list {
|
|
||||||
gap: .5rem;
|
|
||||||
display: grid;
|
|
||||||
margin-top: .625rem;
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.sku-spec-item {
|
|
||||||
gap: .375rem;
|
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
|
||||||
padding: .5rem .625rem;
|
|
||||||
align-items: baseline;
|
|
||||||
background: var(--td-bg-color-container);
|
|
||||||
border-radius: .625rem;
|
|
||||||
|
|
||||||
.spec-name {
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
flex: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
min-width: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sku-spec-empty,
|
|
||||||
.unit-empty {
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sku-spec-empty {
|
|
||||||
margin-top: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.t-cell-group) {
|
|
||||||
margin: 0 0 .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.media-selector) {
|
|
||||||
margin: 0 .75rem .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-section {
|
|
||||||
margin-top: .75rem;
|
margin-top: .75rem;
|
||||||
border-top: 1px solid var(--td-component-border);
|
border-top: 1px solid var(--td-component-border);
|
||||||
}
|
|
||||||
|
|
||||||
.unit-heading {
|
.header {
|
||||||
gap: .5rem;
|
gap: .5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: .75rem 1rem .5rem;
|
padding: .75rem 1rem .5rem;
|
||||||
@@ -478,35 +406,42 @@ onUnmounted(() => navBarStore.clearRight());
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.unit-list {
|
.items {
|
||||||
gap: .5rem;
|
|
||||||
display: flex;
|
:deep(.t-cell-group) {
|
||||||
padding: 0 1rem .75rem;
|
margin: 0;
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.unit-item {
|
.item {
|
||||||
gap: .375rem;
|
|
||||||
display: flex;
|
|
||||||
padding: .625rem .75rem;
|
|
||||||
background: var(--td-bg-color-secondarycontainer);
|
|
||||||
border-radius: .75rem;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-name {
|
.title {
|
||||||
gap: .5rem;
|
gap: .5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-meta {
|
.transfer {
|
||||||
color: var(--td-text-color-secondary);
|
color: var(--td-text-color-secondary);
|
||||||
font-size: .75rem;
|
font-size: .75rem;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.note {
|
||||||
|
|
||||||
|
.price {
|
||||||
|
color: var(--td-error-color);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
gap: .5rem;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:global(html.theme-dark) .product-detail .hero {
|
:global(html.theme-dark) .product-detail .hero {
|
||||||
background: linear-gradient(135deg, rgba(15, 118, 110, .2), rgba(37, 99, 235, .18));
|
background: linear-gradient(135deg, rgba(15, 118, 110, .2), rgba(37, 99, 235, .18));
|
||||||
|
|||||||
Reference in New Issue
Block a user