官网开发中 0803
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import type { PageSeo } from '~/types/site';
|
||||
|
||||
/**
|
||||
* 页面 SEO 适配
|
||||
*
|
||||
* 从 dashboard 的 page-seo 配置读取 meta_title / meta_description / meta_keywords / og_image_url,
|
||||
* 应用到当前页面的 useHead;未配置时回退到全局 SEO 默认值或页面默认标题。
|
||||
*/
|
||||
export async function usePageSeo(pageType: string, entityId?: number, fallbackTitle?: string) {
|
||||
const { getPageSeo } = useSiteApi();
|
||||
const siteStore = useSiteStore();
|
||||
// 注意:本函数可能在 onMounted 等异步上下文中被调用,useI18n 要求 setup 顶层,
|
||||
// 这里改用全局 i18n 实例($i18n.t 跟随当前 locale,任意上下文安全)
|
||||
const i18n = (useNuxtApp() as unknown as { $i18n?: { t(key: string): string } }).$i18n;
|
||||
const t = (key: string) => i18n?.t(key) || key;
|
||||
|
||||
let seo: PageSeo | null = null;
|
||||
try {
|
||||
seo = await getPageSeo(pageType, entityId);
|
||||
} catch {
|
||||
seo = null;
|
||||
}
|
||||
|
||||
const title = seo?.meta_title || fallbackTitle || t('app.name');
|
||||
const description = seo?.meta_description || siteStore.seo?.meta_description || '';
|
||||
const keywords = seo?.meta_keywords || siteStore.seo?.meta_keywords || '';
|
||||
|
||||
useHead({
|
||||
title,
|
||||
meta: [
|
||||
...(description ? [{ name: 'description', content: description }] : []),
|
||||
...(keywords ? [{ name: 'keywords', content: keywords }] : []),
|
||||
...(seo?.og_image_url ? [{ property: 'og:image', content: seo.og_image_url }] : [])
|
||||
]
|
||||
});
|
||||
}
|
||||
@@ -23,6 +23,12 @@ export function useSectionContent(section: SectionBlock) {
|
||||
/** 深色主题区块 */
|
||||
const isDark = computed(() => section.theme === 'dark');
|
||||
|
||||
// 前景文案自定义颜色(空 = 跟随 theme 默认配色,由布局组件的 class 控制)
|
||||
// 内联 style 优先级高于 class,非空时直接覆盖默认色
|
||||
const overlineStyle = computed(() => (section.overline_color ? { color: section.overline_color } : undefined));
|
||||
const titleStyle = computed(() => (section.title_color ? { color: section.title_color } : undefined));
|
||||
const bodyStyle = computed(() => (section.body_color ? { color: section.body_color } : undefined));
|
||||
|
||||
return {
|
||||
isEn,
|
||||
overline,
|
||||
@@ -33,6 +39,9 @@ export function useSectionContent(section: SectionBlock) {
|
||||
ctaSecondaryText,
|
||||
mediaUrl,
|
||||
config,
|
||||
isDark
|
||||
isDark,
|
||||
overlineStyle,
|
||||
titleStyle,
|
||||
bodyStyle
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
import type { GlobalConfig, NavConfig, SectionBlock, I18nEntry, ProductsData } from '~/types/site';
|
||||
import type {
|
||||
GlobalConfig,
|
||||
NavConfig,
|
||||
SectionBlock,
|
||||
I18nEntry,
|
||||
ProductsData,
|
||||
NewsArticle,
|
||||
NewsDetail,
|
||||
NewsListConfig,
|
||||
ProductListConfig,
|
||||
AboutConfig,
|
||||
SupportConfig,
|
||||
ContactConfig,
|
||||
PageSeo
|
||||
} from '~/types/site';
|
||||
|
||||
/**
|
||||
* 官网前台公开接口服务层
|
||||
@@ -35,5 +49,37 @@ export function useSiteApi() {
|
||||
return get<ProductsData>('/site/products');
|
||||
}
|
||||
|
||||
return { getGlobal, getNav, getSections, getI18n, getProducts };
|
||||
/** 新闻列表(仅已发布) */
|
||||
function getNews(skip = 0, limit = 9) {
|
||||
return get<{ items: NewsArticle[]; total: number; skip: number; limit: number }>('/site/news', { skip, limit });
|
||||
}
|
||||
|
||||
/** 新闻详情(按 slug,含推荐) */
|
||||
function getNewsDetail(slug: string) {
|
||||
return get<NewsDetail>(`/site/news/${encodeURIComponent(slug)}`);
|
||||
}
|
||||
|
||||
/** 页面配置:product-list / news-list / about / support */
|
||||
function getPageConfig<T>(type: 'product-list' | 'news-list' | 'about' | 'support') {
|
||||
return get<T>('/site/page', { type });
|
||||
}
|
||||
|
||||
/** 页面 SEO 配置 */
|
||||
function getPageSeo(pageType: string, entityId?: number) {
|
||||
const params: Record<string, unknown> = { page_type: pageType };
|
||||
if (entityId) params.entity_id = entityId;
|
||||
return get<PageSeo | null>('/site/page-seo', params);
|
||||
}
|
||||
|
||||
/** 联系表单配置 + 字段 */
|
||||
function getContact() {
|
||||
return get<ContactConfig>('/site/contact');
|
||||
}
|
||||
|
||||
/** 提交联系表单 */
|
||||
function submitContact(formData: Record<string, string>) {
|
||||
return useRequest().post<null>('/site/contact/submit', { form_data: formData });
|
||||
}
|
||||
|
||||
return { getGlobal, getNav, getSections, getI18n, getProducts, getNews, getNewsDetail, getPageConfig, getPageSeo, getContact, submitContact };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user