sunhongyao341504 пре 2 година
родитељ
комит
080c220384

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


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


+ 23 - 0
src/assets/test/2-rect.svg

@@ -0,0 +1,23 @@
+<svg width="160" height="38" fill="currentColor" xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <linearGradient x1="100%" y1="51.673%" x2="0%" y2="48.327%" id="prefix__a">
+            <stop stop-color="currentColor" offset="0%" />
+            <stop stop-color="currentColor" stop-opacity=".5" offset="100%" />
+        </linearGradient>
+    </defs>
+    <g transform="translate(0 1)" fill="none" fill-rule="evenodd">
+        <g transform="translate(8.27 23.337)" fill-rule="nonzero">
+            <path stroke="currentColor" stroke-width=".5" d="M.664.476l3.984 2.857h80.56L89.191.476h52.674" />
+            <circle fill="currentColor" cx=".664" cy=".476" r="1" />
+            <path fill="currentColor" d="M102.471.476H92.069v1h10.402z" />
+            <path fill="currentColor" d="M85.207 3.333H4.647v1h80.56z" />
+        </g>
+        <path d="M13.426 14.448l-10.62 5.32V9.129l10.62 5.32z" stroke="currentColor" stroke-width=".5" />
+        <path fill="currentColor" d="M10.175 14.448l-6.349 3.18v-6.36z" />
+        <path d="M146.904 14.448l10.62 5.32V9.129l-10.62 5.32z" stroke="currentColor" stroke-width=".5" />
+        <path fill="currentColor" d="M150.155 14.448l6.349 3.18v-6.36z" />
+        <path d="M159.428.25v28.705H5.179L.25 24.36V2.315L3.428.25h156z" stroke-opacity=".498" stroke="#FFFFFF"
+            stroke-width=".5" fill-opacity=".7" fill="url(#prefix__a)" transform="translate(0 -.154)" />
+    </g>
+</svg>

Разлика између датотеке није приказан због своје велике величине
+ 6 - 0
src/assets/test/2-shine.svg


Разлика између датотеке није приказан због своје велике величине
+ 100 - 488
src/views/page-config/ConfigEdit.vue


+ 511 - 0
src/views/page-config/ConfigEdit1.vue

