rindy vor 2 Jahren
Ursprung
Commit
415ab90203
6 geänderte Dateien mit 499 neuen und 3 gelöschten Zeilen
  1. 1 1
      .env
  2. 7 1
      public/smart-laser-bim.html
  3. 20 0
      src/assets/index.scss
  4. 432 0
      src/pages/LaserBim.vue
  5. 38 0
      src/pages/laser-bim.js
  6. 1 1
      vue.config.js

+ 1 - 1
.env

@@ -1,2 +1,2 @@
 # 静态资源目录
-VUE_APP_STATIC_DIR=resource
+VUE_APP_STATIC_DIR=static

+ 7 - 1
public/smart-laser-bim.html

@@ -4,7 +4,13 @@
         <title>BIM</title>
         <meta charset="utf-8" />
         <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
+        <link rel="stylesheet" href="<%= BASE_URL %><%= VUE_APP_STATIC_DIR %>/lib/iconfont/iconfont.css" />
     </head>
-    <body></body>
+    <body>
+        <noscript>
+            <strong>We're sorry but doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+        </noscript>
+        <div id="app"></div>
+    </body>
  
 </html>

+ 20 - 0
src/assets/index.scss

@@ -0,0 +1,20 @@
+html {
+    line-height: 1.15;
+    -webkit-text-size-adjust: 100%;
+}
+html,
+body {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    font-size: 14px;
+    overflow: hidden;
+    user-select: none;
+}
+#app {
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    color: #fff;
+    background-color: #232323;
+}

+ 432 - 0
src/pages/LaserBim.vue

