feat: 拍照攻略组件
This commit is contained in:
@@ -43,11 +43,17 @@ for (const snippet of forbiddenCompatibilitySnippets) {
|
|||||||
const requiredStrictRenderingSnippets = [
|
const requiredStrictRenderingSnippets = [
|
||||||
"LONG_TEXT_KEYS.sceneImage",
|
"LONG_TEXT_KEYS.sceneImage",
|
||||||
"LONG_TEXT_KEYS.commodityList",
|
"LONG_TEXT_KEYS.commodityList",
|
||||||
|
"LONG_TEXT_KEYS.photoList",
|
||||||
"commodity.commodity_id",
|
"commodity.commodity_id",
|
||||||
"commodity.commodity_name",
|
"commodity.commodity_name",
|
||||||
"commodity.commodity_price",
|
"commodity.commodity_price",
|
||||||
"commodity.commodity_tag",
|
"commodity.commodity_tag",
|
||||||
"commodity.commodity_photo",
|
"commodity.commodity_photo",
|
||||||
|
"<swiper",
|
||||||
|
"<swiper-item",
|
||||||
|
"photo.photo_name",
|
||||||
|
"photo.photo_description",
|
||||||
|
"photo.photo_url",
|
||||||
"content-body-list-marker",
|
"content-body-list-marker",
|
||||||
"entry.value.length > 1",
|
"entry.value.length > 1",
|
||||||
"formatListMarker(index)",
|
"formatListMarker(index)",
|
||||||
|
|||||||
@@ -61,6 +61,12 @@ const expectedNewKeys = {
|
|||||||
pitfallSectionTitle: "pitfall_section_title",
|
pitfallSectionTitle: "pitfall_section_title",
|
||||||
pitfallSectionItems: "pitfall_section_items",
|
pitfallSectionItems: "pitfall_section_items",
|
||||||
commodityList: "commodity_list",
|
commodityList: "commodity_list",
|
||||||
|
photoSpotSectionTitle: "photo_spot_section_title",
|
||||||
|
photoSpotSectionItems: "photo_spot_section_items",
|
||||||
|
bestTimeSuggestion: "best_time_suggestion",
|
||||||
|
phoneSectionTitle: "phone_section_title",
|
||||||
|
phoneSectionItems: "phone_section_items",
|
||||||
|
photoList: "photo_list",
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [keyName, keyValue] of Object.entries(expectedNewKeys)) {
|
for (const [keyName, keyValue] of Object.entries(expectedNewKeys)) {
|
||||||
|
|||||||
@@ -67,6 +67,38 @@
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="shouldRenderPhotoList">
|
||||||
|
<view class="detail-action-zone">
|
||||||
|
<view class="detail-action-label mt-12">查看机位图</view>
|
||||||
|
<swiper
|
||||||
|
class="photo-card-swiper"
|
||||||
|
:indicator-dots="photoItems.length > 1"
|
||||||
|
indicator-color="#FFFFFF"
|
||||||
|
indicator-active-color="#00A6FF"
|
||||||
|
circular
|
||||||
|
:duration="250"
|
||||||
|
>
|
||||||
|
<swiper-item
|
||||||
|
v-for="photo in photoItems"
|
||||||
|
:key="photo.photo_url || photo.photo_name"
|
||||||
|
>
|
||||||
|
<view class="photo-card" @click="handlePreviewClick(photo.photo_url, photoItems.map(p => p.photo_url))">
|
||||||
|
<image class="photo-card-image" :src="photo.photo_url" mode="aspectFill" />
|
||||||
|
<view class="photo-card-caption">
|
||||||
|
<view v-if="photo.photo_name" class="photo-card-title">
|
||||||
|
{{ photo.photo_name }}
|
||||||
|
</view>
|
||||||
|
<view v-if="photo.photo_description" class="photo-card-subtitle">
|
||||||
|
{{ photo.photo_description }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="photo-card-expand">↗</view>
|
||||||
|
</view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<template v-for="entry in renderFieldEntries" :key="entry.key">
|
<template v-for="entry in renderFieldEntries" :key="entry.key">
|
||||||
<view v-if="entry.type === 'text'" class="content-body-text">
|
<view v-if="entry.type === 'text'" class="content-body-text">
|
||||||
@@ -193,6 +225,7 @@ const isContentImageField = computed(() =>
|
|||||||
const isSpotLocateField = computed(() => props.fieldKey === LONG_TEXT_KEYS.spotLocate);
|
const isSpotLocateField = computed(() => props.fieldKey === LONG_TEXT_KEYS.spotLocate);
|
||||||
const isQuestionSuggestField = computed(() => props.fieldKey === LONG_TEXT_KEYS.questionSuggest);
|
const isQuestionSuggestField = computed(() => props.fieldKey === LONG_TEXT_KEYS.questionSuggest);
|
||||||
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 displayValue = computed(() => sanitizeValue(props.value));
|
const displayValue = computed(() => sanitizeValue(props.value));
|
||||||
|
|
||||||
@@ -235,6 +268,19 @@ const commodityItems = computed(() => {
|
|||||||
.filter((commodity) => hasDisplayValue(commodity));
|
.filter((commodity) => hasDisplayValue(commodity));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const photoItems = computed(() => {
|
||||||
|
if (!isArrayValue(displayValue.value)) return [];
|
||||||
|
|
||||||
|
return displayValue.value
|
||||||
|
.filter((item) => isObjectValue(item))
|
||||||
|
.map((photo) => ({
|
||||||
|
photo_name: toTrimmedText(photo.photo_name),
|
||||||
|
photo_description: toTrimmedText(photo.photo_description),
|
||||||
|
photo_url: toTrimmedText(photo.photo_url),
|
||||||
|
}))
|
||||||
|
.filter((photo) => !!photo.photo_url);
|
||||||
|
});
|
||||||
|
|
||||||
const shouldRenderContentImage = computed(() => {
|
const shouldRenderContentImage = computed(() => {
|
||||||
return isContentImageField.value && !!contentImageUrl.value;
|
return isContentImageField.value && !!contentImageUrl.value;
|
||||||
});
|
});
|
||||||
@@ -251,6 +297,10 @@ const shouldRenderCommodityList = computed(() => {
|
|||||||
return isCommodityListField.value && commodityItems.value.length > 0;
|
return isCommodityListField.value && commodityItems.value.length > 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const shouldRenderPhotoList = computed(() => {
|
||||||
|
return isPhotoListField.value && photoItems.value.length > 0;
|
||||||
|
});
|
||||||
|
|
||||||
/// 其他字段走通用渲染逻辑
|
/// 其他字段走通用渲染逻辑
|
||||||
const renderFieldEntries = computed(() => {
|
const renderFieldEntries = computed(() => {
|
||||||
if (isIgnoredField.value || !hasDisplayValue(props.value)) return [];
|
if (isIgnoredField.value || !hasDisplayValue(props.value)) return [];
|
||||||
@@ -305,7 +355,8 @@ const shouldRenderField = computed(() => {
|
|||||||
shouldRenderContentImage.value ||
|
shouldRenderContentImage.value ||
|
||||||
shouldRenderSpotLocate.value ||
|
shouldRenderSpotLocate.value ||
|
||||||
shouldRenderQuestionSuggest.value ||
|
shouldRenderQuestionSuggest.value ||
|
||||||
shouldRenderCommodityList.value
|
shouldRenderCommodityList.value ||
|
||||||
|
shouldRenderPhotoList.value
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -351,10 +402,10 @@ const openCommodityDetail = (commodity) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePreviewClick = (imageUrl) => {
|
const handlePreviewClick = (imageUrl, imageUrls) => {
|
||||||
uni.previewImage({
|
uni.previewImage({
|
||||||
current: imageUrl,
|
current: imageUrl,
|
||||||
urls: [imageUrl],
|
urls: imageUrls && imageUrls.length > 0 ? imageUrls : [imageUrl],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -226,6 +226,64 @@
|
|||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.photo-card-swiper {
|
||||||
|
width: 100%;
|
||||||
|
height: 228px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-card {
|
||||||
|
position: relative;
|
||||||
|
height: 200px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #f8fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-card-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
background: #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-card-caption {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 28px 14px 12px;
|
||||||
|
background: linear-gradient(to top, rgba(15, 23, 42, 0.58), rgba(15, 23, 42, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-card-title {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-card-subtitle {
|
||||||
|
margin-top: 2px;
|
||||||
|
color: rgba(255, 255, 255, 0.78);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-card-expand {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(15, 23, 42, 0.42);
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 28px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.detail-faq-wrap {
|
.detail-faq-wrap {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ export const LONG_TEXT_KEYS = {
|
|||||||
guideConclusion: "guide_conclusion",
|
guideConclusion: "guide_conclusion",
|
||||||
keyFacts: "key_facts",
|
keyFacts: "key_facts",
|
||||||
sceneImage: "scene_image",
|
sceneImage: "scene_image",
|
||||||
|
photoSpotSectionTitle: "photo_spot_section_title",
|
||||||
|
photoSpotSectionItems: "photo_spot_section_items",
|
||||||
|
bestTimeSuggestion: "best_time_suggestion",
|
||||||
|
phoneSectionTitle: "phone_section_title",
|
||||||
|
phoneSectionItems: "phone_section_items",
|
||||||
|
photoList: "photo_list",
|
||||||
preparationSectionTitle: "preparation_section_title",
|
preparationSectionTitle: "preparation_section_title",
|
||||||
preparationSectionItems: "preparation_section_items",
|
preparationSectionItems: "preparation_section_items",
|
||||||
sectionSuggestionTitle: "section_suggestion_title",
|
sectionSuggestionTitle: "section_suggestion_title",
|
||||||
@@ -62,6 +68,12 @@ export const LONG_TEXT_FIELD_CONFIG = [
|
|||||||
{ key: LONG_TEXT_KEYS.guideConclusion },
|
{ key: LONG_TEXT_KEYS.guideConclusion },
|
||||||
{ key: LONG_TEXT_KEYS.keyFacts },
|
{ key: LONG_TEXT_KEYS.keyFacts },
|
||||||
{ key: LONG_TEXT_KEYS.sceneImage },
|
{ key: LONG_TEXT_KEYS.sceneImage },
|
||||||
|
{ key: LONG_TEXT_KEYS.photoSpotSectionTitle },
|
||||||
|
{ key: LONG_TEXT_KEYS.photoSpotSectionItems },
|
||||||
|
{ key: LONG_TEXT_KEYS.bestTimeSuggestion },
|
||||||
|
{ key: LONG_TEXT_KEYS.phoneSectionTitle },
|
||||||
|
{ key: LONG_TEXT_KEYS.phoneSectionItems },
|
||||||
|
{ key: LONG_TEXT_KEYS.photoList },
|
||||||
{ key: LONG_TEXT_KEYS.preparationSectionTitle },
|
{ key: LONG_TEXT_KEYS.preparationSectionTitle },
|
||||||
{ key: LONG_TEXT_KEYS.preparationSectionItems },
|
{ key: LONG_TEXT_KEYS.preparationSectionItems },
|
||||||
{ key: LONG_TEXT_KEYS.sectionSuggestionTitle },
|
{ key: LONG_TEXT_KEYS.sectionSuggestionTitle },
|
||||||
|
|||||||
Reference in New Issue
Block a user