diff --git a/app/pages/article/[id].vue b/app/pages/article/[id].vue index de945fc..8662013 100644 --- a/app/pages/article/[id].vue +++ b/app/pages/article/[id].vue @@ -215,7 +215,7 @@ const { async () => { if (!isValidNavigationId.value) return null return await pageCmsArticle({ - navigationId: navigationId.value, + categoryId: navigationId.value, page: page.value, limit: limit.value, keywords: keywords.value || undefined diff --git a/app/pages/index.vue b/app/pages/index.vue index 65454be..2579f37 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -26,22 +26,30 @@
-
+
{{ c.title }}
- 更多 + + 更多 + + 更多 +
@@ -83,6 +91,10 @@ import { usePageSeo } from '@/composables/usePageSeo' import { getAdByCode } from '@/api/cms/cmsAd' import type { CmsAd } from '@/api/cms/cmsAd/model' import { COMPANY } from '@/config/company' +import { listCmsNavigation } from '@/api/cms/cmsNavigation' +import type { CmsNavigation } from '@/api/cms/cmsNavigation/model' +import { pageCmsArticle } from '@/api/cms/cmsArticle' +import type { CmsArticle } from '@/api/cms/cmsArticle/model' usePageSeo({ title: '首页', @@ -163,38 +175,78 @@ const services = [ } ] -const columns = [ - { - title: '公司动态', - items: [ - '桂乐淘官方网站上线公告', - '业务范围与资质信息已更新', - '合作咨询:欢迎留言,我们将尽快联系', - '合规提示:涉及许可项目以许可文件为准', - '更多动态敬请期待...' - ] - }, - { - title: '行业资讯', - items: [ - '生物基材料与绿色低碳趋势速览', - '食品流通与预包装食品合规要点', - '冷链与生鲜品质管理建议', - '更多资讯敬请期待...', - '更多资讯敬请期待...' - ] - }, - { - title: '合规与公告', - items: [ - '一般项目:凭营业执照依法自主开展经营活动', - '许可项目:依法须经批准的项目,经批准后方可开展', - '具体经营项目以相关部门批准文件或许可证件为准', - '更多公告敬请期待...', - '更多公告敬请期待...' - ] +const NEWS_PARENT_ID = 4548 + +type HomeNewsColumn = { + key: string + navId?: number + title: string + moreTo: string | null + items: CmsArticle[] +} + +function resolveNavTitle(nav: CmsNavigation) { + return String(nav.title || nav.label || nav.code || '').trim() +} + +function resolveArticleTitle(a: CmsArticle) { + return String(a.title || a.code || '未命名文章').trim() +} + +function resolveArticleLink(a: CmsArticle, navId?: number) { + const articleId = typeof a.articleId === 'number' && Number.isFinite(a.articleId) ? a.articleId : NaN + const code = String(a.code || '').trim() + return { + path: '/article-item', + query: { + id: Number.isFinite(articleId) ? String(articleId) : undefined, + code: !Number.isFinite(articleId) && code ? code : undefined, + navId: typeof navId === 'number' && Number.isFinite(navId) ? String(navId) : undefined + } } -] +} + +const { data: newsRaw, pending: newsPending } = await useAsyncData( + `home-news-${NEWS_PARENT_ID}`, + async () => { + const navs = await listCmsNavigation({ parentId: NEWS_PARENT_ID }).catch(() => []) + const top3 = [...navs] + .filter((it) => typeof it?.navigationId === 'number') + .sort((a, b) => (a.sortNumber ?? 0) - (b.sortNumber ?? 0)) + .slice(0, 3) + + const bundles = await Promise.all( + top3.map(async (nav) => { + const navId = nav.navigationId + const title = resolveNavTitle(nav) || (typeof navId === 'number' ? `栏目 ${navId}` : '栏目') + const page = typeof navId === 'number' + ? await pageCmsArticle({ categoryId: navId, page: 1, limit: 10 }).catch(() => null) + : null + + return { + key: String(navId ?? title), + navId, + title, + moreTo: typeof navId === 'number' ? `/article/${navId}` : null, + items: page?.list ?? [] + } satisfies HomeNewsColumn + }) + ) + + return bundles + } +) + +const columns = computed(() => { + if (newsRaw.value?.length) return newsRaw.value + if (!newsPending.value) return [] + // Keep layout stable while SSR/client is loading. + return [ + { key: 'news-loading-1', navId: undefined, title: '加载中', moreTo: null, items: [] }, + { key: 'news-loading-2', navId: undefined, title: '加载中', moreTo: null, items: [] }, + { key: 'news-loading-3', navId: undefined, title: '加载中', moreTo: null, items: [] } + ] +}) const compliance = [ { @@ -393,6 +445,12 @@ function scrollToCompany() { padding: 10px 14px 14px; } +.column-empty { + padding: 12px 0; + font-size: 13px; + color: rgba(0, 0, 0, 0.45); +} + .column-item { display: block; padding: 8px 0;