From 52a98a0384faedb2916ebe34eb0ea1990ada15ca Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Fri, 09 May 2025 13:35:50 +0800
Subject: [PATCH] Merge branch 'master' of http://139.196.74.78:10010/r/drone/drone-web-manage

---
 src/config/website.js                    |    4 
 src/views/wel/components/statistics.vue  |  447 +++++++++++++
 src/views/wel/index.vue                  |  652 +++++++++++++++++++
 src/assets/images/workbench/fy1.png      |    0 
 public/fonts/font.css                    |   53 +
 src/assets/images/workbench/st1.png      |    0 
 src/router/views/index.js                |   32 
 src/assets/images/workbench/jc1.png      |    0 
 src/assets/images/workbench/st2.png      |    0 
 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 ++++++
 pnpm-lock.yaml                           |   20 
 src/assets/images/workbench/tc1.png      |    0 
 src/assets/images/workbench/tc6.png      |    0 
 src/assets/images/workbench/fy4.png      |    0 
 public/fonts/SourceHanSansCN-Medium.otf  |    0 
 src/assets/images/workbench/st3.png      |    0 
 src/views/wel/components/calendarBox.vue |  152 ++++
 public/fonts/YouSheBiaoTiHei.TTF         |    0 
 src/assets/images/workbench/jc2.png      |    0 
 src/assets/images/workbench/st7.png      |    0 
 src/router/page/index.js                 |   20 
 public/img/bg/index_logo.png             |    0 
 src/assets/images/workbench/st4.png      |    0 
 src/views/wel/components/flyratio.vue    |  200 ++++++
 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-hover.png      |    0 
 src/hooks/useEchartsResize.js            |   38 +
 src/assets/images/workbench/st8.png      |    0 
 src/styles/common.scss                   |    3 
 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 
 package.json                             |    3 
 src/assets/images/workbench/tc3.png      |    0 
 src/assets/images/workbench/st9.png      |    0 
 42 files changed, 1,836 insertions(+), 50 deletions(-)

diff --git a/package.json b/package.json
index f601572..5687523 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
         "axios": "^0.21.1",
         "crypto-js": "^4.1.1",
         "dayjs": "^1.11.13",
+        "echarts": "^5.6.0",
         "element-plus": "^2.9.7",
         "js-base64": "^3.7.4",
         "js-cookie": "^3.0.0",
@@ -47,4 +48,4 @@
         "vite-plugin-compression": "^0.5.1",
         "vite-plugin-vue-setup-extend": "^0.4.0"
     }
-}
\ No newline at end of file
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4637136..0a91992 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -38,6 +38,9 @@
   dayjs:
     specifier: ^1.11.13
     version: 1.11.13
+  echarts:
+    specifier: ^5.6.0
+    version: 5.6.0
   element-plus:
     specifier: ^2.9.7
     version: 2.9.7(vue@3.4.30)
@@ -2426,6 +2429,13 @@
     resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==}
     dev: false
 
+  /echarts@5.6.0:
+    resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==}
+    dependencies:
+      tslib: 2.3.0
+      zrender: 5.6.1
+    dev: false
+
   /ee-first@1.1.1:
     resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
     dev: false
@@ -3554,6 +3564,10 @@
       commander: 2.20.3
     dev: false
 
+  /tslib@2.3.0:
+    resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
+    dev: false
+
   /turf-jsts@1.2.3:
     resolution: {integrity: sha512-Ja03QIJlPuHt4IQ2FfGex4F4JAr8m3jpaHbFbQrgwr7s7L6U8ocrHiF3J1+wf9jzhGKxvDeaCAnGDot8OjGFyA==}
     dev: false
@@ -3776,3 +3790,9 @@
       wmf: 1.0.2
       word: 0.3.0
     dev: false
