Introduce.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <template>
  2. <div class="software-intro-container">
  3. <!-- 加载状态 -->
  4. <div v-if="isLoading" class="loading-message">加载中...</div>
  5. <!-- 错误信息 -->
  6. <div v-else-if="error" class="error-message">{{ error }}</div>
  7. <!-- 正常展示内容 -->
  8. <div v-else class="content-wrapper">
  9. <h1 class="title">{{ softwareIntro.title }}</h1>
  10. <div v-for="(paragraph, index) in softwareIntro.introParagraphs" :key="index" class="paragraph">
  11. <p v-html="paragraph"></p>
  12. </div>
  13. </div>
  14. </div>
  15. </template>
  16. <script setup lang="ts">
  17. import { ref, onMounted, defineProps } from 'vue';
  18. import axios from 'axios';
  19. // 定义 targetId 为 prop
  20. const props = defineProps({
  21. targetId: {
  22. type: Number,
  23. default: 1
  24. }
  25. });
  26. // 存储介绍内容
  27. const softwareIntro = ref({
  28. title: '',
  29. introParagraphs: []
  30. });
  31. // 加载状态
  32. const isLoading = ref(true);
  33. // 错误信息
  34. const error = ref('');
  35. // 判断是否为标题段落
  36. const isTitle = (paragraph: string) => {
  37. return /^[^\s].*[::]$/.test(paragraph);
  38. };
  39. const imageBaseUrl = ref(import.meta.env.VITE_IMAGE_BASE_URL);
  40. // 处理段落,将图片路径转换为 <img> 标签
  41. const processParagraph = (paragraph: string) => {
  42. // 假设图片路径是相对路径
  43. const imgRegex = /([^\s]+(\.jpg|\.jpeg|\.png|\.gif))/g;
  44. return paragraph.replace(imgRegex, `<img src="${imageBaseUrl.value}$1" alt="图片" class="intro-image">`);
  45. };
  46. onMounted(async () => {
  47. try {
  48. // 从后端获取介绍数据
  49. const response = await axios.get(`https://soilgd.com:5000/software-intro/${props.targetId}`);
  50. const { title, intro } = response.data;
  51. // 保留 \r\n 换行符
  52. const processedIntro = intro.replace(/<p>/g, '').replace(/<\/p>/g, '\r\n').replace(/<br>/g, '');
  53. softwareIntro.value.introParagraphs = processedIntro.split('\r\n').filter((paragraph: string) => paragraph.trim()!== '');
  54. softwareIntro.value.title = title;
  55. } catch (err: any) {
  56. error.value = err.message || '请求数据时发生错误';
  57. } finally {
  58. isLoading.value = false;
  59. }
  60. });
  61. </script>
  62. <style scoped lang="scss">
  63. * {
  64. margin: 0;
  65. padding: 0;
  66. box-sizing: border-box;
  67. }
  68. body {
  69. background-color: white;
  70. font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* 更美观的字体 */
  71. padding: 0;
  72. }
  73. .software-intro-container {
  74. width: 95%;
  75. margin: 0 auto;
  76. padding: 20px;
  77. background-color: #fff;
  78. border-radius: 8px; /* 圆角 */
  79. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
  80. height: 80vh; /* 设置容器高度为视口高度的 80% */
  81. overflow-y: auto; /* 当内容超出容器高度时,显示垂直滚动条 */
  82. scrollbar-width: none; /* Firefox */
  83. -ms-overflow-style: none; /* Internet Explorer 10+ */
  84. }
  85. .loading-message {
  86. text-align: center;
  87. font-size: 18px;
  88. color: #999;
  89. padding: 20px;
  90. }
  91. .error-message {
  92. text-align: center;
  93. font-size: 18px;
  94. color: #ff0000; /* 红色错误信息 */
  95. padding: 20px;
  96. }
  97. .title {
  98. font-size: 36px;
  99. text-align: center;
  100. margin-bottom: 20px;
  101. color: #333; /* 深灰色标题 */
  102. }
  103. .paragraph {
  104. margin-bottom: 20px;
  105. }
  106. p {
  107. font-size: 16px;
  108. line-height: 1.8; /* 增大行高 */
  109. color: #666; /* 灰色文字 */
  110. }
  111. .intro-image {
  112. max-width: 100%;
  113. height: auto;
  114. border-radius: 4px; /* 图片圆角 */
  115. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 图片阴影 */
  116. margin-bottom: 10px;
  117. }
  118. /* 响应式设计 */
  119. @media (max-width: 768px) {
  120. .software-intro-container {
  121. padding: 15px;
  122. height: 90vh; /* 在小屏幕上,调整容器高度为视口高度的 90% */
  123. }
  124. .title {
  125. font-size: 28px;
  126. }
  127. p {
  128. font-size: 14px;
  129. }
  130. }
  131. </style>