fix sku display

This commit is contained in:
Timi
2026-09-19 22:28:24 +08:00
parent 79d9efad73
commit 2aa29da3ff
15 changed files with 148 additions and 82 deletions
-4
View File
@@ -89,10 +89,6 @@ html.theme-dark body {
text-overflow: unset; text-overflow: unset;
} }
} }
.t-cell__description {
margin-top: 0;
}
} }
.t-dialog__footer { .t-dialog__footer {
+4
View File
@@ -9,6 +9,7 @@
> >
<span class="picker-text" v-text="selectedProductName || props.placeholder" /> <span class="picker-text" v-text="selectedProductName || props.placeholder" />
</t-form-item> </t-form-item>
<product-sku-form-item :sku="selectedSku" :unit="selectedUnit" />
<bottom-popup <bottom-popup
v-model="visible" v-model="visible"
title="选择产品 SKU" title="选择产品 SKU"
@@ -103,6 +104,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { BottomPopup } from "timi-tdesign-mobile"; import { BottomPopup } from "timi-tdesign-mobile";
import ProductAPI from "@/api/ProductAPI"; import ProductAPI from "@/api/ProductAPI";
import ProductSkuFormItem from "@/components/ProductSkuFormItem.vue";
import type { import type {
Product, Product,
ProductSelection, ProductSelection,
@@ -143,6 +145,8 @@ const selectedProduct = computed(() => {
return props.selectedProduct || productList.value.find(item => item.skuList?.some(sku => sku.id === props.modelValue?.skuId)); return props.selectedProduct || productList.value.find(item => item.skuList?.some(sku => sku.id === props.modelValue?.skuId));
}); });
const selectedProductName = computed(() => selectedProduct.value?.name || ""); const selectedProductName = computed(() => selectedProduct.value?.name || "");
const selectedSku = computed(() => selectedProduct.value?.skuList?.find(sku => sku.id === props.modelValue?.skuId));
const selectedUnit = computed(() => selectedSku.value?.unitList?.find(unit => unit.id === props.modelValue?.skuUnitId));
const filteredProductList = computed(() => { const filteredProductList = computed(() => {
const text = keyword.value.toLocaleLowerCase(); const text = keyword.value.toLocaleLowerCase();
return productList.value.filter(item => !text || `${item.name}${item.code}`.toLocaleLowerCase().includes(text)); return productList.value.filter(item => !text || `${item.name}${item.code}`.toLocaleLowerCase().includes(text));
+22
View File
@@ -0,0 +1,22 @@
<template>
<t-form-item v-if="skuText || unitText" label="产品 SKU" content-align="right">
<product-sku-tags :fallback="skuText" :unit="unitText" />
</t-form-item>
</template>
<script setup lang="ts">
import ProductSkuTags from "@/components/ProductSkuTags.vue";
import type { ProductSku, ProductSkuUnit } from "@/types/Product";
defineOptions({ name: "ProductSkuFormItem" });
interface Props {
sku?: ProductSku;
unit?: ProductSkuUnit;
}
const props = defineProps<Props>();
const skuText = computed(() => props.sku?.name?.trim() || props.sku?.specSummary?.trim() || "");
const unitText = computed(() => props.unit?.name?.trim() || "");
</script>
@@ -8,6 +8,7 @@
variant="light-outline" variant="light-outline"
:content="tag.content" :content="tag.content"
/> />
<t-tag v-if="unitText" size="small" :content="unitText" />
</div> </div>
</template> </template>
@@ -15,7 +16,7 @@
import type { ProductSkuSpecSnapshot } from "@/types/Product"; import type { ProductSkuSpecSnapshot } from "@/types/Product";
import { getProductSkuSnapshotText } from "@/utils/product"; import { getProductSkuSnapshotText } from "@/utils/product";
defineOptions({ name: "ProductSkuSnapshotTags" }); defineOptions({ name: "ProductSkuTags" });
interface Props { interface Props {
productName?: string | null; productName?: string | null;
@@ -42,7 +42,7 @@
v-if="item.skuCodeSnapshot || item.skuSpecSnapshot?.length || item.skuNameSnapshot || item.specSummarySnapshot || item.unitSnapshot" v-if="item.skuCodeSnapshot || item.skuSpecSnapshot?.length || item.skuNameSnapshot || item.specSummarySnapshot || item.unitSnapshot"
class="sku-tags" class="sku-tags"
> >
<product-sku-snapshot-tags <product-sku-tags
:product-name="item.productNameSnapshot" :product-name="item.productNameSnapshot"
:snapshot="item.skuSpecSnapshot" :snapshot="item.skuSpecSnapshot"
:fallback="item.specSummarySnapshot || item.skuNameSnapshot" :fallback="item.specSummarySnapshot || item.skuNameSnapshot"
@@ -128,7 +128,7 @@ import SalesOrderAPI from "@/api/SalesOrderAPI";
import FulfillmentAPI from "@/api/FulfillmentAPI"; import FulfillmentAPI from "@/api/FulfillmentAPI";
import ProductAPI from "@/api/ProductAPI"; import ProductAPI from "@/api/ProductAPI";
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue"; import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
import ProductSkuSnapshotTags from "@/components/ProductSkuSnapshotTags.vue"; import ProductSkuTags from "@/components/ProductSkuTags.vue";
import ProductStockPreview from "@/components/ProductStockPreview.vue"; import ProductStockPreview from "@/components/ProductStockPreview.vue";
import { useNavBarStore } from "@/store/navBarStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { Attachment } from "timi-web-api"; import type { Attachment } from "timi-web-api";
@@ -50,7 +50,7 @@
<template #description> <template #description>
<div class="item-description"> <div class="item-description">
<t-tag v-if="isGiftedFulfillmentItem(item)" size="small" theme="success" content="赠送" /> <t-tag v-if="isGiftedFulfillmentItem(item)" size="small" theme="success" content="赠送" />
<product-sku-snapshot-tags <product-sku-tags
:product-name="item.productNameSnapshot" :product-name="item.productNameSnapshot"
:snapshot="item.skuSpecSnapshot" :snapshot="item.skuSpecSnapshot"
:fallback="item.specSummarySnapshot || item.skuNameSnapshot || '默认 SKU'" :fallback="item.specSummarySnapshot || item.skuNameSnapshot || '默认 SKU'"
@@ -152,7 +152,7 @@ import FulfillmentAPI from "@/api/FulfillmentAPI";
import ProductAPI from "@/api/ProductAPI"; import ProductAPI from "@/api/ProductAPI";
import SalesOrderAPI from "@/api/SalesOrderAPI"; import SalesOrderAPI from "@/api/SalesOrderAPI";
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue"; import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
import ProductSkuSnapshotTags from "@/components/ProductSkuSnapshotTags.vue"; import ProductSkuTags from "@/components/ProductSkuTags.vue";
import ProductStockPreview from "@/components/ProductStockPreview.vue"; import ProductStockPreview from "@/components/ProductStockPreview.vue";
import { useNavBarStore } from "@/store/navBarStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { OrderFulfillment, OrderFulfillmentItem } from "@/types/Fulfillment"; import type { OrderFulfillment, OrderFulfillmentItem } from "@/types/Fulfillment";
+19 -18
View File
@@ -30,7 +30,6 @@
<t-cell <t-cell
class="item" class="item"
v-for="item in config.itemList || []" v-for="item in config.itemList || []"
:title="getItemTitle(item)"
:key="item.id || `${item.skuId}-${item.skuUnitId}`" :key="item.id || `${item.skuId}-${item.skuUnitId}`"
:note="`${item.defaultQuantity} ${item.unitSnapshot || ''}${item.remark ? `|${item.remark}` : ''}`" :note="`${item.defaultQuantity} ${item.unitSnapshot || ''}${item.remark ? `|${item.remark}` : ''}`"
> >
@@ -48,12 +47,14 @@
v-text="(item.productNameSnapshot || '产').slice(0, 1)" v-text="(item.productNameSnapshot || '产').slice(0, 1)"
/> />
</template> </template>
<template #description> <template #title>
<t-tag <div class="title">
:content="item.skuCodeSnapshot || item.sku?.code || 'SKU'" <span v-text="item.productNameSnapshot || '未命名产品'" />
theme="primary" <product-sku-tags
variant="light" :product-name="item.productNameSnapshot"
/> :fallback="item.specSummarySnapshot || item.skuNameSnapshot || '默认 SKU'"
/>
</div>
</template> </template>
</t-cell> </t-cell>
<div v-if="!config.itemList?.length" class="empty" v-text="'暂无产品权益'" /> <div v-if="!config.itemList?.length" class="empty" v-text="'暂无产品权益'" />
@@ -82,6 +83,7 @@ import { DialogPlugin } from "tdesign-mobile-vue";
import { Time } from "timi-web"; import { Time } from "timi-web";
import { useUserStore } from "timi-web-api"; import { useUserStore } from "timi-web-api";
import PackageAPI from "@/api/PackageAPI"; import PackageAPI from "@/api/PackageAPI";
import ProductSkuTags from "@/components/ProductSkuTags.vue";
import { useCurrentStoreStore } from "@/store/currentStoreStore"; import { useCurrentStoreStore } from "@/store/currentStoreStore";
import { useNavBarStore } from "@/store/navBarStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { GaoPackageConfig, PackageConfigItem, PackageConfigStatus } from "@/types/Package"; import type { GaoPackageConfig, PackageConfigItem, PackageConfigStatus } from "@/types/Package";
@@ -89,7 +91,7 @@ import { getErrorMessage } from "@/utils/error";
import { formatPackageAmount, getPackageConfigStatusText } from "@/utils/package"; import { formatPackageAmount, getPackageConfigStatusText } from "@/utils/package";
import { Message } from "@/utils/message"; import { Message } from "@/utils/message";
import { gaoRoleCodes, permissionCodes } from "@/utils/permission"; import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
import { getProductPhotoURL as getProductPhotoUrl, getProductSkuSnapshotText } from "@/utils/product"; import { getProductPhotoURL as getProductPhotoUrl } from "@/utils/product";
defineOptions({ name: "PackageConfigDetail" }); defineOptions({ name: "PackageConfigDetail" });
@@ -116,11 +118,6 @@ function getItemPhotoURL(item: PackageConfigItem): string {
return getProductPhotoUrl(item.sku || {}); return getProductPhotoUrl(item.sku || {});
} }
function getItemTitle(item: PackageConfigItem): string {
const skuText = getProductSkuSnapshotText(item.productNameSnapshot, item.skuNameSnapshot, item.specSummarySnapshot);
return `${item.productNameSnapshot || "未命名产品"}${skuText ? ` · ${skuText}` : ""}`;
}
async function loadData(): Promise<void> { async function loadData(): Promise<void> {
const id = String(route.params.id || ""); const id = String(route.params.id || "");
if (!id) { if (!id) {
@@ -286,16 +283,20 @@ onUnmounted(() => navBarStore.clearRight());
.item { .item {
padding: 10px; padding: 10px;
.item-title { :deep(.t-cell__title) {
gap: .5rem;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
} }
.avatar { .avatar {
width: 3.5rem; width: 2.5rem;
height: 3.5rem; height: 2.5rem;
}
.title {
gap: .5rem;
display: flex;
align-items: center;
} }
} }
} }
-3
View File
@@ -52,9 +52,6 @@
@update:model-value="applyProduct(index, $event)" @update:model-value="applyProduct(index, $event)"
@select="applyProductSelection(index, $event)" @select="applyProductSelection(index, $event)"
/> />
<t-form-item v-if="item.skuId" label="SKU 单位" content-align="right">
<span v-text="getUnit(item)?.name || '未选择单位'" />
</t-form-item>
<t-form-item label="默认配额" content-align="right" required-mark> <t-form-item label="默认配额" content-align="right" required-mark>
<t-stepper <t-stepper
v-model="item.defaultQuantity" v-model="item.defaultQuantity"
+20 -32
View File
@@ -5,6 +5,7 @@
v-model="selection" v-model="selection"
:selected-product="form.product" :selected-product="form.product"
required-mark required-mark
@select="handleProductSelection"
/> />
<t-form-item label="默认积分" required-mark> <t-form-item label="默认积分" required-mark>
<t-input <t-input
@@ -34,10 +35,14 @@
<t-textarea v-model.trim="form.remark" maxlength="500" autosize /> <t-textarea v-model.trim="form.remark" maxlength="500" autosize />
</t-form-item> </t-form-item>
</t-form> </t-form>
<div v-if="form.id" class="actions" v-entrance-transition="70"> <t-button
<t-button class="bg-white" theme="danger" variant="outline" @click="disable">停用配置</t-button> v-if="form.id"
<t-button theme="danger" @click="remove">删除</t-button> class="cell-button"
</div> theme="danger"
v-entrance-transition="70"
content="删除"
@click="remove"
/>
</div> </div>
<t-popup v-model="statusVisible" placement="bottom"> <t-popup v-model="statusVisible" placement="bottom">
<t-picker <t-picker
@@ -55,6 +60,7 @@ import PointAPI from "@/api/PointAPI";
import ProductSelector from "@/components/ProductSelector.vue"; import ProductSelector from "@/components/ProductSelector.vue";
import { useNavBarStore } from "@/store/navBarStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { PointRedeemSku, PointRedeemSkuStatus } from "@/types/Point"; import type { PointRedeemSku, PointRedeemSkuStatus } from "@/types/Point";
import type { ProductSelection } from "@/types/Product";
import { getErrorMessage } from "@/utils/error"; import { getErrorMessage } from "@/utils/error";
import { Message } from "@/utils/message"; import { Message } from "@/utils/message";
import { normalizePackageQuantity } from "@/utils/package"; import { normalizePackageQuantity } from "@/utils/package";
@@ -71,6 +77,8 @@ const isSaving = ref(false);
const form = reactive({ const form = reactive({
id: "", id: "",
product: undefined as PointRedeemSku["product"], product: undefined as PointRedeemSku["product"],
sku: undefined as PointRedeemSku["sku"],
unit: undefined as PointRedeemSku["unit"],
pointText: "", pointText: "",
status: "DRAFT" as PointRedeemSkuStatus, status: "DRAFT" as PointRedeemSkuStatus,
totalText: "", totalText: "",
@@ -97,6 +105,12 @@ function parseLimit(value: string): string | null | undefined {
return value ? normalizePackageQuantity(value) : null; return value ? normalizePackageQuantity(value) : null;
} }
function handleProductSelection(value: ProductSelection): void {
form.product = value.product;
form.sku = value.sku;
form.unit = value.unit;
}
function confirmStatus(value: Array<string | number>): void { function confirmStatus(value: Array<string | number>): void {
form.status = String(value[0]) as PointRedeemSkuStatus; form.status = String(value[0]) as PointRedeemSkuStatus;
statusVisible.value = false; statusVisible.value = false;
@@ -110,6 +124,8 @@ async function load(): Promise<void> {
const item = await PointAPI.redeemSkuDetail(id); const item = await PointAPI.redeemSkuDetail(id);
form.id = item.id || ""; form.id = item.id || "";
form.product = item.product; form.product = item.product;
form.sku = item.sku;
form.unit = item.unit;
selection.value = item.skuId && item.skuUnitId ? { skuId: item.skuId, skuUnitId: item.skuUnitId } : undefined; selection.value = item.skuId && item.skuUnitId ? { skuId: item.skuId, skuUnitId: item.skuUnitId } : undefined;
form.pointText = String(item.defaultPointCost || ""); form.pointText = String(item.defaultPointCost || "");
form.status = item.status || "DRAFT"; form.status = item.status || "DRAFT";
@@ -155,22 +171,6 @@ async function save(): Promise<void> {
} }
} }
async function disable(): Promise<void> {
if (!form.id || isSaving.value) {
return;
}
isSaving.value = true;
try {
await PointAPI.redeemSkuDisable(form.id);
Message.success("兑换配置已停用");
await router.replace({ name: "PointRedeemSkuList" });
} catch (error) {
Message.error(getErrorMessage(error, "兑换配置停用失败"));
} finally {
isSaving.value = false;
}
}
async function remove(): Promise<void> { async function remove(): Promise<void> {
if (!form.id || isSaving.value) { if (!form.id || isSaving.value) {
return; return;
@@ -209,17 +209,5 @@ onUnmounted(() => navBarStore.clearRight());
.tips { .tips {
font-size: .875rem; font-size: .875rem;
} }
.actions {
--td-button-border-radius: 1rem;
gap: .75rem;
margin: 0 1rem;
display: flex;
.t-button {
flex: 1;
}
}
} }
</style> </style>
+18 -9
View File
@@ -16,8 +16,8 @@
v-for="(item, index) in result.list" v-for="(item, index) in result.list"
:key="item.id" :key="item.id"
class="item" class="item"
:title="item.product?.name || item.sku?.name || '未命名产品'"
arrow arrow
:description="item.unit?.name || '单位未知'"
v-entrance-transition="index * 30" v-entrance-transition="index * 30"
@click="toEdit(item)" @click="toEdit(item)"
> >
@@ -35,19 +35,23 @@
v-text="(item.product?.name || item.sku?.name || '产').slice(0, 1)" v-text="(item.product?.name || item.sku?.name || '产').slice(0, 1)"
/> />
</template> </template>
<template #title> <template #note>
<div class="title"> <span class="orange" v-text="formatPoint(item.defaultPointCost)" />
<strong v-text="item.product?.name || item.sku?.name || '未命名产品'" /> </template>
<template #description>
<div class="description">
<t-tag <t-tag
size="small" size="small"
:theme="item.status === 'ACTIVE' ? 'success' : 'default'" :theme="item.status === 'ACTIVE' ? 'success' : 'default'"
:content="statusText(item.status)" :content="statusText(item.status)"
/> />
<product-sku-tags
:product-name="item.product?.name"
:fallback="item.sku?.specSummary || item.sku?.name || '默认 SKU'"
:unit="item.unit?.name"
/>
</div> </div>
</template> </template>
<template #note>
<span class="orange" v-text="formatPoint(item.defaultPointCost)" />
</template>
</t-cell> </t-cell>
</t-cell-group> </t-cell-group>
<t-empty v-else :description="isLoading ? '正在加载兑换配置' : '暂无兑换配置'" /> <t-empty v-else :description="isLoading ? '正在加载兑换配置' : '暂无兑换配置'" />
@@ -63,6 +67,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Toolkit } from "timi-web"; import { Toolkit } from "timi-web";
import PointAPI from "@/api/PointAPI"; import PointAPI from "@/api/PointAPI";
import ProductSkuTags from "@/components/ProductSkuTags.vue";
import { useNavBarStore } from "@/store/navBarStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { PointRedeemSku, PointRedeemSkuStatus } from "@/types/Point"; import type { PointRedeemSku, PointRedeemSkuStatus } from "@/types/Point";
import { Message } from "@/utils/message"; import { Message } from "@/utils/message";
@@ -202,12 +207,16 @@ onUnmounted(() => {
.item { .item {
padding: 10px; padding: 10px;
border-radius: 1rem;
.avatar { .avatar {
width: 3.5rem; width: 3.5rem;
height: 3.5rem; height: 3.5rem;
border-radius: .875rem; }
.description {
gap: .5rem;
display: flex;
align-items: center;
} }
} }
+54 -3
View File
@@ -46,6 +46,10 @@
<t-form-item label="兑换商品" required-mark content-align="right" arrow @click="skuVisible = true"> <t-form-item label="兑换商品" required-mark content-align="right" arrow @click="skuVisible = true">
<span v-text="skuName || '请选择兑换商品'" /> <span v-text="skuName || '请选择兑换商品'" />
</t-form-item> </t-form-item>
<product-sku-form-item
:sku="selectedSku?.sku"
:unit="selectedSku?.unit"
/>
<t-form-item label="兑换数量" content-align="right" required-mark> <t-form-item label="兑换数量" content-align="right" required-mark>
<t-stepper <t-stepper
v-model="quantity" v-model="quantity"
@@ -97,10 +101,26 @@
v-for="item in skuList" v-for="item in skuList"
:key="item.id" :key="item.id"
:title="item.product?.name || item.sku?.name || '未命名产品'" :title="item.product?.name || item.sku?.name || '未命名产品'"
:note="`${item.sku?.specSummary || item.sku?.code || '默认 SKU'} · ${item.unit?.name || ''} · ${formatPoint(item.defaultPointCost)} / 单位`" :note="`${formatPoint(item.defaultPointCost)} / ${item.unit?.name || '单位未知'}`"
class="item"
arrow arrow
@click="selectSku(item)" @click="selectSku(item)"
/> >
<template #left-icon>
<t-image
v-if="getProductPhoto(item)"
:src="getProductPhoto(item)"
:alt="item.product?.name || item.sku?.name || '产品图片'"
fit="cover"
class="avatar"
/>
<div
v-else
class="avatar fallback"
v-text="(item.product?.name || item.sku?.name || '产').slice(0, 1)"
/>
</template>
</t-cell>
<t-empty v-if="!skuList.length" description="暂无启用的兑换商品" /> <t-empty v-if="!skuList.length" description="暂无启用的兑换商品" />
</div> </div>
</bottom-popup> </bottom-popup>
@@ -124,7 +144,7 @@ import { getErrorMessage } from "@/utils/error";
import { Message } from "@/utils/message"; import { Message } from "@/utils/message";
import { formatWanInteger } from "@/utils/money"; import { formatWanInteger } from "@/utils/money";
import { normalizePackageQuantity } from "@/utils/package"; import { normalizePackageQuantity } from "@/utils/package";
import { getProductQuantityStep } from "@/utils/product"; import { getProductPhotoURL, getProductQuantityStep } from "@/utils/product";
import { uploadPhotoList } from "@/utils/photo"; import { uploadPhotoList } from "@/utils/photo";
import { permissionCodes } from "@/utils/permission"; import { permissionCodes } from "@/utils/permission";
@@ -254,6 +274,11 @@ function selectSku(item: PointRedeemSku): void {
skuVisible.value = false; skuVisible.value = false;
} }
function getProductPhoto(item: PointRedeemSku): string {
const product = item.product || item.sku;
return product ? getProductPhotoURL(product) : "";
}
function closeSkuPicker(): void { function closeSkuPicker(): void {
skuVisible.value = false; skuVisible.value = false;
} }
@@ -351,6 +376,32 @@ onUnmounted(() => navBarStore.clearRight());
max-height: 70vh; max-height: 70vh;
overflow: auto; overflow: auto;
padding: 1rem 0; padding: 1rem 0;
.item {
padding: .625rem 1rem;
border-radius: 1rem;
:deep(.t-cell__title) {
display: flex;
align-items: center;
}
.avatar {
width: 2.5rem;
height: 2.5rem;
border-radius: .5rem !important;
}
.fallback {
color: var(--td-brand-color);
display: flex;
font-size: 1rem;
background: var(--td-brand-color-1);
font-weight: 600;
align-items: center;
justify-content: center;
}
}
} }
:global(html.theme-dark) { :global(html.theme-dark) {
@@ -5,7 +5,7 @@
<section class="snapshot-head" v-entrance-transition> <section class="snapshot-head" v-entrance-transition>
<div class="eyebrow">库存 SKU 快照</div> <div class="eyebrow">库存 SKU 快照</div>
<h2 v-text="record.productNameSnapshot || '未命名产品'" /> <h2 v-text="record.productNameSnapshot || '未命名产品'" />
<product-sku-snapshot-tags <product-sku-tags
class="sku" class="sku"
:product-name="record.productNameSnapshot" :product-name="record.productNameSnapshot"
:snapshot="record.skuSpecSnapshot" :snapshot="record.skuSpecSnapshot"
@@ -138,7 +138,7 @@ import { PassTimeLabel } from "timi-web";
import { useUserStore, type Attachment } from "timi-web-api"; import { useUserStore, type Attachment } from "timi-web-api";
import ProductAPI from "@/api/ProductAPI"; import ProductAPI from "@/api/ProductAPI";
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue"; import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
import ProductSkuSnapshotTags from "@/components/ProductSkuSnapshotTags.vue"; import ProductSkuTags from "@/components/ProductSkuTags.vue";
import { useNavBarStore } from "@/store/navBarStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { PhotoItem } from "@/types/Photo"; import type { PhotoItem } from "@/types/Photo";
import type { StockBizType, StockRecord } from "@/types/Product"; import type { StockBizType, StockRecord } from "@/types/Product";
@@ -169,7 +169,7 @@ 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 skuSpecEntries = computed(() => getProductSkuSpecEntries(sku.value, props.specList));
const skuTitle = computed(() => 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 {
editorVisible.value = true; editorVisible.value = true;
@@ -62,9 +62,6 @@
required-mark required-mark
@update:model-value="applyProduct(index, $event)" @update:model-value="applyProduct(index, $event)"
/> />
<t-form-item v-if="item.skuId" label="SKU 单位" content-align="right">
<span v-text="getUnit(item)?.name || '未选择单位'" />
</t-form-item>
<t-form-item :label="canPriceOverride ? '成交单价' : '单价'"> <t-form-item :label="canPriceOverride ? '成交单价' : '单价'">
<t-input <t-input
v-model.trim="item.unitPriceText" v-model.trim="item.unitPriceText"
+2 -2
View File
@@ -113,7 +113,7 @@
v-text="`¥${formatPackageAmount(item.lineAmount)}`" v-text="`¥${formatPackageAmount(item.lineAmount)}`"
/> />
<t-tag v-else size="small" content="套餐权益" /> <t-tag v-else size="small" content="套餐权益" />
<product-sku-snapshot-tags <product-sku-tags
:product-name="item.productNameSnapshot" :product-name="item.productNameSnapshot"
:snapshot="item.skuSpecSnapshot" :snapshot="item.skuSpecSnapshot"
:fallback="item.specSummarySnapshot || item.skuNameSnapshot" :fallback="item.specSummarySnapshot || item.skuNameSnapshot"
@@ -226,7 +226,7 @@ import FulfillmentAPI from "@/api/FulfillmentAPI";
import SalesOrderAPI from "@/api/SalesOrderAPI"; import SalesOrderAPI from "@/api/SalesOrderAPI";
import CustomerProfileCard from "@/components/CustomerProfileCard.vue"; import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue"; import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
import ProductSkuSnapshotTags from "@/components/ProductSkuSnapshotTags.vue"; import ProductSkuTags from "@/components/ProductSkuTags.vue";
import { useNavBarStore } from "@/store/navBarStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { GaoSalesOrderItem, GaoSalesPaymentStatus, SalesOrder } from "@/types/SalesOrder"; import type { GaoSalesOrderItem, GaoSalesPaymentStatus, SalesOrder } from "@/types/SalesOrder";
import type { PhotoItem } from "@/types/Photo"; import type { PhotoItem } from "@/types/Photo";