@@ -0,0 +1,432 @@
+<template>
+    <header>
+        <div v-if="project">项目 - {{ project.name }}</div>
+    </header>
+    <article>
+        <main>
+            <div class="split" v-if="source">
+                <iframe ref="sourceFrame" :src="`smart-laser.html?m=${source.num}`" frameborder="0" @load="onLoadSource"></iframe>
+            </div>
+            <div class="split" v-if="target">
+                <iframe ref="targetFrame" :src="`test-bim.html?m=${target.num}`" frameborder="0" @load="onLoadTarget"></iframe>
+            </div>
+            <div class="tools" v-if="source">
+                <div class="item-date">
+                    <span class="prev" @click="onPrevDate()"><i class="iconfont icon-show_back"></i></span>
+                    <span @click="onPickDate('all')">{{ source.date }}</span>
+                    <span class="next" @click="onNextDate()"><i class="iconfont icon-show_back"></i></span>
+                </div>
+                <div class="item-split" @click="onCompare">
+                    <i class="iconfont icon-size-o"></i>
+                </div>
+            </div>
+            <div class="popup" v-if="source && datepickName">
+                <div>
+                    <span @click="onPickClose"><i class="iconfont icon-close"></i></span>
+                    <datepicker :inline="true" :value="datepickValue" :highlighted="highlighted" @selected="onSelected"></datepicker>
+                </div>
+            </div>
+        </main>
+    </article>
+</template>
+
+<script setup>
+import Datepicker from 'vuejs3-datepicker'
+import { ref, onActivated, onDeactivated, reactive, onMounted, computed } from 'vue'
+import ConvertViews from '@/utils/ConvertViews'
+let sourceApp = null
+let targetApp = null
+const views = new ConvertViews()
+const datepickName = ref(null)
+const datepickValue = ref(null)
+const sourceFrame = ref(null)
+const targetFrame = ref(null)
+const source = ref(null)
+const target = ref(null)
+const project = ref(null)
+const projects = reactive([{ pid: '001', name: '五楼办公区', num: 'SS-t-bFMqa1dqUU', date: '2022-09-01' }])
+const scenes = reactive([
+    { pid: '001', num: 'SS-t-bFMqa1dqUU', date: '2022-09-01' },
+    { pid: '001', num: 'SS-t-xp9BDKfzhR', date: '2022-09-03' },
+    { pid: '001', num: 'SS-t-lc5OWhZPaC', date: '2022-09-05' },
+    { pid: '001', num: 'SS-t-Y6gLRFwxE5', date: '2022-09-10' }
+])
+const highlighted = computed(() => {
+    let dates = []
+    if (datepickName.value) {
+        if (datepickName.value == 'source') {
+            dates = scenes.filter(item => item.date != target.value.date).map(item => item.date.toDate())
+        } else if (datepickName.value == 'target') {
+            dates = scenes.filter(item => item.date != source.value.date).map(item => item.date.toDate())
+        } else {
+            dates = scenes.map(item => item.date.toDate())
+        }
+    }
+    return {
+        dates: dates
+    }
+})
+
+const onLoadSource = () => {
+    sourceApp = sourceFrame.value.contentWindow.app
+    // sourceApp.Scene.on('loaded', () => {
+    //     sourceApp.Camera.setCompassDisplay(false)
+    //     sourceApp.Connect.sync.start()
+    //     sourceApp.VRScreenSYNC = false
+
+    //     console.log('sourceApp.Scene loaded')
+    //     views.KanKan = sourceFrame.value.contentWindow.KanKan
+    //     views.bind({ sourceApp })
+    //     targetApp && targetApp.Connect.sync.sync()
+    // })
+    // sourceApp.Connect.sync.on('data', data => {
+    //     if (targetApp) {
+    //         views.applyDiff(targetApp, data)
+    //         targetApp.Connect.sync.receive(data)
+    //     }
+    // })
+}
+const onLoadTarget = () => {
+    targetApp = targetFrame.value.contentWindow.app
+    // targetApp.Scene.on('loaded', () => {
+    //     targetApp.Camera.setCompassDisplay(false)
+    //     targetApp.Connect.sync.start()
+    //     targetApp.VRScreenSYNC = false
+    //     console.log('targetApp.Scene loaded')
+
+    //     views.bind({ targetApp })
+    //     sourceApp && sourceApp.Connect.sync.sync()
+    // })
+    // targetApp.Connect.sync.on('data', data => {
+    //     if (sourceApp) {
+    //         views.applyDiff(sourceApp, data)
+    //         sourceApp.Connect.sync.receive(data)
+    //     }
+    // })
+}
+const onModeChange = mode => {
+    if (sourceApp) {
+        sourceApp.Camera[mode]()
+    }
+}
+const onPickDate = name => {
+    if (name == 'target') {
+        datepickValue.value = target.value.date.toDate()
+    } else {
+        datepickValue.value = source.value.date.toDate()
+    }
+    datepickName.value = name
+}
+const onPickClose = () => {
+    datepickName.value = null
+    datepickValue.value = null
+}
+const onSelected = payload => {
+    if (!payload) {
+        return
+    }
+
+    var date = payload.format('YYYY-mm-dd')
+    var dates = highlighted.value.dates.map(item => item.format('YYYY-mm-dd'))
+
+    if (dates.indexOf(date) != -1) {
+        var find = scenes.find(c => c.date == date)
+        if (find) {
+            if (datepickName.value) {
+                if (datepickName.value == 'all' || datepickName.value == 'source') {
+                    if (find.num != source.value.num) {
+                        source.value = find
+                    }
+                } else if (datepickName.value == 'target') {
+                    if (find.num != target.value.num) {
+                        target.value = find
+                    }
+                }
+            } else {
+                if (find.num != source.value.num) {
+                    source.value = find
+                }
+            }
+        }
+    }
+
+    datepickName.value = null
+}
+const onCompare = () => {
+    if (target.value) {
+        target.value = null
+        targetApp = null
+        return
+    }
+    let index = scenes.findIndex(item => item.num == source.value.num)
+    if (index == -1) {
+        return
+    }
+    if (++index > scenes.length - 1) {
+        index = 0
+    }
+    target.value = scenes[index]
+}
+
+const onPrevDate = name => {
+    if (!scene) {
+        scene = source
+    }
+    let scene = null
+    if (!name || name == 'source') {
+        scene = source
+    } else {
+        scene = target
+    }
+    let index = scenes.findIndex(item => item.num == scene.value.num)
+    if (index == -1) {
+        return
+    }
+    if (--index == -1) {
+        index = scenes.length - 1
+    }
+
+    if (name) {
+        if (name == 'source') {
+            if (scenes[index].num == target.value.num) {
+                index--
+            }
+        } else {
+            if (scenes[index].num == source.value.num) {
+                index--
+            }
+        }
+    }
+    if (index == -1) {
+        index = scenes.length - 1
+    }
+    scene.value = scenes[index]
+}
+const onNextDate = name => {
+    let scene = null
+    if (!name || name == 'source') {
+        scene = source
+    } else {
+        scene = target
+    }
+    let index = scenes.findIndex(item => item.num == scene.value.num)
+    if (index == -1) {
+        return
+    }
+    if (++index > scenes.length - 1) {
+        index = 0
+    }
+    if (name) {
+        if (name == 'source') {
+            if (scenes[index].num == target.value.num) {
+                index++
+            }
+        } else {
+            if (scenes[index].num == source.value.num) {
+                index++
+            }
+        }
+    }
+    if (index > scenes.length - 1) {
+        index = 0
+    }
+    scene.value = scenes[index]
+}
+
+onMounted(() => {
+    project.value = projects[0]
+    if (project.value) {
+        source.value = scenes.find(item => item.num == project.value.num)
+    }
+})
+</script>
+
+<style lang="scss" scoped>
+header {
+    height: 60px;
+    background-color: rgba(0, 0, 0, 0.8);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    font-size: 18px;
+}
+article {
+    display: flex;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+}
+aside {
+    width: 160px;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.8);
+    h4 {
+        font-size: 16px;
+        text-align: center;
+    }
+    ul {
+        margin-top: 20px;
+    }
+    li {
+        margin: 0;
+        padding: 0;
+        font-size: 16px;
+        margin-left: 20px;
+        cursor: pointer;
+        &:hover,
+        &.active {
+            color: #00c8af;
+        }
+    }
+}
+main {
+    flex: 1;
+    width: 100%;
+    height: 100%;
+    position: relative;
+    display: flex;
+    &.full {
+        .split {
+            width: 50%;
+        }
+    }
+    iframe {
+        position: absolute;
+        left: 0;
+        top: 0;
+        z-index: 1000;
+        width: 100%;
+        height: 100%;
+    }
+    .split {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        position: relative;
+        .tools {
+            width: 100%;
+            padding-left: 20px;
+            padding-right: 20px;
+            justify-content: space-between;
+            left: 0;
+            transform: none;
+            .item-mode {
+                display: flex;
+                align-items: center;
+                justify-content: space-around;
+                height: 34px;
+                border-radius: 17px;
+                background-color: rgba(0, 0, 0, 0.3);
+                > div {
+                    position: relative;
+                    margin-left: 20px;
+                    margin-right: 20px;
+                    cursor: pointer;
+                }
+                i {
+                    font-size: 18px;
+                }
+            }
+        }
+    }
+    .tools {
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        bottom: 10px;
+        z-index: 1000;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        color: #fff;
+        i {
+            font-size: 18px;
+        }
+        .item-date {
+            position: relative;
+            height: 34px;
+            border-radius: 17px;
+            background-color: rgba(0, 0, 0, 0.3);
+            padding: 0 30px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            margin-left: 10px;
+            margin-right: 10px;
+            span {
+                cursor: pointer;
+            }
+            .prev,
+            .next {
+                position: absolute;
+                left: 5px;
+            }
+            .next {
+                left: auto;
+                right: 5px;
+                transform: rotate(180deg);
+            }
+        }
+
+        .item-split {
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            width: 34px;
+            height: 34px;
+            border-radius: 50%;
+            background-color: rgba(0, 0, 0, 0.3);
+            cursor: pointer;
+        }
+    }
+    .popup {
+        position: absolute;
+        left: 0;
+        top: 0;
+        width: 100%;
+        height: 100%;
+        z-index: 1000;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        > div {
+            position: relative;
+            color: #444;
+            span {
+                position: absolute;
+                right: -20px;
+                top: -20px;
+                cursor: pointer;
+                background-color: rgba(0, 0, 0, 0.3);
+                width: 24px;
+                height: 24px;
+                border-radius: 50%;
+                z-index: 1000;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                color: #fff;
+            }
+            i {
+                font-size: 12px;
+            }
+        }
+    }
+}
+</style>
+<style lang="scss">
+#app {
+    background-color: #fff !important;
+    display: flex;
+    flex-direction: column;
+}
+.vuejs3-datepicker__calendar-topbar {
+    display: none !important;
+}
+.highlighted {
+    background: #4ebde1 !important;
+}
+.selected {
+    background: #00c8af !important;
+}
+</style>

