Hwf 6 månader sedan
förälder
incheckning
4e78cfc764

+ 1 - 3
src/hooks/AMap/useAMap.ts

@@ -17,7 +17,7 @@ export function useAMap(options) {
         : ['AMap.Scale', 'AMap.RangingTool', 'AMap.MouseTool', 'AMap.PolygonEditor', 'AMap.MarkerCluster', 'AMap.DistrictSearch', 'AMap.MoveAnimation']
     }).then((res) => {
       AMap = res;
-      map = new AMap.Map('aMap', {
+      map = new AMap.Map(options.el ? options.el : 'aMap', {
         WebGLParams: {
           preserveDrawingBuffer: true
         },
@@ -75,8 +75,6 @@ export function useAMap(options) {
     addPoints = points;
     const count = points.length;
     const _renderClusterMarker = function (context) {
-      console.log(context);
-      console.log('21312', context.clusterData);
       // 聚合中点个数
       const clusterCount = context.count;
       const div = document.createElement('div');

+ 1 - 3
src/types/components.d.ts

@@ -43,8 +43,6 @@ declare module 'vue' {
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
-    ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
-    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElSlider: typeof import('element-plus/es')['ElSlider']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
@@ -52,7 +50,6 @@ declare module 'vue' {
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
     ElTree: typeof import('element-plus/es')['ElTree']
     ElUpload: typeof import('element-plus/es')['ElUpload']
-    ElUploadListItem: typeof import('element-plus/es')['ElUploadListItem']
     FileUpload: typeof import('./../components/FileUpload/index.vue')['default']
     FooterSection: typeof import('./../components/FooterSection/index.vue')['default']
     Hamburger: typeof import('./../components/Hamburger/index.vue')['default']
@@ -94,6 +91,7 @@ declare module 'vue' {
     VideoContainer: typeof import('./../components/HKVideo/video-container.vue')['default']
     VideoContainer2: typeof import('./../components/HKVideo/video-container2.vue')['default']
     YMap: typeof import('./../components/Map/YMap.vue')['default']
+    YMapold: typeof import('./../components/Map/YMapold.vue')['default']
     YztMap: typeof import('./../components/Map/YztMap/index.vue')['default']
   }
 }

+ 55 - 4
src/utils/olMap/olMap.ts

@@ -24,7 +24,8 @@ import GeoJSON from 'ol/format/GeoJSON';
 import { fromLonLat } from 'ol/proj';
 import axios from 'axios';
 import { fromExtent } from 'ol/geom/Polygon';
-import { LinearRing } from 'ol/geom';
+import { LinearRing, Polygon } from 'ol/geom';
+import { Tile } from 'ol';
 // import olPlot from 'ol-plot';
 // import { activate } from '../ol-plot/ol-plot'
 
@@ -62,6 +63,7 @@ export class olMap {
   private graphicsType = '';
   private plot;
   private vectorLayer;
+  private maskLayer;
 
   constructor(options) {
     this.options = options;
@@ -241,20 +243,20 @@ export class olMap {
   }
 
   addMarker(points) {
+    this.clearMarker('point');
     points.forEach((point) => {
       // 创建标注点
       const feature = new Feature({
-        geometry: new Point([point.longitude, point.latitude]),
+        geometry: new Point(point.lnglat),
         name: point.name
       });
-
       // 定义样式
       const style = new Style({
         image: new Icon({
           anchor: [0.5, point.size[1]],
           anchorXUnits: 'fraction',
           anchorYUnits: 'pixels',
-          src: point.image
+          src: point.icon
         }),
         text: new Text({
           text: point.name,
@@ -336,4 +338,53 @@ export class olMap {
     layer.set('layerName', layerName);
     return layer;
   }
+  // 分布图遮罩层
+  createMask(data) {
+    this.removeMask();
+    if (!data || data.length === 0) return;
+    data.forEach((item) => {
+      if (!item.points || item.points.length === 0) return;
+      // 遮罩图层的样式
+      const maskStyle = new Style({
+        fill: new Fill({
+          color: item.color // 红色遮罩,50%透明度
+        }),
+        stroke: new Stroke({
+          color: 'rgba(159,159,159,0.7)',
+          width: 1
+        })
+      });
+
+      // 遮罩图层的矢量数据源(初始为空)
+      const maskSource = new VectorSource();
+      // 创建一个多边形特征
+      const polygonFeature = new Feature({
+        geometry: new Polygon(item.points)
+      });
+      const maskLayer = new VectorLayer({
+        source: maskSource,
+        style: maskStyle,
+        properties: {
+          name: 'mask'
+        }
+      });
+      this.map.addLayer(maskLayer);
+      // 将多边形特征添加到遮罩数据源中
+      maskSource.addFeature(polygonFeature);
+    });
+  }
+  removeMask() {
+    //移除图层
+    const layersArray = this.map.getLayers().getArray();
+    const layers = [];
+    layersArray.forEach((layer) => {
+      // 检查图层是否有自定义属性,并且该属性是否匹配你要移除的图层的标识符
+      if (layer.get('name') === 'mask') {
+        layers.push(layer);
+      }
+    });
+    layers.forEach((layer) => {
+      this.map.removeLayer(layer);
+    });
+  }
 }

+ 437 - 0
src/views/globalMap/RightMenu/OnlinePlotting/ShareDialog.vue

@@ -0,0 +1,437 @@
+<template>
+  <Dialog custom-show type="lg" title="分享" @close="handleClose" @confirm="handleConfirm">
+    <div class="content">
+      <div class="left-content">
+        <el-input v-model="queryParams.keyword" class="custom-input" placeholder="组织架构搜索">
+          <template #prefix>
+            <el-icon class="el-input__icon"><search /></el-icon>
+          </template>
+        </el-input>
+        <div class="tree-container">
+          <div class="tree-box">
+            <el-tree :data="treeData" accordion @node-click="handleNodeClick" />
+          </div>
+        </div>
+      </div>
+      <div class="middle-content">
+        <div class="search-box">
+          <el-select
+            v-model="queryParams.value1"
+            class="custom-select select-box"
+            placeholder="全部"
+            popper-class="custom-select-popper"
+            :teleported="false"
+          >
+            <el-option v-for="level in options" :key="level.value" :label="level.name" :value="level.value"></el-option>
+          </el-select>
+          <el-input v-model="queryParams.keyword" class="custom-input" placeholder="组织架构搜索">
+            <template #prefix>
+              <el-icon class="el-input__icon"><search /></el-icon>
+            </template>
+          </el-input>
+        </div>
+        <div class="user-box">
+          <div class="user-table">
+            <div class="tr">
+              <div class="td2">
+                <div :class="getCheckedClass()" @click="handleChecked"></div>
+              </div>
+              <div class="td">姓名</div>
+              <div class="td3">职务</div>
+            </div>
+            <div class="table-content">
+              <div v-for="(item, index) in userList" :key="index" class="tr2">
+                <div class="td2">
+                  <div :class="item.checked ? 'common-checked-active' : 'common-checked'" @click="handleChecked2(item)"></div>
+                </div>
+                <div class="td">{{ item.name }}</div>
+                <div class="td3">
+                  {{ item.duty }}
+                  <div class="phone-icon"></div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="select-box2">
+        <div class="select-header">
+          <div class="left-item">
+            <div>已选择:</div>
+            <div class="text">{{ selectList.length }}</div>
+            <div>人</div>
+          </div>
+          <div class="clear-btn" @click="clearSelect">清空</div>
+        </div>
+        <div class="select-content">
+          <div v-for="(item, index) in selectList" :key="index" class="box-item">
+            <div class="line">
+              <div class="text1">{{ item.name }}</div>
+              <div class="text2">{{ item.duty }}</div>
+            </div>
+            <div class="line" style="margin-top: 20px">
+              <div class="text2">{{ item.dept }}</div>
+            </div>
+            <div class="close-btn" @click="deleteItem(item)"></div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </Dialog>
+</template>
+
+<script lang="ts" setup name="ShareDialog">
+import { Search } from '@element-plus/icons-vue';
+defineProps({
+  modelValue: Boolean
+});
+const emits = defineEmits(['update:modelValue', 'close', 'confirm']);
+let activeIndex = ref(0);
+const options = ref([{ name: '全部', value: '全部' }]);
+const queryParams = ref({
+  value1: '',
+  keyword: ''
+});
+const menu = ref([{ name: '视频会商' }, { name: '无人机' }, { name: '单兵设备' }]);
+const treeData = ref([
+  {
+    label: '茂名市',
+    children: [
+      {
+        label: '茂名市委',
+        children: [
+          {
+            label: '茂名市纪委监委',
+            isLeaf: true
+          },
+          {
+            label: '茂名市委办公室',
+            isLeaf: true
+          },
+          {
+            label: '茂名市委组织部',
+            isLeaf: true
+          }
+        ]
+      },
+      {
+        label: '茂名市人大',
+        children: [
+          {
+            label: '茂名市人大常委会秘书长、副秘书长',
+            isLeaf: true
+          },
+          {
+            label: '茂名市人大常委会办公室',
+            isLeaf: true
+          },
+          {
+            label: '茂名市人大常委会研究室',
+            isLeaf: true
+          }
+        ]
+      }
+    ]
+  }
+]);
+const userList = ref([]);
+const selectList = computed(() => {
+  const data = [];
+  userList.value.forEach((item) => {
+    if (item.checked) {
+      data.push(item);
+    }
+  });
+  return data;
+});
+const getCheckedClass = () => {
+  let res = 'common-checked';
+  const len = userList.value.length;
+  const len2 = selectList.value.length;
+  if (len2 > 0 && len2 === len) {
+    res = 'common-checked-active';
+  } else if (len2 > 0) {
+    res = 'common-checked-half';
+  }
+  return res;
+};
+const handleNodeClick = (item) => {
+  if (item.isLeaf) {
+    const data = [
+      {
+        id: 1,
+        name: '李莉莉',
+        duty: '副主任',
+        dept: '茂名市/茂名市政府/茂名应急管理局'
+      },
+      {
+        id: 2,
+        name: '何里',
+        duty: '副主任',
+        dept: '茂名市/茂名市政府/茂名应急管理局'
+      },
+      {
+        id: 3,
+        name: '张三',
+        duty: '副主任',
+        dept: '茂名市/茂名市政府/茂名应急管理局'
+      },
+      {
+        id: 4,
+        name: '张三',
+        duty: '副主任',
+        dept: '茂名市/茂名市政府/茂名应急管理局'
+      },
+      {
+        id: 5,
+        name: '张三',
+        duty: '副主任',
+        dept: '茂名市/茂名市政府/茂名应急管理局'
+      },
+      {
+        id: 6,
+        name: '张三',
+        duty: '副主任',
+        dept: '茂名市/茂名市政府/茂名应急管理局'
+      }
+    ];
+    data.forEach((item) => {
+      item.checked = false;
+    });
+    userList.value = data;
+  }
+};
+// 全选、全取消
+const handleChecked = () => {
+  const checkedClass = getCheckedClass();
+  let flag = true;
+  if (checkedClass === 'common-checked-active') {
+    flag = false;
+  }
+  userList.value.forEach((item) => {
+    item.checked = flag;
+  });
+};
+// 单个选中、取消选中
+const handleChecked2 = (item) => {
+  item.checked = !item.checked;
+};
+// 清空
+const clearSelect = () => {
+  userList.value.forEach((item) => {
+    if (item.checked) {
+      item.checked = false;
+    }
+  });
+};
+// 清空指定项
+const deleteItem = (item) => {
+  for (let i = 0; i < userList.value.length; i++) {
+    if (item.id === userList.value[i].id) {
+      userList.value[i].checked = false;
+      break;
+    }
+  }
+};
+
+// 弹窗关闭后
+const handleClose = () => {
+  emits('update:modelValue', false);
+  emits('close');
+};
+
+//
+const handleConfirm = () => {
+  emits('confirm', selectList.value);
+  emits('update:modelValue', false);
+};
+</script>
+
+<style lang="scss" scoped>
+.content {
+  display: flex;
+  margin-top: 12px;
+  .left-content {
+    width: 910px;
+    padding-right: 30px;
+    border-right: 1px solid #2187ff;
+  }
+  .middle-content {
+    width: 910px;
+    padding: 0 30px;
+    border-right: 1px solid #2187ff;
+    .search-box {
+      display: flex;
+      .select-box {
+        flex-shrink: 0;
+        width: 176px !important;
+        height: 56px;
+        line-height: 56px;
+        margin: 0 10px;
+        color: #83a3be;
+        font-size: 32px;
+      }
+    }
+    .user-box {
+      margin-left: 10px;
+      width: 100%;
+      height: 100%;
+      .user-table {
+        padding: 15px 0;
+        display: flex;
+        flex-direction: column;
+        font-size: 38px;
+        color: #fbffff;
+        .tr {
+          background-color: #102e76;
+        }
+        .tr,
+        .tr2 {
+          display: flex;
+          padding: 6px 0;
+          .td {
+            flex: 1;
+            display: flex;
+            align-items: center;
+          }
+          .td2 {
+            width: 65px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+          }
+          .td3 {
+            flex: 2;
+            display: flex;
+            align-items: center;
+          }
+        }
+        .table-content {
+          height: 858px;
+          overflow-y: auto;
+        }
+        .tr2 {
+          margin-top: 10px;
+          background-color: #122868;
+        }
+        .phone-icon {
+          width: 62px;
+          height: 63px;
+          background: url('@/assets/images/emergencyCommandMap/communication/phone.png');
+          cursor: pointer;
+        }
+      }
+    }
+  }
+
+  .custom-select-popper {
+    .el-scrollbar {
+      .el-select-dropdown__item {
+        color: #b1cae0;
+        font-size: 32px;
+        height: 56px;
+        line-height: 56px;
+      }
+    }
+  }
+  .input {
+    background: transparent;
+    color: #83a3be;
+    font-size: 32px;
+    outline: none;
+    appearance: none;
+    height: 100%;
+    border: none;
+    &::placeholder {
+      color: #83a3be;
+    }
+  }
+  .tree-container {
+    margin-top: 15px;
+    display: flex;
+    .tree-box {
+      width: 100%;
+      height: 920px;
+      overflow-y: auto;
+      padding: 15px 8px;
+      :deep(.el-tree) {
+        height: 100%;
+        background-color: transparent;
+        color: #fbffff;
+        font-size: 38px;
+        .el-tree-node__content {
+          height: auto;
+          padding-top: 10px;
+          padding-bottom: 10px;
+          white-space: normal;
+          word-break: break-all;
+        }
+        .el-tree-node__expand-icon {
+          color: #297cfc;
+          font-size: 23px;
+        }
+        .el-tree-node:focus > .el-tree-node__content,
+        .el-tree-node__content:hover {
+          background-color: transparent !important;
+        }
+      }
+    }
+  }
+  .select-box2 {
+    margin-left: 30px;
+    width: 910px;
+    height: 100%;
+    .select-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      color: #fbffff;
+      font-size: 32px;
+      border-bottom: 1px solid #247dff;
+      padding: 20px;
+      .left-item {
+        display: flex;
+        align-items: center;
+        .text {
+          margin: 0 10px;
+          color: #00e8ff;
+          font-family: 'BEBAS-1';
+        }
+      }
+      .clear-btn {
+        color: #00e8ff;
+        cursor: pointer;
+      }
+    }
+    .select-content {
+      height: 858px;
+      overflow-y: auto;
+      .box-item {
+        border-bottom: 1px solid #247dff;
+        padding: 20px;
+        position: relative;
+        .line {
+          color: #fff;
+          font-size: 38px;
+          display: flex;
+          .text1 {
+            margin-right: 35px;
+          }
+          .text2 {
+            color: #a7ccdf;
+          }
+        }
+        .close-btn {
+          position: absolute;
+          right: 10px;
+          top: 50px;
+          cursor: pointer;
+          width: 29px;
+          height: 29px;
+          background: url('@/assets/images/emergencyCommandMap/communication/close.png') no-repeat;
+        }
+      }
+    }
+  }
+}
+</style>

+ 100 - 23
src/views/globalMap/RightMenu/OnlinePlotting/index.vue

@@ -12,6 +12,13 @@
         当前地图截图导出
       </div>
     </div>
+    <div class="btn-box">
+      <div v-show="!collaboration" class="btn1" @click="handleShare('1')">
+        协同标绘
+      </div>
+      <div v-show="collaboration" class="btn1" @click="handleCloseCollaboration">关闭协同</div>
+      <div v-show="collaboration" class="btn1">保存</div>
+    </div>
     <div v-if="menuActive1 === 0" class="content">
       <div class="box1">
         <div class="box-item">
@@ -69,14 +76,14 @@
       </div>
     </div>
     <div v-else-if="menuActive1 === 1" class="tab-content3">
-<!--      <div class="box1">-->
-<!--        <div class="box-item">-->
-<!--          <div class="btn">-->
-<!--            <div class="merge-icon"></div>-->
-<!--            合并-->
-<!--          </div>-->
-<!--        </div>-->
-<!--      </div>-->
+      <!--      <div class="box1">-->
+      <!--        <div class="box-item">-->
+      <!--          <div class="btn">-->
+      <!--            <div class="merge-icon"></div>-->
+      <!--            合并-->
+      <!--          </div>-->
+      <!--        </div>-->
+      <!--      </div>-->
       <div class="params-box">
         <el-input v-model="queryParams.pattern_name" class="custom-input" placeholder="请输入" @input="handleQuery">
           <template #prefix>
@@ -103,11 +110,11 @@
               <div class="edit-icon"></div>
               编辑
             </div>
-<!--            <div class="line2"></div>-->
-<!--            <div class="btn">-->
-<!--              <div class="share-icon"></div>-->
-<!--              分享-->
-<!--            </div>-->
+            <div class="line2"></div>
+            <div class="btn" @click="handleShare('2', item.id)">
+              <div class="share-icon"></div>
+              分享
+            </div>
           </div>
         </div>
         <div class="footer">
@@ -130,6 +137,7 @@
   <div v-show="tipTitle !== ''" class="tipTitle">{{ tipTitle }}</div>
   <!--保存修改弹窗-->
   <EditDialog v-if="showEdit" v-model="showEdit" :edit-data="editData" @submit="handleSubmit" />
+  <ShareDialog v-if="shareState.showShare" v-model="shareState.showShare" @close="handleCloseShare" @confirm="handleShareConfirm" />
 </template>
 
 <script lang="ts" setup name="OnlinePlotting">
@@ -141,6 +149,7 @@ import TextEdit from '@/views/globalMap/RightMenu/OnlinePlotting/TextEdit.vue';
 import EditDialog from '@/views/globalMap/RightMenu/OnlinePlotting/EditDialog.vue';
 import { Search } from '@element-plus/icons-vue';
 import html2canvas from 'html2canvas';
+import ShareDialog from '@/views/globalMap/RightMenu/OnlinePlotting/ShareDialog.vue';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const getDrawTool = inject('getDrawTool');
@@ -235,8 +244,20 @@ const menu = ref([
         value: 'fireGround',
         children: [
           { name: '火场', value: 'marker', image: getImageUrl('fireground'), icon: getImageUrl('fireground'), size: [166, 88] },
-          { name: '受控火场', value: 'marker', image: getImageUrl('controlledfireground'), icon: getImageUrl('controlledfireground'), size: [166, 88] },
-          { name: '已灭火场', value: 'marker', image: getImageUrl('extinguishedfireground'), icon: getImageUrl('extinguishedfireground'), size: [166, 88] }
+          {
+            name: '受控火场',
+            value: 'marker',
+            image: getImageUrl('controlledfireground'),
+            icon: getImageUrl('controlledfireground'),
+            size: [166, 88]
+          },
+          {
+            name: '已灭火场',
+            value: 'marker',
+            image: getImageUrl('extinguishedfireground'),
+            icon: getImageUrl('extinguishedfireground'),
+            size: [166, 88]
+          }
         ]
       },
       {
@@ -265,7 +286,7 @@ const menu = ref([
           { name: '军队', value: 'marker', image: getImageUrl('army'), icon: getImageUrl('army'), size: [166, 88] },
           { name: '武警', value: 'marker', image: getImageUrl('armedpolice'), icon: getImageUrl('armedpolice'), size: [166, 88] },
           { name: '森林警察', value: 'marker', image: getImageUrl('forestpoliceman'), icon: getImageUrl('forestpoliceman'), size: [166, 88] },
-          { name: '扑火队伍', value: 'marker', image: getImageUrl('firefightingteam'), icon: getImageUrl('firefightingteam'), size: [166, 88] },
+          { name: '扑火队伍', value: 'marker', image: getImageUrl('firefightingteam'), icon: getImageUrl('firefightingteam'), size: [166, 88] }
           // { name: '扑火队伍路线', value: 'marker', image: getImageUrl('Firefightingteamroute'), icon: getImageUrl('Firefightingteamroute'), size: [166, 88] }
         ]
       },
@@ -277,8 +298,20 @@ const menu = ref([
           { name: '直升机', value: 'marker', image: getImageUrl('helicopter'), icon: getImageUrl('helicopter'), size: [166, 88] },
           { name: '无人机', value: 'marker', image: getImageUrl('UAV'), icon: getImageUrl('UAV'), size: [166, 88] },
           { name: '指挥车', value: 'marker', image: getImageUrl('commandvehicle'), icon: getImageUrl('commandvehicle'), size: [166, 88] },
-          { name: '飞机航线设置', value: 'marker', image: getImageUrl('aircraftroutesetting'), icon: getImageUrl('aircraftroutesetting'), size: [166, 88] },
-          { name: '直升机航线设置', value: 'marker', image: getImageUrl('helicopterroutesetting'), icon: getImageUrl('helicopterroutesetting'), size: [166, 88] }
+          {
+            name: '飞机航线设置',
+            value: 'marker',
+            image: getImageUrl('aircraftroutesetting'),
+            icon: getImageUrl('aircraftroutesetting'),
+            size: [166, 88]
+          },
+          {
+            name: '直升机航线设置',
+            value: 'marker',
+            image: getImageUrl('helicopterroutesetting'),
+            icon: getImageUrl('helicopterroutesetting'),
+            size: [166, 88]
+          }
         ]
       },
       {
@@ -286,13 +319,18 @@ const menu = ref([
         value: 'basicSetting',
         children: [
           { name: '航站', value: 'marker', image: getImageUrl('terminal'), icon: getImageUrl('terminal'), size: [166, 88] },
-          { name: '起降点', value: 'marker', image: getImageUrl('takeoffandlandingpoint'), icon: getImageUrl('takeoffandlandingpoint'), size: [166, 88] },
+          {
+            name: '起降点',
+            value: 'marker',
+            image: getImageUrl('takeoffandlandingpoint'),
+            icon: getImageUrl('takeoffandlandingpoint'),
+            size: [166, 88]
+          },
           { name: '取水点', value: 'marker', image: getImageUrl('waterpoint'), icon: getImageUrl('waterpoint'), size: [166, 88] },
           { name: '瞭望塔', value: 'marker', image: getImageUrl('watchtower'), icon: getImageUrl('watchtower'), size: [166, 88] },
-          { name: '物资库', value: 'marker', image: getImageUrl('materialwarehouse'), icon: getImageUrl('materialwarehouse'), size: [166, 88] },
-
+          { name: '物资库', value: 'marker', image: getImageUrl('materialwarehouse'), icon: getImageUrl('materialwarehouse'), size: [166, 88] }
         ]
-      },
+      }
       // {
       //   name: '其他',
       //   value: 'other',
@@ -321,6 +359,15 @@ const lineWidthOptions = reactive([
 ]);
 let showTextEdit = ref();
 let lnglat = ref([]);
+// 协同
+let collaboration = ref(false);
+// 分享
+let shareState = reactive({
+  type: '',
+  showShare: false,
+  id: ''
+});
+let shareId = ref('');
 const overlays = [];
 const overlaysData = [];
 watch(
@@ -645,6 +692,31 @@ const handleEdit = (id) => {
   });
   showEdit.value = true;
 };
+const handleShare = (type, id?: string) => {
+  if (type === '1') {
+    // 创建协同
+    collaboration.value = true;
+  }
+  shareState.type = type;
+  shareState.id = id;
+  shareState.showShare = true;
+};
+const handleCloseShare = () => {
+  shareState.type = '';
+  shareState.id = '';
+};
+const handleCloseCollaboration = () => {
+  collaboration.value = false;
+}
+const handleShareConfirm = (data) => {
+  if (shareState.type === '1') {
+    // 协同标绘
+  } else {
+    // 分享
+  }
+  shareState.type = '';
+  shareState.id = '';
+};
 const handleShowDialog = () => {
   editData.value = {
     id: '',
@@ -672,7 +744,7 @@ const handleScreenshot = () => {
       logging: false // 不启动日志调试
     };
     // canvasBox是要截图的元素,options是一些相关配置
-    html2canvas(canvasBox,options).then((canvas) => {
+    html2canvas(canvasBox, options).then((canvas) => {
       // toDataURL 图片格式转成 base64
       dataURL.value = canvas.toDataURL('image/png');
       // 新建一个a标签
@@ -1066,4 +1138,9 @@ onMounted(() => {
     }
   }
 }
+.btn-box {
+  display: flex;
+  align-items: center;
+  margin: 10px 0;
+}
 </style>