地图书签功能

主要逻辑:保存地图中心点、缩放级别、当前的地图图片与图层。

<template>
    <!-- 书签管理 -->
    <div class="bookmark">
        <ag-panel-title title="书签" :show-close="true" @close="handleClose" />
        <div v-if="pageType==='list'" class="bookmark-list">
            <div style="margin: 10px;">
                <el-input
                    placeholder="输入关键字搜索"
                    prefix-icon="el-icon-search"
                    v-model="search"
                    clearable
                    @input="searchBookmark"
                />
            </div>
            <ul>
                <li v-for="(item,index) in bookmarkList" :key="index" @click="handleClick(item)">
                    <div class="left">
                        <i class="el-icon-menu" style="margin-right: 6px;" />
                        <ag-image
                            :src="item.fileUrl" 
                        />
                        <span :class="{'active':item.id===currentRow.id}" style="margin-left: 6px;">{{ item.markName }}</span>
                    </div>
                    <div class="el-icon-edit" @click="openAddForm('edit',item)" style="cursor: pointer;" />
                </li>
            </ul>
            <div style="text-align: center;">
                <el-button type="primary" size="small" @click="openAddForm('add',{})">添加书签</el-button>
            </div>
        </div>
        <div v-if="pageType==='add'||pageType==='edit'">
            <div class="sub-title">
                <div @click="goBack" title="返回" class="el-icon-arrow-left" style="margin: 10px 0 0 8px; cursor: pointer;" />
                <ag-panel-title :title="pageType==='add'?'添加书签':'编辑'" />
            </div>
            <el-form style="padding: 10px;">
                <el-form-item label="标题">
                    <el-input v-model="form.markName" />
                </el-form-item>
                <el-form-item label="图片" v-if="pageType==='edit'">
                    <ag-image
                        :src="form.fileUrl" 
                        :preview-src-list="[{attPath:form.fileUrl}]"
                    />
                </el-form-item>
            </el-form>
            <div style="text-align: center;">
                <el-button type="danger" size="small" @click="deleteBookMark" v-if="pageType==='edit'">删 除</el-button>
                <el-button size="small" @click="goBack">取 消</el-button>
                <el-button type="primary" size="small" :loading="loading" @click="addBookMark" v-if="pageType==='add'">添 加</el-button>
                <el-button type="primary" size="small" @click="updateBookMark" v-if="pageType==='edit'">保 存</el-button>
            </div>
        </div>
    </div>
</template>

