feat(home): 更新首页新闻栏目数据获取逻辑
- 将硬编码的新闻栏目数据替换为从CMS动态获取 - 添加了新闻栏目数据类型定义和解析函数 - 实现了新闻文章链接生成和标题解析功能 - 更新了页面参数传递,将navigationId改为categoryId - 添加了加载状态和空数据状态的UI显示 - 集成了文章详情页的动态路由跳转功能
This commit is contained in:
@@ -215,7 +215,7 @@ const {
|
|||||||
async () => {
|
async () => {
|
||||||
if (!isValidNavigationId.value) return null
|
if (!isValidNavigationId.value) return null
|
||||||
return await pageCmsArticle({
|
return await pageCmsArticle({
|
||||||
navigationId: navigationId.value,
|
categoryId: navigationId.value,
|
||||||
page: page.value,
|
page: page.value,
|
||||||
limit: limit.value,
|
limit: limit.value,
|
||||||
keywords: keywords.value || undefined
|
keywords: keywords.value || undefined
|
||||||
|
|||||||
@@ -26,22 +26,30 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6 grid grid-cols-12 gap-6">
|
<div class="mt-6 grid grid-cols-12 gap-6">
|
||||||
<div v-for="c in columns" :key="c.title" class="col-span-12 lg:col-span-4">
|
<div v-for="c in columns" :key="c.key" class="col-span-12 lg:col-span-4">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="column-head">
|
<div class="column-head">
|
||||||
<div class="column-title">{{ c.title }}</div>
|
<div class="column-title">{{ c.title }}</div>
|
||||||
<a href="#" class="column-more" @click.prevent>更多 +</a>
|
<NuxtLink v-if="c.moreTo" :to="c.moreTo" class="column-more">更多 +</NuxtLink>
|
||||||
|
<span v-else class="column-more opacity-60">更多 +</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="column-list">
|
<div class="column-list">
|
||||||
<a
|
<template v-if="newsPending">
|
||||||
v-for="it in c.items"
|
<div class="column-empty">加载中...</div>
|
||||||
:key="it"
|
</template>
|
||||||
class="column-item"
|
<template v-else-if="!c.items.length">
|
||||||
href="#"
|
<div class="column-empty">暂无文章</div>
|
||||||
@click.prevent
|
</template>
|
||||||
>
|
<template v-else>
|
||||||
{{ it }}
|
<NuxtLink
|
||||||
</a>
|
v-for="(it, idx) in c.items"
|
||||||
|
:key="String(it.articleId ?? it.code ?? `${c.key}-${idx}`)"
|
||||||
|
class="column-item"
|
||||||
|
:to="resolveArticleLink(it, c.navId)"
|
||||||
|
>
|
||||||
|
{{ resolveArticleTitle(it) }}
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,6 +91,10 @@ import { usePageSeo } from '@/composables/usePageSeo'
|
|||||||
import { getAdByCode } from '@/api/cms/cmsAd'
|
import { getAdByCode } from '@/api/cms/cmsAd'
|
||||||
import type { CmsAd } from '@/api/cms/cmsAd/model'
|
import type { CmsAd } from '@/api/cms/cmsAd/model'
|
||||||
import { COMPANY } from '@/config/company'
|
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({
|
usePageSeo({
|
||||||
title: '首页',
|
title: '首页',
|
||||||
@@ -163,38 +175,78 @@ const services = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const columns = [
|
const NEWS_PARENT_ID = 4548
|
||||||
{
|
|
||||||
title: '公司动态',
|
type HomeNewsColumn = {
|
||||||
items: [
|
key: string
|
||||||
'桂乐淘官方网站上线公告',
|
navId?: number
|
||||||
'业务范围与资质信息已更新',
|
title: string
|
||||||
'合作咨询:欢迎留言,我们将尽快联系',
|
moreTo: string | null
|
||||||
'合规提示:涉及许可项目以许可文件为准',
|
items: CmsArticle[]
|
||||||
'更多动态敬请期待...'
|
}
|
||||||
]
|
|
||||||
},
|
function resolveNavTitle(nav: CmsNavigation) {
|
||||||
{
|
return String(nav.title || nav.label || nav.code || '').trim()
|
||||||
title: '行业资讯',
|
}
|
||||||
items: [
|
|
||||||
'生物基材料与绿色低碳趋势速览',
|
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 {
|
||||||
title: '合规与公告',
|
path: '/article-item',
|
||||||
items: [
|
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<HomeNewsColumn[]>(
|
||||||
|
`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<HomeNewsColumn[]>(() => {
|
||||||
|
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 = [
|
const compliance = [
|
||||||
{
|
{
|
||||||
@@ -393,6 +445,12 @@ function scrollToCompany() {
|
|||||||
padding: 10px 14px 14px;
|
padding: 10px 14px 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.column-empty {
|
||||||
|
padding: 12px 0;
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgba(0, 0, 0, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
.column-item {
|
.column-item {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user