Ver código fonte

feat: 绑定panos

rindy 3 anos atrás
pai
commit
028ed2cfd8
4 arquivos alterados com 246 adições e 148 exclusões
  1. 103 0
      src/components/calendar/mobile.vue
  2. 21 13
      src/components/header/index.vue
  3. 96 118
      src/pages/SViewer.vue
  4. 26 17
      src/pages/Viewer.vue

+ 103 - 0
src/components/calendar/mobile.vue

@@ -0,0 +1,103 @@
+<template>
+    <div class="calendar" v-show="!showCalendar">
+        <span class="prev" @click="emits('prev')"><i class="iconfont icon-arrows_left"></i></span>
+        <span class="cale" @click="onPickDate()">{{ date }}<i class="iconfont icon-date"></i></span>
+        <span class="next" @click="emits('next')"><i class="iconfont icon-arrows_right"></i></span>
+    </div>
+    <div class="calendar-list" v-if="showCalendar" @click="showCalendar = false">
+        <div @click.stop>
+            <van-datetime-picker v-model="props.value" type="date" title="选择时间" confirm-button-text="确定" />
+        </div>
+    </div>
+</template>
+<script setup>
+import { ref, defineProps, computed } from 'vue'
+const props = defineProps({
+    value: Date,
+    highlighted: Object,
+})
+const emits = defineEmits(['prev', 'selected', 'next', 'pick'])
+const date = computed(() => {
+    if (!props.value) {
+        return ''
+    }
+    return props.value.format('YYYY-mm-dd')
+})
+const showCalendar = ref(false)
+
+const onPickDate = () => {
+    showCalendar.value = !showCalendar.value
+    if (showCalendar.value) {
+        emits('pick')
+    }
+}
+const onSelected = payload => {
+    emits('selected', { payload })
+    showCalendar.value = false
+}
+</script>
+<style lang="scss" scoped>
+.calendar {
+    height: 50px;
+    background: rgba(27, 27, 28, 0.8);
+    box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
+    border-radius: 47px 47px 47px 47px;
+    border: 1px solid #000000;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin-left: 10px;
+    margin-right: 10px;
+    font-size: 16px;
+    padding: 0 16px;
+    span {
+        cursor: pointer;
+    }
+    .cale {
+        i {
+            margin-left: 4px;
+            font-size: 15px;
+        }
+    }
+    .prev {
+        margin-right: 10px;
+    }
+    .next {
+        margin-left: 10px;
+    }
+}
+.calendar-list {
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    height: 100vh;
+    z-index: 1000;
+    display: flex;
+    align-items: flex-end;
+    justify-content: center;
+    > div {
+        width: 100%;
+    }
+}
+</style>
+<style lang="scss">
+:root {
+    --van-gray-8: rgba(255, 255, 255, 0.3);
+    --van-picker-background-color: rgba(0, 0, 0, 0.8);
+}
+.van-picker__mask {
+    display: none;
+}
+.van-picker__toolbar {
+    button {
+        font-size: 16px !important;
+        &.van-picker__confirm {
+            color: #0076f6;
+        }
+    }
+}
+.van-picker-column__item--selected {
+    color: #fff;
+}
+</style>

+ 21 - 13
src/components/header/index.vue

@@ -39,7 +39,7 @@
     </footer>
 </template>
 <script setup>
-import { ref, defineProps, onMounted } from 'vue'
+import { ref, defineProps, onMounted, watchEffect } from 'vue'
 import { http } from '@/utils/request'
 import browser from '@/utils/browser'
 import Login from './Login'
@@ -55,29 +55,28 @@ const user = ref(null)
 const points = ref({ p1: null, p2: null })
 const showLogin = ref(false)
 
