fix ProductSkuUnit style
This commit is contained in:
@@ -114,63 +114,7 @@
|
|||||||
<strong>销售单位</strong>
|
<strong>销售单位</strong>
|
||||||
<span>采购、销售和库存操作共用</span>
|
<span>采购、销售和库存操作共用</span>
|
||||||
</div>
|
</div>
|
||||||
<t-cell-group
|
<product-sku-unit-list v-if="selectedSku.unitList?.length" :unit-list="selectedSku.unitList" />
|
||||||
v-if="selectedSku.unitList?.length"
|
|
||||||
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 || '未命名单位'" />
|
|
||||||
<div class="transfer" v-text="getUnitDescription(unit, selectedSku)" />
|
|
||||||
</div>
|
|
||||||
</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>
|
|
||||||
</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>
|
|
||||||
</template>
|
|
||||||
</t-cell>
|
|
||||||
</t-cell-group>
|
|
||||||
<div v-else class="center-tips" v-text="'暂无销售单位'" />
|
<div v-else class="center-tips" v-text="'暂无销售单位'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -185,14 +129,14 @@ import ProductAPI from "@/api/ProductAPI";
|
|||||||
import NavBarActionMenu from "@/components/NavBarActionMenu.vue";
|
import NavBarActionMenu from "@/components/NavBarActionMenu.vue";
|
||||||
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
|
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
|
||||||
import ProductProfile from "@/pages/product/component/ProductProfile.vue";
|
import ProductProfile from "@/pages/product/component/ProductProfile.vue";
|
||||||
|
import ProductSkuUnitList from "@/pages/product/component/ProductSkuUnitList.vue";
|
||||||
import { useNavBarStore } from "@/store/navBarStore";
|
import { useNavBarStore } from "@/store/navBarStore";
|
||||||
import type { NavBarAction } from "@/types/NavBarAction";
|
import type { NavBarAction } from "@/types/NavBarAction";
|
||||||
import type { PhotoItem } from "@/types/Photo";
|
import type { PhotoItem } from "@/types/Photo";
|
||||||
import type { Product, ProductSku, ProductSkuUnit } from "@/types/Product";
|
import type { Product, ProductSku } from "@/types/Product";
|
||||||
import { getAttachmentReadURL } from "@/utils/attachment";
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
import { getErrorMessage } from "@/utils/error";
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import {
|
import {
|
||||||
formatProductAmount,
|
|
||||||
getProductPhotoURL,
|
getProductPhotoURL,
|
||||||
getProductQuantityText,
|
getProductQuantityText,
|
||||||
getProductStatusText
|
getProductStatusText
|
||||||
@@ -286,14 +230,6 @@ function closeSkuDetail(): void {
|
|||||||
skuDetailVisible.value = false;
|
skuDetailVisible.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUnitDescription(unit: ProductSkuUnit, sku: ProductSku): string {
|
|
||||||
if (unit.isBase) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
const baseUnitName = sku.unitList?.find(item => item.isBase)?.name || "基础单位";
|
|
||||||
return `1 ${unit.name || "单位"} = ${getProductQuantityText(unit.baseQuantityPerUnit)} ${baseUnitName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentRouteDepth(): number {
|
function getCurrentRouteDepth(): number {
|
||||||
const transitionDepth = Array.isArray(route.query.transitionDepth)
|
const transitionDepth = Array.isArray(route.query.transitionDepth)
|
||||||
? route.query.transitionDepth[0]
|
? route.query.transitionDepth[0]
|
||||||
@@ -380,7 +316,7 @@ onUnmounted(() => navBarStore.clearRight());
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sku-popup {
|
.sku-popup {
|
||||||
padding: 1rem 0 calc(1rem + env(safe-area-inset-bottom, 0px));
|
padding: 0 0 calc(1rem + env(safe-area-inset-bottom, 0px));
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
@@ -406,40 +342,6 @@ onUnmounted(() => navBarStore.clearRight());
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.items {
|
|
||||||
|
|
||||||
:deep(.t-cell-group) {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
|
||||||
|
|
||||||
.title {
|
|
||||||
gap: .5rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.transfer {
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.note {
|
|
||||||
|
|
||||||
.price {
|
|
||||||
color: var(--td-error-color);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
gap: .5rem;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<t-swipe-cell class="sku-cell item">
|
<t-swipe-cell class="sku-cell item">
|
||||||
<t-cell role="button" tabindex="0" arrow @click="openEditor">
|
<t-cell
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
arrow
|
||||||
|
@click="openEditor"
|
||||||
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<t-tag size="small" variant="light" :content="sku.code"/>
|
<strong class="name clip-text" v-text="skuTitle" />
|
||||||
<strong class="title clip-text" v-text="skuTitle" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #note>
|
|
||||||
<t-tag
|
|
||||||
size="small"
|
|
||||||
variant="light"
|
|
||||||
:theme="sku.status === 'ACTIVE' ? 'success' : 'warning'"
|
|
||||||
:content="sku.status === 'ACTIVE' ? '启用' : '停用'"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #description>
|
|
||||||
<div class="tags">
|
|
||||||
<t-tag
|
|
||||||
v-for="entry in skuSpecEntries"
|
|
||||||
:key="`${entry.specName}-${entry.valueName}`"
|
|
||||||
size="small"
|
|
||||||
theme="primary"
|
|
||||||
variant="light-outline"
|
|
||||||
:content="entry.valueName"
|
|
||||||
/>
|
|
||||||
<t-tag
|
<t-tag
|
||||||
v-if="sku.stockEnabled"
|
v-if="sku.stockEnabled"
|
||||||
theme="warning"
|
theme="warning"
|
||||||
@@ -39,6 +23,14 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #note>
|
||||||
|
<t-tag
|
||||||
|
size="small"
|
||||||
|
variant="light"
|
||||||
|
:theme="sku.status === 'ACTIVE' ? 'success' : 'warning'"
|
||||||
|
:content="sku.status === 'ACTIVE' ? '启用' : '停用'"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</t-cell>
|
</t-cell>
|
||||||
<template #right>
|
<template #right>
|
||||||
<t-button class="delete-action swipe-cell-button" theme="danger" @click.stop="requestRemove">
|
<t-button class="delete-action swipe-cell-button" theme="danger" @click.stop="requestRemove">
|
||||||
@@ -59,28 +51,7 @@
|
|||||||
@right-button-click="closeEditor"
|
@right-button-click="closeEditor"
|
||||||
>
|
>
|
||||||
<div class="sku-popup">
|
<div class="sku-popup">
|
||||||
<div class="header">
|
<t-form class="form" label-align="left" label-width="5.5rem">
|
||||||
<span class="index" v-text="String(props.skuIndex + 1).padStart(2, '0')" />
|
|
||||||
<strong v-text="skuTitle" />
|
|
||||||
</div>
|
|
||||||
<div class="hero">
|
|
||||||
<div class="title">
|
|
||||||
<strong>销售规格</strong>
|
|
||||||
<span v-if="sku.specSummary" v-text="`摘要:${sku.specSummary}`" />
|
|
||||||
</div>
|
|
||||||
<div v-if="skuSpecEntries.length" class="spec-list">
|
|
||||||
<div
|
|
||||||
v-for="entry in skuSpecEntries"
|
|
||||||
:key="`${entry.specName}-${entry.valueName}`"
|
|
||||||
class="item"
|
|
||||||
>
|
|
||||||
<span class="name" v-text="entry.specName" />
|
|
||||||
<strong class="value clip-text" v-text="entry.valueName" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="sku-spec-empty" v-text="props.specList.length ? '请重新生成 SKU 明细以匹配规格项和规格值' : '无多规格产品,使用默认 SKU'" />
|
|
||||||
</div>
|
|
||||||
<t-form class="form" label-align="left" label-width="5rem">
|
|
||||||
<t-form-item label="SKU 编码" required-mark help="门店内唯一;已有 SKU 修改失败时请保留原编码">
|
<t-form-item label="SKU 编码" required-mark help="门店内唯一;已有 SKU 修改失败时请保留原编码">
|
||||||
<t-input v-model.trim="sku.code" borderless maxlength="64" placeholder="如 TSHIRT-RED-M" />
|
<t-input v-model.trim="sku.code" borderless maxlength="64" placeholder="如 TSHIRT-RED-M" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
@@ -120,16 +91,7 @@
|
|||||||
<strong>销售单位</strong>
|
<strong>销售单位</strong>
|
||||||
<span>采购、销售和库存操作共用</span>
|
<span>采购、销售和库存操作共用</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="items">
|
<product-sku-unit-list :unit-list="sku.unitList" />
|
||||||
<div
|
|
||||||
v-for="unit in sku.unitList"
|
|
||||||
:key="unit.clientKey"
|
|
||||||
class="item"
|
|
||||||
>
|
|
||||||
<strong v-text="unit.name || '未命名单位'" />
|
|
||||||
<span v-text="getUnitSummary(unit)" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<t-button
|
<t-button
|
||||||
class="cell-button"
|
class="cell-button"
|
||||||
variant="dashed"
|
variant="dashed"
|
||||||
@@ -146,9 +108,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { BottomPopup } from "timi-tdesign-mobile";
|
import { BottomPopup } from "timi-tdesign-mobile";
|
||||||
import type { ProductType } from "@/types/Product";
|
import type { ProductType } from "@/types/Product";
|
||||||
import type { ProductSkuForm, ProductSpecForm, ProductSkuUnitForm } from "@/types/ProductEditor";
|
import type { ProductSkuForm, ProductSpecForm } from "@/types/ProductEditor";
|
||||||
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
|
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
|
||||||
import { formatProductAmount, getProductSkuSpecEntries, parseProductAmount } from "@/utils/product";
|
import ProductSkuUnitList from "@/pages/product/component/ProductSkuUnitList.vue";
|
||||||
import { uploadPhotoList } from "@/utils/photo";
|
import { uploadPhotoList } from "@/utils/photo";
|
||||||
|
|
||||||
defineOptions({ name: "ProductSkuEditor" });
|
defineOptions({ name: "ProductSkuEditor" });
|
||||||
@@ -168,7 +130,6 @@ const emit = defineEmits<{
|
|||||||
const editorVisible = ref(false);
|
const editorVisible = ref(false);
|
||||||
const skuEditorZIndex = 12000;
|
const skuEditorZIndex = 12000;
|
||||||
const photoUrlList = computed(() => sku.value.photoItemList.map(item => item.url));
|
const photoUrlList = computed(() => sku.value.photoItemList.map(item => item.url));
|
||||||
const skuSpecEntries = computed(() => getProductSkuSpecEntries(sku.value, props.specList));
|
|
||||||
const skuTitle = computed(() => sku.value.name?.trim() || sku.value.specSummary?.trim() || (props.specList.length ? `SKU 明细 ${props.skuIndex + 1}` : "默认 SKU"));
|
const skuTitle = computed(() => sku.value.name?.trim() || sku.value.specSummary?.trim() || (props.specList.length ? `SKU 明细 ${props.skuIndex + 1}` : "默认 SKU"));
|
||||||
|
|
||||||
function openEditor(): void {
|
function openEditor(): void {
|
||||||
@@ -193,14 +154,6 @@ function setSkuStatus(value: boolean | string | number): void {
|
|||||||
sku.value.status = active ? "ACTIVE" : "INACTIVE";
|
sku.value.status = active ? "ACTIVE" : "INACTIVE";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUnitSummary(unit: ProductSkuUnitForm): string {
|
|
||||||
const quantityText = unit.isBase ? "基础单位" : `1 ${unit.name || "单位"} = ${unit.baseQuantityPerUnit || "?"} 基础单位`;
|
|
||||||
const salePrice = parseProductAmount(unit.salePriceText);
|
|
||||||
const priceText = salePrice === undefined ? "未定价" : `¥${formatProductAmount(salePrice)}`;
|
|
||||||
const saleText = unit.allowSale ? "可销售" : "停售";
|
|
||||||
const purchaseText = unit.allowPurchase ? "可采购" : "禁采购";
|
|
||||||
return `${quantityText} · ${priceText} · ${saleText} · ${purchaseText}`;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
@@ -208,19 +161,19 @@ function getUnitSummary(unit: ProductSkuUnitForm): string {
|
|||||||
|
|
||||||
.title {
|
.title {
|
||||||
gap: .5rem;
|
gap: .5rem;
|
||||||
|
min-width: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.title {
|
.name {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
font-size: .875rem;
|
font-size: .875rem;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags {
|
|
||||||
gap: .5rem;
|
|
||||||
margin-top: .5rem;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sku-popup {
|
.sku-popup {
|
||||||
@@ -228,77 +181,6 @@ function getUnitSummary(unit: ProductSkuUnitForm): string {
|
|||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
.header {
|
|
||||||
gap: .5rem;
|
|
||||||
display: flex;
|
|
||||||
padding: 0 1rem .75rem;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.index {
|
|
||||||
flex: none;
|
|
||||||
width: 1.75rem;
|
|
||||||
height: 1.75rem;
|
|
||||||
color: var(--td-brand-color);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: var(--td-brand-color-1);
|
|
||||||
border-radius: .625rem;
|
|
||||||
font-size: .6875rem;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero {
|
|
||||||
margin: 0 .75rem .75rem;
|
|
||||||
padding: .75rem;
|
|
||||||
background: var(--td-bg-color-secondarycontainer);
|
|
||||||
border-radius: .875rem;
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec-list {
|
|
||||||
gap: .5rem;
|
|
||||||
display: grid;
|
|
||||||
margin-top: .625rem;
|
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
||||||
|
|
||||||
.item {
|
|
||||||
gap: .375rem;
|
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
|
||||||
padding: .25rem .5rem;
|
|
||||||
align-items: baseline;
|
|
||||||
background: var(--td-bg-color-container);
|
|
||||||
border-radius: .625rem;
|
|
||||||
|
|
||||||
.name {
|
|
||||||
flex: none;
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
font-size: .875rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.form {
|
.form {
|
||||||
|
|
||||||
.photo-wrap {
|
.photo-wrap {
|
||||||
@@ -323,40 +205,6 @@ function getUnitSummary(unit: ProductSkuUnitForm): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.items {
|
|
||||||
gap: .5rem;
|
|
||||||
display: flex;
|
|
||||||
padding: 0 1rem .5rem;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.item {
|
|
||||||
gap: .5rem;
|
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
|
||||||
padding: .625rem .75rem;
|
|
||||||
align-items: center;
|
|
||||||
background: var(--td-bg-color-secondarycontainer);
|
|
||||||
border-radius: .75rem;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
strong {
|
|
||||||
max-width: 5rem;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
min-width: 0;
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
text-align: right;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<bottom-popup
|
<bottom-popup
|
||||||
v-model="visible"
|
v-model="visible"
|
||||||
title="配置 SKU 单位"
|
height="min(78vh, 48rem)"
|
||||||
height="min(88vh, 48rem)"
|
|
||||||
left-button-text="关闭"
|
left-button-text="关闭"
|
||||||
right-button-text="完成"
|
right-button-text="完成"
|
||||||
:z-index="unitEditorZIndex"
|
:z-index="unitEditorZIndex"
|
||||||
@@ -10,64 +9,57 @@
|
|||||||
@left-button-click="close"
|
@left-button-click="close"
|
||||||
@right-button-click="close"
|
@right-button-click="close"
|
||||||
>
|
>
|
||||||
<div v-if="sku" class="unit-editor">
|
<template #title v-if="sku">
|
||||||
<div class="editor-context">
|
<span>配置</span>
|
||||||
<span class="context-label">当前 SKU 明细</span>
|
<span class="word-space" v-text="sku.name || sku.specSummary || '默认 SKU'" />
|
||||||
<strong class="context-title" v-text="sku.name || sku.specSummary || '默认 SKU'" />
|
<span>单位</span>
|
||||||
<div v-if="skuSpecEntries.length" class="context-spec-list">
|
</template>
|
||||||
<div v-for="entry in skuSpecEntries" :key="`${entry.specName}-${entry.valueName}`" class="context-spec">
|
<div v-if="sku" class="product-sku-unit-editor">
|
||||||
<span v-text="entry.specName" />
|
<div
|
||||||
<strong v-text="entry.valueName" />
|
class="item"
|
||||||
</div>
|
v-for="(unit, unitIndex) in sku.unitList"
|
||||||
</div>
|
:key="unit.clientKey"
|
||||||
<span v-else class="context-empty">无多规格</span>
|
>
|
||||||
<div class="context-count" v-text="`${sku.unitList.length} 个单位`" />
|
<div class="header">
|
||||||
</div>
|
<strong v-text="`单位 ${unitIndex + 1}`" />
|
||||||
|
|
||||||
<div class="unit-list">
|
|
||||||
<div v-for="(unit, unitIndex) in sku.unitList" :key="unit.clientKey" class="unit-card">
|
|
||||||
<div class="unit-card-header">
|
|
||||||
<strong v-text="`单位 ${unitIndex + 1}`" />
|
|
||||||
<t-button
|
|
||||||
v-if="1 < sku.unitList.length"
|
|
||||||
theme="danger"
|
|
||||||
variant="text"
|
|
||||||
size="extra-small"
|
|
||||||
:content="unit.id ? '停售' : '删除'"
|
|
||||||
:disabled="!!unit.id && unit.allowSale === false && unit.allowPurchase === false"
|
|
||||||
@click="removeUnit(unitIndex)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<t-form class="unit-form" label-align="left" label-width="6rem">
|
|
||||||
<t-form-item label="单位名称" required-mark>
|
|
||||||
<t-input v-model.trim="unit.name" borderless maxlength="32" placeholder="如 件、盒、箱" />
|
|
||||||
</t-form-item>
|
|
||||||
<t-form-item label="基础单位" content-align="right">
|
|
||||||
<t-switch v-model="unit.isBase" size="small" :disabled="sku.unitList.length === 1" @change="setBaseUnit(unitIndex)" />
|
|
||||||
</t-form-item>
|
|
||||||
<t-form-item label="换算数量" help="1 个当前单位对应的基础单位数量" required-mark>
|
|
||||||
<t-input v-model.trim="unit.baseQuantityPerUnit" type="number" align="right" borderless :disabled="unit.isBase" placeholder="1" />
|
|
||||||
</t-form-item>
|
|
||||||
<t-form-item label="售价(元)">
|
|
||||||
<t-input v-model.trim="unit.salePriceText" type="number" align="right" borderless placeholder="选填" />
|
|
||||||
</t-form-item>
|
|
||||||
<t-form-item label="允许采购" content-align="right">
|
|
||||||
<t-switch v-model="unit.allowPurchase" size="small" :disabled="props.productType === 'SERVICE'" />
|
|
||||||
</t-form-item>
|
|
||||||
<t-form-item label="允许销售" content-align="right">
|
|
||||||
<t-switch v-model="unit.allowSale" size="small" />
|
|
||||||
</t-form-item>
|
|
||||||
</t-form>
|
|
||||||
</div>
|
|
||||||
<t-button
|
<t-button
|
||||||
class="add"
|
v-if="1 < sku.unitList.length"
|
||||||
variant="dashed"
|
theme="danger"
|
||||||
size="small"
|
variant="text"
|
||||||
theme="light"
|
size="extra-small"
|
||||||
content="添加 SKU 单位"
|
:content="unit.id ? '停售' : '删除'"
|
||||||
@click="addUnit"
|
:disabled="!!unit.id && unit.allowSale === false && unit.allowPurchase === false"
|
||||||
|
@click="removeUnit(unitIndex)"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<t-form class="form" label-align="left" label-width="6rem">
|
||||||
|
<t-form-item label="单位名称" required-mark>
|
||||||
|
<t-input v-model.trim="unit.name" borderless maxlength="32" placeholder="如 件、盒、箱" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="基础单位" content-align="right">
|
||||||
|
<t-switch v-model="unit.isBase" size="small" :disabled="sku.unitList.length === 1" @change="setBaseUnit(unitIndex)" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="换算数量" help="1 个当前单位对应的基础单位数量" required-mark>
|
||||||
|
<t-input v-model.trim="unit.baseQuantityPerUnit" type="number" align="right" borderless :disabled="unit.isBase" placeholder="1" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="售价(元)">
|
||||||
|
<t-input v-model.trim="unit.salePriceText" type="number" align="right" borderless placeholder="选填" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="允许采购" content-align="right">
|
||||||
|
<t-switch v-model="unit.allowPurchase" size="small" :disabled="props.productType === 'SERVICE'" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="允许销售" content-align="right">
|
||||||
|
<t-switch v-model="unit.allowSale" size="small" />
|
||||||
|
</t-form-item>
|
||||||
|
</t-form>
|
||||||
</div>
|
</div>
|
||||||
|
<t-button
|
||||||
|
class="add"
|
||||||
|
variant="dashed"
|
||||||
|
theme="light"
|
||||||
|
content="添加 SKU 单位"
|
||||||
|
@click="addUnit"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</bottom-popup>
|
</bottom-popup>
|
||||||
</template>
|
</template>
|
||||||
@@ -170,85 +162,30 @@ function setBaseUnit(index: number): void {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.unit-editor {
|
.product-sku-unit-editor {
|
||||||
|
gap: .75rem;
|
||||||
|
display: flex;
|
||||||
|
padding: .5rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 1rem 0 calc(1rem + env(safe-area-inset-bottom, 0px));
|
flex-direction: column;
|
||||||
|
|
||||||
.editor-context {
|
.item {
|
||||||
margin: 0 1rem .75rem;
|
|
||||||
padding: .75rem;
|
|
||||||
background: var(--td-bg-color-secondarycontainer);
|
|
||||||
border-radius: .875rem;
|
|
||||||
|
|
||||||
.context-label,
|
|
||||||
.context-empty {
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-label {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: .25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-title {
|
|
||||||
display: block;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-spec-list {
|
|
||||||
gap: .375rem;
|
|
||||||
display: flex;
|
|
||||||
margin-top: .625rem;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-spec {
|
|
||||||
gap: .25rem;
|
|
||||||
display: flex;
|
|
||||||
padding: .25rem .5rem;
|
|
||||||
background: var(--td-bg-color-container);
|
|
||||||
border-radius: .5rem;
|
|
||||||
font-size: .75rem;
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-count {
|
|
||||||
margin-top: .625rem;
|
|
||||||
color: var(--td-text-color-secondary);
|
|
||||||
font-size: .75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-list {
|
|
||||||
gap: .75rem;
|
|
||||||
display: flex;
|
|
||||||
padding: 0 1rem 1rem;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-card {
|
|
||||||
border: 1px solid var(--td-component-border);
|
border: 1px solid var(--td-component-border);
|
||||||
padding: .5rem 0;
|
padding: .5rem 0;
|
||||||
border-radius: .75rem;
|
border-radius: .75rem;
|
||||||
}
|
|
||||||
|
|
||||||
.unit-card-header {
|
.header {
|
||||||
gap: .5rem;
|
gap: .5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 .75rem .5rem;
|
padding: 0 .75rem .5rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unit-form {
|
.form {
|
||||||
margin: 0 .75rem;
|
margin: 0 .75rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.add {
|
.add {
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
<template>
|
||||||
|
<t-cell-group
|
||||||
|
v-if="unitList.length"
|
||||||
|
class="items empty-cell-title-margin"
|
||||||
|
theme="card"
|
||||||
|
>
|
||||||
|
<t-cell
|
||||||
|
v-for="unit in unitList"
|
||||||
|
:key="unit.id || unit.clientKey || unit.name"
|
||||||
|
class="item"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<div class="title">
|
||||||
|
<strong v-text="unit.name || '未命名单位'" />
|
||||||
|
<div class="transfer" v-text="getUnitDescription(unit)" />
|
||||||
|
</div>
|
||||||
|
</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>
|
||||||
|
</template>
|
||||||
|
<template #note>
|
||||||
|
<div class="note">
|
||||||
|
<span
|
||||||
|
v-if="getSalePrice(unit) !== undefined"
|
||||||
|
class="price"
|
||||||
|
v-text="`¥${formatProductAmount(getSalePrice(unit))}`"
|
||||||
|
/>
|
||||||
|
<t-tag
|
||||||
|
v-else
|
||||||
|
size="small"
|
||||||
|
theme="warning"
|
||||||
|
variant="light-outline"
|
||||||
|
content="未定价"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</t-cell>
|
||||||
|
</t-cell-group>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ProductSkuUnit } from "@/types/Product";
|
||||||
|
import type { ProductSkuUnitForm } from "@/types/ProductEditor";
|
||||||
|
import { formatProductAmount, getProductQuantityText, parseProductAmount } from "@/utils/product";
|
||||||
|
|
||||||
|
defineOptions({ name: "ProductSkuUnitList" });
|
||||||
|
|
||||||
|
type ProductSkuUnitItem = ProductSkuUnit & Partial<Pick<ProductSkuUnitForm, "clientKey" | "salePriceText">>;
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
unitList?: ProductSkuUnitItem[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const unitList = computed(() => props.unitList || []);
|
||||||
|
|
||||||
|
function getUnitDescription(unit: ProductSkuUnitItem): string {
|
||||||
|
if (unit.isBase) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const baseUnitName = unitList.value.find(item => item.isBase)?.name || "基础单位";
|
||||||
|
return `1 ${unit.name || "单位"} = ${getProductQuantityText(unit.baseQuantityPerUnit)} ${baseUnitName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSalePrice(unit: ProductSkuUnitItem): number | undefined {
|
||||||
|
if (unit.salePriceText !== undefined) {
|
||||||
|
return parseProductAmount(unit.salePriceText);
|
||||||
|
}
|
||||||
|
return unit.salePrice ?? undefined;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.items {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
:deep(.t-cell-group) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
|
||||||
|
.title {
|
||||||
|
gap: .5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.transfer {
|
||||||
|
color: var(--td-text-color-secondary);
|
||||||
|
font-size: .75rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.note {
|
||||||
|
|
||||||
|
.price {
|
||||||
|
color: var(--td-error-color);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
gap: .5rem;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user