Explorar o código

feat: 添加公司主页配置的移动端视角

wyf hai 1 ano
pai
achega
36c61032de

+ 2 - 0
src/api/scene/scene.ts

@@ -108,6 +108,8 @@ export type CompanyInfoItem = {
   labelList: SceneLabelOrModuleItem[];
   /** 场景模板列表 */
   moduleList: SceneLabelOrModuleItem[];
+  // 模板列表信息
+  labelModuleList: { sceneLabel: SceneLabelOrModuleItem; sceneModule: SceneLabelOrModuleItem }[];
 };
 
 /** 获取公司-工厂-工位数据 */

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 38 - 0
src/assets/images/MobileConfigMap/life.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 37 - 0
src/assets/images/MobileConfigMap/logistics.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 34 - 0
src/assets/images/MobileConfigMap/production-safe.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 36 - 0
src/assets/images/MobileConfigMap/safe-env.svg


+ 45 - 19
src/views/page-config/ConfigEdit.vue

@@ -20,23 +20,31 @@
           </el-select>
         </div>
         <div v-if="selectedCompany" style="display: flex">
-          <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
+          <div style="display: flex">
+            <div class="label-workshop" style="margin-left: 0px">选择标签:</div>
+            <div>
+              <el-radio-group
+                v-model="label"
+                :border="true"
+                style="display: flex"
+                @change="changeShop"
               >
-            </el-radio-group></div
-          >
+                <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 v-if="label" style="display: flex">
+            <div class="label-workshop" style="margin-left: 10px">是否开启移动端视角</div>
+            <div>
+              <el-switch v-model="isMobileView" style="margin-left: 10px" />
+            </div>
+          </div>
         </div>
         <div class="flex">
           <!-- <el-button @click="toJson">tojson</el-button> -->
@@ -96,7 +104,12 @@
       </div>
       <div ref="drawContainer" id="drawContainer" class="draw-container">
         <div id="shopEditContainer" v-moveable:1>
-          <MapContainer ref="mapContainerRef" @on-open="openConfig" />
+          <MapContainer
+            ref="mapContainerRef"
+            :is-mobile-view="isMobileView"
+            :module-code="labelMouduleCode"
+            @on-open="openConfig"
+          />
         </div>
         <el-upload
           v-if="!hasBg"
@@ -122,7 +135,7 @@
       placement="left"
     >
       <div
-        v-if="leftShow && activeShopId && activeShopId != -1"
+        v-if="leftShow && activeShopId && !isMobileView && activeShopId != -1"
         class="circle-rectangle"
         :class="{ 'shape-shadow': shadow }"
         @mouseover="shadowAdd"
@@ -135,6 +148,7 @@
     </el-tooltip>
 
     <ConfigDialog
+      v-if="!isMobileView"
       ref="configDrawer"
       @on-close="onClose"
       @transformer-change="transformChange"
@@ -154,7 +168,7 @@
   import ConfigDialog from './component/ConfigDrawer.vue';
   import ConfigFinish from './component/ConfigFinish.vue';
   import { storeToRefs } from 'pinia';
-  import { ElMessage, ElInput } from 'element-plus';
+  import { ElMessage, ElInput, ElSwitch } from 'element-plus';
   import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
   import { WorkShopInfoItem } from '@/api/scene/scene';
   import { computed } from 'vue';
@@ -185,6 +199,9 @@
   // 是否已有背景图
   const hasBg = ref(false);
 