+ 38 - 0
src/pages/laser-bim.js

@@ -0,0 +1,38 @@
+import '../assets/index.scss'
+import { createApp } from 'vue'
+import App from './LaserBim'
+
+Date.prototype.format = function(fmt = 'YYYY-mm-dd HH:MM:SS') {
+    var res = ''
+    try {
+        var date = this
+        var opt = {
+            'Y+': date.getFullYear().toString(), // 年
+            'm+': (date.getMonth() + 1).toString(), // 月
+            'd+': date.getDate().toString(), // 日
+            'H+': date.getHours().toString(), // 时
+            'M+': date.getMinutes().toString(), // 分
+            'S+': date.getSeconds().toString() // 秒
+        }
+        for (var k in opt) {
+            var ret = new RegExp('(' + k + ')').exec(fmt)
+            if (ret) {
+                fmt = fmt.replace(ret[1], ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0'))
+            }
+        }
+        res = fmt
+    } catch (error) {
+        logger.warn('ERROR formatDate', error)
+    }
+    return res
+}
+
+String.prototype.toDate = function() {
+    if (!this) {
+        return null
+    }
+    return new Date(this.replace(/\//g, '-').replace(' ', 'T'))
+}
+
+const app = (window.__app = createApp(App))
+app.mount('#app')

+ 1 - 1
vue.config.js

@@ -47,7 +47,7 @@ const config = {
         resolve: {
             symlinks: false,
             alias: {
-                vue: path.resolve(`../../node_modules/vue`)
+                vue: path.resolve(`node_modules/vue`)
             }
         }
     }