Files
MiniProgram/DailyFortuneGuide/store/fortuneStore.js

177 lines
4.6 KiB
JavaScript
Raw Normal View History

2025-11-09 18:41:07 +08:00
const config = require("../config/index");
const { formatDate } = require("../utils/date");
const { safeGetStorage, safeSetStorage } = require("../utils/storage");
const { normalizeRegionArray, deriveRegionFromParts, getRegionParts } = require("../utils/region");
const STORAGE_KEYS = {
history: "fortune:history",
quotaPrefix: "fortune:quota:",
form: "fortune:form"
};
function createDefaultForm() {
return {
birthDate: formatDate(new Date()),
birthTime: "",
birthProvince: "",
birthCity: "",
birthDistrict: "",
birthRegion: []
};
}
function normalizeForm(payload, fallback) {
const base = fallback || createDefaultForm();
const toStringValue = (value, fallbackValue = "") => (typeof value === "string" ? value : fallbackValue);
const normalized = {
birthDate: toStringValue(payload && payload.birthDate, base.birthDate),
birthTime: toStringValue(payload && payload.birthTime, base.birthTime || ""),
birthProvince: toStringValue(payload && payload.birthProvince, base.birthProvince || ""),
birthCity: toStringValue(payload && payload.birthCity, base.birthCity || ""),
birthDistrict: toStringValue(payload && payload.birthDistrict, base.birthDistrict || ""),
birthRegion: []
};
const persistedRegion = normalizeRegionArray(payload && payload.birthRegion);
const baseRegion = normalizeRegionArray(base.birthRegion);
if (persistedRegion.length) {
normalized.birthRegion = persistedRegion;
} else if (baseRegion.length) {
normalized.birthRegion = baseRegion;
} else {
normalized.birthRegion = deriveRegionFromParts({
province: normalized.birthProvince,
city: normalized.birthCity,
district: normalized.birthDistrict
});
}
const parts = getRegionParts(normalized.birthRegion, {
province: normalized.birthProvince,
city: normalized.birthCity,
district: normalized.birthDistrict
});
normalized.birthProvince = parts.province;
normalized.birthCity = parts.city;
normalized.birthDistrict = parts.district;
return normalized;
}
function loadPersistedForm() {
const stored = safeGetStorage(STORAGE_KEYS.form, null);
if (stored && typeof stored === "object") {
return normalizeForm(stored);
}
const defaults = createDefaultForm();
safeSetStorage(STORAGE_KEYS.form, defaults);
return defaults;
}
function persistForm(form) {
const normalized = normalizeForm(form);
safeSetStorage(STORAGE_KEYS.form, normalized);
}
const state = {
form: loadPersistedForm(),
currentFortune: null,
history: [],
quota: {
date: "",
count: 0
},
lastError: ""
};
function getQuotaStorageKey(dateStr) {
return `${STORAGE_KEYS.quotaPrefix}${dateStr.replace(/-/g, "")}`;
}
function syncQuota() {
const today = formatDate(new Date());
const storageKey = getQuotaStorageKey(today);
const stored = safeGetStorage(storageKey, 0);
const count = typeof stored === "number" ? stored : 0;
state.quota = {
date: today,
count
};
}
function incrementQuota() {
const today = formatDate(new Date());
if (state.quota.date !== today) {
syncQuota();
}
const nextCount = state.quota.count + 1;
state.quota = {
date: today,
count: nextCount
};
safeSetStorage(getQuotaStorageKey(today), nextCount);
}
function canGenerateToday() {
const today = formatDate(new Date());
if (state.quota.date !== today) {
syncQuota();
}
return state.quota.count < config.maxDailyQuota;
}
function loadHistory() {
const stored = safeGetStorage(STORAGE_KEYS.history, []);
state.history = Array.isArray(stored) ? stored : [];
}
function saveHistory() {
safeSetStorage(STORAGE_KEYS.history, state.history);
}
function appendHistory(formSnapshot, fortune) {
const snapshot = normalizeForm(formSnapshot, state.form);
const entry = {
id: `${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
createdAt: new Date().toISOString(),
formSnapshot: snapshot,
fortune
};
const next = [entry, ...state.history];
state.history = next.slice(0, config.historyLimit);
saveHistory();
return entry;
}
function getHistoryById(id) {
return state.history.find((item) => item.id === id);
}
function setForm(partial) {
const merged = Object.assign({}, state.form, partial);
state.form = normalizeForm(merged, state.form);
persistForm(state.form);
}
function setCurrentFortune(fortune) {
state.currentFortune = fortune;
}
function getState() {
return state;
}
function initStore() {
syncQuota();
loadHistory();
}
module.exports = {
initStore,
getState,
setForm,
setCurrentFortune,
appendHistory,
loadHistory,
getHistoryById,
canGenerateToday,
incrementQuota
};