From b6aad0df3b7226fd5ad2ddeccd0851d72dc7fda4 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Fri, 09 May 2025 09:44:55 +0800
Subject: [PATCH] 个人工作台处理
---
src/views/wel/components/statistics.vue | 447 ++++++++++++++++
src/api/algorithm.js | 19
src/assets/images/workbench/fy1.png | 0
public/fonts/font.css | 53 +
src/assets/images/workbench/st1.png | 0
src/assets/images/workbench/jc1.png | 0
src/assets/images/workbench/st2.png | 0
src/utils/coordinateTransformation.js | 103 +++
src/assets/images/workbench/tc2.png | 0
src/assets/images/workbench/st6.png | 0
src/api/home/index.js | 50 +
src/views/wel/components/backlog.vue | 212 +++++++
src/assets/images/workbench/tc1.png | 0
src/assets/map_images/Startingpointicon.png | 0
src/assets/images/workbench/tc6.png | 0
src/assets/images/workbench/fy4.png | 0
public/fonts/SourceHanSansCN-Medium.otf | 0
src/views/algorithmRepository/algorithmRepository.vue | 336 ++++++++++++
src/assets/images/workbench/st3.png | 0
src/views/wel/components/calendarBox.vue | 158 +++++
public/fonts/YouSheBiaoTiHei.TTF | 0
src/assets/images/workbench/jc2.png | 0
src/assets/images/workbench/st7.png | 0
src/assets/images/workbench/st4.png | 0
src/views/wel/components/flyratio.vue | 198 +++++++
public/img/bg/index_logo2.png | 0
public/fonts/SourceHanSansCN-Bold.otf | 0
src/assets/images/workbench/fy3.png | 0
src/assets/images/workbench/tc5.png | 0
src/assets/images/ht-sfbg.png | 0
src/assets/images/ht-sfbg-hover.png | 0
src/hooks/useEchartsResize.js | 38 +
src/assets/map_images/EndPointicon.png | 0
src/assets/images/workbench/st8.png | 0
public/fonts/SourceHanSansCN-Regular.otf | 0
src/assets/images/workbench/fy2.png | 0
src/assets/images/workbench/st5.png | 0
src/assets/images/ht-sfbg-click.png | 0
src/assets/images/workbench/tc4.png | 0
src/assets/images/workbench/tc3.png | 0
src/assets/images/workbench/st9.png | 0
41 files changed, 1,614 insertions(+), 0 deletions(-)
diff --git a/public/fonts/SourceHanSansCN-Bold.otf b/public/fonts/SourceHanSansCN-Bold.otf
new file mode 100644
index 0000000..4b3429a
--- /dev/null
+++ b/public/fonts/SourceHanSansCN-Bold.otf
Binary files differ
diff --git a/public/fonts/SourceHanSansCN-Medium.otf b/public/fonts/SourceHanSansCN-Medium.otf
new file mode 100644
index 0000000..53e03e0
--- /dev/null
+++ b/public/fonts/SourceHanSansCN-Medium.otf
Binary files differ
diff --git a/public/fonts/SourceHanSansCN-Regular.otf b/public/fonts/SourceHanSansCN-Regular.otf
new file mode 100644
index 0000000..886f82f
--- /dev/null
+++ b/public/fonts/SourceHanSansCN-Regular.otf
Binary files differ
diff --git a/public/fonts/YouSheBiaoTiHei.TTF b/public/fonts/YouSheBiaoTiHei.TTF
new file mode 100644
index 0000000..3729151
--- /dev/null
+++ b/public/fonts/YouSheBiaoTiHei.TTF
Binary files differ
diff --git a/public/fonts/font.css b/public/fonts/font.css
new file mode 100644
index 0000000..f429581
--- /dev/null
+++ b/public/fonts/font.css
@@ -0,0 +1,53 @@
+@font-face {
+ font-family: "Source Han Sans CN";
+ src: url("SourceHanSansCN-Regular.otf") format("opentype");
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "Source Han Sans CN";
+ src: url("SourceHanSansCN-Medium.otf") format("opentype");
+ font-weight: 500;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "Source Han Sans CN";
+ src: url("SourceHanSansCN-Bold.otf") format("opentype") ;
+ font-weight: 700;
+ font-style: normal;
+}
+
+
+@font-face {
+ font-family: "Segoe UI";
+ src: url("SourceHanSansCN-Regular.otf") format("opentype");
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "Segoe UI";
+ src: url("SourceHanSansCN-Medium.otf") format("opentype");
+ font-weight: 500;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "Segoe UI";
+ src: url("SourceHanSansCN-Bold.otf") format("opentype") ;
+ font-weight: 700;
+ font-style: normal;
+}
+
+
+
+
+/* 额外的标题字体 */
+@font-face {
+ font-family: "YouSheBiaoTiHei";
+ src: url("YouSheBiaoTiHei.TTF") format("truetype");
+ font-weight: normal;
+ font-style: normal;
+}
diff --git a/public/img/bg/index_logo2.png b/public/img/bg/index_logo2.png
new file mode 100644
index 0000000..738596e
--- /dev/null
+++ b/public/img/bg/index_logo2.png
Binary files differ
diff --git a/src/api/algorithm.js b/src/api/algorithm.js
new file mode 100644
index 0000000..0543cdf
--- /dev/null
+++ b/src/api/algorithm.js
@@ -0,0 +1,19 @@
+// 算法仓库
+import request from '@/axios'
+// 图片列表
+export const getalgorithmList = (data, params) => {
+ return request({
+ url: `/drone-device-core/aiTmp/list`,
+ method: 'post',
+ data,
+ params
+ })
+ }
+//机巢查询
+export const selectDeviceList = data => {
+ return request({
+ url: `/drone-device-core/aiTmp/devices`,
+ method: 'get',
+ data: data,
+ })
+}
\ No newline at end of file
diff --git a/src/api/home/index.js b/src/api/home/index.js
new file mode 100644
index 0000000..f76f7d2
--- /dev/null
+++ b/src/api/home/index.js
@@ -0,0 +1,50 @@
+import request from '@/axios'
+// 事件概况总数
+export const getJobEventTotal = () => {
+ return request({
+ url: '/drone-device-core/jobEvent/total',
+ method: 'get',
+ })
+}
+// 事件概况分类数
+export const getJobEventByStatus = data => {
+ return request({
+ url: '/drone-device-core/jobEvent/eventByStatus',
+ method: 'post',
+ data,
+ })
+}
+// 行业任务统计
+export const industryJobNumPieChart = data => {
+ return request({
+ url: '/drone-device-core/jobEvent/deviceEventList',
+ method: 'post',
+ data: data,
+ })
+}
+// 事件任务统计
+export const jobEventBar = data => {
+ return request({
+ url: '/drone-device-core/wayline/waylineJobInfo/jobEventBar',
+ method: 'post',
+ data: data,
+ })
+}
+// 设备统计
+export const getStatics = (areaCode) => {
+ return request({
+ url: '/drone-device-core/manage/api/v1/devices/deviceStatistics',
+ method: 'post',
+ params: {
+ areaCode
+ },
+ });
+ };
+ // 日历
+export const getCalen = data => {
+ return request({
+ url: '/drone-device-core/wayline/waylineJobInfo/jobEventBar',
+ method: 'post',
+ data,
+ })
+}
\ No newline at end of file
diff --git a/src/assets/images/ht-sfbg-click.png b/src/assets/images/ht-sfbg-click.png
new file mode 100644
index 0000000..5d9c6da
--- /dev/null
+++ b/src/assets/images/ht-sfbg-click.png
Binary files differ
diff --git a/src/assets/images/ht-sfbg-hover.png b/src/assets/images/ht-sfbg-hover.png
new file mode 100644
index 0000000..3feee60
--- /dev/null
+++ b/src/assets/images/ht-sfbg-hover.png
Binary files differ
diff --git a/src/assets/images/ht-sfbg.png b/src/assets/images/ht-sfbg.png
new file mode 100644
index 0000000..c60dfd0
--- /dev/null
+++ b/src/assets/images/ht-sfbg.png
Binary files differ
diff --git a/src/assets/images/workbench/fy1.png b/src/assets/images/workbench/fy1.png
new file mode 100644
index 0000000..e215275
--- /dev/null
+++ b/src/assets/images/workbench/fy1.png
Binary files differ
diff --git a/src/assets/images/workbench/fy2.png b/src/assets/images/workbench/fy2.png
new file mode 100644
index 0000000..8af105a
--- /dev/null
+++ b/src/assets/images/workbench/fy2.png
Binary files differ
diff --git a/src/assets/images/workbench/fy3.png b/src/assets/images/workbench/fy3.png
new file mode 100644
index 0000000..0851dfb
--- /dev/null
+++ b/src/assets/images/workbench/fy3.png
Binary files differ
diff --git a/src/assets/images/workbench/fy4.png b/src/assets/images/workbench/fy4.png
new file mode 100644
index 0000000..79910c8
--- /dev/null
+++ b/src/assets/images/workbench/fy4.png
Binary files differ
diff --git a/src/assets/images/workbench/jc1.png b/src/assets/images/workbench/jc1.png
new file mode 100644
index 0000000..f3adde6
--- /dev/null
+++ b/src/assets/images/workbench/jc1.png
Binary files differ
diff --git a/src/assets/images/workbench/jc2.png b/src/assets/images/workbench/jc2.png
new file mode 100644
index 0000000..079fed4
--- /dev/null
+++ b/src/assets/images/workbench/jc2.png
Binary files differ
diff --git a/src/assets/images/workbench/st1.png b/src/assets/images/workbench/st1.png
new file mode 100644
index 0000000..ff489d1
--- /dev/null
+++ b/src/assets/images/workbench/st1.png
Binary files differ
diff --git a/src/assets/images/workbench/st2.png b/src/assets/images/workbench/st2.png
new file mode 100644
index 0000000..392672b
--- /dev/null
+++ b/src/assets/images/workbench/st2.png
Binary files differ
diff --git a/src/assets/images/workbench/st3.png b/src/assets/images/workbench/st3.png
new file mode 100644
index 0000000..f4a5b76
--- /dev/null
+++ b/src/assets/images/workbench/st3.png
Binary files differ
diff --git a/src/assets/images/workbench/st4.png b/src/assets/images/workbench/st4.png
new file mode 100644
index 0000000..b132892
--- /dev/null
+++ b/src/assets/images/workbench/st4.png
Binary files differ
diff --git a/src/assets/images/workbench/st5.png b/src/assets/images/workbench/st5.png
new file mode 100644
index 0000000..54387d3
--- /dev/null
+++ b/src/assets/images/workbench/st5.png
Binary files differ
diff --git a/src/assets/images/workbench/st6.png b/src/assets/images/workbench/st6.png
new file mode 100644
index 0000000..f7e73a7
--- /dev/null
+++ b/src/assets/images/workbench/st6.png
Binary files differ
diff --git a/src/assets/images/workbench/st7.png b/src/assets/images/workbench/st7.png
new file mode 100644
index 0000000..651c41b
--- /dev/null
+++ b/src/assets/images/workbench/st7.png
Binary files differ
diff --git a/src/assets/images/workbench/st8.png b/src/assets/images/workbench/st8.png
new file mode 100644
index 0000000..621ae26
--- /dev/null
+++ b/src/assets/images/workbench/st8.png
Binary files differ
diff --git a/src/assets/images/workbench/st9.png b/src/assets/images/workbench/st9.png
new file mode 100644
index 0000000..471e38c
--- /dev/null
+++ b/src/assets/images/workbench/st9.png
Binary files differ
diff --git a/src/assets/images/workbench/tc1.png b/src/assets/images/workbench/tc1.png
new file mode 100644
index 0000000..1a38d3e
--- /dev/null
+++ b/src/assets/images/workbench/tc1.png
Binary files differ
diff --git a/src/assets/images/workbench/tc2.png b/src/assets/images/workbench/tc2.png
new file mode 100644
index 0000000..e7a3721
--- /dev/null
+++ b/src/assets/images/workbench/tc2.png
Binary files differ
diff --git a/src/assets/images/workbench/tc3.png b/src/assets/images/workbench/tc3.png
new file mode 100644
index 0000000..86ac43f
--- /dev/null
+++ b/src/assets/images/workbench/tc3.png
Binary files differ
diff --git a/src/assets/images/workbench/tc4.png b/src/assets/images/workbench/tc4.png
new file mode 100644
index 0000000..86c6cec
--- /dev/null
+++ b/src/assets/images/workbench/tc4.png
Binary files differ
diff --git a/src/assets/images/workbench/tc5.png b/src/assets/images/workbench/tc5.png
new file mode 100644
index 0000000..a8e2670
--- /dev/null
+++ b/src/assets/images/workbench/tc5.png
Binary files differ
diff --git a/src/assets/images/workbench/tc6.png b/src/assets/images/workbench/tc6.png
new file mode 100644
index 0000000..fc7bfc7
--- /dev/null
+++ b/src/assets/images/workbench/tc6.png
Binary files differ
diff --git a/src/assets/map_images/EndPointicon.png b/src/assets/map_images/EndPointicon.png
new file mode 100644
index 0000000..eb54b86
--- /dev/null
+++ b/src/assets/map_images/EndPointicon.png
Binary files differ
diff --git a/src/assets/map_images/Startingpointicon.png b/src/assets/map_images/Startingpointicon.png
new file mode 100644
index 0000000..e79d9a6
--- /dev/null
+++ b/src/assets/map_images/Startingpointicon.png
Binary files differ
diff --git a/src/hooks/useEchartsResize.js b/src/hooks/useEchartsResize.js
new file mode 100644
index 0000000..76f9600
--- /dev/null
+++ b/src/hooks/useEchartsResize.js
@@ -0,0 +1,38 @@
+import * as echarts from 'echarts'
+
+
+/**
+ * ECharts自适应容器大小Hook
+ *
+ * @param {Object} domRef - DOM元素引用对象,需包含value属性指向要挂载的DOM节点
+ * @returns {Object} chart - 包含value属性的对象,value保存ECharts实例引用
+ */
+const useEchartsResize = (domRef) => {
+ // 图表实例容器,用对象包装便于保持引用地址
+ const chart = {value: null}
+
+ // 窗口大小变化处理函数
+ const resizeChart = () => {
+ chart.value?.resize()
+ }
+
+ // 组件挂载后初始化逻辑
+ onMounted(() => {
+ if (!domRef.value) return
+ // 初始化ECharts实例并注册resize监听
+ chart.value = echarts.init(domRef.value)
+ window.addEventListener('resize', resizeChart)
+ })
+
+ // 组件卸载前清理逻辑
+ onBeforeUnmount(() => {
+ // 移除监听并清理图表实例
+ window.removeEventListener('resize', resizeChart)
+ chart.value?.dispose()
+ chart.value = null
+ })
+
+ return {chart}
+}
+
+export default useEchartsResize
diff --git a/src/utils/coordinateTransformation.js b/src/utils/coordinateTransformation.js
new file mode 100644
index 0000000..b451e3b
--- /dev/null
+++ b/src/utils/coordinateTransformation.js
@@ -0,0 +1,103 @@
+/*
+ * @Author: GuLiMmo 2820890765@qq.com
+ * @Date: 2024-06-12 13:51:57
+ * @LastEditors: GuLiMmo 2820890765@qq.com
+ * @LastEditTime: 2024-06-12 13:54:00
+ * @FilePath: /bigScreen/src/utils/coordinateTransformation.js
+ * @Description:
+ * Copyright (c) 2024 by GuLiMmo, All Rights Reserved.
+ */
+const PI = Math.PI;
+const a = 6378245.0;
+const ee = 0.00669342162296594323;
+
+export function wgs84ToGcj02(lng, lat) {
+ if (out_of_china(lng, lat)) {
+ return [lng, lat];
+ } else {
+ var dlat = transformlat(lng - 105.0, lat - 35.0);
+ var dlng = transformlng(lng - 105.0, lat - 35.0);
+ var radlat = (lat / 180.0) * PI;
+ var magic = Math.sin(radlat);
+ magic = 1 - ee * magic * magic;
+ var sqrtmagic = Math.sqrt(magic);
+ dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
+ dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
+ var mglat = lat + dlat;
+ var mglng = lng + dlng;
+ return [mglng, mglat];
+ }
+}
+
+export function gcj02ToWgs84(lng, lat) {
+ if (out_of_china(lng, lat)) {
+ return [lng, lat];
+ } else {
+ var dlat = transformlat(lng - 105.0, lat - 35.0);
+ var dlng = transformlng(lng - 105.0, lat - 35.0);
+ var radlat = (lat / 180.0) * PI;
+ var magic = Math.sin(radlat);
+ magic = 1 - ee * magic * magic;
+ var sqrtmagic = Math.sqrt(magic);
+ dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
+ dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
+ var mglat = lat + dlat;
+ var mglng = lng + dlng;
+ return [lng * 2 - mglng, lat * 2 - mglat];
+ }
+}
+
+function transformlat(lng, lat) {
+ var ret =
+ -100.0 +
+ 2.0 * lng +
+ 3.0 * lat +
+ 0.2 * lat * lat +
+ 0.1 * lng * lat +
+ 0.2 * Math.sqrt(Math.abs(lng));
+ ret +=
+ ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
+ 2.0) /
+ 3.0;
+ ret +=
+ ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) *
+ 2.0) /
+ 3.0;
+ ret +=
+ ((160.0 * Math.sin((lat / 12.0) * PI) +
+ 320 * Math.sin((lat * PI) / 30.0)) *
+ 2.0) /
+ 3.0;
+ return ret;
+}
+
+function transformlng(lng, lat) {
+ var ret =
+ 300.0 +
+ lng +
+ 2.0 * lat +
+ 0.1 * lng * lng +
+ 0.1 * lng * lat +
+ 0.1 * Math.sqrt(Math.abs(lng));
+ ret +=
+ ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) *
+ 2.0) /
+ 3.0;
+ ret +=
+ ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) *
+ 2.0) /
+ 3.0;
+ ret +=
+ ((150.0 * Math.sin((lng / 12.0) * PI) +
+ 300.0 * Math.sin((lng / 30.0) * PI)) *
+ 2.0) /
+ 3.0;
+ return ret;
+}
+
+// 判断是否在国内,不在国内则不做偏移
+function out_of_china(lng, lat) {
+ return (
+ lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271 || false
+ );
+}
diff --git a/src/views/algorithmRepository/algorithmRepository.vue b/src/views/algorithmRepository/algorithmRepository.vue
new file mode 100644
index 0000000..ac63bf2
--- /dev/null
+++ b/src/views/algorithmRepository/algorithmRepository.vue
@@ -0,0 +1,336 @@
+<template>
+ <basic-container>
+ <div class="algorithContainer">
+ <div class="algorithItem" v-if="!showDetail">
+ <div
+ class="item"
+ v-for="(item, index) in AlgorithmData"
+ :key="index"
+ :class="{ 'active-bg': activeItem === item.dictValue }"
+ @click="jumpDatail(item)"
+ >
+ <img class="imgicon" :src="`${baseUrl}/后台-算法仓库/${item.dictValue}.png`" alt="" />
+ <div>{{ item.dictValue }}</div>
+ <div
+ :class="!statusSign && item.dictValue === nameSign ? 'stopStatus' : 'normalStatus'"
+ @click.stop="changeStatus(item)"
+ >
+ {{ !statusSign && item.dictValue === nameSign ? '停用状态' : '正常状态' }}
+ </div>
+ </div>
+ </div>
+ <!-- 详情页 -->
+ <div class="algorithItemDetail" v-else>
+ <div class="search">
+ <div class="searchBox">
+ <div class="item">
+ <div class="itemchild">模糊查询:</div>
+ <el-input
+ v-model="params.name"
+ class="filter-item"
+ placeholder="请输入事件名称"
+ clearable
+ ></el-input>
+ </div>
+ <div class="item">
+ <el-date-picker
+ type="daterange"
+ range-separator="至"
+ start-placeholder="开始日期"
+ end-placeholder="结束日期"
+ value-format="YYYY-MM-DD"
+ v-model="taskData"
+ placeholder="请选择日期"
+ @change="changeselect"
+ />
+ </div>
+ <div class="item">
+ <div class="itemchild">机巢查询:</div>
+ <el-select v-model="params.device_name" placeholder="请选择" class="filter-item">
+ <el-option v-for="item in jcoptions" :key="item" :label="item" :value="item" />
+ </el-select>
+ </div>
+ </div>
+ <div class="search-btn">
+ <el-button type="primary" icon="el-icon-back" @click="goback">返回</el-button>
+ <el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
+ <el-button icon="el-icon-delete" @click="handleReset">清空</el-button>
+ </div>
+ </div>
+
+ <div
+ class="pictureitem"
+ v-if="detailData.length > 0"
+ v-loading="loading"
+ element-loading-text="加载中"
+ >
+ <div class="imgitem" v-for="(item, index) in detailData" :key="index">
+ <img :src="item.url" alt="" />
+ <div class="info">
+ <div class="name">{{ item.name }}</div>
+ <div class="time">{{ item.create_time.slice(5, 16).replace('-', '/', 1) }}</div>
+ </div>
+ </div>
+ </div>
+ <el-empty class="custom-empty" v-else>
+ <template #description>
+ <span class="custom-text">暂无数据</span>
+ </template>
+ </el-empty>
+ <!-- 分页 -->
+ <el-pagination
+ class="pageStyle"
+ background
+ :page-sizes="[10, 20, 30, 50]"
+ v-model:current-page="params.current"
+ v-model:page-size="params.size"
+ layout="total, prev, pager, next,sizes, jumper"
+ :total="total"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+ </div>
+ </basic-container>
+</template>
+
+<script setup>
+defineOptions({
+ name: 'algorithmRepository',
+});
+import { getDictionaryByCode } from '@/api/system/dictbiz';
+import { getalgorithmList, selectDeviceList } from '@/api/algorithm';
+
+import { useRouter } from 'vue-router';
+const router = useRouter();
+const baseUrl = import.meta.env.VITE_APP_TERRAIN_URL;
+const showDetail = ref(false);
+const taskData = ref('');
+const jcvalue = ref('');
+const jcoptions = ref([]);
+const total = ref(0);
+const loading = ref(true);
+const params = ref({
+ ai_type_key: '',
+ start_date: null,
+ end_date: null,
+ device_name: '',
+ name: '',
+ current: 1,
+ size: 10,
+});
+// 请求字典字段
+let AlgorithmData = ref([]);
+const detailData = ref([]);
+const requestDictionary = () => {
+ getDictionaryByCode('SF').then(res => {
+ if (res.code !== 0) {
+ // 处理数据
+ AlgorithmData.value = res.data.data['SF'];
+ }
+ });
+};
+const activeItem = ref(null);
+const jumpDatail = val => {
+ showDetail.value = true;
+ activeItem.value = val.dictValue;
+ params.value.ai_type_key = val.dictKey;
+ getList();
+};
+const statusSign = ref(true);
+const nameSign = ref('');
+const changeStatus = val => {
+ nameSign.value = val.dictValue;
+ statusSign.value = !statusSign.value;
+};
+// 详情
+const getList = () => {
+ getalgorithmList(params.value).then(res => {
+ loading.value = true;
+ detailData.value = res.data.data.records;
+ total.value = res.data.data.total;
+ setTimeout(() => {
+ loading.value = false;
+ }, 1000);
+ });
+};
+// 机巢查询
+const getDeviceList = () => {
+ selectDeviceList().then(res => {
+ jcoptions.value = res.data.data;
+ });
+};
+// 日期选择
+const changeselect = () => {
+ params.value.start_date = taskData.value.length ? `${taskData.value[0]} 00:00:00` : null;
+ params.value.end_date = taskData.value.length ? `${taskData.value[1]} 23:59:59` : null;
+};
+const handleSearch = () => {
+ getList();
+};
+const handleReset = () => {
+ params.value.start_date = null;
+ params.value.end_date = null;
+ params.value.device_name = '';
+ params.value.name = '';
+ getList();
+};
+const goback = () => {
+ showDetail.value = false;
+ activeItem.value = null;
+};
+// 分页大小改变
+const handleSizeChange = val => {
+ params.size = val;
+ getList();
+};
+// 页码改变
+const handleCurrentChange = val => {
+ params.current = val;
+ getList();
+};
+onMounted(() => {
+ requestDictionary();
+ getDeviceList();
+});
+</script>
+
+<style scoped lang="scss">
+.algorithItem {
+ padding: 20px;
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ gap: 53px;
+ text-align: center;
+ vertical-align: middle;
+ .item {
+ height: 300px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ background: url('/src/assets/images/ht-sfbg.png') no-repeat center;
+ background-size: 100% 100%;
+ .imgicon {
+ width: 100px;
+ height: 100px;
+ margin-bottom: 47px;
+ }
+ &:hover {
+ background: url('/src/assets/images/ht-sfbg-hover.png') no-repeat center;
+ background-size: 100% 100%;
+ }
+ &.active-bg {
+ background: url('/src/assets/images/ht-sfbg-click.png') no-repeat center;
+ background-size: 100% 100%;
+ }
+
+ .normalStatus {
+ width: 116px;
+ height: 43px;
+ background: #ebfbee;
+ border-radius: 50px;
+ text-align: center;
+ line-height: 43px;
+ font-weight: 400;
+ font-size: 16px;
+ color: #029d36;
+ margin-top: 23px;
+ cursor: pointer;
+ }
+ .stopStatus {
+ width: 116px;
+ height: 43px;
+ background: #e8e8e8;
+ border-radius: 50px 50px 50px 50px;
+ text-align: center;
+ line-height: 43px;
+ font-weight: 400;
+ font-size: 16px;
+ color: #464747;
+ margin-top: 23px;
+ cursor: pointer;
+ }
+ .normalStatus:hover {
+ background: rgba(6, 217, 87, 0.2);
+ }
+ }
+}
+.algorithItemDetail {
+ padding: 20px;
+
+ .pictureitem {
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ gap: 24px;
+
+ .imgitem {
+ border-radius: 12px 12px 0 0;
+ overflow: hidden;
+ img {
+ width: 100%;
+ height: 200px;
+ display: block;
+ margin: 0;
+ padding: 0;
+ }
+ .info {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ height: 42px;
+ border-radius: 0 0 12px 12px;
+ overflow: hidden;
+ background: linear-gradient(180deg, #ffffff 0%, #e5edff 100%);
+ border: 1px solid #1c5cff;
+ border-top: none !important;
+
+ .name {
+ margin-left: 12px;
+ font-weight: 500;
+ font-size: 16px;
+ color: #363636;
+ }
+ .time {
+ margin-right: 12px;
+ font-weight: 500;
+ font-size: 14px;
+ color: #595959;
+ }
+ }
+ }
+ }
+ .search {
+ display: flex;
+ justify-content: space-between;
+ }
+ .searchBox {
+ display: flex;
+ align-items: center;
+ margin-bottom: 27px;
+ .itemchild {
+ white-space: nowrap;
+ margin-right: 5px;
+ font-weight: 400;
+ font-size: 14px;
+ color: #363636;
+ }
+ .item {
+ display: flex;
+ align-items: center;
+ margin-right: 49px;
+ }
+ }
+ .search-btn {
+ display: flex;
+ }
+ .filter-item {
+ width: 218px;
+ }
+}
+.pageStyle {
+ margin-top: 32px;
+ display: flex;
+ justify-content: right;
+}
+</style>
diff --git a/src/views/wel/components/backlog.vue b/src/views/wel/components/backlog.vue
new file mode 100644
index 0000000..8b302b8
--- /dev/null
+++ b/src/views/wel/components/backlog.vue
@@ -0,0 +1,212 @@
+<template>
+ <div class="bocklogBox">
+ <div class="block">
+ <div class="title">待办事项</div>
+
+ <div class="todo-items">
+ <div
+ v-for="(item, index) in todos"
+ :key="index"
+ class="todo-item"
+ :class="`status-${item.status}`"
+ >
+ <div class="status-indicator"></div>
+
+ <div class="content-wrapper">
+ <div class="main-content">
+ <span class="status-tag">{{ statusMap[item.status] }}</span>
+ <span class="todo-text">{{ item.title }}</span>
+ </div>
+
+ <div class="action-area">
+ <img :src="st7" alt="">
+ <span class="todo-date">{{ item.date }}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import st7 from '@/assets/images/workbench/st7.png'
+// 状态显示映射
+const statusMap = {
+ pending: '待审核',
+ processing: '处理中',
+ todo: '待处理',
+};
+
+// 待办事项数据
+const todos = ref([
+ {
+ status: 'pending',
+ title: '发现暴露垃圾事件',
+ date: '2025.03.26',
+ },
+ {
+ status: 'todo',
+ title: '发现暴露垃圾事件',
+ date: '2025.03.26',
+ },
+ {
+ status: 'processing',
+ title: '发现暴露垃圾事件',
+ date: '2025.03.26',
+ },
+ {
+ status: 'pending',
+ title: '发现暴露垃圾事件',
+ date: '2025.03.26',
+ },
+ {
+ status: 'todo',
+ title: '发现暴露垃圾事件',
+ date: '2025.03.26',
+ },
+]);
+</script>
+
+<style lang="scss" scoped>
+.bocklogBox {
+ width: 100%;
+ height: 306px;
+ background: rgba(255, 255, 255, 0.41);
+ box-shadow: 0px 3px 4px -1px rgba(125, 125, 125, 0.25);
+ border-radius: 8px 8px 8px 8px;
+ border: 2px solid #ffffff;
+ .block {
+ margin: 11px 21px 13px 22px;
+ .title {
+ font-weight: bold;
+ font-size: 16px;
+ color: #363636;
+ }
+
+ .todo-items {
+ display: grid;
+ gap: 0.8rem;
+ margin-top: 10px;
+ }
+
+ .todo-item {
+ display: flex;
+ align-items: center;
+
+ background: #FFFFFF;
+ border-radius: 8px;
+ box-shadow: 0px 2px 4px 0px rgba(173, 173, 173, 0.18);
+ transition: all 0.2s ease;
+ border-left: 4px solid transparent;
+ height: 42px;
+ &:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.05);
+ }
+
+ .status-indicator {
+ margin-left: 18px;
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ flex-shrink: 0;
+ }
+
+ .content-wrapper {
+ flex: 1;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 1rem;
+ }
+
+ .main-content {
+ display: flex;
+ align-items: center;
+ gap: 0.8rem;
+
+ .status-tag {
+ font-weight: 400;
+ font-size: 14px;
+
+ padding: 0.3rem 0.5rem;
+ border-radius: 12px;
+ }
+
+ .todo-text {
+ font-size: 14px;
+ color: #343434;
+ }
+ }
+
+ .action-area {
+ display: flex;
+ align-items: center;
+ margin-right: 42px;
+
+ .todo-date {
+ color: #666;
+ font-size: 0.9rem;
+ }
+
+
+ }
+ }
+
+ // 状态颜色方案
+ .status-pending {
+ border-left-color: #FF6560;
+ color: #FF6560;
+ .status-indicator {
+ background: #FF6560;
+ }
+ }
+
+ .status-todo {
+ border-left-color: #5D77FB;
+ color: #5D77FB;
+ .status-indicator {
+ background: #5D77FB;
+ }
+ }
+
+ .status-processing {
+ border-left-color: #FF8B26;
+ color: #FF8B26;
+
+ .status-indicator {
+ background: #FF8B26;
+ }
+ }
+ }
+
+ // @media (max-width: 768px) {
+ // .todo-list-container {
+ // padding: 1rem;
+
+ // .content-wrapper {
+ // flex-direction: column;
+ // align-items: flex-start !important;
+ // gap: 0.5rem !important;
+ // }
+
+ // .action-area {
+ // width: 100%;
+ // justify-content: space-between;
+ // }
+ // }
+ // }
+
+ // @media (max-width: 480px) {
+ // .main-content {
+ // flex-direction: column;
+ // align-items: flex-start !important;
+ // }
+
+ // .status-tag {
+ // margin-bottom: 0.3rem;
+ // }
+ // }
+}
+</style>
diff --git a/src/views/wel/components/calendarBox.vue b/src/views/wel/components/calendarBox.vue
new file mode 100644
index 0000000..aea2ade
--- /dev/null
+++ b/src/views/wel/components/calendarBox.vue
@@ -0,0 +1,158 @@
+<template>
+ <div class="calenBox">
+ <el-calendar ref="calendar" v-model="leftValue" @change="handleMonthChange(date)">
+ <template #date-cell="{ data }">
+ <div>
+ <div class="date-number">{{ data.day.slice(8, 10) }}</div>
+ <div class="events">
+ <div
+ v-for="(event, index) in getEvents(data.day)"
+ :key="index"
+ class="event-item"
+ :class="event.type"
+ >
+ <span></span>
+ {{ event.content }}
+ </div>
+ </div>
+ </div>
+ </template>
+ </el-calendar>
+ </div>
+</template>
+
+<script setup>
+import dayjs from 'dayjs';
+import { jobEventBar, getCalen } from '@/api/home/index';
+// 日历事件数据
+// 格式: 'YYYY-MM-DD': [...events]
+const events = ref({
+ '2025-05-01': [
+ { type: 'work-order', content: '工单26' },
+ { type: 'task', content: '任务26' },
+ ],
+ '2025-05-04': [
+ { type: 'task', content: '任务26' },
+ { type: 'work-order', content: '工单26' },
+ ],
+});
+const params = ref({
+ end_date: undefined,
+ start_date: undefined,
+});
+
+function getCurrentMonthRange() {
+ return {
+ start_date: dayjs().startOf('month').format('YYYY-MM-DD HH:mm:ss'),
+ end_date: dayjs().endOf('month').format('YYYY-MM-DD HH:mm:ss'),
+ };
+}
+const leftValue = ref(new Date());
+watch(
+ () => leftValue.value,
+ (newV, oldV) => {
+ if (newV && dayjs(newV).isSame(dayjs(), 'day')) {
+ console.log('点击了今天');
+ }
+
+ if (newV && oldV) {
+ const newDate = dayjs(newV);
+ const oldDate = dayjs(oldV);
+
+ // 格式化为 YYYY-MM-DD HH:mm:ss
+ const newDateStr = newDate.format('YYYY-MM-DD HH:mm:ss');
+ const oldDateStr = oldDate.format('YYYY-MM-DD HH:mm:ss');
+ params.
+ console.log('新日期:', newDateStr, '旧日期:', oldDateStr);
+
+ if (newDate.isBefore(oldDate, 'month')) {
+ console.log('点击了上个月',newDateStr);
+ } else if (newDate.isAfter(oldDate, 'month')) {
+ console.log('点击了下个月',newDateStr);
+ }
+ }
+ },
+ { deep: true }
+);
+const handleMonthChange = date => {
+ console.log('date', date);
+
+ // 获取当前视图月份的第一天
+ const firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
+
+ // 获取当前视图月份的最后一天
+ const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
+
+ // 格式化为YYYY-MM-DD格式(可选)
+ const formatDate = d => d.toISOString().slice(0, 10);
+
+ console.log('首日:', formatDate(firstDay));
+ console.log('末日:', formatDate(lastDay));
+};
+// 获取日期数字
+const getDate = date => {
+ return date.getDate();
+};
+// 获取对应日期的事件
+const getEvents = dateString => {
+ // console.log('000',dateString);
+
+ return events.value[dateString] || [];
+};
+const getJobEventBar = () => {
+ const monthRange = getCurrentMonthRange();
+ params.value = monthRange;
+ console.log(monthRange);
+ getCalen(params.value).then(res => {
+ if (res.data.code !== 0) return;
+ // events.value = res.data.data
+ console.log('日历', res.data.data);
+ });
+};
+onMounted(() => {
+ getJobEventBar();
+});
+</script>
+
+<style lang="scss" scoped>
+.calenBox {
+ margin-top: 10px;
+ height: 546px;
+ overflow: hidden;
+ .event-item {
+ font-size: 12px;
+ padding: 2px;
+ margin: 2px 0;
+ border-radius: 3px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ &.work-order {
+ // background: #ecf5ff;
+ color: #409eff;
+ span {
+ display: inline-block;
+ width: 7px;
+ height: 7px;
+ background: #1c5cff;
+ border-radius: 50%;
+ margin-right: 2px;
+ }
+ }
+
+ &.task {
+ // background: #f0f9eb;
+ color: #67c23a;
+ span {
+ display: inline-block;
+ width: 7px;
+ height: 7px;
+ background: #029d36;
+ border-radius: 50%;
+ margin-right: 2px;
+ }
+ }
+ }
+}
+</style>
diff --git a/src/views/wel/components/flyratio.vue b/src/views/wel/components/flyratio.vue
new file mode 100644
index 0000000..38fc011
--- /dev/null
+++ b/src/views/wel/components/flyratio.vue
@@ -0,0 +1,198 @@
+<template>
+ <div class="machineNest">
+ <div class="nestTop">
+ <div class="card-title">
+ <img :src="jc1" alt="" />
+ <div class="cardtotal">
+ <p>机巢事件数量排名</p>
+ <!-- <div class="total-number">111</div>
+ <span>个</span> -->
+ </div>
+ </div>
+ <!-- <div class="status-grid">
+ <div v-for="(item, index) in jcOrder" :key="index" class="status-item">
+ <img :src="jc2" alt="" />
+ <div>
+ <div class="status-label">{{ item.name }}</div>
+ <div :style="{ color: '#387FC8' }" class="status-value">
+ {{ item.value }}
+ </div>
+ </div>
+ </div>
+ </div> -->
+ </div>
+ <div class="nestCenter">
+ <div class="chart" ref="echartsRef"></div>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import * as echarts from 'echarts';
+import useEchartsResize from '@/hooks/useEchartsResize';
+import jc1 from '@/assets/images/workbench/jc1.png';
+import jc2 from '@/assets/images/workbench/jc2.png';
+import { industryJobNumPieChart } from '@/api/home/index';
+const echartsRef = ref(null);
+let { chart: jcchart } = useEchartsResize(echartsRef);
+const jcOrder = ref([]);
+// 获取机巢事件数据
+const getIndustryJobNumPieChart = value => {
+ industryJobNumPieChart(value).then(res => {
+ const resList = res?.data?.data || [];
+ jcOrder.value = resList;
+ pieInit(resList);
+ });
+};
+const pieInit = resList => {
+ // 处理数据,过滤掉没有name的项
+ const validData = resList.filter(item => item.name);
+
+ // 准备图表数据
+ const optionData = {
+ yAxisData: validData.map(item => item.name),
+ seriesData: validData.map(item => item.value),
+ };
+
+ const option = {
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow',
+ },
+ formatter: '{b}: {c}',
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true,
+ },
+ xAxis: {
+ type: 'value',
+ splitLine: {
+ lineStyle: {
+ color: '#E5E5E5',
+ },
+ },
+ axisLabel: {
+ color: '#35455aa6',
+ },
+ boundaryGap: [0, 0.01],
+ },
+ yAxis: {
+ type: 'category',
+ data: optionData.yAxisData, // 使用处理后的分类数据
+ axisLabel: {
+ color: '#35455aa6',
+ },
+ axisLine: {
+ lineStyle: {
+ color: '#D1D1D1',
+ },
+ },
+ axisTick: {
+ show: false,
+ },
+ },
+ series: [
+ {
+ type: 'bar',
+ data: optionData.seriesData, // 使用处理后的数值数据
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+ { offset: 0, color: '#93BAFF' },
+ { offset: 1, color: '#C5DEFF' },
+ ]),
+ },
+ barWidth: '30%',
+ label: {
+ show: true,
+ position: 'right',
+ formatter: '{c}',
+ },
+ },
+ ],
+ };
+
+ jcchart.value.setOption(option);
+};
+onMounted(() => {
+ getIndustryJobNumPieChart({ date_enum: 'CURRENT_WEEK' });
+});
+</script>
+
+<style scoped lang="scss">
+.machineNest {
+ .nestTop {
+ .card-title {
+ display: flex;
+ margin-left: 57px;
+ margin-bottom: 15px;
+ align-items: center;
+ img {
+ width: 36px;
+ height: 40px;
+ }
+ }
+ .cardtotal {
+ display: flex;
+ align-items: center;
+ margin-left: 9px;
+ p {
+ font-weight: bold;
+ font-size: 14px;
+ color: #363636;
+ }
+ span {
+ font-weight: 400;
+ font-size: 14px;
+ color: #7c8091;
+ }
+ .total-number {
+ font-family: 'YouSheBiaoTiHei';
+ font-weight: bold;
+ font-size: 32px;
+ color: #2a54ff;
+ }
+ }
+ .status-grid {
+ margin-left: 30px;
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ row-gap: 17px;
+ .status-item {
+ display: flex;
+ text-align: center;
+ align-items: center;
+ justify-content: center;
+ background: #f6f8fe;
+ margin-right: 10px;
+ padding: 10px;
+ img {
+ width: 40px;
+ height: 40px;
+ margin-right: 13px;
+ }
+ .status-label {
+ font-size: 14px;
+ color: #383838;
+ }
+ .status-value {
+ font-family: 'YouSheBiaoTiHei';
+ font-weight: bold;
+ font-size: 20px;
+ }
+ }
+ }
+ }
+ .nestCenter {
+ width: 100%;
+ height: 600px;
+ .chart {
+ width: 100%;
+ height: 100%;
+ }
+ }
+}
+</style>
diff --git a/src/views/wel/components/statistics.vue b/src/views/wel/components/statistics.vue
new file mode 100644
index 0000000..c4cda57
--- /dev/null
+++ b/src/views/wel/components/statistics.vue
@@ -0,0 +1,447 @@
+<template>
+ <div class="statistics">
+ <div class="title">
+ <div class="name">
+ <span> 设备统计</span>
+ <img src="/src/assets/images/workbench/st1.png" alt="" />
+ </div>
+ <div class="arrow">
+ <img src="/src/assets/images/workbench/st2.png" alt="" />
+ </div>
+ </div>
+ <!-- <div class="grid-container">
+ <div v-for="(item, index) in Object.keys(newtitleData)" :key="index" class="device-card">
+ <div class="device-title">
+ <img :src="test[item].img" :alt="newtitleData[item].name" />
+ <div class="itemcenter">
+ <div>{{ test[item]?.name || '--' }}</div>
+ <span class="shu">{{ newtitleData[item].total_num }}</span>
+ <span>个</span>
+ </div>
+ </div>
+ <div class="status-list">
+
+ <div
+ v-for="(status, statusIndex) in newtitleData[item].status_map"
+ :key="statusIndex"
+ class="status-item"
+ :class="getStatusStyle(test[item]?.name, statusIndex)"
+ :style="{ color: getStatusColor(test[item]?.name, statusIndex) }"
+ >
+ <span class="indicator"></span>
+ <span class="label">{{ getStatusLabel(test[item]?.name, statusIndex) }}</span>
+ <span class="count"
+ >{{ status }} {{ test[item]?.name === '无人机' ? '架' : '个' }}</span
+ >
+ </div>
+ </div>
+ </div>
+ </div> -->
+ <div class="grid-container1">
+ <div v-for="(item, index) in Object.keys(newtitleData)" :key="index" class="device-card">
+ <div class="device-title">
+ <img :src="test[item].img" :alt="newtitleData[item].name" />
+ <div class="itemcenter">
+ <div>{{ test[item]?.name || '--' }}</div>
+ <span class="shu">{{ newtitleData[item].total_num }}</span>
+ <span>个</span>
+ </div>
+ </div>
+ <div class="status-list">
+ <!-- :class="`status-${statusIndex}`" -->
+ <div
+ v-for="(status, statusIndex) in newtitleData[item].status_map"
+ :key="statusIndex"
+ class="status-item"
+ :class="getStatusStyle(test[item]?.name, statusIndex)"
+ :style="{ color: getStatusColor(test[item]?.name, statusIndex) }"
+ >
+ <span
+ class="indicator"
+ :style="{
+ backgroundColor: getStatusBackground(test[item]?.name, statusIndex),
+ color: getStatusColor(test[item]?.name, statusIndex),
+ }"
+ ></span>
+ <span class="label">{{ getStatusLabel(test[item]?.name, statusIndex) }}</span>
+ <span class="count"
+ >{{ status }} {{ test[item]?.name === '无人机' ? '架' : '个' }}</span
+ >
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { useStore } from 'vuex';
+import { computed } from 'vue';
+import titleImg1 from '@/assets/images/workbench/st3.png';
+import titleImg2 from '@/assets/images/workbench/st4.png';
+import titleImg3 from '@/assets/images/workbench/st5.png';
+import titleImg4 from '@/assets/images/workbench/st6.png';
+import titleImg5 from '@/assets/images/workbench/st8.png';
+import titleImg6 from '@/assets/images/workbench/st9.png';
+import { getStatics } from '@/api/home/index';
+const store = useStore();
+Object.key;
+const userInfo = computed(() => store.getters.userInfo);
+const newtitleData = ref({});
+const test = {
+ no_move_list: {
+ name: '机巢',
+ img: titleImg1,
+ },
+ plant_list: {
+ name: '无人机',
+ img: titleImg2,
+ },
+ flow_type_list: {
+ name: '机巢流量',
+ img: titleImg3,
+ },
+ monitor_list: {
+ name: '监控设备',
+ img: titleImg4,
+ },
+ move_list: {
+ name: '移动机巢',
+ img: titleImg5,
+ },
+
+ insure_list: {
+ name: '机巢保险',
+ img: titleImg6,
+ },
+};
+const statusSelect = {
+ 0: '空闲中',
+ 4: '作业中',
+ '-1': '离线中',
+};
+// 流量 状态 0充足,1=流量到期,2=不足
+const flowStatus = {
+ 0: '流量无忧',
+ 1: '流量到期',
+ 2: '流量不足',
+};
+// "监控状态 1=在线,0=离线"
+const monitorStatus = {
+ 0: '离线中',
+ 1: '在线中',
+};
+// 机巢保险 1=保险,0=未保险
+const insureStatus = {
+ 0: '临近到期',
+ 1: '正常期限',
+};
+// 样式配置对象
+const statusStyles = {
+ 机巢保险: {
+ 0: { class: 'expired', color: '#7C8091', background: '#7C8091' },
+ 1: { class: 'normal', color: '#1B94FF', background: '#1B94FF' },
+ },
+
+ 机巢流量: {
+ 0: { class: 'offline', color: '#11CE3E', background: '#11CE3E' },
+ 1: { class: 'flying', color: '#1B94FF', background: '#1B94FF' },
+ 2: { class: 'flying', color: '#7C8091', background: '#7C8091' },
+ },
+ 监控设备: {
+ 0: { class: 'offline', color: '#bababa', background: '#bababa' },
+ 1: { class: 'flying', color: '#1B94FF', background: '#1B94FF' },
+ },
+ // 默认样式配置
+ default: {
+ 0: { class: 'warning', color: '#1b94ff', background: '#1b94ff' },
+ 4: { class: 'success', color: '#11ce3e', background: '#11ce3e' },
+ '-1': { class: 'success', color: '#bababa', background: '#bababa' },
+ },
+};
+const getStatusStyle = (name, statusIndex) => {
+ // 获取样式配置,优先使用名称专属配置
+ const styleConfig = statusStyles[name] || statusStyles.default;
+ return styleConfig[statusIndex]?.class || '';
+};
+
+const getStatusColor = (name, statusIndex) => {
+ // 获取颜色配置,优先使用名称专属配置
+ const styleConfig = statusStyles[name] || statusStyles.default;
+ return styleConfig[statusIndex]?.color || '#333';
+};
+// 新增背景颜色获取方法
+const getStatusBackground = (name, statusIndex) => {
+ const styleConfig = statusStyles[name] || statusStyles.default;
+ return (
+ styleConfig[statusIndex]?.background ||
+ styleConfig[statusIndex]?.color || // 降级使用字体颜色
+ '#F0F0F0'
+ ); // 最终默认颜色
+};
+const getStatusLabel = (itemName, statusCode) => {
+ switch (itemName) {
+ case '机巢流量':
+ return flowStatus[statusCode] || statusSelect[statusCode];
+ case '监控设备':
+ return monitorStatus[statusCode] || statusSelect[statusCode];
+ case '机巢保险':
+ return insureStatus[statusCode] || statusSelect[statusCode];
+ default:
+ return statusSelect[statusCode] || `未知状态(${statusCode})`;
+ }
+};
+const getStaticsList = () => {
+ getStatics(userInfo.value.detail.areaCode).then(res => {
+ newtitleData.value = res.data.data;
+ console.log('设备', newtitleData.value);
+ });
+};
+
+const unitMap = {
+ drone: '架',
+ nest: '个',
+ monitor: '个',
+ mobile: '个',
+};
+const titleData = ref([
+ {
+ img: titleImg1,
+ name: '机巢',
+ type: 'nest',
+ data: 52,
+ statuses: [
+ { type: 'working', label: '作业中', count: 20 },
+ { type: 'idle', label: '空间中', count: 20 },
+ { type: 'offline', label: '离线中', count: 20 },
+ ],
+ },
+ {
+ img: titleImg2,
+ name: '无人机',
+ data: 52,
+ type: 'drone',
+ statuses: [
+ { type: 'working', label: '作业中', count: 20 },
+ { type: 'idle', label: '空间中', count: 20 },
+ { type: 'offline', label: '离线中', count: 20 },
+ ],
+ },
+ {
+ img: titleImg3,
+ name: '监控设备',
+ type: 'monitor',
+ data: 52,
+ statuses: [
+ { type: 'working', label: '作业中', count: 20 },
+ { type: 'idle', label: '空间中', count: 20 },
+ { type: 'offline', label: '离线中', count: 20 },
+ ],
+ },
+ {
+ img: titleImg4,
+ name: '移动机巢',
+ type: 'mobile',
+ data: 52,
+ statuses: [
+ { type: 'working', label: '作业中', count: 20 },
+ { type: 'idle', label: '空间中', count: 20 },
+ { type: 'offline', label: '离线中', count: 20 },
+ ],
+ },
+]);
+onMounted(() => {
+ getStaticsList();
+});
+</script>
+
+<style scoped lang="scss">
+.statistics {
+ // height: 174px;
+ background: #ffffff;
+ border-radius: 8px 8px 8px 8px;
+ margin-bottom: 10px;
+ .title {
+ padding: 14px 14px 0 21px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ .name {
+ display: flex;
+ align-items: center;
+ span {
+ margin-right: 4px;
+ }
+ }
+ .arrow {
+ cursor: pointer;
+ }
+ }
+ .grid-container {
+ padding: 0 14px 0 21px;
+ display: grid;
+ grid-template-columns: repeat(6, 1fr);
+ .device-card {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ .device-title {
+ display: flex;
+ align-items: center;
+ img {
+ width: 43px;
+ height: 44px;
+ }
+ }
+ .itemcenter {
+ margin-left: 14px;
+ font-weight: 400;
+ font-size: 14px;
+ color: #343434;
+ .shu {
+ font-weight: bold;
+ font-size: 36px;
+ color: #363636;
+ }
+ span {
+ font-weight: 400;
+ font-size: 12px;
+ color: #7c8091;
+ }
+ }
+ }
+ .status-list {
+ display: grid;
+
+ .status-item {
+ display: flex;
+ align-items: center;
+ border-radius: 6px;
+ background: #fff;
+ font-size: 12px;
+ gap: 10px;
+ margin-bottom: 5px;
+ .indicator {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ }
+ .label {
+ flex: 1;
+ // font-size: clamp(12px, 1vw, 14px);
+ }
+
+ .count {
+ // font-size: clamp(14px, 1.1vw, 16px);
+ font-size: 14px;
+ color: #7c8091;
+ }
+
+ &.status-4 .indicator {
+ background: #11ce3e;
+ }
+ &.status-4 {
+ color: #11ce3e;
+ }
+ &.status-0 .indicator {
+ background: #1b94ff;
+ }
+ &.status-0 {
+ color: #1b94ff;
+ }
+
+ &.status--1 .indicator {
+ background: #bababa;
+ }
+ &.status--1 {
+ color: #bababa;
+ }
+ }
+ }
+ }
+ .grid-container1 {
+ padding: 0 14px 0 21px;
+ display: grid;
+ grid-template-columns: repeat(6, 1fr);
+ .device-card {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ .device-title {
+ display: flex;
+ align-items: center;
+ img {
+ width: 43px;
+ height: 44px;
+ }
+ }
+ .itemcenter {
+ margin-left: 14px;
+ font-weight: 400;
+ font-size: 14px;
+ color: #343434;
+ .shu {
+ font-weight: bold;
+ font-size: 36px;
+ color: #363636;
+ }
+ span {
+ font-weight: 400;
+ font-size: 12px;
+ color: #7c8091;
+ }
+ }
+ }
+ .status-list {
+ display: grid;
+
+ .status-item {
+ display: flex;
+ align-items: center;
+ border-radius: 6px;
+ background: #fff;
+ font-size: 12px;
+ gap: 10px;
+ margin-bottom: 5px;
+ .indicator {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ }
+ .label {
+ flex: 1;
+ // font-size: clamp(12px, 1vw, 14px);
+ }
+
+ .count {
+ // font-size: clamp(14px, 1.1vw, 16px);
+ font-size: 14px;
+ color: #7c8091;
+ }
+
+ &.status-4 .indicator {
+ background: #11ce3e;
+ }
+ &.status-4 {
+ color: #11ce3e;
+ }
+ &.status-0 .indicator {
+ background: #1b94ff;
+ }
+ &.status-0 {
+ color: #1b94ff;
+ }
+
+ &.status--1 .indicator {
+ background: #bababa;
+ }
+ &.status--1 {
+ color: #bababa;
+ }
+ }
+ }
+ }
+}
+</style>
--
Gitblit v1.9.3