index.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <template>
  2. <div class="hotspot-page">
  3. <div class="hotspot-page-container">
  4. <!-- 音频播放器 -->
  5. <audio
  6. id="myAudio"
  7. v-if="audio"
  8. ref="volumeRef"
  9. v-show="isOneAduio"
  10. :src="audio"
  11. controls
  12. ></audio>
  13. <!-- 模型页面 -->
  14. <Swiper
  15. v-if="myType === 'model'"
  16. class="hotspot-page-swiper hotspot-page-model"
  17. @swiper="initSwiper"
  18. @slideChange="handleChange"
  19. >
  20. <SwiperSlide v-for="(item, index) in curList" :key="item.url">
  21. <iframe v-if="index === myInd" :src="item" frameborder="0" />
  22. </SwiperSlide>
  23. </Swiper>
  24. <!-- 视频页面 -->
  25. <Swiper
  26. v-if="myType === 'video'"
  27. class="hotspot-page-swiper hotspot-page-video"
  28. @swiper="initSwiper"
  29. @slideChange="handleChange"
  30. >
  31. <SwiperSlide v-for="(item, index) in curList" :key="item.url">
  32. <video
  33. v-if="index === myInd"
  34. id="videoID"
  35. class="hotspot-page-video"
  36. controls
  37. :src="item.url"
  38. autoplay
  39. />
  40. </SwiperSlide>
  41. </Swiper>
  42. <!-- 图片页面 -->
  43. <Swiper
  44. v-if="myType === 'img'"
  45. class="hotspot-page-swiper hotspot-page-img-swiper"
  46. @swiper="initSwiper"
  47. @slideChange="handleChange"
  48. >
  49. <SwiperSlide v-for="item in curList" :key="item">
  50. <div class="hotspot-page-img">
  51. <el-image :src="item" fit="contain" style="width: 100%; height: 100%" />
  52. </div>
  53. </SwiperSlide>
  54. </Swiper>
  55. <template v-if="curList.length > 1">
  56. <div class="hotspot-page-swiper__left" @click="handlePre" />
  57. <div class="hotspot-page-swiper__right" @click="handleNext" />
  58. </template>
  59. <!-- 底部的tab -->
  60. <div v-if="flooTab.length > 1" class="hotspot-page-nav">
  61. <div
  62. v-for="item in flooTab"
  63. :key="item.id"
  64. :class="[
  65. 'hotspot-page-nav__item',
  66. {
  67. active: myType === item.type,
  68. },
  69. ]"
  70. @click="handleTab(item)"
  71. >
  72. <img :class="`${item.type}-icon`" :src="myType === item.type ? item.acIcon : item.icon" />
  73. <!-- {{ item.name }}
  74. {{ item.type === 'img' ? `${myInd + 1}/${data.img.length}` : '' }} -->
  75. </div>
  76. </div>
  77. <!-- 音频图标 -->
  78. <div
  79. v-if="audio && !isOneAduio"
  80. class="audioIcon"
  81. :title="audioSta ? '关闭音频' : '打开音频'"
  82. @click="audioSta = !audioSta"
  83. >
  84. <img :src="audioSta ? VolumeOff : VolumeOn" alt="" />
  85. </div>
  86. </div>
  87. <el-scrollbar :height="150" style="margin-top: 20px; height: 150px; flex-shrink: 0">
  88. <div class="hotspot-page-info">
  89. <h3>{{ myTitle }}</h3>
  90. <p>{{ myTxt }}</p>
  91. </div>
  92. </el-scrollbar>
  93. </div>
  94. </template>
  95. <script>
  96. import { Swiper, SwiperSlide } from 'swiper/vue';
  97. import 'swiper/css';
  98. import { parseUrlParams } from '@/utils';
  99. import ModelIcon from '@hotspot/assets/images/icon-model@2x.png';
  100. import AcModelIcon from '@hotspot/assets/images/icon-model-1@2x.png';
  101. import ImageIcon from '@hotspot/assets/images/icon-image@2x.png';
  102. import AcImageIcon from '@hotspot/assets/images/icon-image-1@2x.png';
  103. import VideoIcon from '@hotspot/assets/images/icon-video@2x.png';
  104. import AcVideoIcon from '@hotspot/assets/images/icon-video-1@2x.png';
  105. import VolumeOn from '@hotspot/assets/images/Volume-on.png';
  106. import VolumeOff from '@hotspot/assets/images/Volume-off.png';
  107. const urlParams = parseUrlParams(window.location.href);
  108. export default {
  109. name: 'hotspot',
  110. components: {
  111. Swiper,
  112. SwiperSlide,
  113. },
  114. data() {
  115. return {
  116. VolumeOn,
  117. VolumeOff,
  118. m: urlParams.m,
  119. id: urlParams.id,
  120. // 音频地址
  121. audio: '',
  122. // 如果只有单独的音频
  123. isOneAduio: false,
  124. // 音频状态
  125. audioSta: false,
  126. data: {
  127. // 模型数组
  128. model: [],
  129. // 视频数组
  130. video: [],
  131. // 图片数组
  132. img: [],
  133. },
  134. // 当前 type
  135. myType: '',
  136. // 当前索引
  137. myInd: 0,
  138. // 底部的tab
  139. flooTab: [],
  140. // 标题
  141. myTitle: '',
  142. // 内容
  143. myTxt: '',
  144. // 视频内容
  145. videoTxt: [],
  146. imgTxt: [],
  147. // 只有标题和文字(没有视频,没有模型,没有图片)
  148. oneTxt: false,
  149. };
  150. },
  151. computed: {
  152. curList() {
  153. return this.data[this.myType] || [];
  154. },
  155. },
  156. watch: {
  157. audioSta(val) {
  158. if (val) {
  159. this.$refs.volumeRef.play();
  160. this.$refs.volumeRef.onended = () => {
  161. // console.log("----音频播放完毕");
  162. this.audioSta = false;
  163. };
  164. } else this.$refs.volumeRef.pause();
  165. },
  166. },
  167. mounted() {
  168. this.getData();
  169. },
  170. methods: {
  171. async getData() {
  172. // https://www.4dmodel.com/
  173. let url = `https://super.4dage.com/data/${this.id}/hot/js/data.js?time=${Math.random()}`;
  174. let result = await fetch(url).then((response) => response.json());
  175. const resData = result[this.m];
  176. console.log('----', resData);
  177. if (resData) {
  178. this.audio = resData.backgroundMusic;
  179. // 只有单独的音频上传
  180. if (resData.backgroundMusic && !resData.model && !resData.video && !resData.images) {
  181. this.isOneAduio = true;
  182. }
  183. // 底部的tab
  184. const arr = [];
  185. const obj = {};
  186. if (resData.model) {
  187. obj.model = resData.model;
  188. arr.push({ id: 1, type: 'model', name: '模型', icon: ModelIcon, acIcon: AcModelIcon });
  189. }
  190. if (resData.video) {
  191. obj.video = resData.video;
  192. arr.push({ id: 2, type: 'video', name: '视频', icon: VideoIcon, acIcon: AcVideoIcon });
  193. } else {
  194. this.$nextTick(() => {
  195. if (
  196. !window.navigator.userAgent.match(
  197. /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
  198. )
  199. ) {
  200. this.audioSta = true;
  201. this.$refs.volumeRef.play();
  202. }
  203. });
  204. }
  205. if (resData.images) {
  206. obj.img = resData.images;
  207. arr.push({ id: 3, type: 'img', name: '图片', icon: ImageIcon, acIcon: AcImageIcon });
  208. }
  209. this.flooTab = arr;
  210. this.data = obj;
  211. // 当前type的值 应该为
  212. if (resData.model) this.myType = 'model';
  213. else if (resData.video) this.myType = 'video';
  214. else if (resData.images) this.myType = 'img';
  215. this.myTitle = resData.title || '';
  216. this.myTxt = resData.content || '';
  217. this.videoTxt = resData.videosDesc || [];
  218. this.imgTxt = resData.imagesDesc || [];
  219. // 只有 标题和 文字介绍(没有视频,没有模型,没有图片)
  220. if (!obj.model && !obj.video && !obj.img && !resData.backgroundMusic) {
  221. this.oneTxt = true;
  222. }
  223. }
  224. },
  225. handleTab(item) {
  226. this.myInd = 0;
  227. this.myType = item.type;
  228. },
  229. initSwiper(swiper) {
  230. this.swiper = swiper;
  231. },
  232. handleChange({ activeIndex }) {
  233. this.myInd = activeIndex;
  234. },
  235. handlePre() {
  236. this.swiper?.slidePrev();
  237. },
  238. handleNext() {
  239. this.swiper?.slideNext();
  240. },
  241. },
  242. };
  243. </script>
  244. <style lang="scss">
  245. @import './index.scss';
  246. </style>