feat: 完整路线和设备设施组件
This commit is contained in:
@@ -17,6 +17,35 @@
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="shouldRenderTourRoutes">
|
||||||
|
<view class="detail-action-zone">
|
||||||
|
<view class="detail-action-label">完整路线</view>
|
||||||
|
<view class="route-step-card">
|
||||||
|
<!-- <view class="route-step-title">{{ tourRoutesValue.full_routes }}</view> -->
|
||||||
|
<ChatMarkdown class="content-body-markdown" :text="tourRoutesValue.full_routes" />
|
||||||
|
<view v-for="(step, index) in tourRoutesValue.mount_condition" :key="step.act" class="route-step">
|
||||||
|
<view class="route-step-index">{{ index + 1 }}</view>
|
||||||
|
<view class="route-step-main">
|
||||||
|
<view class="route-step-act">{{ step.from }} → {{ step.to }}</view>
|
||||||
|
<view class="route-step-meta">{{ step.howToGetThere }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="shouldRenderFacilitiesAlongTheWay">
|
||||||
|
<view class="route-step-card">
|
||||||
|
<!-- <view class="route-step-title"> {{ facilitiesAlongTheWayValue.facilities_title }} </view> -->
|
||||||
|
<ChatMarkdown class="content-body-markdown" :text="facilitiesAlongTheWayValue.facilities_title" />
|
||||||
|
<view v-for="facility in facilitiesAlongTheWayValue.facility_types" :key="facility.facility_type"
|
||||||
|
class="facility-row">
|
||||||
|
<view class="facility-label">{{ facility.facility_type }}</view>
|
||||||
|
<view>{{ facility.facility_content }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template v-else-if="shouldRenderQuestionSuggest">
|
<template v-else-if="shouldRenderQuestionSuggest">
|
||||||
<view class="detail-action-label">继续追问</view>
|
<view class="detail-action-label">继续追问</view>
|
||||||
<scroll-view class="detail-faq-wrap" scroll-x>
|
<scroll-view class="detail-faq-wrap" scroll-x>
|
||||||
@@ -300,6 +329,8 @@ const isQuestionSuggestField = computed(() => props.fieldKey === LONG_TEXT_KEYS.
|
|||||||
const isCommodityListField = computed(() => props.fieldKey === LONG_TEXT_KEYS.commodityList);
|
const isCommodityListField = computed(() => props.fieldKey === LONG_TEXT_KEYS.commodityList);
|
||||||
const isPhotoListField = computed(() => props.fieldKey === LONG_TEXT_KEYS.photoList);
|
const isPhotoListField = computed(() => props.fieldKey === LONG_TEXT_KEYS.photoList);
|
||||||
const isAigcComponetField = computed(() => props.fieldKey === LONG_TEXT_KEYS.aigcComponet);
|
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 displayValue = computed(() => sanitizeValue(props.value));
|
const displayValue = computed(() => sanitizeValue(props.value));
|
||||||
|
|
||||||
@@ -379,6 +410,41 @@ const getAigcComponetValue = (value) => {
|
|||||||
|
|
||||||
const aigcComponetValue = computed(() => getAigcComponetValue(displayValue.value));
|
const aigcComponetValue = computed(() => getAigcComponetValue(displayValue.value));
|
||||||
|
|
||||||
|
const getTourRoutesValue = (value) => {
|
||||||
|
const tourRoutes = isObjectValue(value) ? value : {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
routes_title: toTrimmedText(tourRoutes.routes_title),
|
||||||
|
full_routes: toTrimmedText(tourRoutes.full_routes),
|
||||||
|
mount_condition: isArrayValue(tourRoutes.mount_condition)
|
||||||
|
? tourRoutes.mount_condition.map((step) => ({
|
||||||
|
from: toTrimmedText(step.from),
|
||||||
|
to: toTrimmedText(step.to),
|
||||||
|
howToGetThere: toTrimmedText(step.howToGetThere),
|
||||||
|
}))
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const tourRoutesValue = computed(() => getTourRoutesValue(displayValue.value));
|
||||||
|
|
||||||
|
const getFacilitiesAlongTheWayValue = (value) => {
|
||||||
|
const facilities = isObjectValue(value) ? value : {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
facilities_title: toTrimmedText(facilities.facilities_title),
|
||||||
|
facility_types: isArrayValue(facilities.facility_types)
|
||||||
|
? facilities.facility_types.map((facility) => ({
|
||||||
|
facility_type: toTrimmedText(facility.facility_type),
|
||||||
|
facility_content: toTrimmedText(facility.facility_content),
|
||||||
|
}))
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const facilitiesAlongTheWayValue = computed(() => getFacilitiesAlongTheWayValue(displayValue.value));
|
||||||
|
|
||||||
|
|
||||||
const createRenderEntry = (key, value) => {
|
const createRenderEntry = (key, value) => {
|
||||||
if (isImageValue(value)) {
|
if (isImageValue(value)) {
|
||||||
return [createImageEntry(key, value)];
|
return [createImageEntry(key, value)];
|
||||||
@@ -438,6 +504,14 @@ const shouldRenderAigcComponet = computed(() => {
|
|||||||
return isAigcComponetField.value && hasDisplayValue(aigcComponetValue.value);
|
return isAigcComponetField.value && hasDisplayValue(aigcComponetValue.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const shouldRenderTourRoutes = computed(() => {
|
||||||
|
return isTourRoutesField.value && hasDisplayValue(tourRoutesValue.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const shouldRenderFacilitiesAlongTheWay = computed(() => {
|
||||||
|
return isFacilitiesAlongTheWayField.value && hasDisplayValue(facilitiesAlongTheWayValue.value);
|
||||||
|
});
|
||||||
|
|
||||||
/// 其他字段走通用渲染逻辑
|
/// 其他字段走通用渲染逻辑
|
||||||
const renderFieldEntries = computed(() => {
|
const renderFieldEntries = computed(() => {
|
||||||
if (isIgnoredField.value || !hasDisplayValue(props.value)) return [];
|
if (isIgnoredField.value || !hasDisplayValue(props.value)) return [];
|
||||||
@@ -476,7 +550,9 @@ const shouldRenderField = computed(() => {
|
|||||||
shouldRenderQuestionSuggest.value ||
|
shouldRenderQuestionSuggest.value ||
|
||||||
shouldRenderCommodityList.value ||
|
shouldRenderCommodityList.value ||
|
||||||
shouldRenderPhotoList.value ||
|
shouldRenderPhotoList.value ||
|
||||||
shouldRenderAigcComponet.value
|
shouldRenderAigcComponet.value ||
|
||||||
|
shouldRenderTourRoutes.value ||
|
||||||
|
shouldRenderFacilitiesAlongTheWay.value
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-body-list-item {
|
.content-body-list-item {
|
||||||
@@ -442,3 +442,105 @@
|
|||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
line-height: 11px;
|
line-height: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.route-step-card {
|
||||||
|
padding: 6px 16px 14px 16px;
|
||||||
|
border: 1px solid rgba(15, 23, 42, 0.07);
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step-title {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
color: #1e293b;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step:not(:last-child)::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 22px;
|
||||||
|
bottom: -4px;
|
||||||
|
left: 8px;
|
||||||
|
width: 2px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #cbd5e1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step:not(:last-child)::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: -4px;
|
||||||
|
left: 4px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-right: 5px solid transparent;
|
||||||
|
border-left: 5px solid transparent;
|
||||||
|
border-top: 5px solid #cbd5e1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step-index {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #fff;
|
||||||
|
background: #8b5cf6;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step-main {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step-act {
|
||||||
|
color: #334155;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-step-meta {
|
||||||
|
margin-top: 1px;
|
||||||
|
color: #94a3b8;
|
||||||
|
font-size: 10.5px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.facility-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 5px 0;
|
||||||
|
color: #475569;
|
||||||
|
font-size: 11.5px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.facility-label {
|
||||||
|
width: 52px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: #7c3aed;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user