<script>
import { queryByPage, addBookMark, updateBookMark, deleteBookMark } from '@/api/fisheryMap/bookmark'
import html2canvas from 'html2canvas'
import { mapState } from 'vuex'
export default {
    props: {
        mapAndView: {
            type: Object,
            default: () => {}
        }
    },
    data() {
        return {
            search: '',
            loading: false,
            form: {
                markName: '',
                remark: ''
            },
            list: [],
            bookmarkList: [],
            pageType: 'list',
            currentRow: {},
            zoom: -1,
            stationaryListener: null
        }
    },
    computed: {
        ...mapState({
            checkedLayerIds: state => state.awater.checkedLayerIds,
            userInfo: state => state.user.userInfo
        })
    },
    watch: {
        
    },
    beforeDestroy() {
        this.stationaryListener.remove()
    },
    mounted() {
        this.getList()
        this.zoom = this.mapAndView.zoom
        this.stationaryListener = this.mapAndView.watch('stationary', event => {
            if (event) {
                let x = this.mapAndView.center.x.toString()
                let y = this.mapAndView.center.y.toString()
                if (x !== this.currentRow.coox || y !== this.currentRow.cooy) {
                    this.currentRow = {}
                }
            }
        })
    },
    methods: {
        handleClose() {
            this.$emit('close')
        },
        // 获取书签列表
        async getList() {
            const { content } = await queryByPage({
                pageNum: 1,
                pageSize: 9999,
                userId: this.userInfo.userId
            })
            this.list = content.list
            this.bookmarkList = JSON.parse(JSON.stringify(content.list)) 
        },
        // 书签列表行点击
        async handleClick(row) {
            this.currentRow = row
            this.$emit('row-click', row)
            if (row.remark) {
                await this.$store.commit('awater/setCheckedLayerIds', [])  
                let layers = row.remark.split(',')
                layers.map(item => {
                    this.$bus.$emit('set-layer-switch', { layer: item, visible: true })
                })
            }
        },
        openAddForm(type, row) {
            this.pageType = type
            this.currentRow = row
            if (type === 'edit') {
                this.form = { ...this.currentRow }
            }
        },
        goBack() {
            this.form.markName = ''
            this.pageType = 'list'
        },
        // 搜索书签
        searchBookmark() {
            this.bookmarkList = this.list.filter(item => {
                return item.markName.indexOf(this.search) !== -1
            })
        },
        // 添加书签
        addBookMark() {
            this.loading = true
            html2canvas(this.$parent.$refs['mapPanel'].$el,
                {
                    width: this.$parent.$refs['mapPanel'].$el.clientWidth - 600
                    // height:''
                }
            ).then(canvas => {
                const base64Data = canvas.toDataURL('image/png')
                const blob = this.base64ToBlob(base64Data)
                // 将Blob对象转换为File对象
                let fileName = Math.floor((Math.random() * (10000 - 1000))) + 1000 // 1000到10000的随机整数(四位数)
                fileName += this.form.markName + '.png'
                const file = new File([blob], fileName, { type: 'image/png' })

                let formData = new FormData()
                formData.append('file', file)
                formData.append('markName', this.form.markName)
                formData.append('markLevel', this.mapAndView.zoom)
                formData.append('coox', this.mapAndView.center.x)
                formData.append('cooy', this.mapAndView.center.y)
                formData.append('remark', this.checkedLayerIds.join(','))
                formData.append('userId', this.userInfo.userId)

                addBookMark(formData).then(res => {
                    if (res.success) {
                        this.$message.success('操作成功')
                        this.goBack()
                        this.getList()
                    }
                    this.loading = false
                }).catch(err => {
                    this.loading = false
                }).finally(() => {
                    this.loading = false
                })
            })
        },
        // 编辑书签
        updateBookMark() {
            updateBookMark({
                ...this.form
            }).then(res => {
                if (res.success) {
                    this.$message.success('操作成功')
                    this.goBack()
                    this.getList()
                }
            })
        },
        // 删除书签
        deleteBookMark() {
            deleteBookMark({
                id: this.form.id
            }).then(res => {
                if (res.success) {
                    this.$message.success('删除成功')
                    this.goBack()
                    this.getList()
                }
            })
        },
        // Base64字符串转换为二进制数据
        base64ToBlob(base64Data) {
            let byteString = base64Data
            if (base64Data.split(',')[0].indexOf('base64') >= 0) {
                byteString = atob(base64Data.split(',')[1]) // base64 解码
            } else {
                byteString = unescape(base64Data.split(',')[1])
            }
            // 获取文件类型
            const mimeString = base64Data.split(';')[0].split(':')[1] // mime类型

            // ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区
            // let arrayBuffer = new ArrayBuffer(byteString.length) // 创建缓冲数组
            // let uintArr = new Uint8Array(arrayBuffer) // 创建视图

            const uintArr = new Uint8Array(byteString.length) // 创建视图

            for (let i = 0; i < byteString.length; i += 1) {
                uintArr[i] = byteString.charCodeAt(i)
            }
            // 生成blob
            const blob = new Blob([uintArr], {
                type: mimeString
            })
            // 使用 Blob 创建一个指向类型化数组的URL, URL.createObjectURL是new Blob文件的方法,可以生成一个普通的url,可以直接使用,比如用在img.src上
            return blob
        }
    }
}
</script>

<style lang="scss" scoped>
.bookmark {
    position: absolute;
    top: 0;
    // right: 665px;
    left: 2px;
    width: 300px;
    max-height: 100%;
    padding-bottom: 20px;
    background: #fff;

    .bookmark-list {
        height: calc(100% - 50px);
    }

    ul {
        max-height: calc(100% - 100px);
        padding: 0;
        overflow: auto;

        li {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 10px 10px;
            cursor: pointer;
            border-bottom: 1px solid #eee;

            .active {
                color: #409eff;
            }

            .left {
                display: flex;
                align-items: center;
            }
        }
    }

    .sub-title {
        display: flex;
        align-items: center;
        border-bottom: 1px solid #ccc;
    }
}
</style>

你可能感兴趣的:(vue.js,前端)