list.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <div class="w-full pt-6">
  3. <div class="main-container flex justify-between items-start">
  4. <div class="w-[860px] bg-[#fff] rounded-[16px] flex flex-col self-stretch overflow-hidden">
  5. <div class="flex justify-between items-start px-[20px] pt-[20px]">
  6. <div class="flex-1 flex flex-wrap" :class="{'h-[34px] overflow-hidden':!isActive}">
  7. <div class="text-[14px] cursor-pointer text-[#666] mb-[20px]" :class="{'!text-[var(--el-color-primary)]': articleTableData.searchParam.category_id == ''}" @click="handleClick('')">全部</div>
  8. <template v-for="(item,index) in categoryList" :key="index">
  9. <div class="text-[14px] cursor-pointer text-[#666] ml-[40px] mb-[20px]" :class="{'!text-[var(--el-color-primary)]': articleTableData.searchParam.category_id == item.category_id}" @click="handleClick(item.category_id)">{{ item.name }}</div>
  10. </template>
  11. </div>
  12. <div v-if="categoryList.length>8" class="flex items-center ml-[20px] !text-[14px] text-[#666] cursor-pointer" @click="handleActive">
  13. <span class="mr-[10px]" >{{ isActive? '收起':'更多'}}</span>
  14. <el-icon v-if="isActive" color="#666" :size="14"><ArrowUp /></el-icon>
  15. <el-icon v-else color="#666" :size="14"><ArrowDown /></el-icon>
  16. </div>
  17. </div>
  18. <div class="flex-1 p-[20px] pt-[10px] border-0 border-t-[1px] border-solid border-[#eee]">
  19. <div v-if="articleTableData.data.length">
  20. <template v-for="(item,index) in articleTableData.data" :key="index">
  21. <div class="py-[20px] flex cursor-pointer" @click="toDetail(item.id)">
  22. <div class="w-[200px] h-[132px] rounded-[12px] overflow-hidden">
  23. <el-image class="w-[200px] h-[132px]" :src="img(item.image ? item.image : '')" fit="cover" />
  24. </div>
  25. <div class="flex-1 flex flex-col justify-between ml-[20px]">
  26. <div>
  27. <h1 class="text-[16px] text-[#333] mb-[20px] hover:text-[var(--el-color-primary)]">{{ item.title }}</h1>
  28. <p class="text-[14px] text-[#666] leading-[22px] multi-hidden max-h-[44px] overflow-hidden">{{ item.intro }}</p>
  29. </div>
  30. <div class="text-[#999] !text-[14px] flex items-center">
  31. <span class="iconfont icon-shijian_o !text-[20px]"></span>
  32. <span class="ml-[5px]">{{ item.update_time }}</span>
  33. <span class="iconfont icon-yanjing_kai !text-[20px] ml-[20px]"></span>
  34. <span class="ml-[5px]">{{ parseInt(item.visit + item.visit_virtual) }}</span>
  35. </div>
  36. </div>
  37. </div>
  38. </template>
  39. <div class="flex justify-center">
  40. <el-pagination v-model:current-page="articleTableData.page" v-model:page-size="articleTableData.limit" layout=" prev, pager, next" :total="articleTableData.total" background hide-on-single-page small @size-change="loadArticleList()" @current-change="loadArticleList" />
  41. </div>
  42. </div>
  43. <div v-else-if="!articleTableData.loading" class="h-full w-full flex items-center justify-center">
  44. <el-empty description="暂无数据" :image-size="200" :image="img('static/resource/images/system/empty.png')" />
  45. </div>
  46. </div>
  47. </div>
  48. <div class="w-[320px] ml-[20px] p-[20px] rounded-[16px] box-border bg-[#fff]">
  49. <h1 class="text-[18px] text-[#333] font-600 mb-[30px]">热门资讯</h1>
  50. <template v-for="(item, index) in articleHotList" :key="index">
  51. <div class="pb-[20px] border-0 border-b-[1px] border-dashed border-[#eee] cursor-pointer" :class="{'mt-[20px]':index}" @click="toDetail(item.id)">
  52. <h3 class="text-[16px] leading-[22px] flex mb-[20px] hover:text-[var(--el-color-primary)]">
  53. <span class="mr-[5px]">{{ index+1 }}.</span>
  54. <span class="text-[#333] max-h-[44px] multi-hidden hover:text-[var(--el-color-primary)]">{{ item.title }}</span>
  55. </h3>
  56. <div class="text-[#999] text-[14px] flex items-center">
  57. <span class="iconfont icon-shijian_o !text-[20px]"></span>
  58. <span class="ml-[3px]">{{ item.create_time }}</span>
  59. </div>
  60. </div>
  61. </template>
  62. <el-empty v-if="!articleHotList.length&&!articleHotLoading" description="暂无数据" :image-size="200" :image="img('static/resource/images/system/empty.png')" />
  63. </div>
  64. </div>
  65. </div>
  66. </template>
  67. <script setup lang="ts">
  68. import { ref, reactive } from 'vue'
  69. import { useRouter } from 'vue-router'
  70. import { getArticleCategory,getArticleList,getArticleHot } from '@/app/api/article'
  71. let router = useRouter()
  72. // 文章栏目
  73. let categoryList = ref([])
  74. const getArticleCategoryFn = () =>{
  75. getArticleCategory().then(res =>{
  76. categoryList.value = res.data
  77. })
  78. }
  79. getArticleCategoryFn()
  80. const articleTableData = reactive({
  81. page: 1,
  82. limit: 10,
  83. total: 0,
  84. loading: true,
  85. data: [],
  86. searchParam: {
  87. title:'',
  88. category_id:''
  89. }
  90. })
  91. // 文章列表
  92. const loadArticleList = (page = 1) => {
  93. articleTableData.page = page
  94. articleTableData.loading = true
  95. getArticleList({
  96. page: articleTableData.page,
  97. limit: articleTableData.limit,
  98. ...articleTableData.searchParam
  99. }).then(res =>{
  100. articleTableData.total = res.data.total
  101. articleTableData.data = res.data.data
  102. articleTableData.loading = false
  103. })
  104. }
  105. loadArticleList()
  106. //点击切换更多/收起
  107. const isActive= ref(false)
  108. const handleActive = () =>{
  109. isActive.value = !isActive.value
  110. }
  111. // 切换文章栏目
  112. const handleClick = (val) =>{
  113. articleTableData.searchParam.category_id = val
  114. loadArticleList()
  115. }
  116. // 文章详情
  117. const toDetail = (id) =>{
  118. router.push({path:'/article/detail',query:{id}})
  119. }
  120. //获取热门推荐
  121. const articleHotList = ref([])
  122. const articleHotLoading = ref(true)
  123. const getArticleHotFn = () =>{
  124. getArticleHot().then(res =>{
  125. articleHotList.value = res.data
  126. articleHotLoading.value = false
  127. }).catch(() =>{
  128. articleHotLoading.value = false
  129. })
  130. }
  131. getArticleHotFn()
  132. </script>
  133. <style lang="scss" scoped>
  134. /* 多行超出隐藏 */
  135. .multi-hidden {
  136. word-break: break-all;
  137. text-overflow: ellipsis;
  138. overflow: hidden;
  139. display: -webkit-box;
  140. -webkit-line-clamp: 2;
  141. -webkit-box-orient: vertical;
  142. }
  143. </style>