+
+  /zrender@5.6.1:
+    resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
+    dependencies:
+      tslib: 2.3.0
+    dev: false
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_logo.png b/public/img/bg/index_logo.png
new file mode 100644
index 0000000..43577c7
--- /dev/null
+++ b/public/img/bg/index_logo.png
Binary files differ
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/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/config/website.js b/src/config/website.js
index 9bba3e6..6a21638 100644
--- a/src/config/website.js
+++ b/src/config/website.js
@@ -33,8 +33,8 @@
   },
   fistPage: {
     name: '事件工单',
-    // path: '/wel/index',
-    path: '/tickets/ticket',
+    path: '/wel/index',
+    // path: '/tickets/ticket',
     
   },
   //配置菜单的属性
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/router/page/index.js b/src/router/page/index.js
index 2006514..0b59c6e 100644
--- a/src/router/page/index.js
+++ b/src/router/page/index.js
@@ -64,15 +64,15 @@
       isAuth: false,
     },
   },
-  // {
-  //   path: '/',
-  //   name: '主页',
-  //   // redirect: '/wel',
-  //   redirect:'/tickets/ticket',
-  // },
   {
-     path: '/',
-     name: '主页',
-     redirect: '/tickets/ticket',
-     },
+    path: '/',
+    name: '主页',
+    redirect: '/wel',
+ 
+  },
+  // {
+  //    path: '/',
+  //    name: '主页',
+  //    redirect: '/tickets/ticket',
+  //    },
 ];
diff --git a/src/router/views/index.js b/src/router/views/index.js
index a8977c6..d2da43f 100644
--- a/src/router/views/index.js
+++ b/src/router/views/index.js
@@ -28,22 +28,22 @@
     ],
   },
   // 事件工单
