123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- <template>
- <div class="treasure-detail">
- <Teleport to="body">
- <TreasureShare
- v-if="isShowShare"
- :info="rawData.value?.entity"
- @close="isShowShare = false"
- />
- </Teleport>
- <button
- class="back"
- @click="$router.go(-1)"
- >
- <img
- class=""
- src="@/assets/images/icon_back.png"
- alt=""
- draggable="false"
- >
- </button>
- <h1>{{ rawData.value?.entity?.name }}</h1>
- <div class="tab-bar">
- <button
- v-if="modelUrlList?.length"
- class="model"
- :class="{
- active: activeTabIndx === 0
- }"
- @click="activeTabIndx = 0"
- >
- <span>模型</span>
- </button>
- <button
- v-if="videoUrlList?.length"
- class="video"
- :class="{
- active: activeTabIndx === 1
- }"
- @click="activeTabIndx = 1"
- >
- <span>视频</span>
- </button>
- <button
- v-if="imageUrlList?.length"
- class="image"
- :class="{
- active: activeTabIndx === 2
- }"
- @click="activeTabIndx = 2"
- >
- <span>图片</span>
- </button>
- </div>
- <div
- class="main-wrapper"
- >
- <div
- class="swiper-root"
- >
- <div
- v-if="activeTabIndx === 0"
- class="swiper-wrapper"
- >
- <iframe
- v-for="(item) in modelUrlList"
- :key="item.id"
- :src="`${prefix}/web-model/index.html#/relic-detail?model-path=${encodeURIComponent(item.filePath)}`"
- frameborder="0"
- class="swiper-slide"
- />
- </div>
- <div
- v-if="activeTabIndx === 1"
- class="swiper-wrapper"
- >
- <video
- v-for="(item) in videoUrlList"
- :key="item.id"
- :src="item.filePath"
- class="swiper-slide"
- />
- </div>
- <div
- v-if="activeTabIndx === 2"
- class="swiper-wrapper"
- >
- <img
- v-for="(item) in imageUrlList"
- :key="item.id"
- draggable="false"
- :src="`${prefix}/${item.filePath}`"
- class="swiper-slide"
- >
- </div>
- <!-- <div class="swiper-pagination">
- <span class="cur">{{ currentSlideIdx + 1 }}</span> / <span>{{ list.length }}</span>
- </div> -->
- </div>
- <!-- <p class="main">
- 厂家:江南造船 尺寸:模型:长1230mm,宽700mm,高2300mm
- </p> -->
- <p class="desc">
- {{ rawData.value?.entity?.description }}
- </p>
- </div>
- <div class="swiper-button-prev" />
- <div class="swiper-button-next" />
- <menu>
- <button @click="isShowShare = true">
- <img
- class=""
- src="@/assets/images/icon_share.png"
- alt=""
- draggable="false"
- >
- </button>
- <button
- v-if="hasMusic"
- @click="isMusicOn = !isMusicOn"
- >
- <img
- class=""
- :src="require(`@/assets/images/icon_music_${isMusicOn ? 'on' : 'off'}.png`)"
- alt=""
- draggable="false"
- >
- </button>
- <button
- v-if="canRecord && activeTabIndx === 0"
- @click="$router.push({name: 'RecordView', query: {
- url: encodeURI(`${prefix}/web-model/index.html#/relic-detail?model-path=${encodeURIComponent(modelUrlList[activeSwiperItemIndex].filePath)}`)
- }})"
- >
- <img
- class=""
- src="@/assets/images/icon_record.png"
- alt=""
- draggable="false"
- >
- </button>
- <button @click="fullScreenStatus = !fullScreenStatus">
- <img
- class=""
- :src="require(`@/assets/images/icon_full_screen_${fullScreenStatus ? 'off' : 'on'}.png`)"
- alt=""
- draggable="false"
- >
- </button>
- </menu>
- <audio
- v-if="hasMusic"
- ref="bgAudio"
- :src="musicUrl"
- style="display: none;"
- />
- </div>
- </template>
- <script>
- import {
- computed,
- nextTick,
- onMounted,
- reactive,
- ref,
- toRefs,
- watch,
- } from 'vue'
- import { useRoute } from "vue-router"
- import TreasureShare from "@/components/TreasureShare.vue"
- import Swiper from 'swiper/bundle'
- import 'swiper/css/bundle'
- export default {
- components: {
- TreasureShare
- },
- setup () {
- const prefix = process.env.VUE_APP_API_ORIGIN
- /**
- * 路由
- */
- const route = useRoute()
- /**
- * tab bar
- */
- const activeTabIndx = ref(0)
- /**
- * swiper 相关
- */
- let swiper = null
- const activeSwiperItemIndex = ref(0)
- function initSwiper() {
- swiper = new Swiper('.swiper-root', {
- // pagination: {
- // el: '.swiper-pagination',
- // },
- // Navigation arrows
- navigation: {
- nextEl: '.swiper-button-next',
- prevEl: '.swiper-button-prev',
- },
- on: {
- afterInit: function (e) {
- activeSwiperItemIndex.value = e.activeIndex
- },
- slideChange: function(e) {
- activeSwiperItemIndex.value = e.activeIndex
- }
- }
- })
- }
- onMounted(initSwiper)
- watch(activeTabIndx, (newV) => {
- swiper.destroy()
- nextTick(() => {
- initSwiper()
- })
- })
- /**
- * 分享
- */
- const isShowShare = ref(false)
- /**
- * 背景音乐相关
- */
- const bgAudio = ref(null)
- const hasMusic = ref(false)
- const musicUrl = ref(require('@/assets/mock/02.mp3'))
- const isMusicOn = ref(false)
- watch(isMusicOn, (newV) => {
- console.log('change!', newV)
- if (newV) {
- bgAudio.value.play()
- } else {
- bgAudio.value.pause()
- }
- })
- /**
- * 录屏相关
- */
- const canRecord = ref(navigator?.mediaDevices?.getDisplayMedia)
- /**
- * 全屏相关
- */
- const fullScreenStatus = ref(false)
- watch(fullScreenStatus, (newVal) => {
- if (newVal) {
- const el = document.querySelector('.treasure-detail')
- if (el) {
- utils.requestFullScreen(el)
- } else {
- console.error('没有找到组件根元素!')
- }
- } else {
- utils.exitFullScreen()
- }
- })
- /**
- * 展示数据
- */
- const rawData = reactive({
- value: null,
- })
- const modelUrlList = reactive([])
- const videoUrlList = reactive([])
- const imageUrlList = reactive([])
- api.getTreasureDetail(route.query.id).then((res) => {
- rawData.value = res
- for (const iterator of rawData.value.file) {
- switch (iterator.type) {
- case 'model':
- modelUrlList.push(iterator)
- break
- case 'video':
- videoUrlList.push(iterator)
- break
- case 'img':
- imageUrlList.push(iterator)
- break
- default:
- break
- }
- }
- })
- return {
- prefix,
- encodeURIComponent,
- activeSwiperItemIndex,
- activeTabIndx,
- bgAudio,
- canRecord,
- fullScreenStatus,
- hasMusic,
- imageUrlList,
- isMusicOn,
- isShowShare,
- modelUrlList,
- musicUrl,
- rawData,
- videoUrlList,
- }
- },
- }
- </script>
- <style lang="less" scoped>
- .treasure-detail {
- width: 100%;
- height: 100%;
- overflow: auto;
- position: relative;
- >button.back {
- position: absolute;
- top: 51px;
- left: 67px;
- width: 40px;
- height: 40px;
- >img {
- width: 100%;
- height: 100%;
- }
- }
- >h1 {
- position: absolute;
- top: 36px;
- left: 50%;
- transform: translateX(-50%);
- font-size: 36px;
- font-family: Source Han Sans CN-Bold, Source Han Sans CN;
- font-weight: bold;
- color: #FFFFFF;
- }
- >.tab-bar {
- position: absolute;
- top: 108px;
- left: 50%;
- transform: translateX(-50%);
- >button {
- margin-right: 50px;
- width: 80px;
- height: 36px;
- background: rgba(255,255,255,0.2);
- border-radius: 18px;
- border: 1px solid #fff;
- font-size: 16px;
- font-family: Source Han Sans CN-Regular, Source Han Sans CN;
- font-weight: 400;
- color: #fff;
- opacity: 0.7;
- &:last-of-type {
- margin-right: initial;
- }
- &.active {
- background: rgba(255,255,255,0.2);
- border: 1px solid #DBC386;
- color: #DBC386;
- opacity: initial;
- }
- }
- }
- >.main-wrapper {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- height: calc(100% - 144px - 128px - 40px);
- width: 80%;
- max-width: 1164px;
- .swiper-root {
- height: calc(100% - 160px);
- width: 100%;
- position: relative;
- overflow: hidden;
- .swiper-wrapper {
- height: 100%;
- margin-left: auto;
- margin-right: auto;
- .swiper-slide {
- user-select: none;
- object-fit: contain;
- }
- }
- // .swiper-pagination {
- // position: absolute;
- // bottom: 10px;
- // left: 50%;
- // transform: translateX(-50%);
- // font-size: 1.33rem;
- // font-family: Inter-Regular, Inter;
- // color: #666;
- // .cur {
- // color: #930909;
- // }
- // }
- }
- >p.main {
- margin-top: 20px;
- font-size: 20px;
- font-family: Source Han Sans CN-Regular, Source Han Sans CN;
- font-weight: 400;
- color: #FFFFFF;
- overflow: hidden;
- white-space: pre;
- text-overflow: ellipsis;
- margin-bottom: 22px;
- text-align: center;
- }
- >p.desc {
- height: 108px;
- width: 100%;
- max-width: 1164px;
- text-align: center;
- font-size: 20px;
- line-height: 23px;
- font-family: Source Han Sans CN-Regular, Source Han Sans CN;
- font-weight: 400;
- color: #FFFFFF;
- overflow: auto;
- opacity: 0.8;
- margin-left: auto;
- margin-right: auto;
- padding-left: 10px;
- margin-top: 20px;
- height: 150px;
- &::-webkit-scrollbar { background: transparent; width: 4px; } /*宽度是对垂直滚动条而言,高度是对水平滚动条而言*/
- &::-webkit-scrollbar-thumb {
- background: rgba(220, 231, 240, 0.2);
- border-radius: 2px;
- }
- }
- }
- .swiper-button-prev {
- left: 44px;
- width: 44px;
- height: 44px;
- background-image: url(@/assets/images/arrow-left-2.png);
- background-size: contain;
- &::after {
- content: '';
- }
- }
- .swiper-button-next {
- right: 44px;
- width: 44px;
- height: 44px;
- background-image: url(@/assets/images/arrow-right-2.png);
- background-size: contain;
- &::after {
- content: '';
- }
- }
- >menu {
- position: absolute;
- right: 44px;
- bottom: 130px;
- > button {
- display: block;
- margin-bottom: 15px;
- width: 44px;
- height: 44px;
- > img {
- width: 100%;
- height: 100%;
- }
- }
- }
- }
- </style>
|