每日运势小程序
This commit is contained in:
150
DailyFortuneGuide/utils/fortuneFormatter.js
Normal file
150
DailyFortuneGuide/utils/fortuneFormatter.js
Normal file
@@ -0,0 +1,150 @@
|
||||
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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user