Sfoglia il codice sorgente

feat: 接入场景树数据和相机列表数据

sunhongyao341504 2 anni fa
parent
commit
16ebc4df63

+ 1 - 1
.env.development

@@ -15,7 +15,7 @@ VITE_DROP_CONSOLE = true
 
 # 跨域代理,可以配置多个,请注意不要换行
 #VITE_PROXY = [["/appApi","http://localhost:8001"],["/upload","http://localhost:8001/upload"]]
-# VITE_PROXY=[["/api","https://naive-ui-admin"]]
+VITE_PROXY=[["/temp","http://172.16.23.144:8800"]]
 
 # API 接口地址
 VITE_GLOB_API_URL = 

+ 79 - 79
package.json

@@ -31,87 +31,87 @@
     "deploy": "gh-pages -d dist"
   },
   "dependencies": {
-    "@element-plus/icons-vue": "^2.0.9",
-    "@vicons/antd": "^0.12.0",
-    "@vicons/ionicons5": "^0.12.0",
+    "@element-plus/icons-vue": "2.0.9",
+    "@vicons/antd": "0.12.0",
+    "@vicons/ionicons5": "0.12.0",
     "@vueup/vue-quill": "1.0.0-beta.8",
-    "@vueuse/core": "^8.9.4",
-    "@wangeditor/editor": "^5.1.23",
-    "@wangeditor/editor-for-vue": "^5.1.12",
-    "axios": "^0.27.2",
-    "blueimp-md5": "^2.19.0",
-    "cropperjs": "^1.5.12",
-    "dayjs": "^1.11.4",
-    "echarts": "^5.3.3",
-    "element-plus": "^2.3.6",
-    "element-resize-detector": "^1.2.4",
-    "fabric": "^5.3.0",
-    "lodash-es": "^4.17.21",
-    "mockjs": "^1.1.0",
-    "nprogress": "^0.2.0",
-    "perfect-scrollbar": "^1.5.5",
-    "pinia": "^2.0.16",
-    "print-js": "^1.6.0",
-    "qrcode": "^1.5.1",
-    "qs": "^6.11.0",
-    "vue": "^3.3.4",
-    "vue-router": "^4.1.2",
-    "vue-types": "^4.1.1",
-    "vuedraggable": "^4.1.0",
-    "xlsx": "^0.18.5"
+    "@vueuse/core": "8.9.4",
+    "@wangeditor/editor": "5.1.23",
+    "@wangeditor/editor-for-vue": "5.1.12",
+    "axios": "0.27.2",
+    "blueimp-md5": "2.19.0",
+    "cropperjs": "1.5.12",
+    "dayjs": "1.11.4",
+    "echarts": "5.3.3",
+    "element-plus": "2.3.6",
+    "element-resize-detector": "1.2.4",
+    "fabric": "5.3.0",
+    "lodash-es": "4.17.21",
+    "mockjs": "1.1.0",
+    "nprogress": "0.2.0",
+    "perfect-scrollbar": "1.5.5",
+    "pinia": "2.0.16",
+    "print-js": "1.6.0",
+    "qrcode": "1.5.1",
+    "qs": "6.11.0",
+    "vue": "3.3.4",
+    "vue-router": "4.1.2",
+    "vue-types": "4.1.1",
+    "vuedraggable": "4.1.0",
+    "xlsx": "0.18.5"
   },
   "devDependencies": {
-    "@commitlint/cli": "^17.0.3",
-    "@commitlint/config-conventional": "^17.0.3",
-    "@types/element-resize-detector": "^1.1.3",
-    "@types/intro.js": "^3.0.2",
-    "@types/lodash-es": "^4.17.6",
-    "@types/node": "^17.0.45",
-    "@types/qrcode": "^1.4.2",
-    "@typescript-eslint/eslint-plugin": "^5.30.7",
-    "@typescript-eslint/parser": "^5.30.7",
-    "@vitejs/plugin-vue": "^2.3.3",
-    "@vitejs/plugin-vue-jsx": "^1.3.10",
-    "@vue/compiler-sfc": "^3.3.4",
-    "autoprefixer": "^10.4.7",
-    "colors": "^1.4.0",
-    "commitizen": "^4.2.5",
-    "core-js": "^3.23.5",
-    "cross-env": "^7.0.3",
-    "dotenv": "^16.0.1",
-    "eslint": "^8.20.0",
-    "eslint-config-prettier": "^8.5.0",
-    "eslint-define-config": "^1.5.1",
-    "eslint-plugin-prettier": "^4.2.1",
-    "eslint-plugin-vue": "^8.7.1",
-    "esno": "^0.16.3",
-    "fs-extra": "^10.1.0",
-    "gh-pages": "^4.0.0",
-    "husky": "^8.0.1",
-    "lint-staged": "^13.0.3",
-    "picocolors": "^1.0.0",
-    "postcss": "^8.4.14",
-    "prettier": "^2.7.1",
-    "pretty-quick": "^3.1.3",
-    "rimraf": "^3.0.2",
-    "rollup-plugin-visualizer": "^5.8.3",
-    "sass": "^1.53.0",
-    "stylelint": "^14.9.1",
-    "stylelint-config-prettier": "^9.0.3",
-    "stylelint-config-standard": "^25.0.0",
-    "stylelint-order": "^5.0.0",
-    "stylelint-scss": "^4.3.0",
-    "tailwindcss": "^3.3.2",
-    "ts-node": "^10.9.1",
-    "typescript": "^4.7.4",
-    "vite": "^3.2.7",
-    "vite-plugin-compression": "^0.5.1",
-    "vite-plugin-html": "^3.2.0",
-    "vite-plugin-mock": "^2.9.6",
-    "vite-plugin-style-import": "^2.0.0",
-    "vite-plugin-vue-setup-extend": "^0.4.0",
-    "vue-eslint-parser": "^9.0.3",
-    "vue-tsc": "^0.35.2"
+    "@commitlint/cli": "17.0.3",
+    "@commitlint/config-conventional": "17.0.3",
+    "@types/element-resize-detector": "1.1.3",
+    "@types/intro.js": "3.0.2",
+    "@types/lodash-es": "4.17.6",
+    "@types/node": "17.0.45",
+    "@types/qrcode": "1.4.2",
+    "@typescript-eslint/eslint-plugin": "5.30.7",
+    "@typescript-eslint/parser": "5.30.7",
+    "@vitejs/plugin-vue": "2.3.3",
+    "@vitejs/plugin-vue-jsx": "1.3.10",
+    "@vue/compiler-sfc": "3.3.4",
+    "autoprefixer": "10.4.7",
+    "colors": "1.4.0",
+    "commitizen": "4.2.5",
+    "core-js": "3.23.5",
+    "cross-env": "7.0.3",
+    "dotenv": "16.0.1",
+    "eslint": "8.20.0",
+    "eslint-config-prettier": "8.5.0",
+    "eslint-define-config": "1.5.1",
+    "eslint-plugin-prettier": "4.2.1",
+    "eslint-plugin-vue": "8.7.1",
+    "esno": "0.16.3",
+    "fs-extra": "10.1.0",
+    "gh-pages": "4.0.0",
+    "husky": "8.0.1",
+    "lint-staged": "13.0.3",
+    "picocolors": "1.0.0",
+    "postcss": "8.4.14",
+    "prettier": "2.7.1",
+    "pretty-quick": "3.1.3",
+    "rimraf": "3.0.2",
+    "rollup-plugin-visualizer": "5.8.3",
+    "sass": "1.53.0",
+    "stylelint": "14.9.1",
+    "stylelint-config-prettier": "9.0.3",
+    "stylelint-config-standard": "25.0.0",
+    "stylelint-order": "5.0.0",
+    "stylelint-scss": "4.3.0",
+    "tailwindcss": "3.3.2",
+    "ts-node": "10.9.1",
+    "typescript": "4.7.4",
+    "vite": "3.2.7",
+    "vite-plugin-compression": "0.5.1",
+    "vite-plugin-html": "3.2.0",
+    "vite-plugin-mock": "2.9.6",
+    "vite-plugin-style-import": "2.0.0",
+    "vite-plugin-vue-setup-extend": "0.4.0",
+    "vue-eslint-parser": "9.0.3",
+    "vue-tsc": "0.35.2"
   },
   "lint-staged": {
     "*.{vue,js,ts,tsx}": "eslint --fix"
@@ -132,7 +132,7 @@
     "typescript"
   ],
   "engines": {
-    "node": "^12 || >=14"
+    "node": "12 || >=14"
   },
   "pnpm": {
     "peerDependencyRules": {

File diff suppressed because it is too large
+ 138 - 326
pnpm-lock.yaml


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

@@ -0,0 +1,116 @@
+import { http } from '@/utils/http/axios';
+
+/** 工位信息 */
+export type WorkSpaceInfoItem = {
+  /** 工位id */
+  id: number;
+  /** 所属工厂id */
+  workshopId: number;
+  /** 工位名称 */
+  name: string;
+  /** 工位code */
+  code: string;
+  /** 工位描述 */
+  remark: string;
+  /** 状态: 0-启用, 1-禁用 */
+  status: number;
+  /** 创建时间 */
+  createdAt: string;
+  /** 更新时间 */
+  updatedAt: string;
+  /** 	0-未删除,大于0-已删除 */
+  isDeleted: number;
+};
+
+/** 工厂信息 */
+export type WorkShopInfoItem = {
+  /** 工厂id */
+  id: number;
+  /** 所属公司id */
+  companyId: number;
+  /** 1-生产安全 2-安全环保 */
+  type: number;
+  /** 工厂名称 */
+  name: string;
+  /** 工厂code */
+  code: string;
+  /** 工厂描述 */
+  remark: string;
+  /** 状态: 0-启用, 1-禁用 */
+  status: number;
+  /** 创建时间 */
+  createdAt: string;
+  /** 更新时间 */
+  updatedAt: string;
+  /** 	0-未删除,大于0-已删除 */
+  isDeleted: number;
+  /** 下属工位列表 */
+  workspaceInfoList: WorkSpaceInfoItem[];
+};
+
+/** 公司信息 */
+export type CompanyInfoItem = {
+  /** 公司id */
+  id: number;
+  /** 上级公司ID, 无上级为0 */
+  parentId: number;
+  /** 公司名称 */
+  name: string;
+  /** 公司code */
+  code: string;
+  /** 公司描述 */
+  remark: string;
+  /** 状态: 0-启用, 1-禁用 */
+  status: number;
+  /** 创建时间 */
+  createdAt: string;
+  /** 更新时间 */
+  updatedAt: string;
+  /** 	0-未删除,大于0-已删除 */
+  isDeleted: number;
+  /** 下属工厂列表 */
+  workshopInfoList: WorkShopInfoItem[];
+};
+
+/** 获取公司-工厂-工位数据 */
+export const getShopSpaceList = () => {
+  return http.request<CompanyInfoItem[]>(
+    {
+      url: '/api/company/getCompanyShopSpaceList',
+      method: 'get',
+      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+    },
+    {
+      urlPrefix: 'temp',
+    },
+  );
+};
+
+export type CameraItem = {
+  /** 相机名称 */
+  name: string;
+  /** 相机code */
+  code: string;
+  /** 相机IP地址 */
+  cameraIp: string;
+  /** 相机描述 */
+  remark: string;
+  /** 状态: 0-启用, 1-禁用 */
+  status: number;
+};
+
+export type WorkSpaceCameraRelative = WorkSpaceInfoItem & { cameraList: CameraItem[] };
+
+export const getCamerasByWorkSpace = (params: { workshopId: number }) => {
+  return http.request<WorkSpaceCameraRelative[]>(
+    {
+      url: '/api/workshop/getWorkspaceCameraList',
+      method: 'get',
+      params,
+      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+    },
+    {
+      urlPrefix: 'temp',
+    },
+  );
+};

+ 81 - 0
src/hooks/useSceneInfos.ts

@@ -0,0 +1,81 @@
+import { ref } from 'vue';
+import {
+  CompanyInfoItem,
+  WorkShopInfoItem,
+  WorkSpaceInfoItem,
+  getShopSpaceList,
+  getCamerasByWorkSpace,
+} from '@/api/scene/scene';
+import { cloneDeep } from 'lodash-es';
+
+type ElTreeItem = {
+  value: any;
+  label: string;
+  children?: ElTreeItem[];
+};
+
+export function useSceneInfos() {
+  const scenesInfos = ref<CompanyInfoItem[]>([]);
+  const scenesTree = ref<ElTreeItem[]>([]);
+  const workSpaces = ref<WorkSpaceInfoItem[]>([]);
+  /** level:1-数据读取至公司 2-数据读取至工厂 3-数据读取至工位 */
+  const level = ref(1);
+
+  const getSpaceItems = (spaces: WorkSpaceInfoItem[]): ElTreeItem[] => {
+    return spaces.map((space) => {
+      workSpaces.value.push(space);
+      return {
+        value: JSON.stringify(space),
+        label: space.name,
+      };
+    });
+  };
+
+  const getShopItems = (shops: WorkShopInfoItem[]): ElTreeItem[] => {
+    return shops.map((shop) => {
+      const temp: any = cloneDeep(shop);
+      delete temp.workspaceInfoList;
+      const shopItem: ElTreeItem = {
+        value: JSON.stringify(temp),
+        label: shop.name,
+      };
+      if (level.value >= 3 && shop.workspaceInfoList && shop.workspaceInfoList.length > 0) {
+        shopItem.children = getSpaceItems(shop.workspaceInfoList);
+      }
+      return shopItem;
+    });
+  };
+
+  const calculateTreeData = (infos: CompanyInfoItem[]): ElTreeItem[] => {
+    return infos.map((company) => {
+      const temp: any = cloneDeep(company);
+      delete temp.workshopInfoList;
+      const companyItem: ElTreeItem = {
+        value: JSON.stringify(temp),
+        label: company.name,
+      };
+      if (level.value >= 2 && company.workshopInfoList && company.workshopInfoList.length > 0) {
+        companyItem.children = getShopItems(company.workshopInfoList);
+      }
+      return companyItem;
+    });
+  };
+
+  const getScenesTree = (_level: number) => {
+    level.value = _level;
+    getShopSpaceList().then((res) => {
+      scenesInfos.value = res;
+      scenesTree.value = calculateTreeData(res);
+    });
+  };
+
+  const getCameraList = (workshop: number) => {
+    return getCamerasByWorkSpace({ workshopId: workshop }).then((res) => {
+      return res;
+    });
+  };
+
+  return { scenesInfos, scenesTree, workSpaces, getScenesTree, getCameraList };
+}
+
+export default useSceneInfos;

+ 2 - 2
src/utils/http/axios/index.ts

@@ -227,9 +227,9 @@ const transform: AxiosTransform = {
           type: 'warning',
         })
           // eslint-disable-next-line prettier/prettier
-          .then(() => { })
+          .then(() => {})
           // eslint-disable-next-line prettier/prettier
-          .catch(() => { });
+          .catch(() => {});
         return Promise.reject(error);
       }
     } catch (error) {

+ 33 - 61
src/views/map-config/mini-map/MiniMapConfig.vue

@@ -5,9 +5,10 @@
         <span>场景:</span>
         <el-tree-select
           v-model="selectedShop"
-          :data="shopList"
+          :data="scenesTree"
           :render-after-expand="false"
           placeholder="请选择场景"
+          @change="changeShop"
         />
       </div>
       <div class="flex ml-20 items-center">
@@ -30,10 +31,16 @@
     <div class="paint-tool mt-10 flex">
       <div class="camera-list">
         <span class="label-text flex">相机列表:</span>
-        <div v-for="item in cameraList" :key="item.id" class="camera-item flex justify-start">
-          <span class="camera-id">{{ item.id }}</span>
-          <span>{{ item.workStation }}</span>
-        </div>
+        <el-scrollbar style="height: calc(100% - 50px)">
+          <div
+            v-for="item in shopCameraList"
+            :key="item.code"
+            class="camera-item flex justify-start"
+          >
+            <span class="camera-id">{{ item.name }}</span>
+            <span>{{ item.workSpaceName }}</span>
+          </div>
+        </el-scrollbar>
       </div>
       <div class="draw-container"></div>
     </div>
@@ -41,67 +48,15 @@
 </template>
 
 <script setup lang="ts">
-  import { ref } from 'vue';
+  import { onMounted } from 'vue';
   import { Plus } from '@element-plus/icons-vue';
   import useMiniMap from './use-mini-map';
   import { storeToRefs } from 'pinia';
+  import { ElMessage } from 'element-plus';
 
   const miniMap = useMiniMap();
-  const { selectedShop, bgImgUrl } = storeToRefs(miniMap);
-
-  const shopList = [
-    {
-      value: '1',
-      label: 'Level one 1',
-      children: [
-        {
-          value: '1-1',
-          label: 'Level two 1-1',
-          children: [
-            {
-              value: '1-1-1',
-              label: 'Level three 1-1-1',
-            },
-          ],
-        },
-      ],
-    },
-    {
-      value: '2',
-      label: 'Level one 2',
-      children: [
-        {
-          value: '2-1',
-          label: 'Level two 2-1',
-          children: [
-            {
-              value: '2-1-1',
-              label: 'Level three 2-1-1',
-            },
-          ],
-        },
-        {
-          value: '2-2',
-          label: 'Level two 2-2',
-          children: [
-            {
-              value: '2-2-1',
-              label: 'Level three 2-2-1',
-            },
-          ],
-        },
-      ],
-    },
-  ];
-
-  const cameraList = [
-    { id: 'ARJ-200-001', workStation: '200工位' },
-    { id: 'ARJ-200-002', workStation: '200工位' },
-    { id: 'ARJ-200-003', workStation: '200工位' },
-    { id: 'ARJ-200-004', workStation: '200工位' },
-    { id: 'ARJ-213-001', workStation: '213工位' },
-    { id: 'ARJ-213-002', workStation: '213工位' },
-  ];
+  const { selectedShop, bgImgUrl, scenesTree, shopCameraList } = storeToRefs(miniMap);
+  const { getScenesTree, getShowCameras } = miniMap;
 
   const beforeAvatarUpload = (rawFile) => {
     console.log('图片信息', rawFile);
@@ -118,6 +73,23 @@
   };
 
   const handleAvatarSuccess = () => {};
+
+  const changeShop = (newVal) => {
+    const info = JSON.parse(newVal);
+
+    if (info.parentId || info.parentId == 0) {
+      ElMessage({
+        message: '该场景暂无相机',
+        type: 'error',
+      });
+      return;
+    }
+    getShowCameras();
+  };
+
+  onMounted(() => {
+    getScenesTree(2);
+  });
 </script>
 
 <style scoped>

+ 30 - 2
src/views/map-config/mini-map/use-mini-map.ts

@@ -1,11 +1,39 @@
-import { ref } from 'vue';
+import { ref, toRefs } from 'vue';
+import useSceneInfos from '@/hooks/useSceneInfos';
+import { CameraItem } from '@/api/scene/scene';
 import { defineStore } from 'pinia';
 
+type ShopMapCamera = CameraItem & {
+  /** 相机是否已经设置 0-false 1-true */
+  isSet: number;
+  /** 工位名称 */
+  workSpaceName: string;
+};
+
 export const useMiniMap = defineStore('mini-map', () => {
+  const sceneInfos = useSceneInfos();
+  const { scenesTree } = toRefs(sceneInfos);
+  const { getScenesTree, getCameraList } = sceneInfos;
+
   const selectedShop = ref('');
   const bgImgUrl = ref('');
 
-  return { selectedShop, bgImgUrl };
+  const shopCameraList = ref<ShopMapCamera[]>([]);
+
+  const getShowCameras = () => {
+    shopCameraList.value = [];
+    getCameraList(JSON.parse(selectedShop.value).id).then((res) => {
+      res.forEach((space) => {
+        if (space.cameraList && space.cameraList.length > 0) {
+          space.cameraList.forEach((camera) => {
+            shopCameraList.value.push({ ...camera, isSet: 0, workSpaceName: space.name });
+          });
+        }
+      });
+    });
+  };
+
+  return { selectedShop, bgImgUrl, scenesTree, shopCameraList, getScenesTree, getShowCameras };
 });
 
 export default useMiniMap;