tangning пре 1 година
родитељ
комит
6bccdc6d55

+ 3 - 0
package.json

@@ -9,12 +9,15 @@
   },
   "dependencies": {
     "core-js": "^3.8.3",
+    "html2canvas": "^1.4.1",
     "less": "^4.2.0",
     "less-loader": "^12.2.0",
     "swiper": "^11.1.0",
     "vue": "^2.6.14",
     "vue-awesome-swiper": "^3.1.3",
+    "vue-qr": "^4.0.9",
     "vue-router": "^3.6.5",
+    "vue2-verify": "^1.1.5",
     "vuex": "^3.6.2"
   },
   "devDependencies": {

Разлика између датотеке није приказан због своје велике величине
+ 756 - 180
public/staticData/data.js


+ 8 - 2
src/App.vue

@@ -1,18 +1,23 @@
 <template>
   <div id="app">
-    <router-view />
+    <feedbackModal v-show="modalState == 'feedback'" />
+    <router-view/>
   </div>
 </template>
 
 <script>
 import dataAll from '/public/staticData/data';
-
+import feedbackModal from './views/Home/feedbackModal.vue'
+import { mapState } from "vuex";
 export default {
   name: 'App',
   data() {
     return {
     };
   },
+  computed: {
+        ...mapState( [ "modalState" ] )
+    },
   methods: {
     // 保存静态数据在vuex中
     initStaticData() {
@@ -24,6 +29,7 @@ export default {
 
   },
   components: {
+    feedbackModal,
   }
 }
 </script>

+ 642 - 0
src/assets/images/home/LeftButtons.vue

@@ -0,0 +1,642 @@
+<template>
+    <div class="controls-left-buttons">
+        <div class="play-control" v-if="tours.length > 0" :class="{ disabled: flying && !isPlay }">
+            <div class="play-btn tour-btn" @click="playTour">
+                <div class="animation-icon" :class="{ action: isPlay }" :style="`background-image: url(${resource.getStaticURL('static/images/walk_animation.png')});`">
+                    <p class="tip">{{ isPlay ? $t('common.pauseTour') : $t('common.playTour') }}</p>
+                </div>
+            </div>
+
+            <div class="tour-btn bor">
+                <ui-icon type="pull-down" @click="openTours" :class="{ active: showTours }"></ui-icon>
+            </div>
+            <!-- <teleport :to="editorMain"> -->
+            <div class="tour-list" :class="{ ban: flying || isSelect }" :style="`height:${showTours ? '120px' : '0px'};`">
+                <div class="part-content" ref="tourScroll">
+                    <!-- 多个片段 -->
+                    <div class="part-list" v-if="tours.length > 1">
+                        <div
+                            @click="changeFrame(1, index)"
+                            class="part-item"
+                            :name="index"
+                            v-for="(i, index) in tours"
+                            :style="`background-image:url(${i.frameId && i.list[i.frameId] ? common.changeUrl(i.list[i.frameId].enter.cover) : common.changeUrl(i.list[0].enter.cover)});`"
+                        >
+                            <div class="part-title">{{ i.name }}</div>
+                            <div v-if="partId == index && progressNum > 0" class="precent" :style="`width:${progressNum}%;`"></div>
+                        </div>
+                    </div>
+                    <!-- 只有一个片段 -->
+                    <div class="part-list frame-list" v-else>
+                        <div @click="changeFrame(2, index)" class="part-item" v-for="(i, index) in tours[0].list" :name="index" :style="`background-image:url(${common.changeUrl(i.enter.cover)});`">
+                            <div class="part-title"></div>
+                            <div v-if="frameId == index && progressNum > 0" class="precent" :style="`width:${progressNum}%;`"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <!-- </teleport> -->
+        </div>
+        <div class="buttons mode" :class="{ disabled: isPlay || flying }">
+            <div v-if="controls.showPanorama" :class="{ active: viewmode == 'panorama' }" @click="onModeChange('panorama')">
+                <ui-icon :tip="$t('mode.panorama')" tipV="top" :type="viewmode == 'panorama' ? 'show_roaming_s' : 'show_roaming_n'"></ui-icon>
+            </div>
+            <div v-if="controls.showFloorplan" :class="{ active: viewmode == 'floorplan' }" @click="onModeChange('floorplan')">
+                <ui-icon :tip="$t('mode.floorplan')" tipV="top" :type="viewmode == 'floorplan' ? 'show_plane_s' : 'show_plane_n'"></ui-icon>
+            </div>
+            <div v-if="controls.showDollhouse" :class="{ active: viewmode == 'dollhouse' }" @click="onModeChange('dollhouse')">
+                <ui-icon :tip="$t('mode.dollhouse')" tipV="top" :type="viewmode == 'dollhouse' ? 'show_3d_s' : 'show_3d_n'"></ui-icon>
+            </div>
+        </div>
+
+        <!-- 导览字幕 -->
+        <!-- <teleport to=".kankan-app" > -->
+        <div class="tours-captions" :class="{ active: showTours }" v-if="tours.length > 0 && isPlay">
+            <div class="captions-title" v-if="tours[partId] && tours[partId].title">{{ tours[partId].title || '' }}</div>
+            <div class="captions-desc" v-if="tours[partId] && tours[partId].description">{{ tours[partId].description || '' }}</div>
+        </div>
+        <!-- </teleport> -->
+    </div>
+</template>
+<script setup>
+import { computed, defineProps, onMounted, ref, nextTick, watch } from 'vue'
+import { Scrollbar, Dialog } from '@kankan/components'
+import { useApp, getApp } from '@/app'
+import { useStore } from 'vuex'
+import browser from '@/utils/browser'
+import common from '@/utils/common'
+import resource from '@/utils/resource'
+import { useMusicPlayer } from '@/utils/sound'
+import { Track, startTrack, endTrack } from '@/utils/track.js'
+// import test from './test.vue'
+const musicPlayer = useMusicPlayer()
+const props = defineProps({
+    isEdit: Boolean,
+})
+let timer = null
+const isSelect = ref(false)
+const store = useStore()
+const tourScroll = ref(null)
+const viewmode = computed(() => store.getters.mode)
+const flying = computed(() => store.getters['flying'])
+const controls = computed(() => store.getters['scene/metadata'].controls || {})
+const showTours = computed(() => store.getters['tour/showTours'])
+const sceneUI = computed(() => store.getters.sceneUI)
+const partId = computed(() => {
+    let id = store.getters['tour/partId']
+    if (isPlay.value) {
+        slideScroll()
+    }
+    return id
+})
+
+const frameId = computed(() => {
+    let id = store.getters['tour/frameId']
+    if (isPlay.value) {
+        slideScroll()
+    }
+    return id
+})
+const progressNum = ref(0)
+const isPlay = computed(() => {
+    let status = store.getters['tour/isPlay']
+    let map = document.querySelector('.kankan-app div[xui_min_map]')
+    if (map) {
+        if (status) {
+            map.classList.add('disabled')
+        } else {
+            map.classList.remove('disabled')
+        }
+    }
+    return status
+})
+const isInit = ref(false)
+const tours = computed(() => {
+    let tours = store.getters['tour/tours']
+    if (tours.length > 0) {
+        if (tourScroll.value && !isInit.value) {
+            isInit.value = true
+            new Scrollbar(tourScroll.value, { onlyHorizontal: true })
+        }
+    }
+    return tours
+})
+
+watch(
+    () => sceneUI.value,
+    (val, old) => {
+        if (showTours.value) {
+            if (val) {
+                store.commit('setControlsBottom', '120px')
+            } else {
+                store.commit('setControlsBottom', '0')
+            }
+        }
+    }
+)
+
+const onModeChange = name => {
+    store.commit('setMode', name)
+    Track('view-button', {
+        eventType: 'click',
+        click: name,
+    })
+}
+const playTour = async () => {
+    let player = await getApp().TourManager.player
+    if (isPlay.value) {
+        store.commit('tour/setData', { isPlay: true })
+        player.pause()
+    } else {
+        store.commit('tour/setData', { isPlay: true })
+        player.play(partId.value, frameId.value)
+    }
+    store.commit('tag/setData', { isFixed: false, isClick: false, flyClose: false })
+    store.commit('tag/closeTag')
+
+    //自动打开导览
+    if (isPlay.value) {
+        store.commit('tour/setData', { showTours: true })
+        let bot = '0px'
+        if (showTours.value) {
+            bot = '120px'
+        } else {
+            bot = '0px'
+        }
+        store.commit('setControlsBottom', bot)
+        nextTick(() => {
+            if (isPlay.value) {
+                slideScroll()
+            }
+        })
+    }
+}
+
+const hanlderTourPartPlay = time => {
+    if (!timer) {
+        timer = KanKan.Animate.transitions.start(progress => {
+            progressNum.value = progress * 100
+        }, time)
+    }
+}
+const cancelTimer = () => {
+    if (timer) {
+        KanKan.Animate.transitions.cancel(timer)
+        timer = null
+    }
+}
+const slideScroll = () => {
+    nextTick(() => {
+        let t = setTimeout(() => {
+            clearTimeout(t)
+            let id = tours.value.length > 1 ? partId.value : frameId.value
+            let item = document.querySelector(`.part-item[name="${id}"]`)
+            item.scrollIntoView({ block: 'nearest', behavior: 'smooth', inline: 'center' })
+        }, 100)
+    })
+}
+let tour_finish = false
+const hanlderTour = async () => {
+    let player = await getApp().TourManager.player
+    player.on('play', data => {
+        tour_finish = false
+        musicPlayer.pause(true)
+        Track('view-tour', {
+            eventType: 'click',
+            click: 'play',
+        })
+    })
+    player.on('pause', tours => {
+        console.log('pause')
+        musicPlayer.resume()
+        currProgress = 0
+        currFrameProgress = 0
+        progressNum.value = 0
+        cancelTimer()
+        store.commit('tour/setData', { isPlay: false })
+    })
+    player.on('end', () => {
+        tour_finish = true
+        musicPlayer.resume()
+        currProgress = 0
+        currFrameProgress = 0
+        progressNum.value = 100
+        slideScroll()
+        store.commit('tour/setData', { isPlay: false })
+        cancelTimer()
+
+        // 循环播放导览
+        if (browser.hasURLParam('tour_loop')) {
+            setTimeout(() => {
+                playTour()
+            }, 1000)
+        }
+        //当最后一个有热点时候,需要展开
+        if (tours.value[partId.value].list[frameId.value].tagId) {
+            getApp().TagManager.open(tours.value[partId.value].list[frameId.value].tagId)
+        }
+    })
+
+    let currPartId = null
+    let currFrameId = null
+    let currProgress = 0
+    let FrameLength = 0
+    let currFrameProgress = 0
+
+    player.on('progress', data => {
+        if (tour_finish) {
+            return
+        }
+        if (currPartId != data.partId || currFrameId != data.frameId) {
+            if (!tours.value[data.partId].list[data.frameId].tagId) {
+                store.commit('tag/closeTag')
+            }
+        }
+        if (tours.value.length == 1) {
+            progressNum.value = data.progress * 100
+            currPartId = data.partId
+            currFrameId = data.frameId
+        } else {
+            // let time = getPartTime(data.partId)
+
+            // hanlderTourPartPlay(time)
+
+            if (currPartId != data.partId) {
+                currProgress = 0
+                currFrameProgress = 0
+                progressNum.value = 0
+                currPartId = data.partId
+                FrameLength = tours.value[data.partId].list.length
+            } else {
+                FrameLength = tours.value[data.partId].list.length
+
+                if (currFrameId != data.frameId) {
+                    currFrameId = data.frameId
+                    currFrameProgress = currProgress
+                } else {
+                    currProgress = (data.progress / FrameLength) * 100 + currFrameProgress
+                }
+                if (currProgress >= 100) {
+                    currProgress = 100
+                }
+
+                progressNum.value = currProgress
+            }
+        }
+        store.commit('tour/setData', { partId: data.partId, frameId: data.frameId })
+    })
+
+    // 导览自动播放
+    getApp().TourManager.on('loaded', () => {
+        if (browser.hasURLParam('autoplay')) {
+            setTimeout(() => {
+                if (tours.value.length) {
+                    let hasMusic = false
+                    for (let i = 0; i < tours.value.length; i++) {
+                        if (tours.value[i].music) {
+                            hasMusic = true
+                            continue
+                        }
+                    }
+                    if (!hasMusic) {
+                        //当所有片段没有背景音乐时,才能自动播放
+                        playTour()
+                    }
+                }
+            }, 500)
+        }
+    })
+}
+const getPartTime = partId => {
+    cancelTimer()
+    let time = 0
+    for (let i = 0; i < tours.value[partId].list.length; i++) {
+        if (!tours.value[partId].list[i]._end) {
+            time += tours.value[partId].list[i].time - 0
+            if (!tours.value[partId].list[i]._notrans) {
+                time += 1000
+            }
+        }
+    }
+    return time
+}
+
+const openTours = () => {
+    // showTours.value = !showTours.value
+    store.commit('tour/setData', { showTours: !showTours.value })
+    let bot = '0px'
+    if (showTours.value) {
+        bot = '120px'
+    } else {
+        bot = '0px'
+    }
+    store.commit('setControlsBottom', bot)
+    nextTick(() => {
+        if (isPlay.value) {
+            slideScroll()
+        }
+    })
+}
+const changeFrame = async (type, id) => {
+    store.commit('tag/closeTag')
+    progressNum.value = 0
+    let player = await getApp().TourManager.player
+    if (type == 1) {
+        Track('view-tour', {
+            eventType: 'click',
+            click: 'part',
+        })
+        store.commit('tour/setData', {
+            frameId: 0,
+            partId: id,
+        })
+        progressNum.value = 0
+
+        player.selectPart(id).then(() => {
+            if (!isPlay.value) {
+                return
+            }
+            store.commit('tour/setData', {
+                isPlay: true,
+            })
+            player.play(id, frameId.value)
+        })
+    } else {
+        Track('view-tour', {
+            eventType: 'click',
+            click: 'frame',
+        })
+
+        store.commit('tour/setData', {
+            frameId: id,
+        })
+        progressNum.value = 0
+        player.selectFrame(id).then(() => {
+            if (!isPlay.value) {
+                return
+            }
+            store.commit('tour/setData', {
+                isPlay: true,
+            })
+            player.play(0, id)
+        })
+    }
+
+    slideScroll()
+}
+const onClickHandler = async () => {
+    if (isPlay.value) {
+        let player = await getApp().TourManager.player
+        player.pause()
+        musicPlayer.resume()
+    }
+}
+onMounted(() => {
+    useApp().then(app => {
+        hanlderTour()
+    })
+
+    nextTick(() => {
+        let player = document.querySelector('.player[name="main"]')
+        player.addEventListener('pointerdown', onClickHandler)
+    })
+})
+</script>
+
+<style lang="scss" scoped>
+.tours-captions {
+    position: absolute;
+    bottom: 64px;
+    left: 20px;
+    width: 480px;
+    word-break: break-all;
+    text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25);
+    text-align: justify;
+    color: #fff;
+    pointer-events: none;
+    z-index: 1;
+    transition: all 0.3s;
+    &.active {
+        // bottom: 184px;
+    }
+    .captions-title {
+        font-size: 28px;
+        margin-bottom: 10px;
+        font-weight: bold;
+    }
+    .captions-desc {
+        font-size: 16px;
+        line-height: 24px;
+    }
+}
+.controls-left-buttons {
+    // margin-left: 20px;
+    // margin-bottom: 20px;
+    display: flex;
+    // justify-content: center;
+    align-items: flex-end;
+    padding: 0 0 20px 20px;
+}
+.buttons.tour {
+    margin-right: 10px;
+    > div {
+        margin-left: 0px;
+        margin-right: 0px;
+        padding: 0 10px;
+        &.show-list {
+            border-left: solid 1px var(--editor-font-color);
+        }
+        .icon-pull-down {
+            font-size: 12px;
+        }
+        span {
+            right: -10px;
+        }
+    }
+}
+.tour-list {
+    width: 100%;
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex: 1;
+    // height: var(--editor-toolbar-height);
+    height: 120px;
+    background-color: var(--editor-menu-back);
+    pointer-events: all;
+    left: var(--editor-toolbox-left);
+    z-index: 1;
+    transition: all 0.3s ease;
+    &::after {
+        width: 100%;
+        position: absolute;
+        content: '';
+        top: 0;
+        left: 0;
+        border-bottom: solid 1px rgba(255, 255, 255, 0.16);
+        border-top: solid 1px #000;
+    }
+    &.ban {
+        pointer-events: none;
+    }
+    .part-content {
+        display: flex;
+        flex-direction: row;
+        overflow: hidden;
+        width: 100%;
+        height: 100%;
+        .part-list {
+            width: 100%;
+            height: 120px;
+            display: flex;
+            align-items: center;
+            justify-content: flex-start;
+            padding: 0 10px;
+            box-sizing: border-box;
+            .part-item {
+                width: 120px;
+                height: 80px;
+                position: relative;
+                cursor: pointer;
+                margin-right: 10px;
+                background-repeat: no-repeat;
+                background-size: 100%;
+                background-position: center;
+                &:last-of-type {
+                    margin-right: 0px;
+                }
+                &:hover {
+                    opacity: 0.6;
+                }
+                .precent {
+                    width: 0%;
+                    height: 3px;
+                    position: absolute;
+                    bottom: 0;
+                    left: 0;
+                    background: var(--editor-main-color);
+                    // opacity: 0.4;
+                    z-index: 100;
+                    // transition: width 0.1s;
+                }
+                .part-title {
+                    width: 100%;
+                    height: 24px;
+                    background: linear-gradient(180deg, rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0.5) 100%);
+                    position: absolute;
+                    bottom: 0;
+                    left: 0;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    font-size: 14px;
+                    z-index: 10;
+                }
+            }
+        }
+    }
+}
+.play-control {
+    pointer-events: all;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 34px;
+    border-radius: 17px;
+    // background-color: rgba(0, 0, 0, 0.3);
+    min-width: 34px;
+    border-radius: 17px;
+    position: relative;
+    z-index: 2;
+    // margin-left: 10px;
+
+    .tour-btn {
+        width: 34px;
+        height: 22px;
+        cursor: pointer;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        > .iconfont {
+            font-size: 14px;
+        }
+        &.play-btn {
+            // border-right: 1px solid rgba(255, 255, 255, 0.2);
+            // > .iconfont {
+            //     font-size: 20px;
+            //     transition: rotate 0.3s;
+            // }
+            position: relative;
+            .animation-icon {
+                width: 24px;
+                height: 24px;
+                // background: red;
+                position: absolute;
+                top: 50%;
+                left: 50%;
+                transform: translate(-50%, -50%);
+                background-repeat: no-repeat;
+                background-position: 0% 0%;
+                background-size: auto 24px;
+                &:hover {
+                    .tip {
+                        opacity: 0.8;
+                    }
+                }
+                .tip {
+                    color: white;
+                    position: absolute;
+                    transform-origin: top center;
+                    background: #000000;
+                    border-radius: 4px;
+                    opacity: 0;
+                    padding: 10px;
+                    margin: 10px;
+                    font-size: 12px;
+                    transition: opacity 0.3s ease;
+                    pointer-events: none;
+                    white-space: nowrap;
+                    left: 50%;
+                    transform: translateX(-50%);
+                    margin-left: 0;
+                    margin-right: 0;
+                    z-index: 10;
+                    bottom: 100%;
+                }
+
+                &.action {
+                    animation: humanAction 1s steps(25) infinite;
+                }
+                @keyframes humanAction {
+                    0% {
+                        background-position: 0% 0%;
+                    }
+                    100% {
+                        background-position: 100% 0%;
+                    }
+                }
+            }
+        }
+        &.bor {
+            height: 16px;
+            border-right: 1px solid;
+            border-image: linear-gradient(to bottom, rgba(194, 194, 194, 0.3), rgba(255, 255, 255, 0.3)) 1;
+
+            padding: 0 34px;
+            cursor: default;
+            > .iconfont {
+                font-size: 18px;
+                transform: rotate(180deg);
+                cursor: pointer;
+                &.active {
+                    transform: rotate(0deg);
+                }
+            }
+        }
+    }
+}
+</style>

Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/assets/images/home/arrow.svg


BIN
src/assets/images/home/back.png


BIN
src/assets/images/home/clear.png


BIN
src/assets/images/home/down.png


BIN
src/assets/images/home/edit.png


BIN
src/assets/images/home/label1.png


BIN
src/assets/images/home/refresh.png


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/assets/images/home/right.svg


BIN
src/assets/images/home/sharediv.png


BIN
src/assets/images/home/watermark.png


BIN
src/assets/images/init/Vector.png


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/components/msg/close.svg


+ 31 - 0
src/components/msg/index.js

@@ -0,0 +1,31 @@
+import vue from 'vue'
+//引入组件
+import messComponent from './messagePage.vue'
+//创建构造器
+const MessConstructor = vue.extend(messComponent)
+function showMessage(text) {
+  const message = new MessConstructor({
+    el: document.createElement('div'),
+    data() {
+      return {
+        text: text,
+        isShow: true,    // 是否显示组件
+        showContent: true  // 作用:在隐藏组件之前,显示隐藏动画
+      }
+    }
+  })
+  document.body.appendChild(message.$el)
+
+
+  setTimeout(() => { message.showContent = false }, 2000)
+  // 过了 duration 时间隐藏组件
+  setTimeout(() => { message.isShow = false }, 2000 * 2)
+}
+
+
+function messageCom() {
+//挂到vue上去,方便调用
+  vue.prototype.$message = showMessage
+}
+export default messageCom
+

+ 67 - 0
src/components/msg/messagePage.vue

@@ -0,0 +1,67 @@
+<template>
+  <div class="wrapper" v-if="isShow" :class="showContent ? 'fadein' : 'fadeout'">{{ text }}</div>
+</template>
+<script>
+
+</script>
+<style scoped>
+.wrapper {
+  /* width: 200px;
+  text-align: center;
+  position: fixed;
+  left: 50%;
+  z-index: 100;
+  top: 50px;
+  background: rgb(0, 0, 0);
+  padding: 10px;
+  border-radius: 5px;
+  border: 1px solid rgb(235, 238, 245);
+  transform: translate(-50%, -50%);
+  color: rgb(201, 173, 153);
+  font-size: 28px !important; */
+  width: 300px;
+  height: 50px;
+  position: fixed;
+  z-index: 9999;
+  left: 50%;
+  margin-left: -150px;
+  top: 25px;
+  line-height: 50px;
+  padding: 0 25px;
+  border: 1px solid #e4e4e4;
+  background: #f5f5f5;
+  color: #999;
+  border-radius: 4px;
+}
+
+.fadein {
+  animation: animate_in 1s;
+}
+
+.fadeout {
+  animation: animate_out 1s;
+  opacity: 0;
+}
+
+@keyframes animate_in {
+  0% {
+    opacity: 0;
+  }
+
+  100% {
+    opacity: 1;
+  }
+}
+
+@keyframes animate_out {
+  0% {
+    opacity: 1;
+  }
+
+  100% {
+    opacity: 0;
+  }
+}
+</style>
+
+

+ 6 - 0
src/main.js

@@ -3,13 +3,19 @@ import App from './App.vue'
 import store from './store' 
 import router from './router'
 import VueAwesomeSwiper from 'vue-awesome-swiper'
+import messageCom from './components/msg/index'
+import messagePage from './components/msg/messagePage.vue'
 
 Vue.config.productionTip = false
 
 // 引入Swiper CSS样式
 import 'swiper/swiper-bundle.css'
+// import 'swiper/dist/css/swiper.css'
+import 'swiper/css';
 
+Vue.use(messageCom)
 Vue.use(VueAwesomeSwiper)
+Vue.component('message-page', messagePage)
 
 new Vue({
   store,

+ 5 - 0
src/router/index.js

@@ -10,6 +10,11 @@ export default new Router({
       path: '/',
       name: 'Home',
       component: () => import('@/views/Home/homePage.vue'), // 异步加载组件示例
+    },
+    {
+      path: '/initialize',
+      name: 'initialize',
+      component: () => import('@/views/initialize/initializePage.vue'), // 异步加载组件示例
     }
     // 更多路由配置...
   ],

+ 5 - 0
src/store/index.js

@@ -7,12 +7,17 @@ Vue.use(Vuex)
 const state = {
   // 初始化静态数据对象
   dataAll: {},
+  modalState: 'share',
 }
 
 const mutations = {
   setDataAll(state, dataAll) {
     state.dataAll = dataAll
   },
+  //设置页码
+  setModalState(state, val) {
+    state.modalState = val
+  },
   // 其他mutation处理函数...
 }
 

+ 171 - 0
src/views/Home/detailPage.vue

@@ -0,0 +1,171 @@
+<template>
+  <div class="detail-home">
+    <div class="detail-left">
+      <img src="@/assets/images/home/back.png" alt="" @click="$emit('cleal')" />
+      <div class="text">
+        <div class="title">藏品标题藏品标题藏品标题藏品标题藏品标题</div>
+        <p>时代:土地革命时期</p>
+        <p>质地:纸</p>
+        <p>简介:这是一段简介简洁</p>
+      </div>
+    </div>
+    <div class="detail-content">
+      <swiper class="swiper" :options="swiperOptions">
+        <swiper-slide class="slide-item" v-for="index in 8" :key="index">
+          <img
+            style="min-height: 15.5vh"
+            :src="`${index}/images/full/$`"
+            @error="
+              (e) => {
+                e.target.src =
+                  'https://4dscene.4dage.com/new4dkk/v2/images/_/common/data/images/bbhhbw.c24ca41.png';
+              }
+            "
+            alt=""
+          />
+        </swiper-slide>
+      </swiper>
+    </div>
+  </div>
+</template>
+<script>
+// import { Swiper, SwiperSlide } from 'vue-awesome-swiper'
+export default {
+  // components: {
+  //   Swiper,
+  //   SwiperSlide,
+  // },
+  data() {
+    return {
+      swiperOptions: {
+        effect: "slide",
+        loop: true,
+        grabCursor: true,
+        slidesPerView: 1.5,
+        coverflowEffect: {
+          rotate: 0,
+          stretch: 50,
+          depth: 500,
+          modifier: 1,
+          slideShadows: false,
+        },
+        pagination: {
+          el: ".swiper-pagination",
+        },
+        navigation: {
+          nextEl: ".swiper-button-next",
+          prevEl: ".swiper-button-prev",
+        },
+
+        // 轮播选项
+        watchSlidesProgress: true,
+        centeredSlides: true,
+        slidesOffsetBefore: 0,
+        // initialSlide: 2,
+        loopedSlides: 5,
+        spaceBetween: 9,
+        // autoplay: true,
+      },
+    };
+  },
+};
+</script>
+<style lang="less" scoped>
+.detail-home {
+  font-family: Source Han Sans SC, Source Han Sans SC;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  .detail-left {
+    width: 20vw;
+    height: 100%;
+    // background: url(@/assets/images/home/greenBg.png);
+    background: rgba(27, 27, 28, 0.9);
+    backdrop-filter: blur(5px);
+    background-size: cover;
+    padding: 32px 62px 32px 52px;
+    position: relative;
+    img {
+      height: 30px;
+      cursor: pointer;
+    }
+    .text {
+      width: calc(100% - 114px);
+      position: absolute;
+      top: 50%;
+      transform: translate(0, -50%);
+      .title {
+        font-weight: 500;
+        font-size: 18px;
+        color: #ffffff;
+        line-height: 21px;
+        padding: 0 20px 50px 20px;
+        border-bottom: 4px dotted #444;
+        text-align: center;
+      }
+      p {
+        margin-top: 35px;
+        font-weight: 500;
+        font-size: 16px;
+        color: #ffffff;
+        line-height: 26px;
+        text-align: left;
+      }
+    }
+  }
+  .detail-content {
+    width: 80vw;
+    background: rgba(10, 59, 64, 0.9);
+    position: relative;
+    .swiper {
+      height: calc(65% + 60px);
+      width: 100%;
+      position: absolute;
+      top: 50%;
+      transform: translate(0, -50%);
+      padding: 15px 0;
+      .slide-item {
+        box-shadow: 0 0 60px #fff;
+        height: calc(100% - 60px);
+        // height: 100%;
+        margin: 30px 0;
+        // transform: scale(0.8);
+        transition-duration: 0.2s;
+        position: relative;
+        // box-shadow: 0px 4px 6px 0px rgba(0,0,0,0.4);
+        img {
+          width: 100%;
+          height: 100%;
+          object-fit: cover;
+        }
+        .swiper-slide {
+          background: #d9d9d9;
+          box-shadow: 0px 4px 6px 0px rgba(0, 0, 0, 0.4);
+          border-radius: 0px 0px 0px 0px;
+        }
+      }
+      .swiper-slide-prev {
+        transform: scale(0.8);
+        left: 50%;
+      }
+      .swiper-slide-next {
+        transform: scale(0.8);
+        left: -50%;
+      }
+    }
+  }
+}
+</style>
+<style lang="less">
+.detail-content {
+  .swiper-slide-active {
+    transform: scale(1) !important;
+    z-index: 1;
+    img {
+      height: 100%;
+      width: 100%;
+      object-fit: cover;
+    }
+  }
+}
+</style>

+ 183 - 0
src/views/Home/feedbackModal.vue

@@ -0,0 +1,183 @@
+<template>
+  <div class="feedbackModal">
+    <div class="feedbackModal-content">
+      <div class="title">留言反馈</div>
+      <textarea v-model="form.text" class="textarea inputNoborder" name="" id="" cols="30" rows="10"  maxlength="500" placeholder="请填入内容,5-500字"></textarea>
+      <div class="input">
+        <div class="info">
+          <input v-model="form.name" class="inputNoborder" style="margin-right:8px" type="text" maxlength="6" placeholder="请填入称呼(必填,1~6个字)">
+          <input v-model="form.mobile" class="inputNoborder" style="margin-right:8px"  type="text" maxlength="11" placeholder="请填入联系方式(必填,1~11个字)">
+        </div>
+        <div class="verifyCode">
+          <input class="inputNoborder" v-model="form.code" type="text" placeholder="请填入图形验证码">
+          <div class="verifyCodeImg">
+            <img style="width:91px" src="https://www.baidu.com/img/bd_logo1.png?where=super" alt="">
+            <span class="refreshdiv">
+              <img class="refresh" src="@/assets/images/home/refresh.png" alt="">
+            </span>
+          </div>
+        </div>
+      </div>
+      <div class="butList">
+        <div class="but close" @click="$store.commit('setModalState',false)">取消</div>
+        <div class="but confirm" @click="submit">确定</div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+// import Verify from 'vue2-verify'
+export default {
+  name: 'feedbackModal',
+  data () {
+    return {
+      form:{
+        text: '',
+        code:'',
+        name:'',
+        mobile:'',
+      }
+
+    }
+  },
+  components: {
+    // Verify
+  },
+  methods: {
+    submit(){
+      if(this.form.text === ''){
+        return this.$message('请填写留言反馈信息内容')
+      }
+      if(this.form.name === '' || this.form.mobile === ''){
+        return this.$message('请填写留言反馈联系人信息')
+      }
+      // const regMobile = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
+      // if(this.form.mobile && regMobile.test(this.form.mobile)){{
+      //   return this.$message('联系')
+      // }
+    }
+  },
+}
+</script>
+<style lang="less" scoped>
+.feedbackModal{
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  background: rgba(10, 59, 64, 0.9);
+  z-index: 10;
+  &-content{
+      width: 711.6px;
+      height: 540px;
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      background-color: #fff;
+      padding: 18px 15px 30px 15px;
+      border-radius: 7px;
+      text-align: center;
+      .title{
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-weight: 500;
+        font-size: 20px;
+        color: #535353;
+        line-height: 23px;
+        margin-bottom: 20px;
+      }
+      .textarea{
+        width: 100%;
+        padding: 22px 30px;
+        border-radius: 7px;
+        background-color: #E5E5E5;
+        height: 308px;
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-weight: 500;
+        font-size: 18px;
+        color: #535353;
+        line-height: 21px;
+        text-align: left;
+        font-style: normal;
+      }
+      .inputNoborder{
+          border: none;
+          resize: none;
+          cursor: pointer;
+          &:focus-visible{
+            outline: none;
+            border: none;
+            resize: none;
+          }
+      }
+      .input{
+        margin: 25px 0 30px 0;
+        display: flex;
+        justify-content: space-between;
+        input{
+            border-radius: 7px;
+            font-family: Source Han Sans SC, Source Han Sans SC;
+            font-weight: 500;
+            font-size: 12px;
+            color: #535353;
+            line-height: 14px;
+            background-color: #CBCBCB;
+            padding: 12px 5px;
+        }
+        .verifyCode{
+          display: flex;
+          justify-content: center;
+          align-items: center;
+        }
+        .verifyCodeImg{
+          width: 133px;
+          background: rgba(203,203,203,0.5);
+          border-radius: 7px;
+          display: flex;
+          justify-content: space-around;
+          align-items: center;
+          .refreshdiv{
+            height: 26.7px;
+            width: 26.7px;
+            border-radius: 50%;
+            background-color: #fff;
+            cursor: pointer;
+            img{
+              height: 18.63px;
+              width: 18.63px;
+              line-height: 26.7px;
+              margin-top: 4.5px;
+            }
+          }
+        }
+      }
+      .butList{
+        text-align: center;
+        .but{
+          width: 194px;
+          height: 34px;
+          line-height: 34px;
+          border-radius: 3px 3px 3px 3px;
+          display: inline-block;
+          font-family: Source Han Sans SC, Source Han Sans SC;
+          font-weight: 500;
+          font-size: 16px;
+          cursor: pointer;
+        }
+        .close{
+          background: rgba(255,255,255,0.7);
+          border-radius: 3px 3px 3px 3px;
+          border: 1px solid;
+          border-image: linear-gradient(180deg, rgba(0, 0, 0, 0.06), rgba(0, 0, 0, 0.16)) 1 1;
+        }
+        .confirm{
+          background: #2CD196;
+          border-radius: 4px 4px 4px 4px;
+          color: #FFFFFF;
+          margin-left: 10px;
+        }
+      }
+  }
+}
+</style>

+ 165 - 84
src/views/Home/homePage.vue

@@ -1,6 +1,7 @@
 <template>
   <div class='home' :class="{ 'homeOther': state !== 'home' }">
-    <div class="left-box" :style="{ 'width': state == 'product' ? '100%' : '' }">
+    <!-- :style="{ 'width': state == 'product' ? '100%' : '' }" -->
+    <div class="left-box">
       <img class="gridding" src="@/assets/images/home/gridding.png" alt="">
       <div v-show="state == 'home'" class="home-page">
         <div class="title">
@@ -11,6 +12,9 @@
           开始探索
           <img src="@/assets/images/home/nextIcon.png" alt="">
         </div>
+        <div class="village">
+          <img class="gridding" src="@/assets/images/init/Vector.png" alt="">
+        </div>
       </div>
       <!-- 左侧列表 -->
       <div class="tabbar-list" v-show="state != 'home'">
@@ -75,7 +79,7 @@
       <!-- 列表右侧 -->
       <div class="babar-content">
         <!-- 简介 -->
-        <div class="info-box" v-show="state == 'info'">{{ dataAll.info.content.info }}</div>
+        <div class="info-box" v-show="state == 'info'" v-html="dataAll.info.content.info"></div>
         <!-- 全景 -->
         <div class="full-box" v-show="state == 'full'">
           <div class="v-list">
@@ -88,53 +92,36 @@
           <div class="v-full-box">
             <div class="full-item" v-for="(item) in currentV.scenes" :key="item.name"
               :class="{ 'hover': isShade && currentHoverName === item.name }"
+              @click="openHtml(item.link)"
               @mousemove="() => { isShade = true, currentHoverName = item.name }"
               @mouseleave="() => { isShade = false, currentHoverName = '' }">
-              <img :src="`${baseUrl}/images/full/${currentV.id}/${item.coverImg}`" alt="">
+              <img style="min-height:15.5vh" :src="item.coverImg"  alt="">
               <div class="shade-box" v-show="isShade && currentHoverName === item.name">{{ item.name }}</div>
             </div>
           </div>
         </div>
         <!-- 展馆 -->
         <div class="scene-box" v-show="state == 'scene'">
-          <div class="box-item" v-for="(item) in dataAll.scenes.content" :key="item.id">
-            <img :src="`${baseUrl}/images/scene/${item.coverImg}`" alt="">
+          <div class="box-item" v-for="(item) in dataAll.scenes.content" :key="item.id" @click="openHtml(item.link)">
+            <img :src="item.coverImg" @error="e => { e.target.src = item.coverImg }" alt="">
+            <!-- <img :src="`${baseUrl}/images/scene/${item.coverImg}`" @error="e => { e.target.src = item.coverImg }" alt=""> -->
             <div>{{ item.name }}</div>
           </div>
         </div>
-        <!-- 馆藏 -->
+        <!-- 新版简介 -->
         <div class="product-box" v-show="state == 'product'">
           <div class="select-box">
-            <!-- 维度筛选 -->
-            <div class="dimension-box ">
-              <div class="box-item" @click="changeDimension('3d')">
-                三维文物
-                <div class="bottomAc" v-show="curDimension == '3d'"></div>
-              </div>
-              <div class="box-item" @click="changeDimension('2d')">
-                二维文物
-                <div class="bottomAc" v-show="curDimension == '2d'"></div>
-              </div>
-              <div class="line"></div>
-
-            </div>
             <!-- 类别选择 -->
             <div class="category-box">
-              <div class="box-item" v-for="(item) in (curDimension == '2d' ? categoryType2D : categoryType3D)"
-                :key="item" @click="() => { curCategoryType = item, getResultProduces() }">
-                {{ item }}
-                <div class="bottomAc" v-show="curCategoryType == item"></div>
+              <div class="box-item" v-for="(item) in dataAll.product.list"
+                :key="item.id" @click="changeType(item)">
+                {{ item.name }}
+                <div class="bottomAc" v-show="productActive == item.id"></div>
               </div>
             </div>
-            <!-- 搜索框 -->
-            <div class="search-box">
-
-            </div>
           </div>
-          <div class="result-box">
-            <div class="result-item" v-for="(item) in resultProduces" :key="item.id">
-              <img :src="`${baseUrl}/images/product/${item.id}/${item.coverImg}`" alt="">
-              <div class="title">{{ item.name }}</div>
+          <div class="result-box" id="result-box-div">
+            <div class="result-html" v-html="productHtml">
             </div>
           </div>
         </div>
@@ -142,29 +129,37 @@
     </div>
     <!-- 村庄标签 -->
     <div class="v-labels" v-show="state == 'info' || state == 'full'" v-for="(item) in dataAll.vLabels" :key="item.name"
-      :style="{ top: item.top, right: item.right }">
+      :style="{ top: item.top, right: item.right, }">
       <img src="@/assets/images/home/label.png" alt="">
-      <div>{{ item.name }}</div>
+      <div style="width:100%">{{ item.name }}</div>
     </div>
     <!-- 展馆标签 -->
-    <div class="v-labels" v-show="state == 'scene'" v-for="(item) in dataAll.scenes.content" :key="item.id"
+    <div class="v-labels" v-show="state == 'scene'" v-for="(item) in dataAll.scenes.lable" :key="item.id"
       :style="{ top: item.top, right: item.right }">
-      <img src="@/assets/images/home/label.png" alt="">
-      <div>{{ item.name }}</div>
+      <img src="@/assets/images/home/label1.png" style="width: 189px;" alt="">
+      <div style="line-height: 20px;">{{ item.name }}</div>
+    </div>
+    <!-- 馆藏详情 -->
+    <div class="v-labels" v-show="state == 'product'" v-for="(item) in dataAll.product.lable" :key="item.id"
+      :style="{ top: item.top, right: item.right }">
+      <img src="@/assets/images/home/label1.png"  style="width: 189px;"  alt="">
+      <div style="line-height: 20px;">{{ item.name }}</div>
     </div>
-
   </div>
 </template>
 
 <script>
-
+// import detailPage from "./detailPage.vue";
 export default {
-  components: {},
+  components: {
+    // detailPage
+  },
   data() {
     return {
       // home-首页,info-简介,full-全景,scene-展馆,product-馆藏
-      state: 'info',
+      state: 'home',
       // state == full 
+      search: '',
       currentV: {},
       isShade: false,
       baseUrl: 'http://localhost:8080/staticData',
@@ -173,8 +168,10 @@ export default {
       categoryType2D: [],
       categoryType3D: [],
       curCategoryType: '',
-      resultProduces: []
-
+      resultProduces: [],
+      detailId: null,
+      productActive: 'history',
+      productHtml:''
     };
   },
   computed: {
@@ -184,6 +181,16 @@ export default {
   },
   watch: {},
   methods: {
+    openHtml(href){
+      if(!href) return 
+      window.open(href)
+    },
+    changeType(item) {
+      this.productActive = item.id
+      this.productHtml = item.text
+      let parent = document.getElementById('result-box-div')
+      parent.scrollTop = 0
+    },
     getResultProduces() {
       this.resultProduces = this.dataAll.product.content.filter((item) => {
         if (this.curCategoryType == '全部') {
@@ -199,28 +206,28 @@ export default {
       this.getResultProduces()
     },
     getCategoryType() {
+      this.productHtml = this.dataAll.product.list.find(item => item.id == this.productActive).text
+      // // 区分出2d 和 3d
+      // var product2Ds = this.dataAll.product.content.filter((item) => {
 
-      // 区分出2d 和 3d
-      var product2Ds = this.dataAll.product.content.filter((item) => {
-
-        return item.type === '2d'
-      })
+      //   return item.type === '2d'
+      // })
 
-      var product3Ds = this.dataAll.product.content.filter((item) => {
-        return item.type === '3d'
-      })
+      // var product3Ds = this.dataAll.product.content.filter((item) => {
+      //   return item.type === '3d'
+      // })
 
-      // 获取2d中所有的类别
-      this.categoryType2D = [...new Set(product2Ds.map(item => item.category))];
-      // 获取3d中所有的类别
-      this.categoryType3D = [...new Set(product3Ds.map(item => item.category))];
+      // // 获取2d中所有的类别
+      // this.categoryType2D = [...new Set(product2Ds.map(item => item.category))];
+      // // 获取3d中所有的类别
+      // this.categoryType3D = [...new Set(product3Ds.map(item => item.category))];
 
-      this.categoryType2D.unshift('全部')
-      this.categoryType3D.unshift('全部')
+      // this.categoryType2D.unshift('全部')
+      // this.categoryType3D.unshift('全部')
 
-      console.log(product2Ds, product3Ds)
+      // console.log(product2Ds, product3Ds)
 
-      this.changeDimension('3d')
+      // this.changeDimension('3d')
 
     }
   },
@@ -296,7 +303,15 @@ export default {
       display: flex;
       flex-direction: column;
       justify-content: space-between;
-
+      .village{
+        img{
+          width: 16.5vw;
+          height: 39.5%;
+          position: absolute;
+          right: -28.3vw;
+          top: 23.7%;
+        }
+      }
       .title {
         color: white;
 
@@ -481,6 +496,7 @@ export default {
           overflow: auto;
           display: grid;
           grid-template-columns: repeat(2, 1fr);
+          overflow-x: hidden;
           // grid-template-rows: repeat(2, minmax(auto, auto));
           gap: 20px;
 
@@ -490,12 +506,12 @@ export default {
             align-items: center;
             cursor: pointer;
             position: relative;
-            width: 95%;
-            height: 95%;
+            width: 100%;
+            height: 100%;
 
             img {
               width: 100%;
-              height: 100%;
+              height: 16.8vh;
               object-fit: fill;
             }
 
@@ -527,16 +543,18 @@ export default {
 
       .scene-box {
         width: 85%;
-        height: 60%;
+        height: 70%;
         overflow: auto;
 
         .box-item {
           width: 98%;
-          margin-top: 25px;
+          margin-bottom: 4vh;
           cursor: pointer;
 
           img {
             width: 100%;
+            height: 282px;
+            object-fit: cover;
           }
 
           div {
@@ -549,10 +567,12 @@ export default {
 
       .product-box {
         width: 90%;
-        height: 70%;
+        height: 60%;
         display: flex;
         flex-direction: column;
         justify-content: space-between;
+        position: relative;
+        // right: -2.5%;
 
         .select-box {
           width: 90%;
@@ -587,7 +607,7 @@ export default {
               width: 2px;
               height: 100%;
               margin-left: 20px;
-              margin-right: 20px;
+              margin-right: 10px;
               background: linear-gradient(to bottom, #ffffff98 0%, #ffffff00 100%);
             }
 
@@ -600,7 +620,8 @@ export default {
             overflow: auto;
 
             .box-item {
-              width: auto;
+              width: 60px;
+              text-align: center;
               height: 100%;
               display: flex;
               flex-direction: column;
@@ -617,31 +638,80 @@ export default {
               }
             }
           }
+          .search-box{
+            // border:solid 1px #ddd;
+            background-color: #fff;
+            border-radius: 25px;
+            height: 28px;
+            margin-bottom: 11px;
+            position: relative;
+            width: 16.8vw;
+            input{
+              border: none;
+              border-radius: 25px;
+              padding: 3px 55px 5px 33px;
+              height: 28px;
+              font-family: Source Han Sans SC, Source Han Sans SC;
+              font-weight: 300;
+              font-size: 14px;
+              color: #9B9B9B;
+              &:focus-visible{
+                border: none;
+                outline:none;
+              }
+              &:focus{
+                border: none;
+              }
+            }
+            .arrow{
+              position: absolute;
+              left: 10px;
+              width: 12.8px;
+              top: 7px;
+            }
+            .but{
+              width: 31.5px;
+              height: 100%;
+              position: absolute;
+              right: 0;
+              border-radius: 0 25px 25px 0;
+              top: 0;
+              background-color: rgba(0, 0, 0, 0.05);
+              text-align: center;
+              line-height: 28px;
+              img{
+                width: 12.8px;
+                transform: rotate(90deg)
+              }
+            }
+
+          }
 
 
 
         }
 
         .result-box {
-          width: 100%;
-
-          .result-item {
-            width: 20vw;
-            height: 100%;
-            margin-right: 20px;
-            box-sizing: initial;
-
-            img {
-              width: 100%;
-              height: 20vh;
-              object-fit: cover;
-            }
-
-            .title {
-              color: white;
+          display: flex;
+          // overflow-x: scroll;
+          // overflow-y: hidden;
+          justify-items: center;
+          height: calc(100% - 55px);
+          overflow-y: scroll;
+          // align-items: center;
+          font-family: Source Han Sans SC, Source Han Sans SC;
+          font-weight: 500;
+          font-size: 20px;
+          color: #FFFFFF;
+          line-height: 36px;
+          letter-spacing: 1px;
+          text-align: left;
+          font-style: normal;
+          .result-html{
+            img{
+              margin: 15px 0;
             }
           }
-
         }
       }
     }
@@ -660,6 +730,7 @@ export default {
     div {
       position: absolute;
       top: 13%;
+      width: calc(100% - 60px);
       left: 50%;
       transform: translateX(-50%);
       text-shadow: 0px 4px 6px rgba(0, 0, 0, 0.6);
@@ -667,8 +738,18 @@ export default {
       font-weight: bold;
       letter-spacing: 2px;
       color: white;
+      text-align: center;
     }
   }
+  .detail{
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 0;
+  }
 }
 
 .homeOther {

+ 158 - 0
src/views/Home/shareModal.vue

@@ -0,0 +1,158 @@
+<template>
+  <div class="shareModal">
+    <div class="shareModal-content" ref="shareImg">
+      <div class="shareImg">
+        <img
+          style="min-height: 15.5vh"
+          crossOrigin="anonymous"
+          :src="`https://4dscene.4dage.com/new4dkk/v2/images/_/common/data/images/bbhhbw.c24ca41.png`"
+          alt=""
+        />
+      </div>
+      <div class="shareinfo">
+        <img
+          class="watermark"
+          src="@/assets/images/home/watermark.png"
+          alt=""
+        />
+        <div class="text">
+          <h2>花垣县双龙镇十八洞村</h2>
+          <p>山峰叠嶂,云雾缭绕 溪流潺潺,古树参天</p>
+        </div>
+        <div class="shareCode">
+          <span>扫码下载照片</span>
+          <div style="margin-top: 7px">
+            <vue-qr :text="baseUrl" margin="0" :size="68"></vue-qr>
+          </div>
+        </div>
+      </div>
+      <div class="butList">
+        <img class="edit" src="@/assets/images/home/edit.png" alt="" />
+        <img class="down" @click="downImg" src="@/assets/images/home/down.png" alt="" />
+        <img
+          class="clear"
+          src="@/assets/images/home/clear.png"
+          @click="$store.commit('setModalState', false)"
+          alt=""
+        />
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import vueQr from "vue-qr";
+import html2canvas from "html2canvas"
+export default {
+  name: "feedbackModal",
+  data() {
+    return {
+      baseUrl: "http://localhost:8080/staticData",
+    };
+  },
+  components: {
+    vueQr,
+  },
+  methods: {
+    downImg() {
+     var opts = {
+           logging: false, //日志开关,便于查看html2canvas的内部执行流程
+           useCORS: true // 【重要】开启跨域配置
+       };
+      html2canvas(this.$refs.shareImg, opts).then(canvas => {
+        // 转成图片,生成图片地址
+        let imgUrl = canvas.toDataURL("image/png");
+        // 创建隐藏的可下载链接
+        var eleLink = document.createElement("a");
+        eleLink.href = imgUrl; // 转换后的图片地址
+        eleLink.download = "分享图片.png"; // 下载的文件名
+        // 触发点击
+        document.body.appendChild(eleLink);
+        eleLink.click();
+        // 然后移除
+        document.body.removeChild(eleLink);
+      });
+    }
+  },
+};
+</script>
+<style lang="less" scoped>
+.shareModal {
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  background: rgba(10, 59, 64, 0.9);
+  z-index: 10;
+  &-content {
+    padding: 35px 35px 25px 35px;
+    width: 711.6px;
+    min-height: 540px;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    background-image: url(@/assets/images/home/sharediv.png);
+    background-size: 100%;
+    background-repeat: no-repeat;
+    // background: url(@/assets/images/home/sharediv.png) 100% 100% no-repeat;
+    .shareImg {
+      margin-bottom: 18px;
+      img {
+        height: 357px;
+        width: 100%;
+        object-fit: cover;
+      }
+    }
+    .shareinfo {
+      position: relative;
+      display: flex;
+      justify-content: space-between;
+      text-align: center;
+      .shareCode {
+        padding: 5px 7px;
+        background: rgba(255, 255, 255, 0.8);
+        box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.2);
+        border-radius: 10px 10px 10px 10px;
+        font-weight: bold;
+        font-size: 10px;
+        color: rgba(143, 143, 143, 0.8);
+        line-height: 12px;
+        span {
+          margin-bottom: 5px;
+        }
+      }
+      .watermark {
+        position: absolute;
+        right: 10px;
+        top: -130px;
+      }
+      .text {
+        text-align: left;
+        font-weight: 500;
+        font-size: 16px;
+        color: rgba(0, 0, 0, 0.6);
+        line-height: 19px;
+        letter-spacing: 3px;
+        h2 {
+          font-weight: 500;
+          font-size: 20px;
+          color: #535353;
+          line-height: 23px;
+          margin-bottom: 11px;
+        }
+      }
+    }
+  }
+  .butList {
+    display: flex;
+    justify-content: space-between;
+    width: 184px;
+    margin: 31px auto;
+    height: 30px;
+    img {
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 107 - 0
src/views/initialize/initializePage.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="init-home">
+    <div class="left-box">
+      <div class="left-bg"></div>
+      <div class="left-text">
+        <div class="left-title">
+          <p>湖南省湘西土家族苗族自治州</p>
+          <img class="title-img" src="@/assets/images/home/title-white.png" alt="">
+        </div>
+        <div class="but" @click="Next">
+          开始探索
+          <img class="but-img" src="@/assets/images/home/nextIcon.png" alt="">
+        </div>
+      </div>
+      <!-- <img class="gridding" src="@/assets/images/home/gridding.png" alt=""> -->
+    </div>
+    <div class="village">
+      <img class="gridding" src="@/assets/images/init/Vector.png" alt="">
+    </div>
+  </div>
+</template>
+
+
+<script>
+export default {
+  components: {},
+  data() {
+    return {}
+  },
+  methods: {
+    Next() {
+      this.$store.commit('setPage', 1)
+    }
+  },
+}
+</script>
+
+<style lang="less" scoped>
+.init-home{
+  width: 100%;
+  height: 100%;
+  background: url(@/assets/images/home/bg1.png);
+  background-size: 100% 100%;
+  position: relative;
+  display: flex;
+  .left-box {
+    width: 60%;
+    height: 100%;
+    overflow: hidden;
+    // background: #2cd1977e;
+    // backdrop-filter: blur(5px);
+    position: relative;
+    .left-bg{
+      width: 100%;
+      height: 100%;
+      background: url(@/assets/images/home/greenBg.png);
+      // background-size: 100% 100%;
+      backdrop-filter: blur(5px);
+      opacity: 0.7;
+      background-repeat: no-repeat;
+
+    }
+    .left-text{
+      position: absolute;
+      left: 0;
+      right: 0;
+      top: 0;
+      bottom: 0;
+      width: 100%;
+      padding: 26.36% 0 19.2% 191px;
+      p{
+        margin-bottom: 12px;
+        font-weight: 500;
+        font-size: 34px;
+        color: #FFFFFF;
+        line-height: 40px;
+        color: #fff;
+      }
+      .title-img{
+        height: 97px;
+      }
+      .but{
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-weight: 400;
+        font-size: 48px;
+        color: #FFFFFF;
+        margin-top: 33.5vh;
+        cursor: pointer;
+        display: flex;
+        position: absolute;
+        bottom: 19.2vh;
+        img{
+          margin-left: 19px;
+        }
+      }
+    }
+  }
+  .village{
+    img{
+      width: 315px;
+      position: absolute;
+      right: 14.43%;
+      top: 23.7%;
+    }
+  }
+}
+</style>

Разлика између датотеке није приказан због своје велике величине
+ 6513 - 0
yarn.lock