Browse Source

修改宁东地图、执法记录仪

傀仙 1 month ago
commit
059e9cc315

+ 3 - 0
.env.development

@@ -0,0 +1,3 @@
+// 开发环境
+VITE_APP_BASE_API = "http://anvideo.nxmy.com:8011/api"
+VITE_APP_TITLE = "开发环境"

+ 3 - 0
.env.production

@@ -0,0 +1,3 @@
+// 生产环境
+VITE_APP_BASE_API = "http://anvideo.nxmy.com:8011/api"
+VITE_APP_TITLE = "生产环境"

+ 24 - 0
.gitignore

@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 3 - 0
.vscode/extensions.json

@@ -0,0 +1,3 @@
+{
+  "recommendations": ["Vue.volar"]
+}

+ 7 - 0
README.md

@@ -0,0 +1,7 @@
+# Vue 3 + Vite
+
+This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
+
+## Recommended IDE Setup
+
+- [VS Code](https://code.visualstudio.com/) + [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously Volar) and disable Vetur

+ 16 - 0
index.html

@@ -0,0 +1,16 @@
+<!doctype html>
+<html lang="zh">
+
+<head>
+  <meta charset="UTF-8" />
+  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>风险作业管控平台</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.js"></script>
+</body>
+
+</html>

+ 27 - 0
package.json

@@ -0,0 +1,27 @@
+{
+  "name": "vite-xixuan-1920",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "autofit.js": "2.0.1",
+    "axios": "^1.7.2",
+    "default-passive-events": "^2.0.0",
+    "echarts": "^5.5.0",
+    "element-plus": "^2.7.3",
+    "path": "^0.12.7",
+    "qs": "^6.12.1",
+    "vue": "^3.4.21",
+    "vue-router": "4"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^5.0.4",
+    "sass": "^1.77.2",
+    "vite": "^5.2.0"
+  }
+}

File diff suppressed because it is too large
+ 1501 - 0
pnpm-lock.yaml


File diff suppressed because it is too large
+ 1 - 0
public/vite.svg


+ 33 - 0
src/App.vue

@@ -0,0 +1,33 @@
+<script setup>
+import { onMounted } from "vue";
+import autofit from "autofit.js";
+
+onMounted(() => {
+    autofit.init(
+        {
+            designHeight: 1080,
+            designWidth: 1920,
+            renderDom: "#app",
+            resize: true,
+            ignore: [{ dom: "" }],
+        },
+        true
+    ); // 可关闭控制台运行提示输出
+});
+</script>
+
+<template>
+    <div class="container">
+        <router-view></router-view>
+    </div>
+</template>
+
+<style scoped>
+.container {
+    height: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background-color: skyblue;
+}
+</style>

BIN
src/assets/images/logo.png


BIN
src/assets/images/map_line.png


BIN
src/assets/images/map_ningdong.png


+ 1 - 0
src/assets/vue.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

+ 79 - 0
src/components/header/index.vue

@@ -0,0 +1,79 @@
+<script setup>
+import { ref } from "vue";
+import {
+    getCurrentDate,
+    getCurrentTime,
+    getCurrentWeekday,
+} from "@/utils/time.js";
+
+const formattedDate = ref(getCurrentDate());
+const currentTime = ref(getCurrentTime());
+const weekDay = ref(getCurrentWeekday());
+
+setInterval(() => {
+    formattedDate.value = getCurrentDate();
+    currentTime.value = getCurrentTime();
+    weekDay.value = getCurrentWeekday();
+}, 1000);
+</script>
+
+
+<template>
+    <div class="header">
+        <div class="logo">
+            <div class="img_box">
+                <img src="@/assets/images/logo.png" alt="" />
+            </div>
+            <div class="title">风险作业管控平台</div>
+        </div>
+        <div class="date_time">
+            <div class="date">{{ formattedDate }}</div>
+            <div class="time">
+                <div class="currentTime">{{ currentTime }}</div>
+                <div class="weekDay">
+                    {{ weekDay }}
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style scoped lang="scss">
+.header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .logo {
+        display: flex;
+        .img_box {
+            margin-right: 60px;
+            img {
+                width: 276px;
+                height: 39px;
+            }
+        }
+        .title {
+            font-weight: 700;
+            font-size: 40px;
+            color: #000000;
+        }
+    }
+    .date_time {
+        height: 67px;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        .date {
+            font-weight: 700;
+            font-size: 30px;
+            color: #3f6fff;
+        }
+        .time {
+            font-size: 20px;
+            color: #4b4b4b;
+            display: flex;
+            justify-content: space-between;
+        }
+    }
+}
+</style>

+ 199 - 0
src/components/table.vue

@@ -0,0 +1,199 @@
+<script setup>
+import { ref } from "vue"
+import { risk_work_detail } from '@/request/api'
+import { ElMessage } from 'element-plus'
+import { get_video_url } from "../utils/get_video_url";
+
+const props = defineProps(['table', 'filters', 'title'])
+
+// 作业详情
+const drawer = ref(false)
+// 摄像头ID
+const camera = ref([])
+const move_camera = ref([])
+const zhifa_camera = ref([])
+const drawer_title = ref("作业详情")
+const drawer_detail_content = ref([
+    {
+        label: "风险类型:",
+        value: "————"
+    },
+    // {
+    //     label: "风险等级:",
+    //     value: "中风险"
+    // },
+    // {
+    //     label: "单位:",
+    //     value: "机电科"
+    // },
+    // {
+    //     label: "风险作业内容:",
+    //     value: "红柳洗煤厂218弛张筛拆除红柳洗煤厂218弛张筛拆除红柳洗煤厂218弛张筛拆除红柳洗煤厂218弛张筛拆除"
+    // },
+    // {
+    //     label: "人数:",
+    //     value: "8"
+    // },
+    // {
+    //     label: "地点:",
+    //     value: "红柳洗煤厂"
+    // },
+    // {
+    //     label: "现场负责人:",
+    //     value: "分厂:张烨博 设备管理员:张宗伟"
+    // },
+    // {
+    //     label: "摄像头类型:",
+    //     value: "固定摄像头"
+    // }
+])
+
+const filterHandler = (value, row, column) => {
+    const property = column['property']
+    return row[property] === value
+}
+
+function drawer_click(item) {
+    drawer.value = true
+    drawer_title.value = props.title + ' : ' + item.unit_name + " " + item.place
+
+    risk_work_detail({
+        id: item.id
+    }).then((res) => {
+
+        drawer_detail_content.value = res.content.detail
+        camera.value = res.content.camera
+        move_camera.value = res.content.move_camera
+        zhifa_camera.value = res.content.zhifa_camera
+
+    })
+}
+
+
+const camera_dialogTableVisible = ref(false)
+const camera_url = ref('')
+// 固定摄像头
+function open_camera(item) {
+    camera_url.value = "http://anstatic.nxmy.com:8011/assets/html/video_pc_m3u8?camera_id=" + item.camera_id + "&parent_id=" + item.parent_id
+    camera_dialogTableVisible.value = true
+
+}
+// 移动摄像头
+async function open_move_camera(item) {
+    let url = await get_video_url(item)
+    camera_url.value = "https://videortsp.nxjiewei.com:5001/demo.html?url="+url
+    camera_dialogTableVisible.value = true
+
+}
+// 执法记录仪
+async function open_zhifa_camera(item) {
+    let url = await get_video_url(item)
+    camera_url.value = "https://videortsp.nxjiewei.com:9091/demo_pc.html?url="+url
+    camera_dialogTableVisible.value = true
+
+}
+</script>
+
+<template>
+    <el-table :data="table" height="500">
+        <el-table-column property="unit_name" label="单位" width="150" :filters="filters"
+            :filter-method="filterHandler" />
+        <el-table-column property="place" label="作业地点" width="150" />
+        <el-table-column property="content" label="作业内容" width="200" />
+        <el-table-column property="risk_type" label="风险类型" width="100" />
+        <el-table-column property="work_people" label="现场负责人" width="200" />
+        <el-table-column label="操作">
+            <template #default="scope">
+                <el-button @click="drawer_click(scope.row)" type="primary">查看详情</el-button>
+            </template>
+        </el-table-column>
+    </el-table>
+
+    <div class="drawer_box">
+        <el-drawer v-model="drawer" :title="drawer_title" :with-header="true" size="40%">
+            <div class="detail_content">
+                <div class="label_value" v-for="(item, index) in drawer_detail_content" :key="index">
+                    <div class="label">{{ item.label }}</div>
+                    <div class="value">{{ item.value }}</div>
+                </div>
+            </div>
+
+            <div class="camera_list detail_content" v-if="camera.length > 0">
+                <div class="label">固定摄像头</div>
+                <div class="list">
+                    <el-button class="camera_btn" v-for="(item, index) in camera" :key="index" type="primary"
+                        size="large" @click="open_camera(item)">{{ item.camera_name }}</el-button>
+                </div>
+            </div>
+            <div class="camera_list detail_content" v-if="move_camera.length > 0">
+                <div class="label">移动摄像头</div>
+                <div class="list">
+                    <el-button class="camera_btn" v-for="(item, index) in move_camera" :key="index" type="primary"
+                        size="large" @click="open_move_camera(item)">{{ item.camera_name }}</el-button>
+                </div>
+            </div>
+            <div class="camera_list detail_content" v-if="zhifa_camera.length > 0">
+                <div class="label">工作记录仪</div>
+                <div class="list">
+                    <el-button class="camera_btn" v-for="(item, index) in zhifa_camera" :key="index" type="primary"
+                        size="large" @click="open_zhifa_camera(item)">{{ item.camera_name }}</el-button>
+                </div>
+            </div>
+
+        </el-drawer>
+    </div>
+
+    <el-dialog v-model="camera_dialogTableVisible" title="摄像头画面" width="1400" align-center>
+        <div style="height: 900px;">
+            <iframe :src="camera_url" frameborder="0" width="100%" height="100%"></iframe>
+        </div>
+    </el-dialog>
+</template>
+
+<style lang="scss" scoped>
+.drawer_box {
+    :deep(.el-drawer.rtl) {
+        padding: 50px 0;
+    }
+
+    :deep(.el-drawer__title) {
+        font-size: 20px;
+        font-weight: 700;
+        color: #000;
+    }
+}
+
+.detail_content {
+    box-sizing: border-box;
+    // padding: 20px;
+    // height: 100%;
+    margin-bottom: 40px;
+
+    .label_value {
+        padding: 10px 0;
+    }
+
+    .label {
+        font-size: 20px;
+        font-weight: 700;
+        color: #6F6F6F;
+        line-height: 36px;
+    }
+
+    .value {
+        text-indent: 2em;
+        font-size: 20px;
+        font-weight: 700;
+        color: #000;
+        line-height: 36px;
+    }
+}
+
+.camera_list {
+    .list {
+        .camera_btn {
+            margin: 10px 10px 10px 0;
+        }
+    }
+}
+</style>

