feat: 商品单个的展示

This commit is contained in:
2026-06-08 12:50:56 +08:00
parent fc1fd6a6d5
commit 564d4de51f
3 changed files with 186 additions and 25 deletions

View File

@@ -6,6 +6,10 @@ const source = await readFile(
resolve("src/pages/ChatMain/ChatLongAnswer/ParsedValueView.vue"),
"utf8"
);
const styleSource = await readFile(
resolve("src/pages/ChatMain/ChatLongAnswer/styles/ParsedValueView.scss"),
"utf8"
);
const forbiddenCompatibilitySnippets = [
"valueObj.image_url",
@@ -80,6 +84,52 @@ for (const snippet of requiredStrictRenderingSnippets) {
);
}
const requiredSingleCommodityOverviewSnippets = [
':scroll-x="!isSingleCommodity"',
"'overview-combo-card': isSingleCommodity",
'v-if="isSingleCommodity"',
'class="overview-combo-body"',
'class="overview-combo-cover"',
'class="overview-combo-info"',
'class="overview-combo-name"',
'class="overview-combo-desc"',
'class="overview-combo-price"',
'class="overview-combo-currency"',
'class="overview-combo-button"',
];
for (const snippet of requiredSingleCommodityOverviewSnippets) {
assert.equal(
source.includes(snippet),
true,
`ParsedValueView single commodity should use overview combo layout: ${snippet}`
);
}
const requiredSingleCommodityOverviewStyleSnippets = [
".overview-combo-card",
".overview-combo-body",
"display: flex;",
".overview-combo-cover",
"width: 78px;",
"height: 78px;",
".overview-combo-info",
".overview-combo-name",
".overview-combo-desc",
".overview-combo-price",
".overview-combo-currency",
".overview-combo-button",
"height: 40px;",
];
for (const snippet of requiredSingleCommodityOverviewStyleSnippets) {
assert.equal(
styleSource.includes(snippet),
true,
`ParsedValueView single commodity should define overview combo style: ${snippet}`
);
}
const removedInnerSpecialEntrySnippets = [
"createSpecialFieldEntry",
"entry.type === 'question-suggest'",

View File

@@ -29,39 +29,71 @@
<template v-else-if="shouldRenderCommodityList">
<view class="detail-action-zone">
<view class="detail-action-label">相关票务</view>
<scroll-view class="detail-product-scroll" scroll-x>
<scroll-view class="detail-product-scroll" :scroll-x="!isSingleCommodity">
<view class="detail-product-row">
<view
v-for="commodity in commodityItems"
:key="commodity.commodity_id || commodity.commodity_name"
class="detail-product-card"
:class="{ 'detail-product-card--full': isSingleCommodity }"
:class="{ 'overview-combo-card': isSingleCommodity }"
>
<image
v-if="commodity.commodity_photo"
class="detail-product-image"
:src="commodity.commodity_photo"
mode="aspectFill"
@click="handlePreviewClick(commodity.commodity_photo)"
/>
<view class="detail-product-body">
<view v-if="commodity.commodity_tag" class="detail-product-tag">
{{ commodity.commodity_tag }}
</view>
<view v-if="commodity.commodity_name" class="detail-product-name">
{{ commodity.commodity_name }}
</view>
<view v-if="commodity.commodity_price" class="detail-product-price">
<text class="detail-product-currency">¥</text>{{ commodity.commodity_price }}
<template v-if="isSingleCommodity">
<view class="overview-combo-body">
<image
v-if="commodity.commodity_photo"
class="overview-combo-cover"
:src="commodity.commodity_photo"
mode="aspectFill"
@click="handlePreviewClick(commodity.commodity_photo)"
/>
<view class="overview-combo-info">
<view v-if="commodity.commodity_name" class="overview-combo-name">
{{ commodity.commodity_name }}
</view>
<view v-if="commodity.commodity_tag" class="overview-combo-desc">
{{ commodity.commodity_tag }}
</view>
<view v-if="commodity.commodity_price" class="overview-combo-price">
<text class="overview-combo-currency">¥</text>{{ commodity.commodity_price }}
</view>
</view>
</view>
<button
v-if="commodity.commodity_id"
class="detail-buy-button"
class="overview-combo-button"
@click.stop="openCommodityDetail(commodity)"
>
立即购买
</button>
</view>
</template>
<template v-else>
<image
v-if="commodity.commodity_photo"
class="detail-product-image"
:src="commodity.commodity_photo"
mode="aspectFill"
@click="handlePreviewClick(commodity.commodity_photo)"
/>
<view class="detail-product-body">
<view v-if="commodity.commodity_tag" class="detail-product-tag">
{{ commodity.commodity_tag }}
</view>
<view v-if="commodity.commodity_name" class="detail-product-name">
{{ commodity.commodity_name }}
</view>
<view v-if="commodity.commodity_price" class="detail-product-price">
<text class="detail-product-currency">¥</text>{{ commodity.commodity_price }}
</view>
<button
v-if="commodity.commodity_id"
class="detail-buy-button"
@click.stop="openCommodityDetail(commodity)"
>
立即购买
</button>
</view>
</template>
</view>
</view>
</scroll-view>
@@ -307,11 +339,11 @@ const getCommodityItems = (value) => {
return value
.filter((item) => isObjectValue(item))
.map((commodity) => ({
commodity_id: toTrimmedText(commodity.commodity_id),
commodity_name: toTrimmedText(commodity.commodity_name),
commodity_price: toTrimmedText(commodity.commodity_price),
commodity_tag: toTrimmedText(commodity.commodity_tag),
commodity_photo: toTrimmedText(commodity.commodity_photo),
commodity_id: toTrimmedText(commodity.commodity_id || commodity.commodityId),
commodity_name: toTrimmedText(commodity.commodity_name || commodity.commodityName),
commodity_price: toTrimmedText(commodity.commodity_price || commodity.commodityPrice),
commodity_tag: toTrimmedText(commodity.commodity_tag || commodity.commodityTag),
commodity_photo: toTrimmedText(commodity.commodity_photo || commodity.commodityIcon),
}))
.filter((commodity) => hasDisplayValue(commodity));
};

View File

@@ -222,6 +222,85 @@
border: 0;
}
.overview-combo-card {
width: 100%;
border-color: #0CCD58;
border-radius: 18px;
box-shadow: none;
}
.overview-combo-body {
display: flex;
gap: 12px;
padding: 12px;
white-space: normal;
}
.overview-combo-cover {
display: block;
width: 78px;
height: 78px;
flex-shrink: 0;
border-radius: 12px;
background: linear-gradient(135deg, #1d9e75, #185fa5);
}
.overview-combo-info {
flex: 1;
min-width: 0;
}
.overview-combo-name {
overflow: hidden;
color: #1e293b;
display: -webkit-box;
font-size: 14px;
font-weight: 900;
line-height: 20px;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.overview-combo-desc {
margin: 3px 0 6px;
overflow: hidden;
color: #94a3b8;
font-size: 11px;
font-weight: 700;
line-height: 17px;
text-overflow: ellipsis;
white-space: nowrap;
}
.overview-combo-price {
color: #f43f5e;
font-size: 22px;
font-weight: 900;
line-height: 28px;
}
.overview-combo-currency {
font-size: 12px;
}
.overview-combo-button {
width: 100%;
height: 40px;
padding: 0;
border: 0;
border-radius: 0;
color: #FFFFFF;
background: #0CCD58;
font-size: 13px;
font-weight: 900;
line-height: 40px;
}
.overview-combo-button::after {
border: 0;
}
.photo-card-swiper {
width: 100%;
height: 228px;