Introduce.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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 } from 'vue';
  18. import { api5000 } from '@/utils/request'; // 导入封装的api5000
  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. // 处理段落,将图片路径转换为 标签
  37. onMounted(async () => {
  38. try {
  39. // 使用 api5000 调用接口
  40. const response = await api5000.get(`/admin/software-intro/${props.targetId}`);
  41. const { title, intro } = response.data;
  42. // 保留 \r\n 换行符
  43. const processedIntro = intro.replace(/<p>/g, '').replace(/<\/p>/g, '\r\n').replace(/<br>/g, '');
  44. softwareIntro.value.introParagraphs = processedIntro.split('\r\n').filter((paragraph: string) => paragraph.trim()!== '');
  45. softwareIntro.value.title = title;
  46. } catch (err: any) {
  47. error.value = err.message || '请求数据时发生错误';
  48. } finally {
  49. isLoading.value = false;
  50. }
  51. // 页面加载完成后,监听视频播放事件
  52. const container = document.querySelector('.software-intro-container');
  53. if (container) {
  54. container.addEventListener('play', (event) => {
  55. if (event.target instanceof HTMLVideoElement) {
  56. const video = event.target;
  57. setVideoStyle(video);
  58. }
  59. }, true);
  60. // 监听窗口大小变化事件,确保视频在窗口大小改变时也能适应
  61. window.addEventListener('resize', () => {
  62. const videos = container.querySelectorAll('video');
  63. videos.forEach((video) => {
  64. if (video instanceof HTMLVideoElement) {
  65. setVideoStyle(video);
  66. }
  67. });
  68. });
  69. }
  70. });
  71. // 封装设置视频样式的函数
  72. const setVideoStyle = (video: HTMLVideoElement) => {
  73. const containerWidth = (document.querySelector('.software-intro-container') as HTMLElement).offsetWidth;
  74. const maxWidth = containerWidth * 0.8; // 最大宽度为容器宽度的 80%
  75. if (video.videoWidth > maxWidth) {
  76. video.style.width = `${maxWidth}px`;
  77. video.style.height = 'auto';
  78. } else {
  79. video.style.width = 'auto';
  80. video.style.height = 'auto';
  81. }
  82. video.style.maxWidth = '80%';
  83. video.style.objectFit = 'contain';
  84. };
  85. </script>
  86. <style scoped lang="scss">
  87. .software-intro-container {
  88. width: 95%;
  89. margin: 0 auto;
  90. padding: 20px;
  91. background-color: #fff;
  92. border-radius: 8px; /* 圆角 */
  93. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
  94. height: 80vh; /* 设置容器高度为视口高度的 80% */
  95. overflow-y: auto; /* 当内容超出容器高度时,显示垂直滚动条 */
  96. scrollbar-width: none; /* Firefox */
  97. -ms-overflow-style: none; /* Internet Explorer 10+ */
  98. }
  99. .loading-message {
  100. text-align: center;
  101. font-size: 18px;
  102. color: #999;
  103. padding: 20px;
  104. }
  105. .error-message {
  106. text-align: center;
  107. font-size: 18px;
  108. color: #ff0000; /* 红色错误信息 */
  109. padding: 20px;
  110. }
  111. .title {
  112. font-size: 36px;
  113. text-align: center;
  114. margin-bottom: 20px;
  115. color: #333; /* 深灰色标题 */
  116. }
  117. .paragraph {
  118. margin-bottom: 20px;
  119. }
  120. p {
  121. font-size: 16px;
  122. line-height: 1.8; /* 增大行高 */
  123. color: #666; /* 灰色文字 */
  124. }
  125. .intro-image {
  126. max-width: 100%;
  127. height: auto;
  128. border-radius: 4px; /* 图片圆角 */
  129. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 图片阴影 */
  130. margin-bottom: 10px;
  131. }
  132. /* 控制视频尺寸 */
  133. video {
  134. width: 80%;
  135. max-width: 80%;
  136. height: auto;
  137. object-fit: contain;
  138. }
  139. /* 响应式设计 */
  140. @media (max-width: 768px) {
  141. .software-intro-container {
  142. padding: 15px;
  143. height: 90vh; /* 在小屏幕上,调整容器高度为视口高度的 90% */
  144. }
  145. .title {
  146. font-size: 28px;
  147. }
  148. p {
  149. font-size: 14px;
  150. }
  151. }
  152. </style>