+ 14 - 0
src/main.js

@@ -0,0 +1,14 @@
+import { createApp } from 'vue'
+import router from "./router"
+import axios from "axios"
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
+import './style.css'
+import 'default-passive-events'
+import App from './App.vue'
+
+const app = createApp(App)
+app.use(router)
+app.use(ElementPlus,{locale: zhCn})
+app.mount('#app')

+ 106 - 0
src/request/api.js

@@ -0,0 +1,106 @@
+import service from "./index"
+
+// 新建示例
+// export const getmapinfo = (data)=>{
+//     return service({
+//         method:"POST",
+//         url:"/api/audit/getmapinfo",
+//         data
+//     })
+// }
+
+// 使用示例
+// import { getmapinfo } from "@/request/api"
+
+// function api_getmapinfo() {
+//     getmapinfo({
+//         type: 1
+//     }).then((res) => {
+//         data.info = res.content
+//     })
+// }
+
+// onMounted(() => {
+//     api_getmapinfo()
+// })
+
+// 风险作业数量统计
+export const main_home = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/main_home_v2",
+        data
+    })
+}
+
+// 风险作业占比
+export const risk_work_percent = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/risk_work_percent_v2",
+        data
+    })
+}
+
+// 片区占比
+export const area_percent = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/area_percent_v2",
+        data
+    })
+}
+
+// 时间段作业量统计-叠状图
+export const time_work_count = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/time_work_count_v2",
+        data
+    })
+}
+
+// 时间段片区统计
+export const time_area_total = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/time_area_total_v2",
+        data
+    })
+}
+
+// 洗煤厂统计
+export const coal_washery_total = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/coal_washery_total_v2",
+        data
+    })
+}
+
+// 风险作业列表
+export const risk_work_list = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/risk_work_list_v2",
+        data
+    })
+}
+
+// 风险作业详情
+export const risk_work_detail = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/risk_work_detail_v2",
+        data
+    })
+}
+
+// map
+export const map_data = (data)=>{
+    return service({
+        method:"POST",
+        url:"/task_xixuan/map_data_v2",
+        data
+    })
+}

+ 38 - 0
src/request/index.js

@@ -0,0 +1,38 @@
+import axios from 'axios'
+import qs from "qs"
+console.log(import.meta.env.VITE_APP_TITLE)
+const service = axios.create({
+    baseURL: import.meta.env.VITE_APP_BASE_API,
+    headers: {
+        'Content-Type': 'application/json;charset=UTF-8',
+        'Content-Type': 'application/x-www-form-urlencoded'
+    },
+    timeout: 8000
+})
+
+// 请求拦截器
+service.interceptors.request.use(config => {
+    // get 参数序列化
+    if (config.method == 'get' && config.url.indexOf("?") != -1) {
+        config.url = config.url + "&" + qs.stringify(config.data)
+    } else if (config.method == 'get' && config.url.indexOf("?") == -1) {
+        config.url = config.url + "?" + qs.stringify(config.data)
+    }
+
+    return config
+})
+
+// 响应拦截器
+service.interceptors.response.use(res => {
+    // console.log(res.data)
+    if (res.status == 200) {
+        // console.log("请求成功")
+    }
+    return res.data
+}, (err) => {
+    // console.log(err)
+    return Promise.reject(err)
+})
+
+
+export default service

+ 31 - 0
src/router/index.js

@@ -0,0 +1,31 @@
+import { createMemoryHistory, createRouter } from 'vue-router'
+
+const routes = [
+  {
+    path: '/',
+    redirect: "/index"
+  },
+  {
+    path: "/index",
+    component: () => import("../views/index.vue"),
+    children: [
+      {
+        path: "/index",
+        component: () => import("../views/index/index.vue")
+      }
+    ]
+  }
+]
+
+const router = createRouter({
+  history: createMemoryHistory(),
+  routes,
+})
+
+router.beforeEach((to, from, next) => {
+
+  next()
+
+})
+
+export default router

+ 43 - 0
src/style.css

@@ -0,0 +1,43 @@
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    font-size: 100%;
+    font: inherit;
+    vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure, 
+footer, header, hgroup, menu, nav, section {
+    display: block;
+}
+body {
+    line-height: 1;
+}
+ol, ul {
+    list-style: none;
+}
+blockquote, q {
+    quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+    content: '';
+    content: none;
+}
+table {
+    border-collapse: collapse;
+    border-spacing: 0;
+}

+ 40 - 0
src/utils/get_video_url.js

@@ -0,0 +1,40 @@
+import axios from "axios";
+
+export async function get_video_url(item) {
+    try {
+        const tokenResponse = await axios({
+            method: 'post',
+            url: 'http://anvideo.nxmy.com:8011/api/oauth/token',
+            headers: {
+                'Content-Type': 'multipart/form-data'
+            },
+            data: {
+                username: 'admin',
+                password: 'Zhks123456+'
+            }
+        });
+
+        const token = `${tokenResponse.data.data.token_type} ${tokenResponse.data.data.access_token}`;
+
+        const videoUrlResponse = await axios({
+            method: 'post',
+            url: 'http://anvideo.nxmy.com:8011/api/camera/geturl',
+            headers: {
+                Authorization: token
+            },
+            data: {
+                camera_id: item.camera_id,
+                parent_id: item.parent_id
+            }
+        });
+
+        if (videoUrlResponse.data.content.data.url) {
+            return videoUrlResponse.data.content.data.url;
+        } else {
+            throw new Error('No URL found in response');
+        }
+    } catch (error) {
+        console.error(error);
+        throw error; // Re-throw the error to be handled by the caller
+    }
+}

+ 31 - 0
src/utils/time.js

@@ -0,0 +1,31 @@
+export function getCurrentDate() {
+  const currentDate = new Date();
+  const year = currentDate.getFullYear();
+  const month = currentDate.getMonth() + 1; // 月份从0开始,所以需要加1
+  const day = currentDate.getDate();
+  return `${year}/${month.toString().padStart(2, '0')}/${day.toString().padStart(2, '0')}`;
+}
+
+export function getCurrentTime() {
+  const now = new Date();
+  const hours = now.getHours().toString().padStart(2, '0');
+  const minutes = now.getMinutes().toString().padStart(2, '0');
+  const seconds = now.getSeconds().toString().padStart(2, '0');
+  return `${hours}:${minutes}:${seconds}`;
+}
+
+export function getCurrentWeekday() {
+  const now = new Date();
+  const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
+  return weekdays[now.getDay()];
+}
+
+
+export function getOneWeekTimePeriod() {
+  const today = new Date();
+  const endDate = today.toISOString().split('T')[0];
+  const startDate = new Date(today.getTime() - (7 * 24 * 60 * 60 * 1000)).toISOString().split('T')[0];
+  return [startDate, endDate];
+}
+
+

+ 21 - 0
src/views/index.vue

@@ -0,0 +1,21 @@
+<script setup>
+import Header from "@/components/header/index.vue"
+</script>
+
+<template>
+    <div class="content">
+        <Header></Header>
+        <router-view></router-view>
+    </div>
+</template>
+
+<style scoped lang="scss">
+.content {
+    width: 1920px;
+    height: 1080px;
+    background-color: #f8f9fe;
+    box-sizing: border-box;
+    padding: 50px;
+
+}
+</style>

+ 368 - 0
src/views/index/digitalStatistics.vue