@@ -0,0 +1,511 @@
+<template>
+  <div class="page">
+    <div class="page-head flex items-center">
+      <el-icon size="20"><ArrowLeft /></el-icon>
+      <div class="head-opt flex-1 flex justify-between items-center">
+        <div>
+          <span>场景:</span>
+          <el-select
+            v-model="selectedCompany"
+            class="m-2"
+            placeholder="请选择相关公司"
+            style="width: 216px"
+            @change="changeCompany"
+          >
+            <el-option
+              v-for="item in scenesInfos"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            />
+          </el-select>
+        </div>
+        <div v-if="selectedCompany" style="display: flex; margin-top: 8px">
+          <div class="label-workshop">选择标签:</div>
+          <div>
+            <el-radio-group
+              v-model="label"
+              :border="true"
+              style="display: flex"
+              @change="changeShop"
+            >
+              <el-radio-button
+                v-for="item in labelList"
+                :key="item.id"
+                :label="item.id!"
+                class="label-select"
+                >{{ item.name }}</el-radio-button
+              >
+            </el-radio-group></div
+          >
+        </div>
+        <div class="flex">
+          <!-- <el-button @click="toJson">tojson</el-button> -->
+          <el-upload
+            class="avatar-uploader flex justify-center items-center"
+            action="/skyeye-admin-api/homepageConfig/updateCompanyPicture"
+            :show-file-list="false"
+            :on-success="handleAvatarSuccess"
+            :with-credentials="true"
+            name="file"
+            :data="{ companyId: selectedCompany, labelId: label, deleteFileName: bgImg }"
+          >
+            <el-button style="font-size: 12px" :icon="Refresh" :disabled="!hasBg">
+              替换照片
+            </el-button>
+          </el-upload>
+
+          <el-button
+            @click="handleSave"
+            style="margin-left: 40px"
+            type="primary"
+            :disabled="!selectedCompany && !label"
+            >保存为布局
+          </el-button>
+        </div>
+      </div>
+    </div>
+    <div class="paint-tool flex">
+      <div class="camera-list">
+        <div>
+          <span class="label-text flex">车间列表:</span>
+          <ElInput
+            class="search-put"
+            style="margin: 10px 0; width: 230px"
+            placeholder="请输入搜索内容"
+            v-model="searchKey"
+            :suffix-icon="Search"
+          />
+        </div>
+        <span v-if="filterShopList.length == 0" class="ml-1" style="color: #3f3f3f">
+          提示:请先选择相应公司和图片
+        </span>
+        <el-scrollbar v-else style="position: relative; height: calc(100% - 90px)">
+          <div
+            v-for="item in filterShopList"
+            :key="item.code"
+            class="camera-item flex justify-start items-center"
+            :class="{
+              isAdded: isAddedShop(item.id),
+              isActive: item.id === activeShop.id,
+            }"
+            @click="handleAddShop(item)"
+          >
+            <span class="camera-id">{{ item.name }}</span>
+          </div>
+        </el-scrollbar>
+      </div>
+      <div ref="drawContainer" id="drawContainer" class="draw-container">
+        <div id="shopEditContainer" v-moveable:1>
+          <MapContainer />
+          <LabelPoint
+            ref="labelPointRef"
+            id="labelPoint"
+            style="position: absolute; left: -3000px; top: 0px"
+          />
+        </div>
+        <el-upload
+          v-if="!hasBg"
+          class="upload-icon flex justify-center items-center"
+          action="/skyeye-admin-api/homepageConfig/uploadCompanyPicture"
+          :show-file-list="false"
+          :before-upload="handleBeforeUpload"
+          :on-success="handleAvatarSuccess"
+          :with-credentials="true"
+          name="file"
+          :data="{ companyId: selectedCompany, labelId: label }"
+        >
+          <img src="~@/assets/images/img-upload.png" />
+        </el-upload>
+      </div>
+    </div>
+    <el-tooltip
+      class="box-item position-tooltip"
+      effect="dark"
+      content="显示侧边栏"
+      :offset="12"
+      placement="left"
+    >
+      <div
+        v-if="leftShow"
+        class="circle-rectangle"
+        :class="{ 'shape-shadow': shadow }"
+        @mouseover="shadowAdd"
+        @mouseout="shadowRemove"
+        @click="dialogReopen"
+      >
+        <el-icon class="left-icon" size="16px"><ArrowLeftBold /></el-icon>
+        <el-icon style="margin-top: 7px" size="16px"><ArrowLeftBold /></el-icon>
+      </div>
+    </el-tooltip>
+
+    <ConfigDialog ref="configDrawer" @on-close="onClose" class="drawer-position" />
+
+    <ConfigFinish
+      :visible="visibleResult"
+      :status="configStatus"
+      @on-close="closeResult"
+      class="feedback-position"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+  import ConfigDialog from './component/ConfigDrawer.vue';
+  import ConfigFinish from './component/ConfigFinish.vue';
+  import LabelPoint from './component/mapContainer/LabelPoint.vue';
+  import { storeToRefs } from 'pinia';
+  import { ElMessage, ElInput } from 'element-plus';
+  import { onBeforeUnmount, onMounted, ref } from 'vue';
+  import { WorkShopInfoItem } from '@/api/scene/scene';
+  import { computed } from 'vue';
+  import { Search, Refresh, ArrowLeftBold, ArrowLeft } from '@element-plus/icons-vue';
+  import usePageConfig from './usePageConfig';
+  import MapContainer from './component/mapContainer/MapContainer.vue';
+  import useMapEditor, { LabelPositionEnum } from './stores/useMapEditor';
+  import { uploadCompanyLayout, updateCompanyLayout, getCompanyLayoutApi } from '@/api/scene/scene';
+  import safeParse from '@/utils/safeParse';
+  import { useRouter } from 'vue-router';
+
+  const mapEditor = useMapEditor();
+  const { bgImg, addedShops, activeShop, labelPointRef } = storeToRefs(mapEditor);
+  const { addShop, addBg, toJson, resetMap, createMap, deleteShop } = mapEditor;
+
+  const router = useRouter();
+
+  const pageConfig = usePageConfig();
+  const { selectedCompany, scenesInfos, label, labelList, shopList, layoutId } = pageConfig;
+
+  const drawContainer = ref<HTMLDivElement>();
+
+  const searchKey = ref('');
+  // 是否已有背景图
+  const hasBg = ref(false);
+
+  const handleBeforeUpload = () => {
+    if (!selectedCompany.value || !label.value) {
+      ElMessage.error({
+        message: '请先选择公司和标签',
+      });
+      return false;
+    }
+  };
+
+  /** 判断相机是否已经添加 */
+  const isAddedShop = (shopId: number) => {
+    const index = addedShops.value.findIndex((item) => item.id === shopId);
+    return index >= 0;
+  };
+
+  //左边的浮动按钮
+  const leftShow = ref(true);
+  const onClose = (val) => {
+    leftShow.value = val;
+  };
+
+  const shadow = ref(false);
+  const shadowAdd = () => {
+    shadow.value = true;
+  };
+  const shadowRemove = () => {
+    shadow.value = false;
+  };
+
+  const configDrawer = ref();
+  const dialogReopen = () => {
+    configDrawer.value.openDialog();
+  };
+
+  //总体的保存,将整个数据传过去
+  const visibleResult = ref(false);
+  const configStatus = ref(true);
+  const closeResult = () => {
+    visibleResult.value = false;
+  };
+  /** ------------- */
+
+  const handleAvatarSuccess = (e) => {
+    bgImg.value = e.data;
+    addBg();
+    hasBg.value = true;
+  };
+
+  const changeShop = () => {
+    // resetMap();
+    getShopContent();
+    // hasBg.value = false;
+  };
+
+  const getShopContent = () => {
+    getCompanyLayoutApi({ companyId: selectedCompany.value || 2, labelId: label.value || 1 }).then(
+      (res) => {
+        if (!res) {
+          return;
+        }
+        layoutId.value = res.id;
+        const layoutJSON = res.layout ? safeParse(res.layout) : null;
+        if (!layoutJSON) {
+          return;
+        }
+        hasBg.value = true;
+        createMap(layoutJSON);
+      },
+    );
+  };
+
+  const changeCompany = () => {
+    label.value = undefined;
+    // resetMap();
+    // hasBg.value = false;
+  };
+
+  const handleKeyDown = (e) => {
+    // 删除键
+    if (e.keyCode === 46 || e.code === 'Delete') {
+      deleteShop();
+    }
+  };
+
+  onMounted(() => {
+    const routerParams = router.currentRoute.value.query;
+    if (routerParams.companyId) {
+      selectedCompany.value = Number(routerParams.companyId);
+      console.log(selectedCompany.value);
+    }
+
+    window.addEventListener('keydown', handleKeyDown);
+
+    if (selectedCompany.value && label.value) {
+      getShopContent();
+    }
+  });
+
+  const filterShopList = computed(() => {
+    const k = searchKey.value.trim();
+    if (!k) return shopList.value;
+    return shopList.value?.filter((x) => x.name?.includes(k));
+  });
+
+  const handleAddShop = (shop: WorkShopInfoItem) => {
+    if (!hasBg.value) {
+      ElMessage.warning({
+        message: '请先添加背景图片',
+      });
+      return;
+    }
+    const shopNode = {
+      ...shop,
+      x: 20,
+      y: 20,
+      scale: 1,
+      bgColor: 'rgba(58, 170, 209, 1)',
+      fontSize: 14,
+      fontColor: '#ffffff',
+      posType: LabelPositionEnum.LEFT,
+    };
+    addShop(shopNode);
+    dialogReopen();
+  };
+
+  const handleSave = () => {
+    const layout = toJson();
+    const param = {
+      layout,
+      targetId: selectedCompany.value || 2,
+      labelId: label.value || 1,
+    };
+    if (!layoutId.value) {
+      uploadCompanyLayout(param).then((res) => {
+        console.log('uploadCompanyLayout', res);
+        layoutId.value = res;
+        ElMessage.success('保存成功');
+      });
+    } else {
+      updateCompanyLayout({ ...param, id: layoutId.value }).then((res) => {
+        console.log('updateCompanyLayout', res);
+        layoutId.value = res;
+        ElMessage.success('更新成功');
+      });
+    }
+  };
+
+  onMounted(() => {
+    addBg();
+    hasBg.value = true;
+  });
+
+  onBeforeUnmount(() => {
+    window.removeEventListener('keydown', handleKeyDown);
+    resetMap();
+  });
+</script>
+
+<style scoped lang="scss">
+  .page {
+  }
+
+  .page-head {
+    height: 54px;
+    padding-left: 15px;
+    background-color: #ffffff;
+  }
+  .head-opt {
+    margin-left: 20px;
+    padding-right: 15px;
+    font-size: 14px;
+    color: #3f3f3f;
+  }
+
+  .avatar-uploader {
+    border-radius: 4px;
+    margin-left: 30px;
+  }
+
+  .label-workshop {
+    font-size: 14px;
+    font-weight: 400;
+    margin-left: 36px;
+    margin-top: 6px;
+    margin-right: 16px;
+  }
+
+  .upload-icon {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    bottom: 0;
+    margin: auto;
+  }
+
+  .paint-tool {
+    position: relative;
+    height: calc(100vh - 138px);
+    margin-top: 2px;
+  }
+
+  .camera-list {
+    width: 250px;
+    padding: 0 10px;
+    background-color: #ffffff;
+  }
+  .label-text {
+    font-size: 14px;
+    font-weight: 600;
+    margin: 10px 0 5px 10px;
+  }
+  .camera-item {
+    height: 32px;
+    font-size: 14px;
+    padding-left: 8px;
+    font-weight: 400;
+    color: #404040;
+    line-height: 14px;
+    cursor: pointer;
+
+    &:hover {
+      background-color: #e6f7ff;
+      color: #1890ff;
+    }
+  }
+  .isAdded {
+    color: #1890ff;
+    cursor: not-allowed;
+  }
+  .isActive {
+    background-color: #e6f7ff;
+    color: #1890ff;
+  }
+  .camera-item-disabled {
+    color: #c6c6c6;
+  }
+  .camera-id {
+    width: 110px;
+  }
+  .space-name {
+    width: 120px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+
+  .draw-container {
+    position: relative;
+    width: calc(100% - 300px);
+    margin: 20px;
+    overflow: hidden;
+  }
+
+  .drawer-position {
+    position: absolute;
+    right: 0px;
+    // left: 1150px;
+    top: 74px;
+    z-index: 99;
+    opacity: 1;
+    background: #ffffff;
+  }
+
+  .dialog-btn {
+    position: absolute;
+    right: 0px;
+    top: 66px;
+  }
+
+  .position-tooltip {
+    margin-right: -10px;
+  }
+
+  .circle-rectangle {
+    width: 40px;
+    height: 30px;
+    border-radius: 50% 0% 0% 50%;
+    position: absolute;
+    right: 0px;
+    top: 66px;
+    background-color: white;
+    display: flex;
+  }
+
+  .shape-shadow {
+    filter: drop-shadow(5px 5px 10px rgb(102, 100, 100));
+  }
+  .left-icon {
+    margin-top: 7px;
+    margin-left: 8px;
+    margin-right: -7px;
+  }
+
+  .feedback-position {
+    position: absolute;
+    left: 460px;
+    top: 150px;
+    z-index: 9999;
+  }
+
+  :deep(.search-put .el-input__wrapper) {
+    background-color: #f0f2f5;
+  }
+  :deep(.el-popper__arrow) {
+    display: none;
+  }
+  :deep(.el-tree-node__content:hover) {
+    background: #e6f4ff;
+  }
+  :deep(.el-button--primary) {
+    --el-button-disabled-bg-color: #bfbfbf;
+  }
+  :deep(.el-popover) {
+    width: unset !important;
+    min-width: 110px;
+    text-align: center;
+    font-weight: 400;
+  }
+  ::v-deep.el-radio-button {
+    margin-right: 8px;
+    box-shadow: none;
+    border-radius: 4px !important;
+    border: 1px solid #d9d9d9 !important;
+  }
+</style>
+./MapBase/useCameraMap ./MapBase/CameraMapBak ./usePageConfig1