+  // 是否开启移动端视图
+  const isMobileView = ref(false);
+
   const handleBeforeUpload = (rawFile) => {
     if (!selectedCompany.value || !label.value) {
       ElMessage.error({
@@ -261,6 +278,15 @@
     addBg();
   };
 
+  const labelMouduleCode = computed(() => {
+    return (
+      scenesInfos.value
+        .find((item) => item.id === selectedCompany.value)
+        ?.labelModuleList.find((item) => item.sceneLabel.id === label.value)?.sceneModule.code ||
+      'default'
+    );
+  });
+
   const changeShop = () => {
     hasBg.value = false;
     resetMap();

+ 93 - 0
src/views/page-config/component/mapContainer/LabelItemMobile.vue

@@ -0,0 +1,93 @@
+<template>
+  <v-image ref="pointRef" :config="getIconConfig(curvImage)" />
+  <!-- <v-image :config="getCirConfig(props.shop.posType, cirImage)" />
+  <v-image ref="rectRef" :config="getRectCurConfig(props.shop.posType, rectImage)" /> -->
+  <v-rect :config="getRectConfig(props.shop)" />
+  <v-text :config="getTextConfig(props.shop)" />
+</template>
+
+<script setup lang="ts">
+  import { ref, onMounted, nextTick, watch } from 'vue';
+  import ProductionSafe from '@/assets/images/MobileConfigMap/production-safe.svg';
+  import SafeEnv from '@/assets/images/MobileConfigMap/safe-env.svg';
+  import Life from '@/assets/images/MobileConfigMap/life.svg';
+  import Logistics from '@/assets/images/MobileConfigMap/logistics.svg';
+  import Konva from 'konva';
+  import { MapWorkShopInfoItem } from '../../stores/useMapEditor';
+  import { getIconConfig, getRectConfig, getTextConfig } from './labelConfigMobile';
+
+  const props = defineProps<{ shop: MapWorkShopInfoItem; moduleCode: string }>();
+
+  const curvImage = ref<HTMLImageElement>(new Image());
+  // const rectImage = ref<HTMLImageElement>(new Image());
+  // const shineImage = ref<HTMLImageElement>(new Image());
+  // const cirImage = ref<HTMLImageElement>(new Image());
+  const rectRef = ref<Konva.Image>();
+  const pointRef = ref<Konva.Image>();
+
+  const nodeUpdateFilter = (node: Konva.Node) => {
+    node.cache();
+    // const rgba = getRGBANum(props.shop.bgColor);
+    // node.red(rgba[0]);
+    // node.green(rgba[1]);
+    // node.blue(rgba[2]);
+    // node.alpha(rgba[3]);
+  };
+
+  const IconMap = {
+    companyLife: Life,
+    companyProductionSafe: ProductionSafe,
+    companySafeEnv: SafeEnv,
+    companyLogistics: Logistics,
+    // 加入了一个默认code用于其他code都找不到的情况
+    default: ProductionSafe,
+  };
+
+  watch(
+    () => props.shop,
+    () => {
+      nextTick(() => {
+        nodeUpdateFilter(pointRef.value!.getNode());
+        nodeUpdateFilter(rectRef.value!.getNode());
+      });
+    },
+    { deep: true },
+  );
+
+  onMounted(() => {
+    const svgImg = new Image();
+    svgImg.onload = () => {
+      curvImage.value = svgImg;
+      nextTick(() => {
+        nodeUpdateFilter(pointRef.value?.getNode());
+      });
+    };
+    svgImg.src = IconMap[props.moduleCode];
+
+    // const rectImg = new Image();
+    // rectImg.onload = () => {
+    //   rectImage.value = rectImg;
+    //   nextTick(() => {
+    //     nodeUpdateFilter(rectRef.value?.getNode());
+    //   });
+    // };
+    // rectImg.src = rectBlock;
+
+    // const shineImg = new Image();
+    // shineImg.onload = () => {
+    //   shineImage.value = shineImg;
+    // };
+    // shineImg.src = shine;
+
+    // const cirImg = new Image();
+    // cirImg.onload = () => {
+    //   cirImage.value = cirImg;
+    // };
+    // cirImg.src = circle;
+
+    // rectRef.value?.getNode().filters([Konva.Filters.RGBA]);
+    // pointRef.value?.getNode().filters([Konva.Filters.RGBA]);
+  });
+</script>
+
+<style scoped></style>

+ 29 - 4
src/views/page-config/component/mapContainer/MapContainer.vue

@@ -14,7 +14,13 @@
           :config="getGroupConfig(item)"
           @dblclick="handleClick"
         >
-          <LabelItem :shop="item" />
+          <LabelItemMobile
+            v-if="isMobileView"
+            :shop="item"
+            :is-mobile-view="isMobileView"
+            :module-code="moduleCode"
+          />
+          <LabelItem v-else :shop="item" :is-mobile-view="isMobileView" />
         </v-group>
         <v-transformer ref="transformerRef" :config="transformerConfig" />
       </v-layer>
@@ -25,6 +31,7 @@
 <script setup lang="ts">
   import { computed, ref, watch, nextTick } from 'vue';
   import LabelItem from './LabelItem.vue';
+  import LabelItemMobile from './LabelItemMobile.vue';
   import { storeToRefs } from 'pinia';
   import useMapEditor, { MapWorkShopInfoItem } from '../../stores/useMapEditor';
   import Konva from 'konva';
@@ -32,6 +39,11 @@
   const mapEditor = useMapEditor();
   const { showShops, bgImage, activeShopId } = storeToRefs(mapEditor);
 
+  const props = defineProps<{
+    isMobileView: boolean;
+    moduleCode: string;
+  }>();
+
   const emit = defineEmits(['onOpen']);
 
   const stageRef = ref<Konva.Stage>();
@@ -66,11 +78,24 @@
     };
   };
 
-  const transformerConfig = {
+  const transformerConfig = ref({
     keepRatio: true,
     rotateEnabled: false,
-    enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
-  };
+    // enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
+    enabledAnchors: !props.isMobileView
+      ? ['top-left', 'top-right', 'bottom-left', 'bottom-right']
+      : [],
+  });
+
+  watch(
+    () => props.isMobileView,
+    (v) => {
+      transformerConfig.value.enabledAnchors = !v
+        ? ['top-left', 'top-right', 'bottom-left', 'bottom-right']
+        : [];
+      updateTransformer();
+    },
+  );
 
   const handleStageMouseDown = (e) => {
     if (e.target.attrs.name === 'bg') {

+ 35 - 0
src/views/page-config/component/mapContainer/labelConfigMobile.ts

@@ -0,0 +1,35 @@
+import { MapWorkShopInfoItem } from '../../stores/useMapEditor';
+export const getIconConfig = (image: any) => {
+  return {
+    x: -25,
+    y: -25,
+    width: 50,
+    height: 50,
+    image: image,
+  };
+};
+
+export const getRectConfig = (shop: MapWorkShopInfoItem) => {
+  return {
+    x: 22,
+    y: -13,
+    fill: '#0000009C',
+    width: shop.name.length * shop.fontSize + 20,
+    height: 26,
+  };
+};
+
+export const getTextConfig = (shop: MapWorkShopInfoItem) => {
+  return {
+    x: 32,
+    y: -13,
+    text: shop.name,
+    fontSize: shop.fontSize,
+    fontFamily: 'TRENDS',
+    fill: shop.fontColor,
+    width: shop.name.length * shop.fontSize,
+    height: 26,
+    align: 'center',
+    verticalAlign: 'middle',
+  };
+};