@@ -0,0 +1,368 @@
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { main_home, risk_work_percent, area_percent, risk_work_list } from '@/request/api'
+import Table from "@/components/table.vue"
+
+import * as echarts from 'echarts';
+
+const digit = reactive({
+    data: [
+        {
+            number: 126,
+            unit: '项',
+            title: "高风险作业",
+            color: "#DA0000"
+        },
+        {
+            number: 556,
+            unit: '项',
+            title: "中风险作业",
+            color: "#FFBA00"
+        },
+        {
+            number: 39,
+            unit: '项',
+            title: "低风险作业",
+            color: "#2BB200"
+        }
+    ]
+})
+
+const option_1 = reactive({
+    tooltip: {
+        trigger: 'item'
+    },
+    legend: {
+        top: '5%',
+        left: '65%',
+        top: "middle"
+    },
+    color: ["#DA0000", "#FFBA00", "#2BB200"],
+    series: [
+        {
+            name: '风险作业占比',
+            type: 'pie',
+            radius: ['40%', '70%'],
+            center: ['35%', '50%'],
+            avoidLabelOverlap: false,
+            itemStyle: {
+                borderRadius: 10,
+                borderColor: '#fff',
+                borderWidth: 2
+            },
+            label: {
+                show: false,
+            },
+            labelLine: {
+                show: false
+            },
+            data: [
+                { value: 1048, name: '高风险' },
+                { value: 735, name: '中风险' },
+                { value: 580, name: '低风险' }
+            ]
+        }
+    ]
+})
+
+const option_2 = reactive({
+    tooltip: {
+        trigger: 'item'
+    },
+    legend: {
+        top: '5%',
+        left: '65%',
+        top: "middle"
+    },
+    color: ["#1777FF", "#FF5B5D"],
+    series: [
+        {
+            name: '片区作业占比',
+            type: 'pie',
+            radius: ['40%', '70%'],
+            center: ['35%', '50%'],
+            avoidLabelOverlap: false,
+            itemStyle: {
+                borderRadius: 10,
+                borderColor: '#fff',
+                borderWidth: 2
+            },
+            label: {
+                show: false,
+            },
+            labelLine: {
+                show: false
+            },
+            data: [
+                { value: 1048, name: '太西片区' },
+                { value: 735, name: '宁东片区' }
+            ]
+        }
+    ]
+})
+
+const dialogTableVisible = ref(false)
+const gridData_title = ref("作业列表")
+const gridData_state = ref(0)
+function dialogTableVisible_click(title, index, coal_washery_id, area_id) {
+    dialogTableVisible.value = true
+    gridData_title.value = title
+    gridData_state.value = index
+    get_risk_work_list(coal_washery_id, area_id)
+}
+defineExpose({
+    dialogTableVisible_click
+})
+const gridData = reactive({
+    data: [
+        {
+            id: "1",
+            unit_name: '————',
+            place: '————',
+            content: '————',
+        },
+        // {
+        //     id: "2",
+        //     unit_name: '工程科',
+        //     place: '红柳洗煤厂',
+        //     content: '红柳洗煤厂801/ 802栈桥除锈、喷漆,803栈桥除锈、喷漆,墙体彩钢板拆除、安装(曲臂车配合施工)★',
+        // },
+        // {
+        //     unit_name: '工程科',
+        //     place: '红柳洗煤厂',
+        //     content: '红柳洗煤厂801/ 802栈桥除锈、喷漆,803栈桥除锈、喷漆,墙体彩钢板拆除、安装(曲臂车配合施工)★',
+        // },
+        // {
+        //     unit_name: '机电科',
+        //     place: '红柳洗煤厂',
+        //     content: '红柳洗煤厂801/ 802栈桥除锈、喷漆,803栈桥除锈、喷漆,墙体彩钢板拆除、安装(曲臂车配合施工)★',
+        // },
+        // {
+        //     unit_name: '综合科',
+        //     place: '红柳洗煤厂',
+        //     content: '红柳洗煤厂801/ 802栈桥除锈、喷漆,803栈桥除锈、喷漆,墙体彩钢板拆除、安装(曲臂车配合施工)★',
+        // },
+        // {
+        //     unit_name: '机电科',
+        //     place: '红柳洗煤厂',
+        //     content: '红柳洗煤厂801/ 802栈桥除锈、喷漆,803栈桥除锈、喷漆,墙体彩钢板拆除、安装(曲臂车配合施工)★',
+        // },
+        // {
+        //     unit_name: '综合科',
+        //     place: '红柳洗煤厂',
+        //     content: '红柳洗煤厂801/ 802栈桥除锈、喷漆,803栈桥除锈、喷漆,墙体彩钢板拆除、安装(曲臂车配合施工)★',
+        // },
+        // {
+        //     unit_name: '金凤洗煤厂',
+        //     place: '红柳洗煤厂',
+        //     content: '红柳洗煤厂801/ 802栈桥除锈、喷漆,803栈桥除锈、喷漆,墙体彩钢板拆除、安装(曲臂车配合施工)★',
+        // },
+        // {
+        //     unit_name: '机电科',
+        //     place: '红柳洗煤厂',
+        //     content: '红柳洗煤厂801/ 802栈桥除锈、喷漆,803栈桥除锈、喷漆,墙体彩钢板拆除、安装(曲臂车配合施工)★',
+        // },
+
+    ]
+})
+
+// 单位筛选
+const filters = reactive({
+    data: [
+        { text: '机电科', value: '机电科' },
+        { text: '工程科', value: '工程科' },
+        { text: '综合科', value: '综合科' },
+        { text: '金凤洗煤厂', value: '金凤洗煤厂' }
+    ]
+})
+
+// 获取作业列表
+function get_risk_work_list(coal_washery_id, area_id) {
+    gridData.data = []
+    risk_work_list({
+        type: gridData_state.value,
+        coal_washery_id: coal_washery_id,
+        area_id: area_id
+    }).then((res) => {
+        filters.data = res.content.unit_list
+        gridData.data = res.content.data
+    })
+}
+
+const chart_1 = ref(null)
+const chart_2 = ref(null)
+
+function initChart() {
+    chart_1.value = echarts.init(document.getElementById('chartDom_1'))
+    chart_2.value = echarts.init(document.getElementById('chartDom_2'))
+    chart_1.value.setOption(option_1)
+    chart_2.value.setOption(option_2)
+}
+
+// 图标数据刷新
+function updateData() {
+    // 模拟图表数据变化时的动态效果
+    // const randomValue = () => Math.floor(Math.random() * 1000)
+
+    // option_1.series[0].data.forEach(item => {
+    //     item.value = randomValue()
+    // })
+    // option_2.series[0].data.forEach(item => {
+    //     item.value = randomValue()
+    // })
+
+    main_home({
+
+    }).then((res) => {
+        digit.data = res.content
+    })
+
+    risk_work_percent({
+
+    }).then((res) => {
+        option_1.series[0].data = res.content
+        chart_1.value.setOption(option_1)
+    })
+    area_percent({
+
+    }).then((res) => {
+        option_2.series[0].data = res.content
+        chart_2.value.setOption(option_2)
+    })
+}
+
+onMounted(() => {
+    // 初始化图表 宏任务 异步等待渲染完毕
+    setTimeout(initChart)
+
+    // 执行模拟图表数据变化时的动态效果
+    // setInterval(updateData, 4000)
+
+    // 获取风险作业数量统计
+    main_home({
+
+    }).then((res) => {
+        digit.data = res.content
+    })
+
+    risk_work_percent({
+
+    }).then((res) => {
+        option_1.series[0].data = res.content
+        chart_1.value.setOption(option_1)
+    })
+
+    area_percent({
+
+    }).then((res) => {
+        option_2.series[0].data = res.content
+        chart_2.value.setOption(option_2)
+    })
+})
+
+
+
+
+</script>
+
+<template>
+    <div class="digitalStatistics">
+        <div class="digit_list">
+            <div class="digit" v-for="(item, index) in digit.data" :key="index">
+                <div class="number_unit">
+                    <div class="number">{{ item.number }}</div>
+                    <div class="unit">{{ item.unit }}</div>
+                </div>
+                <div class="title" :style="{ backgroundColor: item.color }"
+                    @click="dialogTableVisible_click(item.title, index)">
+                    {{ item.title }}
+                </div>
+            </div>
+        </div>
+
+        <div class="statistics">
+            <div class="chartDom" id="chartDom_1"></div>
+            <div class="chartDom" id="chartDom_2"></div>
+        </div>
+    </div>
+
+    <el-dialog v-model="dialogTableVisible" :title="gridData_title" width="" align-center>
+        <Table :title="gridData_title" :table="gridData.data" :filters="filters.data"></Table>
+    </el-dialog>
+
+</template>
+
+<style scoped lang="scss">
+.digitalStatistics {
+    margin-top: 26px;
+    display: flex;
+    justify-content: space-between;
+
+    .digit_list {
+        display: flex;
+        align-items: center;
+
+        .digit {
+            width: 343px;
+            height: 224px;
+            background: #FFFFFF;
+            border-radius: 30px;
+
+            display: flex;
+            flex-direction: column;
+            justify-content: space-between;
+            align-items: center;
+
+            margin-right: 30px;
+
+            box-sizing: border-box;
+            padding: 40px 0px;
+
+            .number_unit {
+                display: flex;
+                justify-content: center;
+                align-items: flex-end;
+                font-weight: 700;
+                color: #000000;
+
+                .number {
+                    font-size: 40px;
+                }
+
+                .unit {
+                    margin-left: 6px;
+                    font-size: 30px;
+                }
+            }
+
+            .title {
+                cursor: pointer;
+                width: 238px;
+                height: 71px;
+                background-color: #DA0000;
+                border-radius: 20px;
+                font-size: 24px;
+                font-weight: 700;
+                color: #FFFFFF;
+                line-height: 71px;
+                text-align: center;
+            }
+        }
+    }
+
+    .statistics {
+        width: 696px;
+        height: 224px;
+        background: #FFFFFF;
+        border-radius: 30px;
+
+        display: flex;
+        justify-content: space-between;
+
+        .chartDom {
+            width: 50%;
+            height: 224px;
+        }
+    }
+}
+</style>

+ 172 - 0
src/views/index/homeworkStatistics.vue

@@ -0,0 +1,172 @@
+<script setup>
+import { ref, reactive, onMounted,shallowRef } from 'vue'
+import { time_work_count } from '@/request/api'
+
+import * as echarts from 'echarts'
+import {
+    getOneWeekTimePeriod
+} from "@/utils/time.js";
+
+const date_value = ref(getOneWeekTimePeriod())
+
+function change() {
+    updateData()
+}
+
+const option = reactive({
+    tooltip: {
+        trigger: 'axis',
+        axisPointer: {
+            type: 'shadow'
+        }
+    },
+    legend: {
+        bottom: "0",
+        itemGap: 20
+    },
+    grid: {
+        right: "3%",
+        bottom: '12%',
+    },
+    xAxis: [
+        {
+            type: 'category',
+            data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+        }
+    ],
+    yAxis: [
+        {
+            type: 'value'
+        }
+    ],
+    series: [
+        {
+            name: '高风险作业',
+            type: 'bar',
+            stack: 'bar_1',
+            data: [120, 132, 101, 134, 90, 230, 210],
+            itemStyle: {
+                color: "#DA0000",
+                borderRadius: [10, 10, 10, 10]
+            }
+        },
+        {
+            name: '中风险作业',
+            type: 'bar',
+            stack: 'bar_2',
+            data: [220, 182, 191, 234, 290, 330, 310],
+            itemStyle: {
+                color: "#FFBA00",
+                borderRadius: [10, 10, 10, 10]
+            }
+        },
+        {
+            name: '低风险作业',
+            type: 'bar',
+            stack: 'bar_3',
+            data: [150, 232, 201, 154, 190, 330, 410],
+            itemStyle: {
+                color: "#2BB200",
+                borderRadius: [10, 10, 10, 10]
+            }
+        }
+    ]
+})
+
+const homework_chart = shallowRef(null)
+
+function initChart() {
+    homework_chart.value = echarts.init(document.getElementById('homework_chart'))
+    homework_chart.value.setOption(option)
+}
+
+// 数据刷新
+function updateData() {
+    time_work_count({
+        start_date: date_value.value[0],
+        end_date: date_value.value[1]
+    }).then((res) => {
+        option.xAxis = res.content.xAxis
+        option.series = res.content.series
+
+        homework_chart.value.setOption(option)
+    })
+}
+
+onMounted(() => {
+    setTimeout(initChart)
+    // setInterval(updateData, 4000)
+
+    time_work_count({
+        start_date: date_value.value[0],
+        end_date: date_value.value[1]
+    }).then((res) => {
+        option.xAxis = res.content.xAxis
+        option.series = res.content.series
+
+        homework_chart.value.setOption(option)
+    })
+})
+</script>
+
+<template>
+    <div class="homework">
+        <div class="date_select">
+            <div class="block">
+                <el-date-picker v-model="date_value" type="daterange" :clearable="false" unlink-panels
+                    range-separator="——" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"
+                    value-format="YYYY-MM-DD" />
+            </div>
+            <!-- <div class="btn_select">查看</div> -->
+        </div>
+
+        <div id="homework_chart" class="chart"></div>
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.homework {
+    width: 100%;
+}
+
+.date_select {
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+
+    .block {
+        :deep(.el-range-editor.el-input__wrapper) {
+            padding: 10px;
+            border-radius: 25px;
+            width: 500px;
+        }
+
+        :deep(.el-date-editor .el-range-input) {
+            color: #393939;
+            font-size: 16px;
+        }
+
+        :deep(.el-date-editor .el-range__icon) {
+            display: none;
+        }
+    }
+
+    .btn_select {
+        width: 113px;
+        height: 50px;
+        line-height: 50px;
+        text-align: center;
+        background: #3F6FFF;
+        border-radius: 25px;
+        border: 1px solid #3F6FFF;
+        font-weight: 700;
+        font-size: 28px;
+        color: #FFFFFF;
+    }
+}
+
+.chart {
+    width: 670px;
+    height: 530px;
+}
+</style>