-  {
-     path: '/tickets',
-    component: () =>
-     Store.getters.isMacOs ? import('@/mac/index.vue') : import('@/page/index/index.vue'),
-     redirect: '/tickets/ticket',
-     children: [
-     {
-     path: 'ticket',
-   name: '事件工单',
-     meta: {
-     i18n: 'dashboard',
-    },
-    component: () => import(/* webpackChunkName: "views" */ '@/views/tickets/ticket.vue'),
-     },
-    ],
-     },
+  // {
+  //    path: '/tickets',
+  //   component: () =>
+  //    Store.getters.isMacOs ? import('@/mac/index.vue') : import('@/page/index/index.vue'),
+  //    redirect: '/tickets/ticket',
+  //    children: [
+  //    {
+  //    path: 'ticket',
+  //  name: '事件工单',
+  //    meta: {
+  //    i18n: 'dashboard',
+  //   },
+  //   component: () => import(/* webpackChunkName: "views" */ '@/views/tickets/ticket.vue'),
+  //    },
+  //   ],
+  //    },
 
   {
     path: '/test',
diff --git a/src/styles/common.scss b/src/styles/common.scss
index df04e57..6986257 100644
--- a/src/styles/common.scss
+++ b/src/styles/common.scss
@@ -73,7 +73,8 @@
   flex: 1;
   box-sizing: border-box;
   overflow: hidden;
-  background: #f0f2f5;
+  // background: #f0f2f5;
+  background: linear-gradient( 180deg, #EEF3FE 0%, #F8F9FB 100%);
 }
 
 #avue-view {
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..92e4549
--- /dev/null
+++ b/src/views/wel/components/calendarBox.vue
@@ -0,0 +1,152 @@
+<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);
+
+      if (newDate.isBefore(oldDate, 'month')) {
+        console.log('点击了上个月');
+      } else if (newDate.isAfter(oldDate, 'month')) {
+        console.log('点击了下个月');
+      }
+    }
+  },
+  { 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..08cb6fc
--- /dev/null
+++ b/src/views/wel/components/flyratio.vue
@@ -0,0 +1,200 @@
+<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 => {
+    console.log('ppp', 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>
diff --git a/src/views/wel/index.vue b/src/views/wel/index.vue
index 916c7af..b7dedcd 100644
--- a/src/views/wel/index.vue
+++ b/src/views/wel/index.vue
@@ -1,29 +1,416 @@
 <template>
-  <div>
-    个人工作台
+  <div class="workbench">
+    <div class="workleft">
+      <!-- 设备统计  -->
+      <statistics></statistics>
+      <!-- 综合统计分析 -->
+      <div class="comprehensiveCon">
+        <div class="comprehensive">
+          <div class="title">
+            <div class="name">
+              <span> 综合统计分析</span>
+              <img src="/src/assets/images/workbench/st1.png" alt="" />
+              <div class="time-card">
+                <div
+                  class="card-item"
+                  :class="item === checked ? 'active' : ''"
+                  v-for="(item, index) in timeListEnum"
+                  :key="index"
+                  @click="timeClick(item, index)"
+                >
+                  {{ timeListStr[index] }}
+                </div>
+              </div>
+            </div>
+            <div class="arrow">
+              <img src="/src/assets/images/workbench/st2.png" alt="" />
+            </div>
+          </div>
+          <div class="center">
+            <div class="centerLeft">
+              <!-- 工单统计 -->
+              <div class="workOrder">
+                <div class="card-group">
+                  <div class="main-card">
+                    <div class="card-title">
+                      <img :src="overviewImg1" alt="" />
+                      <div class="cardtotal">
+                        <p>工单统计占比</p>
+                        <!-- <div class="total-number">{{ eventTotal }}</div>
+                        <span>个</span> -->
+                      </div>
+                    </div>
+
+                    <div class="status-grid">
+                      <div class="status-item" v-for="(item, index) in eventTypeList" :key="index">
+                        <div class="statusCon">
+                          <div class="status-label">{{ item.name }}</div>
+                          <div :style="{ color: item.color }" class="status-value">
+                            {{ item.value }}<span>个</span>
+                          </div>
+                          <div class="ratio">
+                            占比
+                            <span :style="{ color: item.color }"
+                              >{{ (item.rate / 100) * 100 }}%</span
+                            >
+                          </div>
+                        </div>
+                        <img :src="item.img" alt="" />
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div class="charts">
+                  <div class="chart" ref="echartsRef"></div>
+                </div>
+              </div>
+              <!-- 飞行统计 -->
+              <div class="flyOrder">
+                <div class="fytitle">
+                  <img src="@/assets/images/workbench/fy1.png" alt="" />
+                  <span>飞行统计</span>
+                </div>
+                <div class="flycenter">
+                  <div class="centerBox">
+                    <div class="centerItem" v-for="(item, index) in 3" :key="index">
+                      <div><img src="@/assets/images/workbench/fy2.png" alt="" />飞行时长</div>
+                      <div class="flydata"><span>5421.56</span>时</div>
+                    </div>
+                  </div>
+                  <div class="lineChart">
+                    <div class="lineBox" ref="chartRef"></div>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="centerRight">
+              <flyratio></flyratio>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="workright">
+      <Bocklog></Bocklog>
+      <CalenBox></CalenBox>
+    </div>
   </div>
 </template>
 
-<script>
+<script setup>
+import flyratio from './components/flyratio.vue';
+import Bocklog from './components/backlog.vue';
+import CalenBox from './components/calendarBox.vue';
+import * as echarts from 'echarts';
+import useEchartsResize from '@/hooks/useEchartsResize';
 import { mapGetters } from 'vuex';
-
-export default {
-  name: 'wel',
-  data() {
-    return {
-      activeNames: ['1', '2', '3', '5'],
-      logActiveNames: ['37'],
-    };
-  },
-  computed: {
-    ...mapGetters(['userInfo']),
-  },
-  methods: {
-    handleChange(val) {
-      window.console.log(val);
-    },
-  },
+import { ref } from 'vue';
+import overviewImg1 from '@/assets/images/workbench/tc1.png';
+import overviewImg2 from '@/assets/images/workbench/tc2.png';
+import overviewImg3 from '@/assets/images/workbench/tc3.png';
+import overviewImg4 from '@/assets/images/workbench/tc4.png';
+import overviewImg5 from '@/assets/images/workbench/tc5.png';
+import overviewImg6 from '@/assets/images/workbench/tc6.png';
+import flyImg1 from '@/assets/images/workbench/fy2.png';
+import statistics from './components/statistics.vue';
+import { getJobEventByStatus, getJobEventTotal } from '@/api/home/index';
+// const value = ref(new Date());
+let checked = ref('CURRENT_WEEK');
+let timeListStr = ['本周', '本月', '本年'];
+let timeListEnum = ['CURRENT_WEEK', 'CURRENT_MONTH', 'CURRENT_YEAR'];
+let timeClick = (item, index) => {
+  checked.value = item;
+  params.value.date_enum = item;
+  console.log('日期选择', params.value.date_enum);
+  getTypeData();
 };
+const eventTypeList = ref([
+  { name: '待审核', value: 0, img: overviewImg2, color: '#FF6560', status: '2', rate: 0 },
+  { name: '待处理', value: 0, img: overviewImg3, color: '#5D77FB', status: '0', rate: 0 },
+  { name: '处理中', value: 0, img: overviewImg4, color: '#FF8B26', status: '3', rate: 0 },
+  { name: '已完成', value: 0, img: overviewImg5, color: '#0291A1', status: '4', rate: 0 },
+]);
+const flyTypeList = ref([
+  { name: '飞行时长', value: 0, img: overviewImg2 },
+  { name: '飞行里程', value: 0, img: overviewImg3 },
+  { name: '任务成功', value: 0, img: overviewImg4 },
+]);
+const params = ref({
+  date_enum: 'CURRENT_WEEK',
+  device_sn: '',
+  end_date: undefined,
+  start_date: undefined,
+});
+const eventTotal = ref(0);
+const data = ref([]);
+//  工单统计
+const getTypeData = () => {
+  getJobEventByStatus(params.value).then(res => {
+    const resList = res?.data?.data || [];
+    console.log('工单统计', res.data.data);
+
+    resList.forEach(item => {
+      eventTypeList.value.forEach(item1 => {
+        if (item1.name === item.name) {
+          item1.value = item.num;
+          item1.rate = item.rate;
+        }
+      });
+    });
+    initChart(resList);
+  });
+};
+// 图表
+const echartsRef = ref(null);
+let { chart } = useEchartsResize(echartsRef);
+const chartRef = ref(null);
+let { chart: lineChart } = useEchartsResize(chartRef);
+const initChart = val => {
+  // 转换数据格式并计算总数
+  const totalNum = val.reduce((sum, item) => sum + item.num, 0);
+  const data = {
+    total: {
+      title: '总计',
+      figure: totalNum.toString(), // 动态计算总数
+    },
+    data: val.map(item => ({
+      value: item.num,
+      name: item.name,
+      rate: item.rate,
+    })),
+  };
+
+  const echartsOption = {
+    color: ['#FF6560', '#5D77FB', '#FF8B26', '#0291A1'],
+    tooltip: {
+      trigger: 'item',
+      padding: 0,
+      borderWidth: 0,
+      formatter: params => {
+        return `<div style="background-color: rgba($color: #FFFFFF, $alpha: 0.95);
+          box-shadow: 0 4px 9px 0 rgba($color: #000000, $alpha: 0.1);
+          padding:0 12px;
+          display: flex;
+          align-items: center;
+          border-radius: 4px;
+          font-size: 12px;" class="tooltip-area">
+          <p>${params.marker}${params.name}</p>
+          <h4 style="margin-left: 30px;">${params.data.rate || params.percent}%</h4>
+        </div>`;
+      },
+    },
+    legend: {
+      show: false,
+    },
+    title: {
+      text: data.total.title,
+      textStyle: {
+        color: 'rgba(28, 31, 35, 0.80)',
+        fontSize: '12px',
+        fontWeight: 'normal',
+      },
+      subtext: data.total.figure,
+      subtextStyle: {
+        color: '#1C1F23',
+        fontSize: '20px',
+        fontWeight: '600',
+      },
+      top: '40%',
+      left: 'center',
+    },
+    series: [
+      {
+        name: '',
+        type: 'pie',
+        radius: ['30%', '45%'],
+        avoidLabelOverlap: true,
+        // avoidLabelOverlap: false,
+        label: {
+          formatter: `{a|{b}}: {b|{d}%}`,
+          alignTo: 'labelLine',
+          rich: {
+            a: {
+              color: 'rgba(28, 31, 35, 0.80)',
+              fontSize: '12px',
+            },
+            b: {
+              color: '#1C1F23',
+              fontSize: '14px',
+              fontWeight: '600',
+            },
+          },
+        },
+        labelLine: {
+          show: true,
+          lineStyle: {
+            cap: 'round',
+          },
+        },
+        data: data.data,
+      },
+    ],
+  };
+
+  chart.value.setOption(echartsOption);
+};
+
+// 柱状图
+const lineCharts = () => {
+  var option = {
+    tooltip: {
+      trigger: 'item',
+      axisPointer: {
+        type: 'shadow',
+      },
+    },
+    grid: {
+      left: '2%',
+      right: '4%',
+      bottom: '14%',
+      top: '16%',
+      containLabel: true,
+    },
+    legend: {
+      data: ['飞行时长', '飞行里程', '任务成果'],
+      left: 'center',
+      top: '5%',
+      textStyle: {
+        color: '#666666',
+      },
+      itemWidth: 15,
+      itemHeight: 10,
+      itemGap: 25,
+    },
+    xAxis: {
+      type: 'category',
+      data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+      axisLine: {
+        lineStyle: {
+          color: '#cdd5e2',
+        },
+      },
+
+      axisLabel: {
+        interval: 0,
+        textStyle: {
+          color: '#666666',
+        },
+      },
+    },
+    yAxis: [
+      // 只保留第一个y轴
+      {
+        type: 'log',
+        name: '单位:万套',
+        nameTextStyle: {
+          color: '#666666',
+        },
+        min: 1,
+        logBase: 3,
+        axisLine: {
+          show: false,
+          lineStyle: {
+            color: '#cdd5e2',
+          },
+        },
+
+        splitLine: {
+          show: true, // 显示分割线
+          lineStyle: {
+            type: 'dashed', // 设置为虚线
+            color: '#cdd5e2', // 颜色与轴线一致
+            width: 1, // 线宽
+            opacity: 0.5, // 透明度
+          },
+        },
+        axisLabel: {
+          textStyle: {
+            color: '#666666',
+          },
+        },
+        axisLine: {
+          lineStyle: {
+            color: '#cdd5e2',
+          },
+        },
+      },
+      // 移除第二个y轴配置
+    ],
+    series: [
+      {
+        name: '飞行时长',
+        type: 'bar',
+        barWidth: '12px',
+        itemStyle: {
+          normal: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              {
+                offset: 0,
+                color: '#29acff',
+              },
+              {
+                offset: 1,
+                color: '#4bdfff',
+              },
+            ]),
+            barBorderRadius: 6,
+          },
+        },
+        data: [11, 14, 133, 4, 10, 14, 116, 12, 12, 58, 15, 12],
+      },
+      {
+        name: '飞行里程',
+        type: 'bar',
+        barWidth: '12px',
+        itemStyle: {
+          normal: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              {
+                offset: 0,
+                color: '#01c871',
+              },
+              {
+                offset: 1,
+                color: '#55f49c',
+              },
+            ]),
+            barBorderRadius: 6,
+          },
+        },
+        data: [0, 1, 9, 0, 5, 3, 0, 2, 0, 0, 1, 0],
+      },
+      {
+        name: '任务成果',
+        type: 'line',
+        yAxisIndex: 0, // 改为使用第一个y轴
+        smooth: true,
+        // symbol: 'circle',
+        // symbolSize: 8,
+        // itemStyle: {
+        //   normal: {
+        //     color: '#ffa43a',
+        //     borderColor: 'rgba(255, 234, 0, 0.5)',
+        //     borderWidth: 5,
+        //   },
+        // },
+        lineStyle: {
+          color: 'rgba(52, 146, 242, 1)',
+        },
+        data: [1, 7, 6, 30, 20, 21.43, 11, 16.67, 22, 88, 6.67, 10],
+      },
+    ],
+  };
+  lineChart.value.setOption(option);
+};
+onMounted(() => {
+  getJobEventTotal().then(res => {
+    eventTotal.value = res?.data?.data || 0;
+  });
+
+  getTypeData();
+  lineCharts();
+});
 </script>
 
 <style>
