Commit f2dec14d by lijiabin

refactor: 重构项目代码

parent b169ea5a
......@@ -230,6 +230,35 @@ export interface ColumnOptionDto {
}
/**
* 首页专栏/专访列表里「文章卡片」的公共字段
*/
export interface YaArticleCardVo {
articleId: number
collectCount: number
content: string
createTime: number
description: string
faceUrl: string
hasPraised: boolean
isRecommend: number
praiseCount: number
replyCount: number
title: string
type: ArticleTypeEnum
viewCount: number
}
/**
* 专栏文章(比专访多视频相关字段)
*/
export interface YaColumnArticleVo extends YaArticleCardVo {
videoDuration: string
showName: string
showAvatar: string
playCount: number
}
/**
* 专栏列表Item
*/
export interface ColumnItemDto {
......@@ -237,25 +266,7 @@ export interface ColumnItemDto {
color: string
sort: number
id: number
yaColumnVoList: {
articleId: number
collectCount: number
content: string
createTime: number
description: string
faceUrl: string
hasPraised: boolean
isRecommend: number
praiseCount: number
replyCount: number
title: string
type: ArticleTypeEnum.COLUMN
viewCount: number
videoDuration: string
showName: string
showAvatar: string
playCount: number
}[]
yaColumnVoList: YaColumnArticleVo[]
}
/**
......@@ -295,21 +306,7 @@ export interface InterviewItemDto {
title: string
color: string
sort: number
yaColumnVoList: {
articleId: number
collectCount: number
content: string
createTime: number
description: string
faceUrl: string
hasPraised: boolean
isRecommend: number
praiseCount: number
replyCount: number
title: string
type: ArticleTypeEnum.INTERVIEW
viewCount: number
}[]
yaColumnVoList: YaArticleCardVo[]
}
/**
......
<template>
<div
class="group cursor-pointer rounded-lg overflow-hidden border border-transparent hover:border-gray-200 hover:shadow-md transition-all duration-300"
>
<!-- 封面图 -->
<div class="relative overflow-hidden">
<img
:src="item.faceUrl"
class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300"
/>
<!-- 推荐角标 -->
<div
v-if="item.isRecommend"
class="absolute top-0 left-0 w-15 h-7 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
>
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" />
<div class="text-12px text-#000 line-height-12px">推荐</div>
</div>
<!-- 底部渐变遮罩 -->
<div
class="absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-black/30 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"
></div>
</div>
<!-- 文字信息 -->
<div class="p-2">
<h3 class="font-medium text-gray-800 mb-2.5 line-clamp-1">
{{ item.title }}
</h3>
<div class="flex items-center justify-between text-xs text-gray-500">
<div class="flex items-center gap-2">
<span class="flex items-center gap-0.5">
<el-icon><IEpView /></el-icon>
{{ item.viewCount }}
</span>
<span class="flex items-center gap-0.5">
<el-icon><IEpChatDotRound /></el-icon>
{{ item.replyCount }}
</span>
<span class="flex items-center gap-0.5">
<el-icon><IEpStar /></el-icon>
{{ item.collectCount }}
</span>
</div>
<div class="text-gray-500">
{{
smallerThanXl
? dayjs(item.createTime * 1000).format('YYYY-MM-DD')
: dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm')
}}
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
import type { YaArticleCardVo } from '@/api/article/types'
defineProps<{ item: YaArticleCardVo }>()
const breakpoints = useBreakpoints(breakpointsTailwind)
const smallerThanXl = breakpoints.smaller('xl')
</script>
<template>
<div
class="bg-white rounded-xl shadow-sm mb-6 overflow-hidden border border-gray-100"
:style="{ '--dynamic-color': item.color }"
>
<!-- 专栏标题栏 -->
<div class="flex items-center justify-between px-5 py-3" :style="{ backgroundColor: item.color }">
<h3 class="text-base font-semibold text-gray-800 flex items-center gap-2">
<span class="w-1 h-5 rounded-full bg-gray-700/60"></span>
{{ item.title }}
</h3>
<div
v-if="moreLink"
class="flex items-center cursor-pointer text-13px text-gray-500 hover:text-indigo-500 transition-colors duration-200"
@click="router.push(moreLink)"
>
查看更多 >>
</div>
</div>
<!-- 内容区 -->
<div class="p-5">
<div
v-if="item.yaColumnVoList.length"
class="grid grid-cols-1 grid-cols-3 xl:grid-cols-3 gap-5"
>
<YaArticleCard
v-for="i in item.yaColumnVoList"
:key="i.articleId"
:item="i"
@click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })"
/>
</div>
<div v-else class="flex items-center justify-center h-48">
<el-empty description="暂无数据" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useRouter, type RouteLocationRaw } from 'vue-router'
import { useNavigation } from '@/hooks'
import YaArticleCard from '@/components/common/YaArticleCard/index.vue'
import type { ColumnItemDto, InterviewItemDto } from '@/api/article/types'
defineProps<{
/** 一个专栏/专访分区的完整数据 */
item: ColumnItemDto | InterviewItemDto
/** 传入则展示「查看更多」并跳转该路由;不传则不展示 */
moreLink?: RouteLocationRaw
}>()
const router = useRouter()
const { jumpToArticleDetailPage } = useNavigation()
</script>
......@@ -2,102 +2,15 @@
<div>
<div v-loading="loading" v-if="list.length">
<div class="w-full max-w-6xl mx-auto">
<div
<YaColumnSection
v-for="(item, index) in list"
:key="index"
class="bg-white rounded-xl shadow-sm mb-6 overflow-hidden border border-gray-100"
:style="{ '--dynamic-color': item.color }"
>
<!-- 专栏标题栏 -->
<div
class="flex items-center justify-between px-5 py-3"
:style="{ backgroundColor: item.color }"
>
<h3 class="text-base font-semibold text-gray-800 flex items-center gap-2">
<span class="w-1 h-5 rounded-full bg-gray-700/60"></span>
{{ item.title }}
</h3>
<div
class="flex items-center cursor-pointer text-13px text-gray-500 hover:text-indigo-500 transition-colors duration-200"
@click="
router.push({
path: `/columnSearchList/${item.id}`,
query: { columnTitle: item.title },
})
"
>
查看更多 >>
</div>
</div>
<!-- 内容区 -->
<div class="p-5">
<div
v-if="item.yaColumnVoList.length"
class="grid grid-cols-1 grid-cols-3 xl:grid-cols-3 gap-5"
>
<div
v-for="i in item.yaColumnVoList"
:key="i.articleId"
class="group cursor-pointer rounded-lg overflow-hidden border border-transparent hover:border-gray-200 hover:shadow-md transition-all duration-300"
@click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })"
>
<!-- 封面图 -->
<div class="relative overflow-hidden">
<img
:src="i.faceUrl"
class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300"
/>
<!-- 推荐角标 -->
<div
v-if="i.isRecommend"
class="absolute top-0 left-0 w-15 h-7 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
>
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" />
<div class="text-12px text-#000 line-height-12px">推荐</div>
</div>
<!-- 底部渐变遮罩 -->
<div
class="absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-black/30 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"
></div>
</div>
<!-- 文字信息 -->
<div class="p-2">
<h3 class="font-medium text-gray-800 mb-2.5 line-clamp-1">
{{ i.title }}
</h3>
<div class="flex items-center justify-between text-xs text-gray-500">
<div class="flex items-center gap-2">
<span class="flex items-center gap-0.5">
<el-icon><IEpView /></el-icon>
{{ i.viewCount }}
</span>
<span class="flex items-center gap-0.5">
<el-icon><IEpChatDotRound /></el-icon>
{{ i.replyCount }}
</span>
<span class="flex items-center gap-0.5">
<el-icon><IEpStar /></el-icon>
{{ i.collectCount }}
</span>
</div>
<div class="text-gray-500">
{{
smallerThanXl
? dayjs(i.createTime * 1000).format('YYYY-MM-DD')
: dayjs(i.createTime * 1000).format('YYYY-MM-DD HH:mm')
}}
</div>
</div>
</div>
</div>
</div>
<div v-else class="flex items-center justify-center h-48">
<el-empty description="暂无数据" />
</div>
</div>
</div>
:item="item"
:more-link="{
path: `/columnSearchList/${item.id}`,
query: { columnTitle: item.title },
}"
/>
</div>
<div class="bottom-pagination border-t border-gray-200">
<div class="max-w-7xl mx-auto py-4">
......@@ -144,18 +57,10 @@
import { getColumnList } from '@/api'
import { usePageSearch, useScrollTop } from '@/hooks'
import { TABS_REF_KEY } from '@/constants'
import dayjs from 'dayjs'
import { useRouter } from 'vue-router'
import { useNavigation } from '@/hooks'
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
const breakpoints = useBreakpoints(breakpointsTailwind)
const smallerThanXl = breakpoints.smaller('xl')
import YaColumnSection from '@/components/common/YaColumnSection/index.vue'
const router = useRouter()
const tabsRef = inject(TABS_REF_KEY)
const { handleBackTop, ScrollTopComp } = useScrollTop(tabsRef!)
const { jumpToArticleDetailPage } = useNavigation()
const { list, total, searchParams, goToPage, changePageSize, loading, refresh } = usePageSearch(
getColumnList,
{
......@@ -165,10 +70,7 @@ const { list, total, searchParams, goToPage, changePageSize, loading, refresh }
)
defineExpose({
refresh: () => {
// searchParams.value.current = 0
refresh()
},
})
</script>
<style scoped></style>
......@@ -2,91 +2,7 @@
<div>
<div v-loading="loading" v-if="list.length">
<div class="w-full max-w-6xl mx-auto">
<div
v-for="(item, index) in list"
:key="index"
class="bg-white rounded-xl shadow-sm mb-6 overflow-hidden border border-gray-100"
:style="{ '--dynamic-color': item.color }"
>
<!-- 专栏标题栏 -->
<div
class="flex items-center justify-between px-5 py-3"
:style="{ backgroundColor: item.color }"
>
<h3 class="text-base font-semibold text-gray-800 flex items-center gap-2">
<span class="w-1 h-5 rounded-full bg-gray-700/60"></span>
{{ item.title }}
</h3>
</div>
<!-- 内容区 -->
<div class="p-5">
<div
v-if="item.yaColumnVoList.length"
class="grid grid-cols-1 grid-cols-3 xl:grid-cols-3 gap-5"
>
<div
v-for="i in item.yaColumnVoList"
:key="i.articleId"
class="group cursor-pointer rounded-lg overflow-hidden border border-transparent hover:border-gray-200 hover:shadow-md transition-all duration-300"
@click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })"
>
<!-- 封面图 -->
<div class="relative overflow-hidden">
<img
:src="i.faceUrl"
class="w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300"
/>
<!-- 推荐角标 -->
<div
v-if="i.isRecommend"
class="absolute top-0 left-0 w-15 h-7 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
>
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" />
<div class="text-12px text-#000 line-height-12px">推荐</div>
</div>
<!-- 底部渐变遮罩 -->
<div
class="absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-black/30 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"
></div>
</div>
<!-- 文字信息 -->
<div class="p-2">
<h3 class="font-medium text-gray-800 mb-2.5 line-clamp-1">
{{ i.title }}
</h3>
<div class="flex items-center justify-between text-xs text-gray-500">
<div class="flex items-center gap-2">
<span class="flex items-center gap-0.5">
<el-icon><IEpView /></el-icon>
{{ i.viewCount }}
</span>
<span class="flex items-center gap-0.5">
<el-icon><IEpChatDotRound /></el-icon>
{{ i.replyCount }}
</span>
<span class="flex items-center gap-0.5">
<el-icon><IEpStar /></el-icon>
{{ i.collectCount }}
</span>
</div>
<div class="text-gray-500">
{{
smallerThanXl
? dayjs(i.createTime * 1000).format('YYYY-MM-DD')
: dayjs(i.createTime * 1000).format('YYYY-MM-DD HH:mm')
}}
</div>
</div>
</div>
</div>
</div>
<div v-else class="flex items-center justify-center h-48">
<el-empty description="暂无数据" />
</div>
</div>
</div>
<YaColumnSection v-for="(item, index) in list" :key="index" :item="item" />
</div>
<div class="bottom-pagination border-t border-gray-200">
<div class="max-w-7xl mx-auto py-4">
......@@ -132,16 +48,12 @@
<script setup lang="ts">
import { getInterviewList } from '@/api'
import { usePageSearch, useScrollTop, useNavigation } from '@/hooks'
import { usePageSearch, useScrollTop } from '@/hooks'
import { TABS_REF_KEY } from '@/constants'
import dayjs from 'dayjs'
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
const breakpoints = useBreakpoints(breakpointsTailwind)
const smallerThanXl = breakpoints.smaller('xl')
const tabsRef = inject(TABS_REF_KEY)
import YaColumnSection from '@/components/common/YaColumnSection/index.vue'
const tabsRef = inject(TABS_REF_KEY)
const { handleBackTop, ScrollTopComp } = useScrollTop(tabsRef!)
const { jumpToArticleDetailPage } = useNavigation()
const { list, total, searchParams, goToPage, changePageSize, loading, refresh } = usePageSearch(
getInterviewList,
{
......@@ -155,5 +67,3 @@ defineExpose({
},
})
</script>
<style scoped></style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment