feat: 增加对比组件

This commit is contained in:
2026-06-12 15:35:02 +08:00
parent 4b4554e901
commit 395ed154b2
4 changed files with 82 additions and 3 deletions

View File

@@ -193,6 +193,19 @@
</scroll-view>
</template>
<template v-else-if="shouldRenderDecisionSuggestionList">
<scroll-view class="route-vs-scroll" scroll-x>
<view class="route-vs-wrap">
<view class="route-vs-col" v-for="suggestion in decisionSuggestionListValue" :key="suggestion.item_name">
<view class="route-vs-head">{{ suggestion.item_name }}</view>
<view class="route-vs-boat" style="color: #2563eb">{{ suggestion.item_commodity_price }}</view>
<ChatMarkdown class="content-body-markdown" :text="suggestion.item_content" />
</view>
</view>
</scroll-view>
</template>
<template v-else>
<template v-for="entry in renderFieldEntries" :key="entry.key">
<ChatMarkdown
@@ -334,6 +347,7 @@ const isPhotoListField = computed(() => props.fieldKey === LONG_TEXT_KEYS.photoL
const isAigcComponetField = computed(() => props.fieldKey === LONG_TEXT_KEYS.aigcComponet);
const isTourRoutesField = computed(() => props.fieldKey === LONG_TEXT_KEYS.tourRoutes);
const isFacilitiesAlongTheWayField = computed(() => props.fieldKey === LONG_TEXT_KEYS.facilitiesAlongTheWay);
const isDecisionSuggestionListField = computed(() => props.fieldKey === LONG_TEXT_KEYS.decisionSuggestionList);
const displayValue = computed(() => sanitizeValue(props.value));
@@ -447,6 +461,21 @@ const getFacilitiesAlongTheWayValue = (value) => {
const facilitiesAlongTheWayValue = computed(() => getFacilitiesAlongTheWayValue(displayValue.value));
const getDecisionSuggestionListValue = (value) => {
if (!isArrayValue(value)) return [];
return value
.filter((item) => isObjectValue(item))
.map((suggestion) => ({
item_name: toTrimmedText(suggestion.item_name),
item_commodity_price: toTrimmedText(suggestion.item_commodity_price),
item_content: toTrimmedText(suggestion.item_content),
}))
.filter((suggestion) => hasDisplayValue(suggestion));
};
const decisionSuggestionListValue = computed(() => getDecisionSuggestionListValue(displayValue.value));
const createRenderEntry = (key, value) => {
if (isImageValue(value)) {
@@ -515,6 +544,10 @@ const shouldRenderFacilitiesAlongTheWay = computed(() => {
return isFacilitiesAlongTheWayField.value && hasDisplayValue(facilitiesAlongTheWayValue.value);
});
const shouldRenderDecisionSuggestionList = computed(() => {
return isDecisionSuggestionListField.value && decisionSuggestionListValue.value.length > 0;
});
/// 其他字段走通用渲染逻辑
const renderFieldEntries = computed(() => {
if (isIgnoredField.value || !hasDisplayValue(props.value)) return [];
@@ -555,7 +588,8 @@ const shouldRenderField = computed(() => {
shouldRenderPhotoList.value ||
shouldRenderAigcComponet.value ||
shouldRenderTourRoutes.value ||
shouldRenderFacilitiesAlongTheWay.value
shouldRenderFacilitiesAlongTheWay.value ||
shouldRenderDecisionSuggestionList.value
) {
return true;
}

View File

@@ -7,7 +7,7 @@
<!-- 滚动区域 -->
<scroll-view class="flex-full overflow-hidden chat-scroll" scroll-y :scroll-into-view="scrollIntoViewId" scroll-with-animation @scroll="onScroll" @touchstart="onTouchStart" @touchend="onTouchEnd" @touchcancel="onTouchEnd">
<view class="flex flex-col pt-12 px-16 pb-24 border-box gap-8">
<view class="flex flex-col pt-12 px-16 pb-24 border-box gap-10">
<template v-if="hasStructuredLongTextData">
<view v-if="headerSections.title || headerSections.tag" class="long-answer-header">
<view v-if="headerSections.title" class="long-answer-title">

View File

@@ -462,7 +462,7 @@
position: relative;
display: flex;
gap: 10px;
margin-bottom: 10px;
margin: 10px 0;
}
.route-step:not(:last-child)::before {
@@ -544,3 +544,46 @@
color: #7c3aed;
font-weight: 900;
}
.route-vs-scroll {
width: 100%;
margin-bottom: 6px;
}
.route-vs-wrap {
display: flex;
flex-direction: row;
}
.route-vs-col {
width: calc(50% - 4px);
flex-shrink: 0;
margin-right: 8px;
box-sizing: border-box;
padding: 11px 12px;
border: 1px solid #e8edf2;
border-radius: 12px;
background: #f8fafc;
}
.route-vs-col:last-child {
margin-right: 0;
}
.route-vs-head {
margin-bottom: 8px;
padding-bottom: 7px;
border-bottom: 1px dashed #d8e0e8;
color: #1e293b;
font-size: 12px;
font-weight: 900;
line-height: 18px;
}
.route-vs-boat {
margin-bottom: 7px;
font-size: 13px;
font-weight: 900;
line-height: 18px;
}

View File

@@ -17,6 +17,7 @@ export const LONG_TEXT_KEYS = {
photoList: "photo_list",
aigcComponet: "aigc_componet",
decisionSection: "decision_section",
decisionSuggestionList: "decision_suggestion_list",
routeWarning: "route_warning",
tourRoutes: "tour_routes",
facilitiesAlongTheWay: "facilities_along_the_way",
@@ -42,6 +43,7 @@ export const LONG_TEXT_FIELD_CONFIG = [
{ key: LONG_TEXT_KEYS.photoList },
{ key: LONG_TEXT_KEYS.aigcComponet },
{ key: LONG_TEXT_KEYS.decisionSection },
{ key: LONG_TEXT_KEYS.decisionSuggestionList },
{ key: LONG_TEXT_KEYS.routeWarning },
{ key: LONG_TEXT_KEYS.tourRoutes },
{ key: LONG_TEXT_KEYS.facilitiesAlongTheWay },