+ 153 - 0
src/views/index/index.vue

@@ -0,0 +1,153 @@
+<script setup>
+import { ref } from "vue";
+import DigitalStatistics from "./digitalStatistics.vue";
+import MapNingdong from "./map.vue";
+import MapTaixi from "./mapTaixi.vue";
+import HomeworkStatistics from "./homeworkStatistics.vue";
+import regionalStatistics_ningdong from "./regionalStatistics_ningdong.vue";
+import regionalStatistics_taixi from "./regionalStatistics_taixi.vue";
+import UnitList from "./unitList.vue";
+
+
+const digitalStatistics = ref()
+function open_dialogTableVisible_ningdong(e){
+    digitalStatistics.value.dialogTableVisible_click(e.title,e.index,'',1)
+}
+function open_dialogTableVisible_taixi(e){
+    digitalStatistics.value.dialogTableVisible_click(e.title,e.index,'',2)
+}
+function open_dialogTableVisible_map(e){
+    digitalStatistics.value.dialogTableVisible_click(e.title,'',e.coal_washery_id,'')
+}
+function open_dialogTableVisible_unit(e){
+    digitalStatistics.value.dialogTableVisible_click(e.title,'',e.coal_washery_id,'')
+}
+
+const map_index = ref(1)
+function change_map(index){
+    map_index.value = index
+}
+
+// 2025-05-21
+// 查看更多
+function more_map(){
+
+}
+
+</script>
+
+<template>
+    <div>
+        <DigitalStatistics ref="digitalStatistics"></DigitalStatistics>
+
+        <div class="section_box">
+            <div class="map_content">
+                <!-- <div class="map_title">
+                    <div class="title" :class="map_index==1?'title_active':''" @click="change_map(1)">宁东片区</div>
+                    <div class="title" :class="map_index==2?'title_active':''" @click="change_map(2)">太西片区</div>
+                </div> -->
+                <!-- <div class="more_title">
+                    <el-button type="primary" @click="more_map()">查看更多</el-button>
+                </div> -->
+                <div class="map_box">
+                    <MapNingdong v-if="map_index==1" @some-event="open_dialogTableVisible_map"></MapNingdong>
+                    <!-- <MapTaixi v-if="map_index==2" @some-event="open_dialogTableVisible_map"></MapTaixi> -->
+                </div>
+            </div>
+
+            <div class="card_box">
+                <el-carousel :interval="4000" type="card" height="630px">
+                    <el-carousel-item>
+                        <div class="section">
+                            <HomeworkStatistics></HomeworkStatistics>
+                        </div>
+                    </el-carousel-item>
+                    <el-carousel-item>
+                        <div class="section">
+                            <regionalStatistics_ningdong @some-event="open_dialogTableVisible_ningdong"></regionalStatistics_ningdong>
+                        </div>
+                    </el-carousel-item>
+                    <el-carousel-item>
+                        <div class="section">
+                            <regionalStatistics_taixi @some-event="open_dialogTableVisible_taixi"></regionalStatistics_taixi>
+                        </div>
+                    </el-carousel-item>
+                    <el-carousel-item>
+                        <div class="section">
+                            <UnitList @some-event="open_dialogTableVisible_unit"></UnitList>
+                        </div>
+                    </el-carousel-item>
+                </el-carousel>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style scoped lang="scss">
+.section_box {
+    margin-top: 30px;
+    display: flex;
+    justify-content: space-between;
+
+    .map_content {
+        position: relative;
+        .map_title {
+            height: 60px;
+            box-sizing: border-box;
+            padding: 0 40px 10px;
+            display: flex;
+            justify-content: space-around;
+            align-items: center;
+            
+            background-color: #FFF;
+            border-radius: 30px 30px 0 0;
+            .title{
+                cursor: pointer;
+                text-align: center;
+                font-size: 24px;
+                font-weight: bold;
+                color: #333333;
+                padding: 10px 40px;
+            }
+            .title_active{
+                border-bottom: 4px solid #1777FF;
+            }
+        }
+        .more_title {
+            z-index: 999;
+            position: absolute;
+            right: 40px;
+            top: 20px;
+            cursor: pointer;
+        }
+        .map_box {
+            width: 717px;
+            // height: 570px;
+            height: 630px;
+            background-color: #FFF;
+            // border-radius: 0 0 30px 30px;
+            border-radius: 30px;
+            box-sizing: border-box;
+            padding: 10px 40px;
+        }
+    }
+
+    .card_box {
+        width: 1070px;
+
+        .el-carousel__item {
+            background-color: #FFF;
+            border-radius: 30px;
+        }
+
+        .el-carousel__item.is-active {
+            width: 717px;
+        }
+
+        .section {
+            box-sizing: border-box;
+            padding: 20px;
+        }
+    }
+}
+</style>

+ 402 - 0
src/views/index/map.vue

