You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
7.4 KiB

9 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
8 months ago
9 months ago
9 months ago
9 months ago
8 months ago
9 months ago
9 months ago
9 months ago
8 months ago
8 months ago
9 months ago
9 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
9 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
8 months ago
8 months ago
8 months ago
9 months ago
  1. <template>
  2. <div class="main">
  3. <div class="mainContent" v-for="article in bloglist">
  4. <a-badge-ribbon :text=article.typename color="black">
  5. <a-card hoverable>
  6. <h2>{{ article.blogtitle }}</h2>
  7. <div class="tag-group">
  8. <a-tag color="#E6E6FA">
  9. <template #icon>
  10. <component :is=iconComponents.RiLiLined />
  11. </template>
  12. {{ article.create_at }}
  13. </a-tag>
  14. <a-tag color="#6495ED">
  15. <template #icon>
  16. <component :is=iconComponents.YanJingLined />
  17. </template>
  18. {{ article.readnum }}
  19. </a-tag>
  20. <a-tag color="#B0C4DE">
  21. <template #icon>
  22. <component :is=iconComponents.XieZiLined />
  23. </template>
  24. 字数{{ article.wordcount }}
  25. </a-tag>
  26. <a-tag color="#20B2AA">
  27. <template #icon>
  28. <component :is=iconComponents.YueDuLined />
  29. </template>
  30. 阅读时长{{ article.readminite }}
  31. </a-tag>
  32. </div>
  33. <div class="blog-content">
  34. <div>
  35. <a-image :preview="false" :width="200" :src=article.imglink />
  36. </div>
  37. <div class="text-container">
  38. {{ article.blogcontent }}
  39. </div>
  40. </div>
  41. <div class="read-button">
  42. <a-button type="primary" shape="round" @click="readMore(article.id)">阅读全文</a-button>
  43. </div>
  44. <hr class="custom-line">
  45. <div>
  46. <a-tag :color=randomColor() v-for="label in JSON.parse(article.labelnames)">{{ label }}</a-tag>
  47. </div>
  48. </a-card>
  49. </a-badge-ribbon>
  50. </div>
  51. <div class="pagination">
  52. <a-pagination v-model:current="current" v-if="dataLoaded" v-model:page-size="pageSizeRef"
  53. :page-size-options="pageSizeOptions" :total="total" show-size-changer @change="onShowSizeChange">
  54. <template #buildOptionText="props">
  55. <span v-if="props.value !== '50'">{{ props.value }}/</span>
  56. <span v-else>全部</span>
  57. </template>
  58. </a-pagination>
  59. </div>
  60. </div>
  61. </template>
  62. <script setup lang='ts'>
  63. import { onMounted, ref } from 'vue';
  64. import iconComponents from '@/assets';
  65. import { useContentStore } from "@/stores"
  66. import dayjs from 'dayjs';
  67. import type { blogInterface } from '@/api/admin';
  68. import { get,put } from "@/tools/request"
  69. import router from '@/router';
  70. const store = useContentStore()
  71. const randomColor = () => {
  72. const labelColor = ref(["processing", "success", "error", "warning", "magenta", "red", "volcano", "orange", "gold", "lime", "green", "cyan", "blue", "geekblue", "purple"])
  73. return labelColor.value[Math.floor(Math.random() * labelColor.value.length)];
  74. }
  75. const dataLoaded = ref(false);
  76. // 分页
  77. const pageSizeOptions = ref<string[]>(['10', '20', '30', '40', '50']);
  78. const current = ref(1);
  79. const total = ref();
  80. const pageSizeRef = ref(10);
  81. const bloglist = ref<blogInterface[]>([])
  82. const onShowSizeChange = (page: number) => {
  83. current.value = page;
  84. blogList(page, pageSizeRef.value)
  85. };
  86. // const blogList = async (page: number, pageSize: number) => {
  87. // try {
  88. // const response = await get('/blogs/list', {
  89. // page,
  90. // page_size: pageSize,
  91. // })
  92. // bloglist.value = response.data.data.blogs;
  93. // total.value = response.data.data.total; // 更新总数
  94. // pageSizeRef.value = pageSize; // 更新页大小,如果需要从接口返回页大小也可以改为 response.data.data.page_size
  95. // dataLoaded.value = true
  96. // } catch (error) {
  97. // console.error('Failed to fetch data', error);
  98. // }
  99. // };
  100. const blogList = async (page: number, pageSize: number) => {
  101. try {
  102. const response = await get('/blogs/list', {
  103. page,
  104. page_size: pageSize,
  105. })
  106. bloglist.value = response.data.data.blogs.map((items: any,index:number) => ({
  107. id: items.id,
  108. key: items.key,
  109. blogtitle: items.blogtitle,
  110. blogcontent: items.blogcontent,
  111. typename: items.typename,
  112. labelnames: items.labelnames,
  113. wordcount: items.blogcontent.length,
  114. create_at: dayjs(items.create_at).format('YYYY-MM-DD HH:mm:ss'),
  115. update_at: dayjs(items.update_at).format('YYYY-MM-DD HH:mm:ss'),
  116. readnum: items.readnum,
  117. readminite: Math.round(items.blogcontent.length/ 200),
  118. imglink: items.imglink,
  119. }))
  120. total.value = response.data.data.total; // 更新总数
  121. pageSizeRef.value = pageSize; // 更新页大小,如果需要从接口返回页大小也可以改为 response.data.data.page_size
  122. dataLoaded.value = true
  123. } catch (error) {
  124. console.error('Failed to fetch data', error);
  125. }
  126. }
  127. const blogCount=async (id:any)=>{
  128. await put(`/blogs/update/${id}/readnum`)
  129. }
  130. const readMore = (id: any) => {
  131. router.push(`/blog/${id}`)
  132. blogCount(id)
  133. }
  134. onMounted(() => {
  135. blogList(current.value, pageSizeRef.value);
  136. });
  137. </script>
  138. <style scoped>
  139. .main {
  140. width: 45%;
  141. margin: 0 24px;
  142. }
  143. .main .mainContent {
  144. margin-bottom: 24px;
  145. }
  146. .main h2 {
  147. text-align: center;
  148. }
  149. .main .tag-group {
  150. display: flex;
  151. justify-content: center;
  152. }
  153. .main .tag-group>* {
  154. color: black;
  155. margin: 0 12px;
  156. }
  157. .main .blog-content {
  158. display: flex;
  159. margin: 48px;
  160. }
  161. .main .blog-content>:first-child {
  162. padding: 4px;
  163. border: 2px solid #ccc;
  164. display: inline-block;
  165. border-radius: 10px;
  166. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  167. }
  168. .main .blog-content>:nth-child(2) {
  169. overflow: hidden;
  170. text-overflow: ellipsis;
  171. white-space: pre-wrap;
  172. /* 防止文本换行 */
  173. }
  174. .main .read-button {
  175. display: flex;
  176. justify-content: center;
  177. }
  178. .main .read-button button {
  179. color: #fff;
  180. border: none;
  181. cursor: pointer;
  182. background-color: #007bff;
  183. /* 初始背景颜色 */
  184. animation: colorChange 3s infinite alternate;
  185. /* 添加颜色变化的动画 */
  186. }
  187. .custom-line {
  188. border: 0;
  189. height: 1px;
  190. background: #d9d6d6;
  191. margin: 48px 0 24px 0;
  192. }
  193. @keyframes colorChange {
  194. 0% {
  195. background-color: #007bff;
  196. /* 初始颜色 */
  197. }
  198. 50% {
  199. background-color: #ff7e5f;
  200. /* 中间颜色 */
  201. }
  202. 100% {
  203. background-color: #feb47b;
  204. /* 结束颜色 */
  205. }
  206. }
  207. .main .text-container {
  208. text-overflow: ellipsis;
  209. display: -webkit-box;
  210. -webkit-box-orient: vertical;
  211. -webkit-line-clamp: 6;
  212. word-wrap: break-word;
  213. overflow-wrap: break-word;
  214. line-height: 2;
  215. margin-left: 24px;
  216. }
  217. .pagination {
  218. margin-bottom: 24px;
  219. display: flex;
  220. justify-content: right;
  221. }
  222. </style>