feat: 组件的数据结构调整

This commit is contained in:
2026-06-05 11:35:06 +08:00
parent 1be97986df
commit 3e06ae544b
7 changed files with 575 additions and 231 deletions

View File

@@ -1,127 +1,56 @@
export const LONG_TEXT_KEYS = {
containerType: "container_type",
tag: "tag",
title: "title",
content: "content",
contentSummary: "content_summary",
guideConclusion: "guide_conclusion",
keyFacts: "key_facts",
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",
aigcComponet: "aigc_componet",
preparationSectionTitle: "preparation_section_title",
preparationSectionItems: "preparation_section_items",
sectionSuggestionTitle: "section_suggestion_title",
sectionSuggestionContent: "section_suggestion_content",
pitfallSectionTitle: "pitfall_section_title",
pitfallSectionItems: "pitfall_section_items",
preparationSection: "preparation_section",
sectionSuggestion: "section_suggestion",
pitfallSection: "pitfall_section",
commodityList: "commodity_list",
contentImage: "content_image",
viewSectionTitle: "view_section_title",
viewSectionItems: "view_section_items",
suggestionSectionTitle: "suggestion_section_title",
suggestionSectionContent: "suggestion_section_content",
lightReminderTitle: "light_reminder_title",
lightReminderItems: "light_reminder_items",
checklistOrSteps: "checklist_or_steps",
bestTimeOrPeople: "best_time_or_people",
avoidPitfalls: "avoid_pitfalls",
nextSuggestion: "next_suggestion",
poiDefinition: "poi_definition",
keyHighlights: "key_highlights",
heroImage: "hero_image",
backgroundStory: "background_story",
bestTime: "best_time",
visitSuggestion: "visit_suggestion",
routeSummary: "route_summary",
routeMeta: "route_meta",
routeSteps: "route_steps",
onsiteClues: "onsite_clues",
realtimeNotice: "realtime_notice",
routeWarning: "route_warning",
arrivalNextStep: "arrival_next_step",
photoConclusion: "photo_conclusion",
photoSpots: "photo_spots",
compositionTips: "composition_tips",
phoneSettings: "phone_settings",
viewSection: "view_section",
suggestionSection: "suggestion_section",
lightReminder: "light_reminder",
sampleImage: "sample_image",
components: "components",
checklist: "checklist",
suggest: "suggest",
commodity: "commodity",
actionZone: "action_zone",
spotLocate: "spot_locate",
photoSpotSection: "photo_spot_section",
phoneSection: "phone_section",
photoList: "photo_list",
aigcComponet: "aigc_componet",
decisionSection: "decision_section",
routeWarning: "route_warning",
tourRoutes: "tour_routes",
facilitiesAlongTheWay: "facilities_along_the_way",
questionSuggest: "question_suggest",
};
export const LONG_TEXT_FIELD_CONFIG = [
{ key: LONG_TEXT_KEYS.containerType },
{ key: LONG_TEXT_KEYS.tag },
{ key: LONG_TEXT_KEYS.title },
{ key: LONG_TEXT_KEYS.content },
{ key: LONG_TEXT_KEYS.contentSummary },
{ key: LONG_TEXT_KEYS.guideConclusion },
{ key: LONG_TEXT_KEYS.keyFacts },
{ 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.aigcComponet },
{ key: LONG_TEXT_KEYS.preparationSectionTitle },
{ key: LONG_TEXT_KEYS.preparationSectionItems },
{ key: LONG_TEXT_KEYS.sectionSuggestionTitle },
{ key: LONG_TEXT_KEYS.sectionSuggestionContent },
{ key: LONG_TEXT_KEYS.pitfallSectionTitle },
{ key: LONG_TEXT_KEYS.pitfallSectionItems },
{ key: LONG_TEXT_KEYS.preparationSection },
{ key: LONG_TEXT_KEYS.sectionSuggestion },
{ key: LONG_TEXT_KEYS.pitfallSection },
{ key: LONG_TEXT_KEYS.commodityList },
{ key: LONG_TEXT_KEYS.contentImage },
{ key: LONG_TEXT_KEYS.viewSectionTitle },
{ key: LONG_TEXT_KEYS.viewSectionItems },
{ key: LONG_TEXT_KEYS.suggestionSectionTitle },
{ key: LONG_TEXT_KEYS.suggestionSectionContent },
{ key: LONG_TEXT_KEYS.lightReminderTitle },
{ key: LONG_TEXT_KEYS.lightReminderItems },
{ key: LONG_TEXT_KEYS.checklistOrSteps },
{ key: LONG_TEXT_KEYS.bestTimeOrPeople },
{ key: LONG_TEXT_KEYS.avoidPitfalls },
{ key: LONG_TEXT_KEYS.nextSuggestion },
{ key: LONG_TEXT_KEYS.poiDefinition },
{ key: LONG_TEXT_KEYS.keyHighlights },
{ key: LONG_TEXT_KEYS.heroImage },
{ key: LONG_TEXT_KEYS.backgroundStory },
{ key: LONG_TEXT_KEYS.bestTime },
{ key: LONG_TEXT_KEYS.visitSuggestion },
{ key: LONG_TEXT_KEYS.routeSummary },
{ key: LONG_TEXT_KEYS.routeMeta },
{ key: LONG_TEXT_KEYS.routeSteps },
{ key: LONG_TEXT_KEYS.onsiteClues },
{ key: LONG_TEXT_KEYS.realtimeNotice },
{ key: LONG_TEXT_KEYS.routeWarning },
{ key: LONG_TEXT_KEYS.arrivalNextStep },
{ key: LONG_TEXT_KEYS.photoConclusion },
{ key: LONG_TEXT_KEYS.photoSpots },
{ key: LONG_TEXT_KEYS.compositionTips },
{ key: LONG_TEXT_KEYS.phoneSettings },
{ key: LONG_TEXT_KEYS.viewSection },
{ key: LONG_TEXT_KEYS.suggestionSection },
{ key: LONG_TEXT_KEYS.lightReminder },
{ key: LONG_TEXT_KEYS.sampleImage },
{ key: LONG_TEXT_KEYS.components },
{ key: LONG_TEXT_KEYS.checklist },
{ key: LONG_TEXT_KEYS.suggest },
{ key: LONG_TEXT_KEYS.commodity },
{ key: LONG_TEXT_KEYS.actionZone },
{ key: LONG_TEXT_KEYS.spotLocate },
{ key: LONG_TEXT_KEYS.photoSpotSection },
{ key: LONG_TEXT_KEYS.phoneSection },
{ key: LONG_TEXT_KEYS.photoList },
{ key: LONG_TEXT_KEYS.aigcComponet },
{ key: LONG_TEXT_KEYS.decisionSection },
{ key: LONG_TEXT_KEYS.routeWarning },
{ key: LONG_TEXT_KEYS.tourRoutes },
{ key: LONG_TEXT_KEYS.facilitiesAlongTheWay },
{ key: LONG_TEXT_KEYS.questionSuggest },
];
const LONG_TEXT_FIELD_KEYS = LONG_TEXT_FIELD_CONFIG.map((item) => item.key);
const LONG_TEXT_FIELD_KEY_SET = new Set(LONG_TEXT_FIELD_KEYS);
export const LONG_TEXT_PREVIEW_KEYS = [
LONG_TEXT_KEYS.contentSummary,
LONG_TEXT_KEYS.title,
@@ -133,9 +62,21 @@ export const createLongTextData = () => ({
parsedValues: {},
});
export const isKnownLongTextKey = (key) => {
return LONG_TEXT_FIELD_KEY_SET.has(String(key));
};
const toText = (value) => {
if (value === undefined || value === null) return "";
return typeof value === "string" ? value : String(value);
if (typeof value === "string") return value;
if (typeof value === "object") {
try {
return JSON.stringify(value);
} catch (e) {
return String(value);
}
}
return String(value);
};
const shouldParseJSON = (raw) => {
@@ -167,6 +108,10 @@ const isLongTextObjectValue = (value) => {
return value !== null && typeof value === "object" && !Array.isArray(value);
};
const hasOwnField = (value, key) => {
return Object.prototype.hasOwnProperty.call(value, key);
};
export const parseLongTextDisplayValue = (value) => {
return parseMaybeJSON(value);
};
@@ -218,15 +163,18 @@ export const formatLongTextDisplayValue = (value, ignoredKeys = []) => {
return String(value);
};
export const appendLongTextChunk = (target, chunk = {}) => {
if (!target || !chunk.contentKey) return target;
const key = String(chunk.contentKey);
const value = toText(chunk.contentValue);
const getChunkContentValue = (chunk = {}) => {
if (!isLongTextObjectValue(chunk)) return chunk;
if (hasOwnField(chunk, "contentValue")) return chunk.contentValue;
if (hasOwnField(chunk, "content")) return chunk.content;
return chunk;
};
const appendLongTextField = (target, key, rawValue) => {
if (!target.values) target.values = {};
if (!target.parsedValues) target.parsedValues = {};
const value = toText(rawValue);
target.values[key] = (target.values[key] || "") + value;
const parsed = tryParseJSON(target.values[key]);
@@ -235,7 +183,12 @@ export const appendLongTextChunk = (target, chunk = {}) => {
} else {
delete target.parsedValues[key];
}
};
export const appendLongTextChunk = (target, chunk = {}) => {
if (!target || !chunk || !chunk.contentKey) return target;
appendLongTextField(target, String(chunk.contentKey), getChunkContentValue(chunk));
return target;
};
@@ -260,14 +213,40 @@ export const getLongTextPreviewText = (data, keys = LONG_TEXT_PREVIEW_KEYS) => {
};
export const hasLongTextExtraSections = (data, previewKeys = LONG_TEXT_PREVIEW_KEYS) => {
if (!data || !data.values) return false;
return Object.keys(data.values).some((key) => !previewKeys.includes(key));
return getLongTextSections(data).some((section) => !previewKeys.includes(section.contentKey));
};
export const getLongTextSections = (data) => {
if (!data || !data.values) return [];
return Object.keys(data.values)
const receivedKeys = Object.keys(data.values);
const extraKeysByAnchor = receivedKeys
.filter((key) => !LONG_TEXT_FIELD_KEY_SET.has(key))
.reduce((result, key) => {
const keyIndex = receivedKeys.indexOf(key);
const anchorKey = receivedKeys
.slice(0, keyIndex)
.reverse()
.find((item) => LONG_TEXT_FIELD_KEY_SET.has(item)) || "";
if (!result[anchorKey]) result[anchorKey] = [];
result[anchorKey].push(key);
return result;
}, {});
const orderedKeys = LONG_TEXT_FIELD_KEYS
.filter((key) =>
Object.prototype.hasOwnProperty.call(data.values, key)
)
.reduce((result, key) => {
result.push(key);
if (extraKeysByAnchor[key]) {
result.push(...extraKeysByAnchor[key]);
}
return result;
}, extraKeysByAnchor[""] || []);
return orderedKeys
.map((key) => ({
contentKey: key,
contentValue: getLongTextValue(data, key),