|
@@ -0,0 +1,292 @@
|
|
|
|
+<template>
|
|
|
|
+ <div>
|
|
|
|
+ <div style="margin-bottom: 10px">
|
|
|
|
+ <el-button type="primary" @click="setBigger">放大</el-button>
|
|
|
|
+ <el-button type="primary" @click="setSmaller">缩小</el-button>
|
|
|
|
+ </div>
|
|
|
|
+ <div id="mapContainer" :style="{width:props.width,height:props.height}" @touchstart="moveOn" @touchmove="dragMove"
|
|
|
|
+ @mousedown="moveOn"
|
|
|
|
+ @mouseup="moveOff" @mousemove="dragMove" @mouseleave="moveOff" @dblclick="dbClick">
|
|
|
|
+ <div id="labelMap" :style="mapStyle">
|
|
|
|
+ <div :key="index" class="labelItem "
|
|
|
|
+ :style="{left: item.x+'px',top:item.y+'px',backgroundColor:statusList[item.status].backGround,width:item.size+'px',height:item.size+'px',fontSize:item.size/3+'px'}"
|
|
|
|
+ v-for="(item,index) in itemList">
|
|
|
|
+ <span :style="{color:statusList[item.status].color}">{{ statusList[item.status].label }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ <el-dialog :title="dialogTitle" v-model="showDialog" width="600px">
|
|
|
|
+ <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
|
|
|
|
+ <el-row>
|
|
|
|
+ <el-col :span="12">
|
|
|
|
+ <el-form-item label="车位编号" prop="positionID">
|
|
|
|
+ <el-input v-model="formData.positionID">
|
|
|
|
+ </el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="12">
|
|
|
|
+ <el-form-item label="销售状态" prop="status">
|
|
|
|
+ <el-select v-model="formData.status">
|
|
|
|
+ <el-option v-for="(item,index) in statusList" :value="index" :label="item.label"></el-option>
|
|
|
|
+ </el-select>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="12">
|
|
|
|
+ <el-form-item label="售价" prop="price">
|
|
|
|
+ <el-input-number style="width: 100%" v-model="formData.price" :min="0" controls-position="right">
|
|
|
|
+ </el-input-number>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="12">
|
|
|
|
+ <el-form-item label="标记尺寸" prop="size">
|
|
|
|
+ <el-radio-group v-model="formData.size">
|
|
|
|
+ <el-radio :label="60">大</el-radio>
|
|
|
|
+ <el-radio :label="30">中</el-radio>
|
|
|
|
+ <el-radio :label="21">小</el-radio>
|
|
|
|
+ </el-radio-group>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="24">
|
|
|
|
+ <el-form-item label="说明" prop="remark">
|
|
|
|
+ <el-input type="textarea" v-model="formData.remark">
|
|
|
|
+ </el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </el-form>
|
|
|
|
+ <template #footer>
|
|
|
|
+ <el-button type="info" @click="showDialog=false">取消</el-button>
|
|
|
|
+ <el-button type="primary" @click="submit()">确定</el-button>
|
|
|
|
+ </template>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+</template>
|
|
|
|
+<script setup>
|
|
|
|
+import {computed, onMounted, reactive, ref, watch} from "vue";
|
|
|
|
+
|
|
|
|
+const emit = defineEmits(['update:value', 'change'])
|
|
|
|
+
|
|
|
|
+const props = defineProps({
|
|
|
|
+ imgUrl: {//地图地址,后期可以不用
|
|
|
|
+ type: String,
|
|
|
|
+ default: ''
|
|
|
|
+ },
|
|
|
|
+ imgID: {//地图id,后期通过地图Id动态获取地图地址
|
|
|
|
+ type: String,
|
|
|
|
+ default: ''
|
|
|
|
+ },
|
|
|
|
+ width: {//外边框尺寸
|
|
|
|
+ type: String,
|
|
|
|
+ default: '100%'
|
|
|
|
+ },
|
|
|
|
+ height: {//外边框尺寸
|
|
|
|
+ type: String,
|
|
|
|
+ default: '400px'
|
|
|
|
+ },
|
|
|
|
+ value: {//标记点列表
|
|
|
|
+ type: Array,
|
|
|
|
+ default: []
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+let itemList = ref([])
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+//图片高度
|
|
|
|
+let height = ref(0)
|
|
|
|
+let width = ref(0)
|
|
|
|
+
|
|
|
|
+//图层样式
|
|
|
|
+let mapStyle = computed(() => {
|
|
|
|
+ return {
|
|
|
|
+ backgroundImage: `url(${props.imgUrl})`,
|
|
|
|
+ width: width.value + 'px',
|
|
|
|
+ height: height.value + 'px',
|
|
|
|
+ left: dragOption.x1 + 'px',
|
|
|
|
+ top: dragOption.y1 + 'px'
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+//图层实例
|
|
|
|
+let labelMap
|
|
|
|
+
|
|
|
|
+onMounted(() => {
|
|
|
|
+ itemList.value = props.value
|
|
|
|
+ labelMap = document.getElementById('labelMap')
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ setImgSize()
|
|
|
|
+ }, 100)
|
|
|
|
+
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+watch(props.value, (n, o) => {
|
|
|
|
+ itemList.value = n
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+//根据容器宽度和原始图片长宽比例设置图层高度
|
|
|
|
+function setImgSize() {
|
|
|
|
+ const m = document.getElementById('mapContainer')
|
|
|
|
+ let img = new Image()
|
|
|
|
+ img.src = props.imgUrl
|
|
|
|
+ width.value = m.clientWidth
|
|
|
|
+ height.value = m.clientWidth * (img.height / img.width)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+//拖拽参数
|
|
|
|
+let dragOption = reactive({
|
|
|
|
+ x1: 0,
|
|
|
|
+ y1: 0,
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 0,
|
|
|
|
+ status: false
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+//启动拖拽
|
|
|
|
+function moveOn(event) {
|
|
|
|
+ dragOption.status = true
|
|
|
|
+ dragOption.x = event.clientX
|
|
|
|
+ dragOption.y = event.clientY
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//关闭拖拽
|
|
|
|
+function moveOff() {
|
|
|
|
+ dragOption.status = false
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//拖拽
|
|
|
|
+function dragMove(event) {
|
|
|
|
+ if (dragOption.status) {
|
|
|
|
+ dragOption.x1 += event.clientX - dragOption.x
|
|
|
|
+ dragOption.y1 += event.clientY - dragOption.y
|
|
|
|
+
|
|
|
|
+ dragOption.x = event.clientX
|
|
|
|
+ dragOption.y = event.clientY
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+let showDialog = ref(false)
|
|
|
|
+let dialogTitle = ref('')
|
|
|
|
+let formRef = ref()
|
|
|
|
+let formData = ref({
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 0,
|
|
|
|
+ size: 30,
|
|
|
|
+ status: 0,
|
|
|
|
+ price: 0,
|
|
|
|
+ positionID: '',
|
|
|
|
+ remark: '',
|
|
|
|
+ imgID: props.imgID,
|
|
|
|
+ pWidth: 0
|
|
|
|
+})
|
|
|
|
+let formRules = reactive({
|
|
|
|
+ status: [{required: true, message: '不能为空', trigger: 'blur'}],
|
|
|
|
+ price: [{required: true, message: '不能为空', trigger: 'blur'}],
|
|
|
|
+ positionID: [{required: true, message: '不能为空', trigger: 'blur'}],
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+let statusList = [
|
|
|
|
+ {label: '可售', backGround: '#0bc933', color: '#000000'},
|
|
|
|
+ {label: '已售', backGround: '#fd0002', color: '#ffffff'},
|
|
|
|
+ {label: '待租', backGround: '#fde801', color: '#000000'},
|
|
|
|
+ {label: '已租', backGround: '#006efd', color: '#ffffff'},
|
|
|
|
+]
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+//双击设置标记
|
|
|
|
+function dbClick(event, item) {
|
|
|
|
+ showDialog.value = true
|
|
|
|
+ //点击地图
|
|
|
|
+ if (event.target.id == 'labelMap') {
|
|
|
|
+ formRef.value?.resetFields()
|
|
|
|
+ formData.value.x = event.layerX - 15
|
|
|
|
+ formData.value.y = event.layerY - 15
|
|
|
|
+ formData.value.pWidth = width.value
|
|
|
|
+ dialogTitle.value = '添加'
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ //点击标记
|
|
|
|
+ else {
|
|
|
|
+
|
|
|
|
+ dialogTitle.value = '编辑'
|
|
|
|
+ }
|
|
|
|
+ //清除校验结果
|
|
|
|
+ formRef.value?.clearValidate()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//提交表单
|
|
|
|
+function submit() {
|
|
|
|
+
|
|
|
|
+ if (dialogTitle.value == '添加') {
|
|
|
|
+ let n = Object.assign({}, formData.value)
|
|
|
|
+ itemList.value.push(n)
|
|
|
|
+ showDialog.value = false
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ emit('update:value', itemList)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+let size = 1
|
|
|
|
+
|
|
|
|
+//缩小
|
|
|
|
+function setSmaller() {
|
|
|
|
+ //边界条件
|
|
|
|
+ if (size < 0.3) return
|
|
|
|
+ size -= 0.1
|
|
|
|
+ labelMap.style.transform = `scale(${size})`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//放大
|
|
|
|
+function setBigger() {
|
|
|
|
+ //边界条件
|
|
|
|
+ if (size > 2) return
|
|
|
|
+ size += 0.1
|
|
|
|
+ labelMap.style.transform = `scale(${size})`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+</script>
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+
|
|
|
|
+#mapContainer {
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ border: #888888 1px solid;
|
|
|
|
+ position: relative
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#labelMap {
|
|
|
|
+ position: absolute;
|
|
|
|
+ background-size: 100% 100%;
|
|
|
|
+ transition: transform 0.5s ease;
|
|
|
|
+ left: 0;
|
|
|
|
+ top: 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+:deep(.labelItem) {
|
|
|
|
+ border-radius: 50%;
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ align-items: center;
|
|
|
|
+ color: #ffffff;
|
|
|
|
+ font-size: 13px;
|
|
|
|
+ user-select: none;
|
|
|
|
+ position: absolute;
|
|
|
|
+
|
|
|
|
+ &:hover {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+</style>
|