Files
MiniProgram/DailyFortuneGuide/utils/fortuneFormatter.js

151 lines
4.9 KiB
JavaScript
Raw Normal View History

2025-11-09 18:41:07 +08:00
const dimensionMeta = require("../constants/dimensions");
const { formatDisplayDateTime } = require("./date");
const dimensionMap = dimensionMeta.reduce((acc, item) => {
acc[item.key] = item;
return acc;
}, {});
function pickValue(source, keys, fallback) {
if (!source) {
return fallback;
}
for (const key of keys) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
const value = source[key];
if (value !== undefined && value !== null) {
return value;
}
}
}
return fallback;
}
function mapTrendText(trend) {
if (trend === "up") {
return "回升";
}
if (trend === "down") {
return "波动";
}
return "平稳";
}
function normalizePillars(pillars) {
if (!Array.isArray(pillars)) {
return [];
}
return pillars
.map((item) => ({
label: pickValue(item, ["label", "Label"], ""),
value: pickValue(item, ["value", "Value"], "")
}))
.filter((item) => item.label || item.value);
}
function formatListText(list, separator = " · ") {
if (!Array.isArray(list) || !list.length) {
return "";
}
return list.join(separator);
}
function normalizeFortunePayload(fortune) {
if (!fortune) {
return null;
}
const dimensionListRaw = pickValue(fortune, ["dimensions", "Dimensions"], []);
const dimensionList = Array.isArray(dimensionListRaw) ? dimensionListRaw : [];
const dimensions = dimensionList.map((item) => {
const key = pickValue(item, ["key", "Key"], "");
const meta = dimensionMap[key] || {};
const trend = pickValue(item, ["trend", "Trend"], "steady");
return {
key,
title: pickValue(item, ["title", "Title"], meta.title || key),
score: pickValue(item, ["score", "Score"], 0),
trend,
insight: pickValue(item, ["insight", "Insight"], ""),
suggestion: pickValue(item, ["suggestion", "Suggestion"], ""),
icon: meta.icon || "⭐",
accent: meta.accent || "#ffb85c",
trendText: mapTrendText(trend)
};
});
const total = dimensions.reduce((acc, current) => acc + (current.score || 0), 0);
const overallScore = dimensions.length ? Math.round(total / dimensions.length) : 0;
return {
fortuneDate: pickValue(fortune, ["fortuneDate", "FortuneDate"], ""),
summary: pickValue(fortune, ["summary", "Summary"], ""),
narrative: pickValue(fortune, ["narrative", "Narrative"], ""),
dimensions,
overallScore,
luckyGuide: normalizeGuide(pickValue(fortune, ["luckyGuide", "LuckyGuide"], null)),
profile: normalizeProfile(pickValue(fortune, ["profile", "Profile"], null))
};
}
function normalizeProfile(profile) {
if (!profile) {
return null;
}
const fiveElements = pickValue(profile, ["fiveElementDistribution", "FiveElementDistribution"], []);
const total = fiveElements.reduce((acc, item) => acc + (pickValue(item, ["count", "Count"], 0) || 0), 0) || 1;
const distribution = fiveElements.map((item) => {
const count = pickValue(item, ["count", "Count"], 0);
const percent = Math.round(((count || 0) / total) * 100);
return {
element: pickValue(item, ["element", "Element"], "未知"),
count,
percent,
width: `${Math.max(percent, 6)}%`
};
});
const birthDateTimeRaw = pickValue(profile, ["birthDateTime", "BirthDateTime"], "");
return {
birthCity: pickValue(profile, ["birthCity", "BirthCity"], ""),
birthProvince: pickValue(profile, ["birthProvince", "BirthProvince"], ""),
birthDateTime: birthDateTimeRaw ? formatDisplayDateTime(birthDateTimeRaw) : "",
birthPillars: normalizePillars(pickValue(profile, ["birthPillars", "BirthPillars"], [])),
todayPillars: normalizePillars(pickValue(profile, ["todayPillars", "TodayPillars"], [])),
distribution,
weakElements: pickValue(profile, ["weakElements", "WeakElements"], []),
strongElements: pickValue(profile, ["strongElements", "StrongElements"], [])
};
}
function normalizeGuide(guide) {
if (!guide) {
return null;
}
const slots = pickValue(guide, ["bestTimeSlots", "BestTimeSlots"], []);
const colors = pickValue(guide, ["colors", "Colors"], []);
const directions = pickValue(guide, ["directions", "Directions"], []);
const props = pickValue(guide, ["props", "Props"], []);
const activities = pickValue(guide, ["activities", "Activities"], []);
return {
element: pickValue(guide, ["element", "Element"], "木"),
colors,
colorText: formatListText(colors),
directions,
directionText: formatListText(directions),
props,
propsText: formatListText(props),
activities,
activitiesText: formatListText(activities, " / "),
bestTimeSlots: Array.isArray(slots)
? slots.map((slot) => ({
label: pickValue(slot, ["label", "Label"], "时段"),
period: pickValue(slot, ["period", "Period"], ""),
reason: pickValue(slot, ["reason", "Reason"], "")
}))
: []
};
}
module.exports = {
normalizeFortunePayload
};