@@ -0,0 +1,402 @@
+<script setup>
+import { ref,reactive, onMounted } from 'vue';
+import { map_data } from '@/request/api';
+
+const emit = defineEmits(['someEvent'])
+const map_click = (title,coal_washery_id) => {
+    emit('someEvent', {title,coal_washery_id})
+}
+
+const tooltip = reactive({
+    data: {}
+})
+
+function get_map_data(){
+    map_data({
+
+    }).then((res)=>{
+        tooltip.data = res.content.map_data
+    })
+}
+
+onMounted(() => {
+    get_map_data()
+})
+
+
+const interval = ref(null);
+const titleItems_hover = ref(0);
+const map = ref(null);
+const titleItems = ref(null);
+
+function init() {
+    map.value = document.querySelector(".map");
+    titleItems.value = document.querySelectorAll('.title_item');
+    
+    map.value.addEventListener("mouseover", handleMouseOver);
+    map.value.addEventListener("mouseout", handleMouseOut);
+    map.value.addEventListener("click", handleMapClick);
+
+    startInterval();
+}
+
+function handleMouseOver(e) {
+    clearInterval(interval.value);
+    const hoveredItem = e.target.closest('.title_item'); // 确保获取到正确的标题项
+    if (hoveredItem) {
+        titleItems.value.forEach((item) => {
+            item.childNodes[1].style.display = item === hoveredItem ? "block" : "none";
+        });
+    }
+}
+
+function handleMouseOut(e) {
+    startInterval();
+    titleItems.value.forEach((item) => {
+        item.childNodes[1].style.display = "none";
+    });
+}
+
+function handleMapClick(e) {
+    const clickedItem = e.target.closest('.title_item'); // 确保获取到正确的标题项
+    if (clickedItem) {
+        titleItems.value.forEach((item) => {
+            item.childNodes[1].style.display = "none";
+        });
+        clickedItem.childNodes[1].style.display = "block";
+    }
+}
+
+function startInterval() {
+    interval.value = setInterval(() => {
+        titleItems.value.forEach((item, index) => {
+            item.childNodes[1].style.display = index === titleItems_hover.value ? "block" : "none";
+        });
+        titleItems_hover.value = (titleItems_hover.value + 1) % titleItems.value.length;
+    }, 3000);
+}
+
+onMounted(() => {
+   setTimeout(() => {
+        init()
+   },2000)
+})
+
+</script>
+
+<template>
+    <div class="map">
+        <div class="map_img">
+            <img src="@/assets/images/map_ningdong.png" alt="">
+        </div>
+        <div class="title_list" v-if="tooltip.data.linxing">
+            <div class="left">
+                <div class="title_item" v-if="tooltip.data.linxing" @click="map_click(tooltip.data.linxing.title,tooltip.data.linxing.id)">
+                    <div class="title">{{ tooltip.data.linxing.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.linxing.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.hongliu" @click="map_click(tooltip.data.hongliu.title,tooltip.data.hongliu.id)">
+                    <div class="title">{{ tooltip.data.hongliu.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.hongliu.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.zaoquan" @click="map_click(tooltip.data.zaoquan.title,tooltip.data.zaoquan.id)">
+                    <div class="title">{{ tooltip.data.zaoquan.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.zaoquan.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jinneng" @click="map_click(tooltip.data.jinneng.title,tooltip.data.jinneng.id)">
+                    <div class="title">{{ tooltip.data.jinneng.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jinneng.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jianxiuyichejian" @click="map_click(tooltip.data.jianxiuyichejian.title,tooltip.data.jianxiuyichejian.id)">
+                    <div class="title">{{ tooltip.data.jianxiuyichejian.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jianxiuyichejian.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jianxiuerchejian" @click="map_click(tooltip.data.jianxiuerchejian.title,tooltip.data.jianxiuerchejian.id)">
+                    <div class="title">{{ tooltip.data.jianxiuerchejian.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jianxiuerchejian.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 2025-05-21:新增 -->
+                <div class="title_item" v-if="tooltip.data.gongchengke" @click="map_click(tooltip.data.gongchengke.title,tooltip.data.gongchengke.id)">
+                    <div class="title">{{ tooltip.data.gongchengke.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.gongchengke.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jidiandonglike" @click="map_click(tooltip.data.jidiandonglike.title,tooltip.data.jidiandonglike.id)">
+                    <div class="title">{{ tooltip.data.jidiandonglike.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jidiandonglike.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.shengchanjishuke" @click="map_click(tooltip.data.shengchanjishuke.title,tooltip.data.shengchanjishuke.id)">
+                    <div class="title">{{ tooltip.data.shengchanjishuke.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shengchanjishuke.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.zongheke" @click="map_click(tooltip.data.zongheke.title,tooltip.data.zongheke.id)">
+                    <div class="title">{{ tooltip.data.zongheke.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.zongheke.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+
+            </div>
+            <div class="right">
+
+                <div class="title_item" v-if="tooltip.data.qingshuiying" @click="map_click(tooltip.data.qingshuiying.title,tooltip.data.qingshuiying.id)">
+                    <div class="title">{{ tooltip.data.qingshuiying.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.qingshuiying.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.meihuajing" @click="map_click(tooltip.data.meihuajing.title,tooltip.data.meihuajing.id)">
+                    <div class="title">{{ tooltip.data.meihuajing.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.meihuajing.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.shicaocun" @click="map_click(tooltip.data.shicaocun.title,tooltip.data.shicaocun.id)">
+                    <div class="title">{{ tooltip.data.shicaocun.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shicaocun.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.shuangma" @click="map_click(tooltip.data.shuangma.title,tooltip.data.shuangma.id)">
+                    <div class="title">{{ tooltip.data.shuangma.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shuangma.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jinfeng" @click="map_click(tooltip.data.jinfeng.title,tooltip.data.jinfeng.id)">
+                    <div class="title">{{ tooltip.data.jinfeng.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jinfeng.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.yangchangwan" @click="map_click(tooltip.data.yangchangwan.title,tooltip.data.yangchangwan.id)">
+                    <div class="title">{{ tooltip.data.yangchangwan.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.yangchangwan.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.yanger" @click="map_click(tooltip.data.yanger.title,tooltip.data.yanger.id)">
+                    <div class="title">{{ tooltip.data.yanger.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.yanger.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    
+
+</template>
+
+<style scoped lang="scss">
+.map {
+    width: 100%;
+    height: 100%;
+
+    position: relative;
+
+    .map_img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+
+        img {
+            width: 335px;
+            height: 550px;
+        }
+    }
+
+    .line_img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+
+        img {
+            width: 398px;
+            height: 499px;
+        }
+    }
+
+    .title_list {
+        margin-top: 30px;
+        width: 100%;
+        height: 100%;
+        position: absolute;
+
+        .title_item {
+            cursor: pointer;
+            text-align: center;
+            padding: 4px 8px;
+            border: 2px solid #3F6FFF;
+            border-radius: 10px;
+            position: relative;
+
+            .title {
+                font-weight: 700;
+            }
+
+            .data {
+                display: none;
+                width: 100px;
+                background-color: #3F6FFF;
+                border-radius: 10px;
+                padding: 10px 20px;
+
+                position: absolute;
+                top: -14px;
+                left: 124px;
+
+                .item {
+                    color: #FFF;
+                    font-size: 14px;
+                    line-height: 30px;
+                    display: flex;
+
+                    .name {
+                        margin-right: 4px;
+                    }
+                }
+            }
+
+            .data::before {
+                content: '';
+                position: absolute;
+                left: -4px;
+                top: 15px;
+                transform: rotate(45deg);
+                width: 20px;
+                height: 20px;
+                background-color: #3F6FFF
+            }
+        }
+
+        .title_item:hover {
+            background-color: #3F6FFF;
+
+            .title {
+                color: #FFF;
+            }
+
+            .data {
+                display: block;
+            }
+        }
+
+        .left {
+            position: absolute;
+            left: -20px;
+            top: 0;
+
+            .title_item {
+                margin-bottom: 34px;
+            }
+
+        }
+
+        .right {
+            position: absolute;
+            left: 490px;
+            top: 0;
+
+            .title_item {
+                margin-bottom: 32px;
+
+                .data {
+                    left: -160px;
+                }
+
+                .data::before {
+                    content: '';
+                    position: absolute;
+                    left: 124px;
+                    top: 15px;
+                    transform: rotate(45deg);
+                    width: 20px;
+                    height: 20px;
+                    background-color: #3F6FFF
+                }
+            }
+
+            .title_item:nth-child(1) {
+                margin-top: 60px;
+            }
+
+            .title_item:nth-child(4) {
+                margin-bottom: 104px;
+            }
+        }
+
+    }
+}
+</style>

+ 375 - 0
src/views/index/mapTaixi.vue

@@ -0,0 +1,375 @@
+<script setup>
+import { ref,reactive, onMounted } from 'vue';
+import { map_data } from '@/request/api';
+
+const emit = defineEmits(['someEvent'])
+const map_click = (title,coal_washery_id) => {
+    emit('someEvent', {title,coal_washery_id})
+}
+
+const tooltip = reactive({
+    data: {}
+})
+
+function get_map_data(){
+    // map_data({
+
+    // }).then((res)=>{
+    //     tooltip.data = res.content.map_data
+    // })
+}
+
+onMounted(() => {
+    get_map_data()
+})
+
+
+const interval = ref(null);
+const titleItems_hover = ref(0);
+const map = ref(null);
+const titleItems = ref(null);
+
+function init() {
+    map.value = document.querySelector(".map");
+    titleItems.value = document.querySelectorAll('.title_item');
+    
+    map.value.addEventListener("mouseover", handleMouseOver);
+    map.value.addEventListener("mouseout", handleMouseOut);
+    map.value.addEventListener("click", handleMapClick);
+
+    startInterval();
+}
+
+function handleMouseOver(e) {
+    clearInterval(interval.value);
+    const hoveredItem = e.target.closest('.title_item'); // 确保获取到正确的标题项
+    if (hoveredItem) {
+        titleItems.value.forEach((item) => {
+            item.childNodes[1].style.display = item === hoveredItem ? "block" : "none";
+        });
+    }
+}
+
+function handleMouseOut(e) {
+    startInterval();
+    titleItems.value.forEach((item) => {
+        item.childNodes[1].style.display = "none";
+    });
+}
+
+function handleMapClick(e) {
+    const clickedItem = e.target.closest('.title_item'); // 确保获取到正确的标题项
+    if (clickedItem) {
+        titleItems.value.forEach((item) => {
+            item.childNodes[1].style.display = "none";
+        });
+        clickedItem.childNodes[1].style.display = "block";
+    }
+}
+
+function startInterval() {
+    interval.value = setInterval(() => {
+        titleItems.value.forEach((item, index) => {
+            item.childNodes[1].style.display = index === titleItems_hover.value ? "block" : "none";
+        });
+        titleItems_hover.value = (titleItems_hover.value + 1) % titleItems.value.length;
+    }, 3000);
+}
+
+onMounted(() => {
+   setTimeout(() => {
+        init()
+   },2000)
+})
+
+</script>
+
+<template>
+    <div class="map">
+        <div class="map_img">
+            <img src="@/assets/images/map_line.png" alt="">
+        </div>
+        <div class="title_list" v-if="tooltip.data.linxing">
+            <div class="left">
+                <div class="title_item" v-if="tooltip.data.linxing" @click="map_click(tooltip.data.linxing.title,tooltip.data.linxing.id)">
+                    <div class="title">{{ tooltip.data.linxing.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.linxing.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.hongliu" @click="map_click(tooltip.data.hongliu.title,tooltip.data.hongliu.id)">
+                    <div class="title">{{ tooltip.data.hongliu.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.hongliu.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.zaoquan" @click="map_click(tooltip.data.zaoquan.title,tooltip.data.zaoquan.id)">
+                    <div class="title">{{ tooltip.data.zaoquan.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.zaoquan.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jinneng" @click="map_click(tooltip.data.jinneng.title,tooltip.data.jinneng.id)">
+                    <div class="title">{{ tooltip.data.jinneng.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jinneng.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jianxiuyichejian" @click="map_click(tooltip.data.jianxiuyichejian.title,tooltip.data.jianxiuyichejian.id)">
+                    <div class="title">{{ tooltip.data.jianxiuyichejian.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jianxiuyichejian.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jianxiuerchejian" @click="map_click(tooltip.data.jianxiuerchejian.title,tooltip.data.jianxiuerchejian.id)">
+                    <div class="title">{{ tooltip.data.jianxiuerchejian.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jianxiuerchejian.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                
+            </div>
+            <div class="right">
+                
+                <div class="title_item" v-if="tooltip.data.qingshuiying" @click="map_click(tooltip.data.qingshuiying.title,tooltip.data.qingshuiying.id)">
+                    <div class="title">{{ tooltip.data.qingshuiying.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.qingshuiying.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.meihuajing" @click="map_click(tooltip.data.meihuajing.title,tooltip.data.meihuajing.id)">
+                    <div class="title">{{ tooltip.data.meihuajing.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.meihuajing.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.shicaocun" @click="map_click(tooltip.data.shicaocun.title,tooltip.data.shicaocun.id)">
+                    <div class="title">{{ tooltip.data.shicaocun.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shicaocun.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.shuangma" @click="map_click(tooltip.data.shuangma.title,tooltip.data.shuangma.id)">
+                    <div class="title">{{ tooltip.data.shuangma.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shuangma.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.jinfeng" @click="map_click(tooltip.data.jinfeng.title,tooltip.data.jinfeng.id)">
+                    <div class="title">{{ tooltip.data.jinfeng.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jinfeng.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.yangchangwan" @click="map_click(tooltip.data.yangchangwan.title,tooltip.data.yangchangwan.id)">
+                    <div class="title">{{ tooltip.data.yangchangwan.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.yangchangwan.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" v-if="tooltip.data.yanger" @click="map_click(tooltip.data.yanger.title,tooltip.data.yanger.id)">
+                    <div class="title">{{ tooltip.data.yanger.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.yanger.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    
+
+</template>
+
+<style scoped lang="scss">
+.map {
+    width: 100%;
+    height: 100%;
+
+    position: relative;
+
+    .map_img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+
+        img {
+            width: 335px;
+            height: 550px;
+        }
+    }
+
+    .line_img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+
+        img {
+            width: 398px;
+            height: 499px;
+        }
+    }
+
+    .title_list {
+        width: 100%;
+        height: 100%;
+        position: absolute;
+
+        .title_item {
+            cursor: pointer;
+            text-align: center;
+            padding: 4px 8px;
+            border: 2px solid #3F6FFF;
+            border-radius: 10px;
+            position: relative;
+
+            .title {
+                font-weight: 700;
+            }
+
+            .data {
+                display: none;
+                width: 100px;
+                background-color: #3F6FFF;
+                border-radius: 10px;
+                padding: 10px 20px;
+
+                position: absolute;
+                top: -14px;
+                left: 124px;
+
+                .item {
+                    color: #FFF;
+                    font-size: 14px;
+                    line-height: 30px;
+                    display: flex;
+
+                    .name {
+                        margin-right: 4px;
+                    }
+                }
+            }
+
+            .data::before {
+                content: '';
+                position: absolute;
+                left: -4px;
+                top: 15px;
+                transform: rotate(45deg);
+                width: 20px;
+                height: 20px;
+                background-color: #3F6FFF
+            }
+        }
+
+        .title_item:hover {
+            background-color: #3F6FFF;
+
+            .title {
+                color: #FFF;
+            }
+
+            .data {
+                display: block;
+            }
+        }
+
+        .left {
+            position: absolute;
+            left: 30px;
+            top: 0;
+
+            .title_item {
+                margin-bottom: 38px;
+            }
+
+            .title_item:nth-child(3) {
+                margin-bottom: 104px;
+            }
+
+            .title_item:nth-child(4) {
+                margin-bottom: 90px;
+            }
+
+
+            .title_item:nth-child(6) {
+                margin-top: -20px;
+            }
+        }
+
+        .right {
+            position: absolute;
+            left: 490px;
+            top: 0;
+
+            .title_item {
+                margin-bottom: 32px;
+
+                .data {
+                    left: -160px;
+                }
+
+                .data::before {
+                    content: '';
+                    position: absolute;
+                    left: 124px;
+                    top: 15px;
+                    transform: rotate(45deg);
+                    width: 20px;
+                    height: 20px;
+                    background-color: #3F6FFF
+                }
+            }
+
+            .title_item:nth-child(1) {
+                margin-top: 60px;
+            }
+
+            .title_item:nth-child(5) {
+                margin-bottom: 104px;
+            }
+        }
+
+    }
+}
+</style>

+ 469 - 0
src/views/index/map_default.vue

@@ -0,0 +1,469 @@
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+
+const tooltip = reactive({
+    data: {
+        "linxing": {
+            title: "灵新洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "hongliu": {
+            title: "红柳洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "zaoquan": {
+            title: "枣泉洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "dawukou": {
+            title: "大武口洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "jinfeng": {
+            title: "金凤洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "jianxiuchejian": {
+            title: "检修车间",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "taixi": {
+            title: "太西洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "qingshuiying": {
+            title: "清水营洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "meihuajing": {
+            title: "梅花井洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "shicaocun": {
+            title: "石槽村洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "shuangma": {
+            title: "双马洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "jinfeng": {
+            title: "金凤洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "yangchangwan": {
+            title: "羊场湾洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "yangchangwanerfenqu": {
+            title: "羊场湾二分区",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        }
+    }
+})
+
+onMounted(() => {
+    
+})
+
+</script>
+
+<template>
+    <div class="map">
+        <div class="map_img">
+            <img src="@/assets/images/map_line.png" alt="">
+        </div>
+        <div class="title_list">
+            <div class="left">
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.linxing.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.linxing.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.hongliu.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.hongliu.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.zaoquan.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.zaoquan.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.dawukou.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.dawukou.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.jinfeng.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jinfeng.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.jianxiuchejian.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jianxiuchejian.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="right">
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.taixi.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.taixi.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.qingshuiying.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.qingshuiying.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.meihuajing.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.meihuajing.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.shicaocun.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shicaocun.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.shuangma.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shuangma.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.jinfeng.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jinfeng.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.yangchangwan.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.yangchangwan.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item">
+                    <div class="title">{{ tooltip.data.yangchangwanerfenqu.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.yangchangwanerfenqu.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style scoped lang="scss">
+.map {
+    width: 100%;
+    height: 100%;
+
+    position: relative;
+
+    .map_img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+
+        img {
+            width: 335px;
+            height: 550px;
+        }
+    }
+
+    .line_img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+
+        img {
+            width: 398px;
+            height: 499px;
+        }
+    }
+
+    .title_list {
+        width: 100%;
+        height: 100%;
+        position: absolute;
+
+        .title_item {
+            cursor: pointer;
+            text-align: center;
+            padding: 4px 8px;
+            border: 2px solid #3F6FFF;
+            border-radius: 10px;
+            position: relative;
+
+            .title {
+                font-weight: 700;
+            }
+
+            .data {
+                display: none;
+                width: 100px;
+                background-color: #3F6FFF;
+                border-radius: 10px;
+                padding: 10px 20px;
+
+                position: absolute;
+                top: -14px;
+                left: 124px;
+
+                .item {
+                    color: #FFF;
+                    font-size: 14px;
+                    line-height: 30px;
+                    display: flex;
+
+                    .name {
+                        margin-right: 4px;
+                    }
+                }
+            }
+
+            .data::before {
+                content: '';
+                position: absolute;
+                left: -4px;
+                top: 15px;
+                transform: rotate(45deg);
+                width: 20px;
+                height: 20px;
+                background-color: #3F6FFF
+            }
+        }
+
+        .title_item:hover {
+            background-color: #3F6FFF;
+
+            .title {
+                color: #FFF;
+            }
+
+            .data {
+                display: block;
+            }
+        }
+
+        .left {
+            position: absolute;
+            left: 30px;
+            top: 0;
+
+            .title_item {
+                margin-bottom: 38px;
+            }
+
+            .title_item:last-child {
+                margin-top: 110px;
+            }
+        }
+
+        .right {
+            position: absolute;
+            left: 490px;
+            top: 0;
+
+            .title_item {
+                margin-bottom: 32px;
+
+                .data {
+                    left: -160px;
+                }
+
+                .data::before {
+                    content: '';
+                    position: absolute;
+                    left: 124px;
+                    top: 15px;
+                    transform: rotate(45deg);
+                    width: 20px;
+                    height: 20px;
+                    background-color: #3F6FFF
+                }
+            }
+
+            .title_item:nth-child(5) {
+                margin-bottom: 104px;
+            }
+        }
+
+    }
+}
+</style>

+ 534 - 0
src/views/index/map_mouseover.vue

@@ -0,0 +1,534 @@
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { map_data } from '@/request/api';
+
+const emit = defineEmits(['someEvent'])
+const map_click = (title,coal_washery_id) => {
+    emit('someEvent', {title,coal_washery_id})
+}
+
+const tooltip = reactive({
+    data: {
+        "linxing": {
+            title: "灵新洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "hongliu": {
+            title: "红柳洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "zaoquan": {
+            title: "枣泉洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "dawukou": {
+            title: "大武口洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "jinfeng": {
+            title: "金凤洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "jianxiuchejian": {
+            title: "检修车间",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "taixi": {
+            title: "太西洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 100
+                },
+                {
+                    name: "中风险作业",
+                    value: 100
+                },
+                {
+                    name: "低风险作业",
+                    value: 100
+                }
+            ]
+        },
+        "qingshuiying": {
+            title: "清水营洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "meihuajing": {
+            title: "梅花井洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "shicaocun": {
+            title: "石槽村洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "shuangma": {
+            title: "双马洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "jinfeng": {
+            title: "金凤洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "yangchangwan": {
+            title: "羊场湾洗煤厂",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        },
+        "yangchangwanerfenqu": {
+            title: "羊场湾二分区",
+            data: [
+                {
+                    name: "高风险作业",
+                    value: 90
+                }
+            ]
+        }
+    }
+})
+
+function get_map_data(){
+    map_data({
+
+    }).then((res)=>{
+        tooltip.data = res.content
+    })
+}
+
+const interval = ref(null)
+const titleItems_hover = ref(0)
+const map = ref(null)
+const titleItems = ref(null)
+
+function init() {
+    map.value = document.querySelector(".map")
+    titleItems.value = document.querySelectorAll('.title_item')
+
+    map.value.addEventListener("mouseover", handleMouseOver)
+    map.value.addEventListener("mouseout", handleMouseOut)
+    map.value.addEventListener("click", handleMapClick)
+
+    startInterval()
+}
+onMounted(() => {
+    setTimeout(() => {
+        init()
+    })
+    
+    get_map_data()
+    // setInterval(get_map_data,4000)
+})
+
+function handleMouseOver(e) {
+    clearInterval(interval.value)
+    titleItems.value[titleItems_hover.value].childNodes[1].style.display = "block"
+}
+
+function handleMouseOut(e) {
+    startInterval()
+    titleItems.value.forEach((item) => {
+        item.childNodes[1].style.display = "none"
+    })
+}
+
+function handleMapClick(e) {
+    const clickedItem = e.target.parentNode
+    titleItems.value.forEach((item) => {
+        item.childNodes[1].style.display = "none"
+    })
+    clickedItem.childNodes[1].style.display = "block"
+}
+
+function startInterval() {
+    interval.value = setInterval(() => {
+        titleItems.value.forEach((item, index) => {
+            item.childNodes[1].style.display = index === titleItems_hover.value ? "block" : "none"
+        })
+        titleItems_hover.value = (titleItems_hover.value + 1) % titleItems.value.length
+    }, 4000)
+}
+
+</script>
+
+<template>
+    <div class="map">
+        <div class="map_img">
+            <img src="@/assets/images/map_line.png" alt="">
+        </div>
+        <div class="title_list">
+            <div class="left">
+                <div class="title_item" @click="map_click(tooltip.data.linxing.title,tooltip.data.linxing.id)">
+                    <div class="title">{{ tooltip.data.linxing.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.linxing.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.hongliu.title,tooltip.data.hongliu.id)">
+                    <div class="title">{{ tooltip.data.hongliu.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.hongliu.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.zaoquan.title,tooltip.data.zaoquan.id)">
+                    <div class="title">{{ tooltip.data.zaoquan.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.zaoquan.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.dawukou.title,tooltip.data.dawukou.id)">
+                    <div class="title">{{ tooltip.data.dawukou.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.dawukou.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.jinfeng.title,tooltip.data.jinfeng.id)">
+                    <div class="title">{{ tooltip.data.jinfeng.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jinfeng.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.jianxiuchejian.title,tooltip.data.jianxiuchejian.id)">
+                    <div class="title">{{ tooltip.data.jianxiuchejian.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jianxiuchejian.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="right">
+                <div class="title_item" @click="map_click(tooltip.data.taixi.title,tooltip.data.taixi.id)">
+                    <div class="title">{{ tooltip.data.taixi.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.taixi.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.qingshuiying.title,tooltip.data.qingshuiying.id)">
+                    <div class="title">{{ tooltip.data.qingshuiying.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.qingshuiying.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.meihuajing.title,tooltip.data.meihuajing.id)">
+                    <div class="title">{{ tooltip.data.meihuajing.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.meihuajing.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.shicaocun.title,tooltip.data.shicaocun.id)">
+                    <div class="title">{{ tooltip.data.shicaocun.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shicaocun.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.shuangma.title,tooltip.data.shuangma.id)">
+                    <div class="title">{{ tooltip.data.shuangma.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.shuangma.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.jinfeng.title,tooltip.data.jinfeng.id)">
+                    <div class="title">{{ tooltip.data.jinfeng.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.jinfeng.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.yangchangwan.title,tooltip.data.yangchangwan.id)">
+                    <div class="title">{{ tooltip.data.yangchangwan.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.yangchangwan.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="title_item" @click="map_click(tooltip.data.yangchangwanerfenqu.title,tooltip.data.yangchangwanerfenqu.id)">
+                    <div class="title">{{ tooltip.data.yangchangwanerfenqu.title }}</div>
+                    <div class="data">
+                        <div class="item" v-for="(item, index) in tooltip.data.yangchangwanerfenqu.data" :key="index">
+                            <div class="name">{{ item.name }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    
+
+</template>
+
+<style scoped lang="scss">
+.map {
+    width: 100%;
+    height: 100%;
+
+    position: relative;
+
+    .map_img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+
+        img {
+            width: 335px;
+            height: 550px;
+        }
+    }
+
+    .line_img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+
+        img {
+            width: 398px;
+            height: 499px;
+        }
+    }
+
+    .title_list {
+        width: 100%;
+        height: 100%;
+        position: absolute;
+
+        .title_item {
+            cursor: pointer;
+            text-align: center;
+            padding: 4px 8px;
+            border: 2px solid #3F6FFF;
+            border-radius: 10px;
+            position: relative;
+
+            .title {
+                font-weight: 700;
+            }
+
+            .data {
+                display: none;
+                width: 100px;
+                background-color: #3F6FFF;
+                border-radius: 10px;
+                padding: 10px 20px;
+
+                position: absolute;
+                top: -14px;
+                left: 124px;
+
+                .item {
+                    color: #FFF;
+                    font-size: 14px;
+                    line-height: 30px;
+                    display: flex;
+
+                    .name {
+                        margin-right: 4px;
+                    }
+                }
+            }
+
+            .data::before {
+                content: '';
+                position: absolute;
+                left: -4px;
+                top: 15px;
+                transform: rotate(45deg);
+                width: 20px;
+                height: 20px;
+                background-color: #3F6FFF
+            }
+        }
+
+        .title_item:hover {
+            background-color: #3F6FFF;
+
+            .title {
+                color: #FFF;
+            }
+
+            .data {
+                display: block;
+            }
+        }
+
+        .left {
+            position: absolute;
+            left: 30px;
+            top: 0;
+
+            .title_item {
+                margin-bottom: 38px;
+            }
+
+            .title_item:last-child {
+                margin-top: 110px;
+            }
+        }
+
+        .right {
+            position: absolute;
+            left: 490px;
+            top: 0;
+
+            .title_item {
+                margin-bottom: 32px;
+
+                .data {
+                    left: -160px;
+                }
+
+                .data::before {
+                    content: '';
+                    position: absolute;
+                    left: 124px;
+                    top: 15px;
+                    transform: rotate(45deg);
+                    width: 20px;
+                    height: 20px;
+                    background-color: #3F6FFF
+                }
+            }
+
+            .title_item:nth-child(5) {
+                margin-bottom: 104px;
+            }
+        }
+
+    }
+}
+</style>

+ 266 - 0
src/views/index/regionalStatistics_ningdong.vue

@@ -0,0 +1,266 @@
+<script setup>
+import { ref, reactive, onMounted,shallowRef } from 'vue'
+import { time_area_total } from '@/request/api'
+import * as echarts from 'echarts'
+import {
+    getOneWeekTimePeriod
+} from "@/utils/time.js";
+
+const emit = defineEmits(['someEvent'])
+const btn_click = (title,index) => {
+    title = '宁东片区'+title
+    emit('someEvent', {title,index})
+}
+const date_value = ref(getOneWeekTimePeriod())
+
+function change() {
+    updateData()
+}
+
+const regional = reactive({
+    data: [
+        {
+            number: 126,
+            unit: '项',
+            title: "高风险作业",
+            color: "#DA0000"
+        },
+        {
+            number: 556,
+            unit: '项',
+            title: "中风险作业",
+            color: "#FFBA00"
+        },
+        {
+            number: 39,
+            unit: '项',
+            title: "低风险作业",
+            color: "#2BB200"
+        }
+    ]
+})
+
+const option = reactive({
+    tooltip: {
+        trigger: 'axis',
+        axisPointer: {
+            type: 'shadow'
+        }
+    },
+    legend: {
+        bottom: "0",
+        itemGap: 20
+    },
+    grid: {
+        top: "6%",
+        right: "3%",
+        bottom: '13%',
+    },
+    xAxis: [
+        {
+            type: 'category',
+            data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+        }
+    ],
+    yAxis: [
+        {
+            type: 'value'
+        }
+    ],
+    series: [
+        {
+            name: '高风险作业',
+            type: 'line',
+            data: [120, 132, 101, 134, 90, 230, 210],
+            itemStyle: {
+                color: "#DA0000",
+                borderRadius: [10, 10, 10, 10]
+            }
+        },
+        {
+            name: '中风险作业',
+            type: 'line',
+            data: [220, 182, 191, 234, 290, 330, 310],
+            itemStyle: {
+                color: "#FFBA00",
+                borderRadius: [10, 10, 10, 10]
+            }
+        },
+        {
+            name: '低风险作业',
+            type: 'line',
+            data: [150, 232, 201, 154, 190, 330, 410],
+            itemStyle: {
+                color: "#2BB200",
+                borderRadius: [10, 10, 10, 10]
+            }
+        }
+    ]
+})
+
+const regional_chart_ningdong = shallowRef(null)
+
+function initChart() {
+    regional_chart_ningdong.value = echarts.init(document.getElementById('regional_chart_ningdong'))
+    regional_chart_ningdong.value.setOption(option)
+}
+
+// 数据刷新
+function updateData() {
+    time_area_total({
+        area_id:1,
+        start_date: date_value.value[0],
+        end_date: date_value.value[1]
+    }).then((res) => {
+        regional.data = res.content.data
+        option.xAxis = res.content.xAxis
+        option.series = res.content.series
+
+        regional_chart_ningdong.value.setOption(option)
+    })
+}
+
+
+onMounted(() => {
+    setTimeout(initChart)
+    // setInterval(updateData, 4000)
+
+    time_area_total({
+        area_id:1,
+        start_date: date_value.value[0],
+        end_date: date_value.value[1]
+    }).then((res) => {
+        regional.data = res.content.data
+        option.xAxis = res.content.xAxis
+        option.series = res.content.series
+
+        regional_chart_ningdong.value.setOption(option)
+    })
+})
+</script>
+
+<template>
+    <div class="regional">
+        <div class="regional_title">宁东片区</div>
+
+        <div class="regional_list">
+            <div class="regional" v-for="(item, index) in regional.data" :key="index">
+                <div class="number_unit">
+                    <div class="number">{{ item.number }}</div>
+                    <div class="unit">{{ item.unit }}</div>
+                </div>
+                <div class="title" :style="{ backgroundColor: item.color }" @click="btn_click(item.title,index)">{{ item.title }}</div>
+            </div>
+        </div>
+
+        <div class="date_select">
+            <div class="block">
+                <el-date-picker v-model="date_value" type="daterange" :clearable="false" unlink-panels range-separator="——"
+                    start-placeholder="开始日期" end-placeholder="结束日期" @change="change" value-format="YYYY-MM-DD" />
+            </div>
+            <!-- <div class="btn_select">查看</div> -->
+        </div>
+
+        <div id="regional_chart_ningdong" class="chart"></div>
+    </div>
+
+</template>
+
+<style lang="scss" scoped>
+.regional_title {
+    text-align: center;
+    font-size: 30px;
+    font-weight: 700;
+    margin-bottom: 20px;
+}
+
+.regional_list {
+    padding: 0 10px;
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+
+    .regional {
+        background: #FFFFFF;
+        border-radius: 30px;
+
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: center;
+
+        margin-bottom: 20px;
+
+        .number_unit {
+            margin-bottom: 15px;
+            display: flex;
+            justify-content: center;
+            align-items: flex-end;
+            font-weight: 700;
+            color: #000000;
+
+            .number {
+                font-size: 26px;
+            }
+
+            .unit {
+                margin-left: 6px;
+                font-size: 18px;
+            }
+        }
+
+        .title {
+            width: 150px;
+            height: 44px;
+            background-color: #DA0000;
+            border-radius: 20px;
+            font-size: 18px;
+            font-weight: 700;
+            color: #FFFFFF;
+            line-height: 44px;
+            text-align: center;
+        }
+    }
+}
+
+.date_select {
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+
+    .block {
+        :deep(.el-range-editor.el-input__wrapper) {
+            padding: 10px;
+            border-radius: 25px;
+            width: 500px;
+        }
+
+        :deep(.el-date-editor .el-range-input) {
+            color: #393939;
+            font-size: 16px;
+        }
+
+        :deep(.el-date-editor .el-range__icon) {
+            display: none;
+        }
+    }
+
+    .btn_select {
+        width: 113px;
+        height: 50px;
+        line-height: 50px;
+        text-align: center;
+        background: #3F6FFF;
+        border-radius: 25px;
+        border: 1px solid #3F6FFF;
+        font-weight: 700;
+        font-size: 28px;
+        color: #FFFFFF;
+    }
+}
+
+.chart {
+    width: 670px;
+    height: 380px;
+}
+</style>

+ 264 - 0
src/views/index/regionalStatistics_taixi.vue

@@ -0,0 +1,264 @@
+<script setup>
+import { ref, reactive, onMounted,shallowRef } from 'vue'
+import { time_area_total } from '@/request/api'
+import * as echarts from 'echarts'
+import {
+    getOneWeekTimePeriod
+} from "@/utils/time.js";
+
+const emit = defineEmits(['someEvent'])
+const btn_click = (title,index) => {
+    title = '太西片区'+title
+    emit('someEvent', {title,index})
+}
+const date_value = ref(getOneWeekTimePeriod())
+
+function change() {
+    updateData()
+}
+
+const regional = reactive({
+    data: [
+        {
+            number: 126,
+            unit: '项',
+            title: "高风险作业",
+            color: "#DA0000"
+        },
+        {
+            number: 556,
+            unit: '项',
+            title: "中风险作业",
+            color: "#FFBA00"
+        },
+        {
+            number: 39,
+            unit: '项',
+            title: "低风险作业",
+            color: "#2BB200"
+        }
+    ]
+})
+
+const option = reactive({
+    tooltip: {
+        trigger: 'axis',
+        axisPointer: {
+            type: 'shadow'
+        }
+    },
+    legend: {
+        bottom: "0",
+        itemGap: 20
+    },
+    grid: {
+        top: "6%",
+        right: "3%",
+        bottom: '13%',
+    },
+    xAxis: [
+        {
+            type: 'category',
+            data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+        }
+    ],
+    yAxis: [
+        {
+            type: 'value'
+        }
+    ],
+    series: [
+        {
+            name: '高风险作业',
+            type: 'line',
+            data: [120, 132, 101, 134, 90, 230, 210],
+            itemStyle: {
+                color: "#DA0000",
+                borderRadius: [10, 10, 10, 10]
+            }
+        },
+        {
+            name: '中风险作业',
+            type: 'line',
+            data: [220, 182, 191, 234, 290, 330, 310],
+            itemStyle: {
+                color: "#FFBA00",
+                borderRadius: [10, 10, 10, 10]
+            }
+        },
+        {
+            name: '低风险作业',
+            type: 'line',
+            data: [150, 232, 201, 154, 190, 330, 410],
+            itemStyle: {
+                color: "#2BB200",
+                borderRadius: [10, 10, 10, 10]
+            }
+        }
+    ]
+})
+
+const regional_chart_taixi = shallowRef(null)
+
+function initChart() {
+    regional_chart_taixi.value = echarts.init(document.getElementById('regional_chart_taixi'))
+    regional_chart_taixi.value.setOption(option)
+}
+
+// 数据刷新
+function updateData() {
+    time_area_total({
+        area_id:2,
+        start_date: date_value.value[0],
+        end_date: date_value.value[1]
+    }).then((res) => {
+        regional.data = res.content.data
+        option.xAxis = res.content.xAxis
+        option.series = res.content.series
+
+        regional_chart_taixi.value.setOption(option)
+    })
+}
+
+onMounted(() => {
+    setTimeout(initChart)
+    // setInterval(updateData, 4000)
+
+    time_area_total({
+        area_id:2,
+        start_date: date_value.value[0],
+        end_date: date_value.value[1]
+    }).then((res) => {
+        regional.data = res.content.data
+        option.xAxis = res.content.xAxis
+        option.series = res.content.series
+
+        regional_chart_taixi.value.setOption(option)
+    })
+})
+</script>
+
+<template>
+    <div class="regional">
+        <div class="regional_title">太西片区</div>
+
+        <div class="regional_list">
+            <div class="regional" v-for="(item, index) in regional.data" :key="index">
+                <div class="number_unit">
+                    <div class="number">{{ item.number }}</div>
+                    <div class="unit">{{ item.unit }}</div>
+                </div>
+                <div class="title" :style="{ backgroundColor: item.color }" @click="btn_click(item.title,index)">{{ item.title }}</div>
+            </div>
+        </div>
+
+        <div class="date_select">
+            <div class="block">
+                <el-date-picker v-model="date_value" type="daterange" :clearable="false" unlink-panels range-separator="——"
+                    start-placeholder="开始日期" end-placeholder="结束日期" @change="change" value-format="YYYY-MM-DD" />
+            </div>
+            <!-- <div class="btn_select">查看</div> -->
+        </div>
+
+        <div id="regional_chart_taixi" class="chart"></div>
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.regional_title {
+    text-align: center;
+    font-size: 30px;
+    font-weight: 700;
+    margin-bottom: 20px;
+}
+
+.regional_list {
+    padding: 0 10px;
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+
+    .regional {
+        background: #FFFFFF;
+        border-radius: 30px;
+
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: center;
+
+        margin-bottom: 20px;
+
+        .number_unit {
+            margin-bottom: 15px;
+            display: flex;
+            justify-content: center;
+            align-items: flex-end;
+            font-weight: 700;
+            color: #000000;
+
+            .number {
+                font-size: 26px;
+            }
+
+            .unit {
+                margin-left: 6px;
+                font-size: 18px;
+            }
+        }
+
+        .title {
+            width: 150px;
+            height: 44px;
+            background-color: #DA0000;
+            border-radius: 20px;
+            font-size: 18px;
+            font-weight: 700;
+            color: #FFFFFF;
+            line-height: 44px;
+            text-align: center;
+        }
+    }
+}
+
+.date_select {
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+
+    .block {
+        :deep(.el-range-editor.el-input__wrapper) {
+            padding: 10px;
+            border-radius: 25px;
+            width: 500px;
+        }
+
+        :deep(.el-date-editor .el-range-input) {
+            color: #393939;
+            font-size: 16px;
+        }
+
+        :deep(.el-date-editor .el-range__icon) {
+            display: none;
+        }
+    }
+
+    .btn_select {
+        width: 113px;
+        height: 50px;
+        line-height: 50px;
+        text-align: center;
+        background: #3F6FFF;
+        border-radius: 25px;
+        border: 1px solid #3F6FFF;
+        font-weight: 700;
+        font-size: 28px;
+        color: #FFFFFF;
+    }
+}
+
+.chart {
+    width: 670px;
+    height: 380px;
+}
+</style>

+ 265 - 0
src/views/index/unitList.vue

@@ -0,0 +1,265 @@
+<script setup>
+import { reactive,onMounted } from "vue";
+import { coal_washery_total } from '@/request/api'
+
+const gridData = reactive({
+    data: [
+        {
+            unit_name: "机电科",
+            place: "红柳洗煤厂红柳洗煤厂红柳洗煤厂",
+            data: [
+                {
+                    label: "高",
+                    value: 156,
+                    color: "#DA0000"
+                },
+                {
+                    label: "中",
+                    value: 30,
+                    color: "#FFBA00"
+                },
+                {
+                    label: "低",
+                    value: 10,
+                    color: "#2BB200"
+                }
+            ]
+        },
+        {
+            unit_name: "综合科",
+            place: "梅花井洗煤厂",
+            data: [
+                {
+                    label: "高",
+                    value: 156,
+                    color: "#DA0000"
+                },
+                {
+                    label: "中",
+                    value: 30,
+                    color: "#FFBA00"
+                },
+                {
+                    label: "低",
+                    value: 10,
+                    color: "#2BB200"
+                }
+            ]
+        },
+        {
+            unit_name: "综合科",
+            place: "梅花井洗煤厂",
+            data: [
+                {
+                    label: "高",
+                    value: 156,
+                    color: "#DA0000"
+                },
+                {
+                    label: "中",
+                    value: 30,
+                    color: "#FFBA00"
+                },
+                {
+                    label: "低",
+                    value: 10,
+                    color: "#2BB200"
+                }
+            ]
+        },
+        {
+            unit_name: "综合科",
+            place: "梅花井洗煤厂",
+            data: [
+                {
+                    label: "高",
+                    value: 156,
+                    color: "#DA0000"
+                },
+                {
+                    label: "中",
+                    value: 30,
+                    color: "#FFBA00"
+                },
+                {
+                    label: "低",
+                    value: 10,
+                    color: "#2BB200"
+                }
+            ]
+        },
+        {
+            unit_name: "综合科",
+            place: "梅花井洗煤厂",
+            data: [
+                {
+                    label: "高",
+                    value: 156,
+                    color: "#DA0000"
+                },
+                {
+                    label: "中",
+                    value: 30,
+                    color: "#FFBA00"
+                },
+                {
+                    label: "低",
+                    value: 10,
+                    color: "#2BB200"
+                }
+            ]
+        },
+        {
+            unit_name: "综合科",
+            place: "梅花井洗煤厂",
+            data: [
+                {
+                    label: "高",
+                    value: 156,
+                    color: "#DA0000"
+                },
+                {
+                    label: "中",
+                    value: 30,
+                    color: "#FFBA00"
+                },
+                {
+                    label: "低",
+                    value: 10,
+                    color: "#2BB200"
+                }
+            ]
+        },
+        {
+            unit_name: "综合科",
+            place: "梅花井洗煤厂",
+            data: [
+                {
+                    label: "高",
+                    value: 156,
+                    color: "#DA0000"
+                },
+                {
+                    label: "中",
+                    value: 30,
+                    color: "#FFBA00"
+                },
+                {
+                    label: "低",
+                    value: 10,
+                    color: "#2BB200"
+                }
+            ]
+        },
+        {
+            unit_name: "综合科",
+            place: "梅花井洗煤厂",
+            data: [
+                {
+                    label: "高",
+                    value: 156,
+                    color: "#DA0000"
+                },
+                {
+                    label: "中",
+                    value: 30,
+                    color: "#FFBA00"
+                },
+                {
+                    label: "低",
+                    value: 10,
+                    color: "#2BB200"
+                }
+            ]
+        }
+    ]
+});
+
+function initChart() {
+    coal_washery_total({
+        
+    }).then((res) => {
+        gridData.data = res.content
+    })
+}
+
+// 数据刷新
+function updateData() {
+    initChart()
+}
+
+const emit = defineEmits(['someEvent'])
+const unit_click = (row) => {
+    let title = row.unit_name
+    let coal_washery_id = row.coal_washery_id
+    emit('someEvent', {title,coal_washery_id})
+}
+
+onMounted(() => {
+    setTimeout(initChart)
+    // setInterval(updateData, 4000)
+})
+</script>
+
+<template>
+    <div>
+        <el-table :data="gridData.data" height="580" @row-click="unit_click">
+            <el-table-column>
+                <template #default="scope">
+                    <div class="place" @click="">{{ scope.row.unit_name }}</div>
+                </template>
+            </el-table-column>
+            <el-table-column width="350">
+                <template #default="scope">
+                    <div class="label_list">
+                        <div class="label_box" v-for="(item, index) in scope.row.data" :key="index">
+                            <div class="label" :style="{ backgroundColor: item.color }">{{ item.label }}</div>
+                            <div class="value">{{ item.value }}</div>
+                        </div>
+                    </div>
+                </template>
+            </el-table-column>
+        </el-table>
+    </div>
+</template>
+
+<style scoped lang="scss">
+:deep(.el-table tr:nth-child(odd)) {
+    background-color: #e7f1ff;
+}
+
+.place {
+    font-size: 26px;
+    font-weight: 700;
+    color: #000;
+    line-height: 36px;
+    padding: 15px 0;
+}
+
+.label_list {
+    display: flex;
+    justify-content: space-between;
+}
+
+.label_box {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap: 6px;
+
+    .label {
+        padding: 6px 10px;
+        background-color: #d90000;
+        font-size: 18px;
+        color: #fff;
+        font-weight: 700;
+        border-radius: 8px;
+    }
+
+    .value {
+        font-weight: 700;
+        font-size: 22px;
+        color: #4b4b4b;
+    }
+}
+</style>

+ 15 - 0
vite.config.js

@@ -0,0 +1,15 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import { resolve } from "path"
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  plugins: [vue()],
+  base: "./",
+  resolve: {
+    // 配置路径别名
+    alias: {
+      '@': resolve(__dirname, './src')
+    },
+  }
+})