@@ -31,3 +418,228 @@
   font-size: 14px;
 }
 </style>
+<style scoped lang="scss">
+// 开始
+.workbench {
+  padding: 0px 20px 0 20px;
+  display: flex;
+  justify-content: space-between;
+}
+.workleft {
+  width: 68%;
+  margin-right: 10px;
+  // 综合
+  .comprehensiveCon {
+    // height: 736px;
+    background: #ffffff;
+    border-radius: 8px 8px 8px 8px;
+    .comprehensive {
+      padding: 14px 14px 0 21px;
+      .title {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .name {
+          display: flex;
+          align-items: center;
+          span {
+            margin-right: 4px;
+          }
+        }
+        .arrow {
+          cursor: pointer;
+        }
+        .time-card {
+          text-align: center;
+          height: 30px;
+          background: #ffffff;
+          border-radius: 4px 0px 0px 4px;
+          border: 1px solid #e5e5e5;
+          font-weight: 400;
+          font-size: 14px;
+          color: #7c8091;
+          display: flex;
+          width: 282px;
+          margin-left: 15px;
+          .card-item {
+            width: 94px;
+            height: 100%;
+            line-height: 32px;
+            cursor: pointer;
+          }
+          .card-item:first-child {
+            border-right: 1px solid #e5e5e5;
+          }
+          .card-item:nth-child(2) {
+            border-right: 1px solid #e5e5e5;
+          }
+          .active {
+            color: #1441ff;
+          }
+        }
+      }
+      // 工、单
+      .center {
+        display: flex;
+        .centerLeft {
+          width: 60%;
+          border-right: 1px solid #dfdfdf;
+          .workOrder {
+            margin-top: 21px;
+            display: flex;
+            border-bottom: 1px solid #dfdfdf;
+            .card-group {
+              width: 40%;
+              .card-title {
+                display: flex;
+                margin-bottom: 10px;
+                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 {
+                display: grid;
+                grid-template-columns: repeat(2, 1fr);
+                row-gap: 14px;
+                gap: 10px;
+                .status-item {
+                  display: flex;
+                  text-align: center;
+                  height: 97px;
+                  background: #f6f8fe;
+                  border-radius: 8px 8px 8px 8px;
+                  img {
+                    width: 26px;
+                    height: 26px;
+                    padding: 9px 2px;
+                  }
+                  .statusCon {
+                    display: flex;
+                    flex-direction: column;
+                    align-items: center;
+                    padding: 9px 4px 0 4px;
+                    .status-label {
+                      font-weight: 400;
+                      font-size: 14px;
+                      color: #383838;
+                    }
+                    .ratio {
+                      font-weight: 400;
+                      font-size: 12px;
+                      color: #363636;
+                      white-space: nowrap;
+                    }
+                    .status-value {
+                      font-family: 'YouSheBiaoTiHei';
+                      font-weight: bold;
+                      font-size: 24px;
+                      margin: 5px 0;
+                      span {
+                        font-weight: 400;
+                        font-size: 14px;
+                        color: #7c8091;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+            .charts {
+              margin-top: 30px;
+              width: 348px;
+              height: 242px;
+              .chart {
+                width: 100%;
+                height: 100%;
+              }
+            }
+          }
+
+          // 飞行统计
+          .flyOrder {
+            margin-top: 5px;
+            .fytitle {
+              display: flex;
+              align-items: center;
+              img {
+                width: 39px;
+                height: 38px;
+              }
+              span {
+                font-weight: bold;
+                font-size: 14px;
+                color: #363636;
+              }
+            }
+            .flycenter {
+              margin-top: 13px;
+              .centerBox {
+                display: flex;
+                justify-content: space-between;
+                .centerItem {
+                  padding: 7px 7px 0 15px;
+                  // width: 196px;
+                  flex: 1;
+                  height: 80px;
+                  background: #f6f8fe;
+                  box-shadow: 0px 5px 4px 0px #ebf1ff;
+                  border-radius: 8px 8px 8px 8px;
+                  border: 1px solid #ffffff;
+                  margin-right: 16px;
+                  .flydata {
+                    margin-top: 15px;
+                    text-align: right;
+                    font-size: 14px;
+                    color: #7c8091;
+                    span {
+                      font-weight: bold;
+                      font-size: 24px;
+                      color: #343434;
+                      margin-right: 6px;
+                    }
+                  }
+                }
+              }
+
+              .lineChart {
+                height: 209px;
+                width: 100%;
+                .lineBox {
+                  width: 100%;
+                  height: 100%;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+.workright {
+  width: 32%;
+}
+</style>

--
Gitblit v1.9.3