Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 

192 Zeilen
6.7 KiB

  1. <template>
  2. <div>
  3. <div class="mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8 lg:py-10">
  4. <div class="lg:grid lg:grid-cols-12 lg:gap-8">
  5. <!-- 正文 -->
  6. <div class="lg:col-span-8">
  7. <article class="overflow-hidden rounded-2xl bg-[var(--c-ffffff)] p-5 shadow-[0_8px_28px_var(--sh-34-68-112-50)] sm:p-8">
  8. <!-- 面包屑 -->
  9. <nav aria-label="面包屑" class="flex flex-wrap items-center gap-1.5 text-xs text-[var(--c-8a97a8)]">
  10. <NuxtLink to="/" class="hover:text-[var(--c-0b8cff)]">首页</NuxtLink>
  11. <span>/</span>
  12. <NuxtLink to="/info" class="hover:text-[var(--c-0b8cff)]">AI 资讯</NuxtLink>
  13. <span>/</span>
  14. <NuxtLink :to="colPath(detail.col_id)" class="hover:text-[var(--c-0b8cff)]">{{ colName(detail.col_id) }}</NuxtLink>
  15. </nav>
  16. <h1 class="mt-4 text-2xl font-extrabold leading-snug text-[var(--c-172033)] sm:text-3xl">
  17. {{ detail.title }}
  18. </h1>
  19. <!-- 元信息 -->
  20. <div class="mt-4 flex flex-wrap items-center gap-4 border-b border-[var(--c-eef2f7)] pb-5 text-xs text-[var(--c-a0aabb)]">
  21. <span class="inline-flex items-center gap-1">
  22. <UIcon name="i-lucide-calendar" class="size-3.5" />
  23. {{ formatTime(detail.publish_time) }}
  24. </span>
  25. <span class="inline-flex items-center gap-1">
  26. <UIcon name="i-lucide-eye" class="size-3.5" />
  27. {{ detail.view_num || 0 }} 次浏览
  28. </span>
  29. <span class="rounded-full bg-[var(--c-eef7ff)] px-2 py-0.5 font-bold text-[var(--c-0b8cff)]">
  30. {{ colName(detail.col_id) }}
  31. </span>
  32. </div>
  33. <!-- 摘要 -->
  34. <p v-if="detail.info" class="mt-5 rounded-xl bg-[var(--c-f7f9fd)] p-4 text-sm leading-relaxed text-[var(--c-4b5b70)]">
  35. {{ detail.info }}
  36. </p>
  37. <!-- 正文富文本 -->
  38. <!-- eslint-disable-next-line vue/no-v-html -->
  39. <div class="article-content mt-6" v-html="detail.content" />
  40. <!-- 标签 -->
  41. <div v-if="detail.tag_list?.length" class="mt-8 flex flex-wrap items-center gap-2 border-t border-[var(--c-eef2f7)] pt-6">
  42. <span class="text-xs font-bold text-[var(--c-8a97a8)]">标签:</span>
  43. <NuxtLink
  44. v-for="tag in detail.tag_list"
  45. :key="tag.id"
  46. :to="`/info/tag/${tag.tag_key}.html`"
  47. class="rounded-full bg-[var(--c-f7f9fd)] px-3 py-1.5 text-xs font-bold text-[var(--c-5b6b80)] transition-colors hover:bg-[var(--c-eef7ff)] hover:text-[var(--c-0b8cff)]"
  48. >
  49. {{ tag.name }}
  50. </NuxtLink>
  51. </div>
  52. <!-- 上一篇 / 下一篇 -->
  53. <div v-if="detail.prev_id || detail.next_id" class="mt-8 grid gap-3 border-t border-[var(--c-eef2f7)] pt-6 sm:grid-cols-2">
  54. <NuxtLink
  55. v-if="detail.prev_id"
  56. :to="`${colPath(detail.col_id)}/${detail.prev_id}.html`"
  57. rel="prev"
  58. class="group rounded-xl bg-[var(--c-f7f9fd)] p-4 transition-colors hover:bg-[var(--c-eef7ff)]"
  59. >
  60. <div class="text-xs text-[var(--c-a0aabb)]">上一篇</div>
  61. <div class="mt-1 text-sm font-bold text-[var(--c-4b5b70)] transition-colors group-hover:text-[var(--c-0b8cff)]">查看上一篇</div>
  62. </NuxtLink>
  63. <NuxtLink
  64. v-if="detail.next_id"
  65. :to="`${colPath(detail.col_id)}/${detail.next_id}.html`"
  66. rel="next"
  67. class="group rounded-xl bg-[var(--c-f7f9fd)] p-4 text-right transition-colors hover:bg-[var(--c-eef7ff)] sm:col-start-2"
  68. >
  69. <div class="text-xs text-[var(--c-a0aabb)]">下一篇</div>
  70. <div class="mt-1 text-sm font-bold text-[var(--c-4b5b70)] transition-colors group-hover:text-[var(--c-0b8cff)]">查看下一篇</div>
  71. </NuxtLink>
  72. </div>
  73. </article>
  74. </div>
  75. <!-- 侧栏 -->
  76. <div class="mt-8 lg:col-span-4 lg:mt-0">
  77. <div class="lg:sticky lg:top-20">
  78. <NewsSidebar :hot-list="hotList" :tag-list="tagList" />
  79. </div>
  80. </div>
  81. </div>
  82. </div>
  83. </div>
  84. </template>
  85. <script setup>
  86. import { colName, colPath, formatTime } from '~/composables/useArticle'
  87. defineProps({
  88. detail: { type: Object, required: true },
  89. hotList: { type: Array, default: () => [] },
  90. tagList: { type: Array, default: () => [] },
  91. })
  92. </script>
  93. <style scoped>
  94. /* 富文本正文排版(后台编辑器输出的 HTML) */
  95. .article-content {
  96. font-size: 15px;
  97. line-height: 1.9;
  98. color: var(--c-3f4c60);
  99. word-break: break-word;
  100. }
  101. .article-content :deep(h1),
  102. .article-content :deep(h2),
  103. .article-content :deep(h3),
  104. .article-content :deep(h4) {
  105. margin: 1.6em 0 0.7em;
  106. font-weight: 800;
  107. color: var(--c-172033);
  108. line-height: 1.4;
  109. }
  110. .article-content :deep(h1) { font-size: 1.5em; }
  111. .article-content :deep(h2) { font-size: 1.3em; }
  112. .article-content :deep(h3) { font-size: 1.15em; }
  113. .article-content :deep(p) { margin: 0.9em 0; }
  114. .article-content :deep(img) {
  115. max-width: 100%;
  116. height: auto;
  117. margin: 1.2em auto;
  118. display: block;
  119. border-radius: 12px;
  120. }
  121. .article-content :deep(a) {
  122. color: var(--c-0b8cff);
  123. text-decoration: underline;
  124. }
  125. .article-content :deep(ul),
  126. .article-content :deep(ol) {
  127. margin: 0.9em 0;
  128. padding-left: 1.4em;
  129. }
  130. .article-content :deep(ul) { list-style: disc; }
  131. .article-content :deep(ol) { list-style: decimal; }
  132. .article-content :deep(li) { margin: 0.4em 0; }
  133. .article-content :deep(blockquote) {
  134. margin: 1.2em 0;
  135. padding: 12px 16px;
  136. border-left: 4px solid var(--c-0b8cff);
  137. border-radius: 0 10px 10px 0;
  138. background: var(--c-f7fbff);
  139. color: var(--c-4b5b70);
  140. }
  141. .article-content :deep(pre) {
  142. margin: 1.2em 0;
  143. padding: 14px 16px;
  144. overflow-x: auto;
  145. border-radius: 12px;
  146. background: var(--c-0e1524);
  147. color: var(--c-eaf0ff);
  148. font-size: 13px;
  149. line-height: 1.7;
  150. }
  151. .article-content :deep(code) {
  152. padding: 2px 6px;
  153. border-radius: 5px;
  154. background: var(--c-f1f5fa);
  155. font-size: 0.92em;
  156. }
  157. .article-content :deep(pre code) {
  158. padding: 0;
  159. background: transparent;
  160. }
  161. .article-content :deep(table) {
  162. width: 100%;
  163. margin: 1.2em 0;
  164. border-collapse: collapse;
  165. font-size: 14px;
  166. }
  167. .article-content :deep(th),
  168. .article-content :deep(td) {
  169. border: 1px solid var(--c-e8eef7);
  170. padding: 8px 12px;
  171. }
  172. .article-content :deep(th) {
  173. background: var(--c-f7f9fd);
  174. font-weight: 700;
  175. }
  176. .article-content :deep(hr) {
  177. margin: 1.6em 0;
  178. border: 0;
  179. border-top: 1px solid var(--c-eef2f7);
  180. }
  181. </style>