ArticleDetail.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <script setup>
  2. import { ref, reactive } from "vue";
  3. import { useRoute, useRouter } from "vue-router";
  4. import { useMainStore } from "@/stores/store";
  5. import axios from "axios";
  6. import moment from "moment";
  7. import bookList from "@/utils/useBookList";
  8. import Navbar from "@/components/Navbar.vue";
  9. const route = useRoute();
  10. const router = useRouter();
  11. const store = useMainStore();
  12. // 網址參數
  13. const articleId = route.params.id;
  14. const articleCategory = route.params.category;
  15. console.log("articleId", articleId);
  16. console.log("articleCategory", articleCategory);
  17. let list = reactive({
  18. data: {},
  19. });
  20. if (articleCategory === "book") {
  21. list.data = bookList[articleId];
  22. } else if (articleCategory === "article") {
  23. getArticle();
  24. }
  25. let filePath = ref("");
  26. let file = reactive({
  27. list: [],
  28. });
  29. async function getArticle() {
  30. try {
  31. const response = await axios.get(
  32. `https://cmm.ai:8088/api/get_article?article_id=${articleId}`
  33. );
  34. console.log("response", response.data.articles[0]);
  35. list.data = response.data.articles[0];
  36. const fileData = response.data.articles[0].files;
  37. // 字符串轉物件
  38. const fileObject = JSON.parse(fileData.replace(/'/g, '"'));
  39. // 遍歷物件後將值存進陣列
  40. file.list = Object.keys(fileObject).map((key) => ({
  41. name: fileObject[key].split("/").pop(),
  42. url: fileObject[key],
  43. }));
  44. console.log("fileList", file.list);
  45. console.log("data", list.data);
  46. } catch (error) {
  47. console.error(error);
  48. }
  49. }
  50. </script>
  51. <template>
  52. <Navbar />
  53. <div class="position-relative mb-16">
  54. <img src="@/assets/img/news/news-01.png" alt="" class="material-img" />
  55. <v-container class="pa-0 pt-16 position-relative">
  56. <div class="content">
  57. <div class="article">
  58. <v-row>
  59. <v-col cols="12">
  60. <div class="d-flex align-center mb-5">
  61. <v-chip size="large" variant="elevated" class="px-8 me-3">
  62. {{
  63. articleCategory === "book"
  64. ? list.data.category
  65. : list.data.group_sort
  66. }}
  67. </v-chip>
  68. <!-- <p>
  69. {{ moment(`${list.data.create_time}`).format("YYYY.MM.DD") }}
  70. </p> -->
  71. </div>
  72. <h2 class="text-center">{{ list.data.title }}</h2>
  73. <v-img
  74. class="cover-img my-10"
  75. :lazy-src="
  76. articleCategory === 'book'
  77. ? list.data.img
  78. : `https://ntcri.org/${list.data.cover_img}`
  79. "
  80. :src="
  81. articleCategory === 'book'
  82. ? list.data.img
  83. : `https://ntcri.org/${list.data.cover_img}`
  84. "
  85. >
  86. <template v-slot:placeholder>
  87. <div class="d-flex align-center justify-center fill-height">
  88. <v-progress-circular
  89. color="grey-lighten-4"
  90. indeterminate
  91. ></v-progress-circular>
  92. </div>
  93. </template>
  94. </v-img>
  95. </v-col>
  96. <v-col cols="12">
  97. <section class="d-flex flex-column pa-0">
  98. <p v-html="list.data.content"></p>
  99. </section>
  100. </v-col>
  101. <v-col cols="12" class="mt-10" v-if="file.list.length">
  102. <p>附件下載:</p>
  103. <ul class="mt-7">
  104. <li
  105. v-for="(item, index) in file.list"
  106. :key="index"
  107. class="d-flex align-center mb-2"
  108. >
  109. <v-icon
  110. icon="mdi-file-download"
  111. color="brown"
  112. size="large"
  113. class="me-2"
  114. ></v-icon>
  115. <a :href="`https://ntcri.org/${item.url}`" download>{{
  116. item.name
  117. }}</a>
  118. </li>
  119. </ul>
  120. <!-- <a :href="`https://ntcri.org/${filePath}`" download class="download-link">附件下載</a> -->
  121. </v-col>
  122. </v-row>
  123. </div>
  124. </div>
  125. </v-container>
  126. <router-link
  127. v-if="articleCategory === 'book'"
  128. to="/crafts"
  129. class="mt-16 back-link"
  130. >< 返回知識文章</router-link
  131. >
  132. <a href="javascript:;" v-else @click="router.go(-1)" class="back-link"
  133. >< 回到上一頁</a
  134. >
  135. <img src="@/assets/img/news/news-01.png" alt="" class="material-img" />
  136. </div>
  137. </template>
  138. <style lang="scss" scoped>
  139. ul {
  140. a {
  141. line-height: 24px;
  142. letter-spacing: 1px;
  143. transition: all 0.3s;
  144. &:hover {
  145. opacity: 0.8;
  146. }
  147. }
  148. }
  149. .btn-block {
  150. display: flex;
  151. justify-content: end;
  152. }
  153. .content {
  154. padding: 20px;
  155. background-image: url("@/assets/img/news/news-02.png");
  156. background-position: center;
  157. background-size: cover;
  158. border-radius: 50px;
  159. @media (max-width: 960px) {
  160. width: 90%;
  161. margin: auto;
  162. }
  163. }
  164. .article {
  165. margin: auto;
  166. padding: 80px 50px;
  167. display: flex;
  168. justify-content: center;
  169. border: 1px solid #d4d6d8;
  170. border-radius: 50px;
  171. // @media (max-width: 960px) {
  172. // width: 80%;
  173. // }
  174. @media (max-width: 600px) {
  175. padding: 50px 0;
  176. border: none;
  177. }
  178. h2 {
  179. margin: 40px auto;
  180. font-size: 28px;
  181. font-weight: 500;
  182. line-height: 38px;
  183. letter-spacing: 2px;
  184. }
  185. section {
  186. height: 100%;
  187. padding: 30px;
  188. p {
  189. font-size: 18px;
  190. font-weight: 400;
  191. line-height: 32px;
  192. letter-spacing: 1px;
  193. white-space: pre-line;
  194. }
  195. }
  196. .cover-img {
  197. width: 100%;
  198. max-height: 500px;
  199. @media (max-width: 600px) {
  200. height: auto;
  201. }
  202. }
  203. }
  204. .bg-img {
  205. height: 1000px;
  206. position: relative;
  207. z-index: -1;
  208. @media (max-width: 600px) {
  209. height: 650px;
  210. }
  211. }
  212. .back-link {
  213. margin-top: 50px;
  214. display: block;
  215. text-align: center;
  216. transition: all 0.3s;
  217. letter-spacing: 1px;
  218. &:hover {
  219. opacity: 0.8;
  220. }
  221. }
  222. .material-img {
  223. position: absolute;
  224. &:first-child {
  225. top: -15vw;
  226. }
  227. &:last-child {
  228. bottom: -130px;
  229. z-index: -5;
  230. transform: scaleX(-1);
  231. @media (max-width: 600px) {
  232. bottom: -50px;
  233. }
  234. }
  235. }
  236. </style>