Files
admin/www/app/stores/site.ts
T
2026-07-31 19:02:00 +08:00

114 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineStore } from 'pinia';
import type {
SiteSettings,
FooterSettings,
SocialLink,
SeoDefaults,
NavItem,
NavAppearance,
ProductSeries,
I18nEntry
} from '~/types/site';
/**
* 官网全局站点状态
*
* 在应用启动时一次性拉取全局配置、导航、产品(Mega Menu)与 i18n 词条,
* 供 AppHeader / AppFooter 及各页面共享使用。
*/
export const useSiteStore = defineStore('site', () => {
const { getGlobal, getNav, getI18n, getProducts } = useSiteApi();
const { locale } = useI18n();
// ===== 全局配置 =====
const site = ref<SiteSettings | null>(null);
const footer = ref<FooterSettings | null>(null);
const social = ref<SocialLink[]>([]);
const seo = ref<SeoDefaults | null>(null);
// ===== 导航 =====
const navItems = ref<NavItem[]>([]);
const navAppearance = ref<NavAppearance | null>(null);
// ===== 产品(导航 Mega Menu =====
const productSeries = ref<ProductSeries[]>([]);
// ===== i18n 词条(dict_key -> entry =====
const i18nMap = ref<Record<string, I18nEntry>>({});
const loaded = ref(false);
const loading = ref(false);
/** 应用启动时调用,并行拉取全局数据 */
async function init() {
if (loaded.value || loading.value) return;
loading.value = true;
try {
const [globalRes, navRes, i18nRes, productsRes] = await Promise.all([
getGlobal(),
getNav(),
getI18n(),
getProducts()
]);
if (globalRes) {
site.value = globalRes.site;
footer.value = globalRes.footer;
social.value = globalRes.social ?? [];
seo.value = globalRes.seo;
}
if (navRes) {
navItems.value = navRes.items ?? [];
navAppearance.value = navRes.appearance;
}
if (i18nRes) {
const map: Record<string, I18nEntry> = {};
for (const entry of i18nRes.items ?? []) {
map[entry.dict_key] = entry;
}
i18nMap.value = map;
}
if (productsRes) {
productSeries.value = productsRes.series ?? [];
}
loaded.value = true;
} finally {
loading.value = false;
}
}
/**
* 翻译 CMS 动态词条(www_i18n_entries
* @param key 词条 key,如 'btn.learn_more'
* @param fallback 词条缺失时的回退文案
*/
function td(key: string, fallback = ''): string {
const entry = i18nMap.value[key];
if (!entry) return fallback || key;
const value = locale.value === 'en' ? entry.value_en : entry.value_zh;
return value || fallback || key;
}
/** 根据当前语言取导航入口名称 */
function navLabel(item: NavItem): string {
return locale.value === 'en' ? item.name_en : item.name_zh;
}
return {
site,
footer,
social,
seo,
navItems,
navAppearance,
productSeries,
i18nMap,
loaded,
loading,
init,
td,
navLabel
};
});