-const getCurPosInfo = ()=>{
+const getCurPosInfo = () => {
     let app = sync.sourceInst
-    let id  
-    if(app.sceneType == 'laser'){
-        id = app.viewer.images360.currentPano.id 
-    }else{
-        id = app.app.core.get('Player').currentPano.id 
+    let id
+    if (app.sceneType == 'laser') {
+        id = app.viewer.images360.currentPano.id
+    } else {
+        id = app.app.core.get('Player').currentPano.id
     }
     let info = sync.targetInst.viewer.getCameraStatus()
     let position = info.position
-    return {id, position}
+    return { id, position }
 }
 
-const onSetP1 = () => { 
+const onSetP1 = () => {
     points.value.p1 = getCurPosInfo()
     console.log(points.value.p1)
-    emits('update','p1')
-
+    emits('update', 'p1')
 }
 const onSetP2 = () => {
     points.value.p2 = getCurPosInfo()
     console.log(points.value.p2)
-    emits('update','p2')
+    emits('update', 'p2')
 }
 
 const getUserInfo = () => {
@@ -121,13 +120,22 @@ const onSubmit = () => {
         .then(response => {
             if (response.success) {
                 window.location.href = window.location.href.replace('&adjust', '&split')
-            }else {
+            } else {
                 alert(response.message)
             }
         })
         .catch(() => {})
 }
 
+watchEffect(() => {
+    if (props.showAdjust) {
+        if (props.project && props.project.panos) {
+            points.value.p1 = props.project.panos.p1
+            points.value.p2 = props.project.panos.p2
+        }
+    }
+})
+
 onMounted(() => {
     if (localStorage.getItem('token')) {
         getUserInfo()

+ 96 - 118
src/pages/SViewer.vue

@@ -1,6 +1,16 @@
 <template>
     <main>
-        <van-datetime-picker v-model="sourceDate" :filter="onFilter" type="date" title="选择年月日" />
+        <iframe v-if="source" :src="sourceURL" frameborder="0"></iframe>
+        <div class="tools" v-show="!bimChecked">
+            <div class="item-date">
+                <Calendar :value="sourceDate" />
+            </div>
+            <!-- <div class="item-mode" v-if="source.type == 2">
+                <div class="iconfont icon-show_roaming" :class="{ active: mode == 0 }" @click="onModeChange(0)"></div>
+                <div class="iconfont icon-show_plane" :class="{ active: mode == 1 }" @click="onModeChange(1)"></div>
+            </div> -->
+        </div>
+        <!-- <van-datetime-picker v-model="sourceDate" :filter="onFilter" :formatter="onFormatter" type="date" title="选择时间" confirm-button-text="确定" /> -->
     </main>
 </template>
 
@@ -8,15 +18,10 @@
 import { ref, onMounted, computed, nextTick } from 'vue'
 import { http } from '@/utils/request'
 import browser from '@/utils/browser'
+import Calendar from '@/components/calendar/mobile.vue'
 import sync, { loadSourceScene, loadTargetScene } from '@/utils/sync'
 
-// 是否校准模式
-const showSplit = ref(browser.urlHasValue('split'))
-const showAdjust = ref(browser.urlHasValue('adjust'))
-
 const bimChecked = ref(null)
-const dbsChecked = ref(null)
-const fscChecked = ref(null)
 
 const datepickName = ref(null)
 
@@ -42,7 +47,7 @@ const scenes = computed(() => {
     })
 })
 const sourceURL = computed(() => {
-    if (bimChecked.value && !dbsChecked.value) {
+    if (bimChecked.value) {
         return `smart-bim.html?m=${source.value.num}`
     }
 
@@ -54,31 +59,13 @@ const sourceURL = computed(() => {
         return `smart-laser.html?m=${source.value.num}&dev`
     }
 })
-const targetURL = computed(() => {
-    if (bimChecked.value) {
-        return `smart-bim.html?m=${target.value.num}`
-    }
 
-    if (source.value.type < 2) {
-        // 看看、看见场景
-        return `smart-kankan.html?m=${target.value.num}&dev`
-    } else {
-        // 深时场景
-        return `smart-laser.html?m=${target.value.num}&dev`
-    }
-})
 const sourceDate = computed(() => {
     if (source.value) {
         return source.value.createTime.toDate()
     }
 })
 
-const targetDate = computed(() => {
-    if (target.value) {
-        return target.value.createTime.toDate()
-    }
-})
-
 const sourceDays = computed(() => {
     let dates = []
     if (datepickName.value == 'source') {
@@ -101,18 +88,23 @@ const sourceDays = computed(() => {
     }
 })
 
-const targetDays = computed(() => {
-    let dates = []
-    if (datepickName.value == 'target') {
-        dates = scenes.value.filter(item => item.createTime != source.value.createTime).map(item => item.createTime.toDate())
+const onFilter = (type, options) => {
+    console.log(type, options)
+    return options
+}
+const onFormatter = (type, val) => {
+    if (type === 'year') {
+        return `${val}年`
     }
-    return {
-        dates: dates,
+    if (type === 'month') {
+        return `${val}月`
     }
-})
-const onFilter = (type, options)=> {
-    console.log(type,options)
+    if (type === 'day') {
+        return `${val}日`
+    }
+    return val
 }
+
 const onLoadSource = () => {
     if (bimChecked.value && !dbsChecked.value) {
         // BIM单屏模式
@@ -121,13 +113,6 @@ const onLoadSource = () => {
 
     loadSourceScene(sourceFrame, source.value.type < 2 ? 'kankan' : 'laser')
 }
-const onLoadTarget = () => {
-    if (bimChecked.value) {
-        loadTargetScene(targetFrame, 'bim')
-    } else {
-        loadTargetScene(targetFrame, target.value.type < 2 ? 'kankan' : 'laser', mode.value)
-    }
-}
 
 const onModeChange = targetMode => {
     if (sync.sourceInst) {
@@ -238,81 +223,11 @@ const onNextDate = name => {
 const onBimChecked = () => {
     if (bimChecked.value) {
         bimChecked.value = false
-        if (dbsChecked.value) {
-            // 判断是否分屏状态
-            let index = scenes.value.findIndex(item => item.num == source.value.num)
-            if (index == -1) {
-                return
-            }
-            if (++index > scenes.value.length - 1) {
-                index = 0
-            }
-            target.value = scenes.value[index]
-        }
     } else {
         bimChecked.value = true
     }
 }
 
-// 分屏点击
-const onDbsChecked = () => {
-    dbsChecked.value = !dbsChecked.value
-    if (dbsChecked.value) {
-        if (bimChecked.value) {
-            // BIM分屏
-            source.value = scenes.value[0]
-            target.value = project.value.bimData
-        } else {
-            // 四维看看、激光场景分屏
-            let index = scenes.value.findIndex(item => item.num == source.value.num)
-            if (index == -1) {
-                return
-            }
-            if (++index > scenes.value.length - 1) {
-                index = 0
-            }
-            target.value = scenes.value[index]
-        }
-    } else {
-        target.value = null
-        targetApp = null
-        views.clear()
-    }
-}
-
-// 全屏点击
-const onFscChecked = () => {
-    let element = document.documentElement
-
-    fscChecked.value = !fscChecked.value
-
-    if (fscChecked.value) {
-        if (element.requestFullscreen) {
-            element.requestFullscreen()
-        } else if (element.webkitRequestFullScreen) {
-            element.webkitRequestFullScreen()
-        } else if (element.mozRequestFullScreen) {
-            element.mozRequestFullScreen()
-        } else if (element.msRequestFullscreen) {
-            element.msRequestFullscreen()
-        }
-    } else {
-        if (document.exitFullscreen) {
-            document.exitFullscreen()
-        } else if (document.webkitCancelFullScreen) {
-            document.webkitCancelFullScreen()
-        } else if (document.mozCancelFullScreen) {
-            document.mozCancelFullScreen()
-        } else if (document.msExitFullscreen) {
-            document.msExitFullscreen()
-        }
-    }
-}
-
-const onPointsUpdate = type => {
-    points.value[type] = true
-}
-
 onMounted(() => {
     const projectId = browser.valueFromUrl('projectId') || 1
     http.get(`smart-site/project/info?projectId=${projectId}`)
@@ -321,25 +236,64 @@ onMounted(() => {
                 project.value = response.data
                 if (project.value.sceneList.length) {
                     source.value = project.value.sceneList[0]
-                    if (showAdjust.value || showSplit.value) {
-                        onBimChecked()
-                        nextTick(() => onDbsChecked())
-                    }
                 }
             } else {
                 alert('获取数据失败')
             }
         })
-        .catch(() => {
+        .catch(err => {
             alert('服务器连接失败')
         })
 })
 </script>
 
 <style lang="scss" scoped>
-main{
+main {
     width: 100%;
     height: 100%;
+    iframe {
+        width: 100%;
+        height: 100%;
+    }
+    .tools {
+        position: absolute;
+        width: 100%;
+        bottom: 40px;
+        z-index: 2000;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        color: #fff;
+        pointer-events: none;
+        > div {
+            pointer-events: all;
+        }
+
+        .item-mode {
+            height: 50px;
+            background: rgba(27, 27, 28, 0.8);
+            box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
+            border-radius: 47px 47px 47px 47px;
+            border: 1px solid #000000;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            margin-left: 10px;
+            margin-right: 10px;
+            font-size: 16px;
+            padding: 0 16px;
+            div {
+                cursor: pointer;
+                font-size: 18px;
+            }
+            div:last-child {
+                margin-left: 20px;
+            }
+            div.active {
+                color: #0076f6;
+            }
+        }
+    }
 }
 </style>
 <style lang="scss">
@@ -348,4 +302,28 @@ main{
     display: flex;
     flex-direction: column;
 }
+:root {
+    --van-gray-8: rgba(255, 255, 255, 0.3);
+    --van-picker-background-color: rgba(0, 0, 0, 0.5);
+}
+// .van-picker {
+//     position: absolute;
+//     left: 0;
+//     right: 0;
+//     bottom: 0;
+// }
+.van-picker__mask {
+    display: none;
+}
+.van-picker__toolbar {
+    button {
+        font-size: 16px !important;
+        &.van-picker__confirm {
+            color: #0076f6;
+        }
+    }
+}
+.van-picker-column__item--selected {
+    color: #fff;
+}
 </style>

+ 26 - 17
src/pages/Viewer.vue

@@ -14,12 +14,12 @@
                     </div>
                 </div>
                 <div class="points" v-if="showAdjust">
-                    <div :class="{active:points.p1}">
-                        <i class="iconfont" :class="[points.p1?'icon-positioning01':'icon-positioning02']"></i>
+                    <div :class="{ active: points.p1 }">
+                        <i class="iconfont" :class="[points.p1 ? 'icon-positioning01' : 'icon-positioning02']"></i>
                         <span>P1</span>
                     </div>
-                    <div :class="{active:points.p2}">
-                        <i class="iconfont" :class="[points.p2?'icon-positioning01':'icon-positioning02']"></i>
+                    <div :class="{ active: points.p2 }">
+                        <i class="iconfont" :class="[points.p2 ? 'icon-positioning01' : 'icon-positioning02']"></i>
                         <span>P2</span>
                     </div>
                 </div>
@@ -32,12 +32,12 @@
                     </div>
                 </div>
                 <div class="points" v-if="showAdjust">
-                    <div :class="{active:points.p1}">
-                        <i class="iconfont" :class="[points.p1?'icon-positioning01':'icon-positioning02']"></i>
+                    <div :class="{ active: points.p1 }">
+                        <i class="iconfont" :class="[points.p1 ? 'icon-positioning01' : 'icon-positioning02']"></i>
                         <span>P1</span>
                     </div>
-                    <div :class="{active:points.p2}">
-                        <i class="iconfont" :class="[points.p2?'icon-positioning01':'icon-positioning02']"></i>
+                    <div :class="{ active: points.p2 }">
+                        <i class="iconfont" :class="[points.p2 ? 'icon-positioning01' : 'icon-positioning02']"></i>
                         <span>P2</span>
                     </div>
                 </div>
@@ -87,7 +87,7 @@ const mode = ref(0)
 const source = ref(null)
 const target = ref(null)
 const project = ref(null)
-const points = ref({p1:false,p2:false})
+const points = ref({ p1: false, p2: false })
 
 const scenes = computed(() => {
     if (!project.value) {
@@ -368,7 +368,7 @@ const onFscChecked = () => {
     }
 }
 
-const onPointsUpdate = type =>{
+const onPointsUpdate = type => {
     points.value[type] = true
 }
 
@@ -377,12 +377,21 @@ onMounted(() => {
     http.get(`smart-site/project/info?projectId=${projectId}`)
         .then(response => {
             if (response.success) {
-                project.value = response.data
-                if (project.value.sceneList.length) {
-                    source.value = project.value.sceneList[0]
-                    if (showAdjust.value || showSplit.value) {
-                        onBimChecked()
-                        nextTick(() => onDbsChecked())
+                if (response.data) {
+                    if (response.data.panos) {
+                        try {
+                            response.data.panos = JSON.parse(response.data.panos)
+                            points.value.p1 = true
+                            points.value.p2 = true
+                        } catch (error) {}
+                    }
+                    project.value = response.data
+                    if (project.value.sceneList.length) {
+                        source.value = project.value.sceneList[0]
+                        if (showAdjust.value || showSplit.value) {
+                            onBimChecked()
+                            nextTick(() => onDbsChecked())
+                        }
                     }
                 }
             } else {
@@ -476,7 +485,7 @@ main {
                 flex-direction: column;
                 align-items: center;
                 justify-content: center;
-                &.active{
+                &.active {
                     color: #0076f6;
                 }
                 i {