可视化地图

文章目录

通过脚手架安装,然后选中这几个选项




首页布局

c 复制代码
//demo\src\views\app-index.vue
<template>
  <div class="box">
    <video style="width: 100%;height: 100%;" muted loop autoplay>
      <source src="../assets/dv-index-main.mp4">
    </video>
    <div class="dv-index-main"></div>
  </div>
</template>

<style scoped lang="scss">
.box{
  position: relative;
  width: 100%;
  height: 100%;
}
.dv-index-main{
  position: absolute;
  left:0px;
  top:0px;
  width: 100%;
  height: 100%;
  background: url('../assets/images/大屏首页.png') no-repeat;
  background-size:100% 100%;
}
</style>

安装sass-embedded,lang="scss"。编译 Sass 代码

其实就是视频上面加个背景图

大屏适配

安装插件:大屏适配插件

复制代码
npm install v-scale-screen@2.0.0

导入进来使用

c 复制代码
<template>
  <div class="box">
    <video style="width: 100%;height: 100%;" muted loop autoplay>
      <source src="../assets/dv-index-main.mp4">
    </video>
    <div class="dv-index-main">
      <div class="dv-btn-group">
        <div
          v-for="(item,index) in btnArr"
          :key="index"
          class="btn-item"
          :class="[btnClassHandle(item.num)]"
        >
          <img :src="getImageUrl(item.url)" alt="">
        </div> 
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const btnArr = ref<any>([
  {
    num:'one',
    url:'安全基础.png'
  },
  {
    num:'two',
    url:'重大危险源.png'
  },
  {
    num:'three',
    url:'双重预防.png'
  },
  {
    num:'four',
    url:'特殊作业.png'
  }
]);
//接收循环的图片名称,然后然后添加路径
const getImageUrl = ( url:string )=>{
  // 作用是动态生成图片资源的完整URL路径
  return new URL(`../assets/images/${url}`,import.meta.url).href;
}
// 接收一个字符串参数 key 并返回一个拼接后的类名字符串
const btnClassHandle = ( key:string  )=>{
  return `btn-item-${key}`;   
}
</script>

<style scoped lang="scss">
.box{
  position: relative;
  width: 100%;
  height: 100%;
}
.dv-index-main{
  position: absolute;
  left:0px;
  top:0px;
  width: 100%;
  height: 100%;
  background: url('../assets/images/大屏首页.png') no-repeat;
  background-size:100% 100%;
  .dv-btn-group{
    position: absolute;
    left:0;
    bottom:145px;
    width:100%;
    height: 370px;
    z-index: 10;
    .btn-item{
      position: absolute;
      width: 145px;
      height: 168px;
      transition: transform .3s;
      cursor: pointer;
      img{
        width:100%;
        height: 100%;
      }
    }
    .btn-item-one{
      top: 143px;
      left: 298px;
    }
    .btn-item-two{
      top: 194px;
      left: 689px;
    }
    .btn-item-three{
      top: 194px;
      right: 683px;
    }
    .btn-item-four{
      top: 143px;
      right: 298px;
    }
  }
}
.btn-item:hover{
  transform: scale(1.2);
}
</style>

引入地图

添加点击事件和路由的数据

引入路由和对路由进行拼接

点击后进入

动态创建地图地址,路由,和class

javascript 复制代码
<template>
  <div class="box">
    <video style="width: 100%;height: 100%;" muted loop autoplay>
      <source src="../assets/dv-index-main.mp4">
    </video>
    <div class="dv-index-main">
      <div class="dv-btn-group">
        <div
          v-for="(item,index) in btnArr"
          :key="index"
          class="btn-item"
          :class="[btnClassHandle(item.num)]"
          @click="btnLinkHandle(item.urlKey)"
        >
          <img :src="getImageUrl(item.url)" alt="">
        </div> 
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter();

const btnArr = ref<any>([
  {
    num:'one',
    url:'安全基础.png',
    urlKey:'datav/security'
  },
  {
    num:'two',
    url:'重大危险源.png',
    urlKey:'datav/major-hazard'
  },
  {
    num:'three',
    url:'双重预防.png',
    urlKey:'datav/double-prevention-mechanism'
  },
  {
    num:'four',
    url:'特殊作业.png',
    urlKey:'datav/double-prevention-mechanism'
  }
]);
//接收循环的图片名称,然后然后添加路径,url是自定义,用来接收值
const getImageUrl = ( url:string )=>{
  // 作用是动态生成图片资源的完整URL路径
  return new URL(`../assets/images/${url}`,import.meta.url).href;
}
//添加动态class, 接收一个字符串参数 key 并返回一个拼接后的类名字符串
const btnClassHandle = ( key:string  )=>{
  return `btn-item-${key}`;   
}
// 添加动态路由
const btnLinkHandle = ( key:string )=>{
  router.push({
    path:`/${key}`
  })
}
</script>

新建子路由

设置地图全局组件


使用:天地图

复制代码
网址:http://lbs.tianditu.gov.cn/api/js4.0/guide.html
c 复制代码
<template>
    <div>
        <div id="tian-map"></div>
    </div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue';


//地图初始化
function initMap(){
    let T = window.T;
    //实例化
    let tmap = new T.Map('tian-map');
    //初始化地图的位置,经度,维度,大小
    tmap.centerAndZoom(new T.LngLat(116.40769, 39.89945), 18);
    //启用地图拖拽
    tmap.enableDrag();
    //设置地图类型
    tmap.setMapType( window.TMAP_SATELLITE_MAP );
}
onMounted(()=>{
    //1. 创建script标签
    const script = document.createElement('script');
    script.src = 'https://api.tianditu.gov.cn/api?v=4.0&tk=2d58761eb6bbdac6095476b73d4d1a82';
    //2. script标签加载完毕:初始化地图
    script.onload = initMap;
    //3. 把script添加到body中
    document.body.appendChild( script );
})
</script>

<style scoped>
#tian-map{
    width: 1920px;
    height: 1080px;
}
</style>

当你点击四个组件就能进去地图的全局组件了


顶部布局

c 复制代码
//demo\src\map\app-map.vue
<template>
    <div class="app-header">
        <div class="app-header-left">
            <div class="weather">
                <div class="tep">10°</div>
                <div class="weater-desc">
                    <p>晴</p>
                    <p>西</p>
                </div>
                <div class="text-base">2024-11-20 14:28:12</div>
            </div>
            <a class="nav-button">数字孪生</a>
        </div>
        <div class="app-header-center">安全基础</div>
        <div class="app-header-right">
            <div class="nav-button">
                <span class="back-btn">返回</span>
            </div>
        </div>
    </div>
</template>

<style scoped lang="scss">
.app-header{
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: fixed;
    width: 100%;
    height: var(--app-header-height);
    left: 0;
    top: 0;
    color: #ffb432;
    background-image:
        url(../assets/images/顶部导航背景.png),
        linear-gradient(to bottom, rgba(0, 0, 0, .1), rgba(0, 0, 0, .01));
    background-repeat: no-repeat;
    background-position: center 0;
    background-size: auto 100%;
    z-index: 1000;
}
.app-header-left{
    width: 28%;
    height: 68px;
    margin-top: 8px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #fff;
    .weather{
        display: flex;
        align-items: center;
        justify-content: space-around;;
        .tep{
            font-size: 33px;
            padding-left: 72px;
            background-image: url(../assets/images/duoyun.png);
            background-repeat: no-repeat;
            background-position: 24px center;
        }
        .weater-desc{
            font-size: 12px;
            padding-left: 1rem;
            padding-right: 1rem;
        }
        .text-base{
            font-size: 1rem;
            line-height: 1.5rem;
        }
    }
}
.nav-button{
    width: 173px;
    height: 46px;
    line-height: 46px;
    font-size: 16px;
    text-align: center;
    color: #fff;
    background-image: url(../assets/images/导航按钮.png);
    background-position: center;
    background-repeat: no-repeat;
    cursor: pointer;
}
.app-header-center{
    line-height: 72px;
    font-size: 40px;
    background-image: linear-gradient(to bottom, #ffb432, #ff9b2f);
    background-clip: text;
    color: transparent;
    font-family: c-huakang;
}
.app-header-right{
    width: 28%;
    height: 68px;
    margin-top: 8px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .back-btn{
        padding-left: 24px;
        background-image: url(../assets/images/返回.png);
        background-repeat: no-repeat;
        background-position: 0 center;
    }
}
</style>

axios二次封装

安装

c 复制代码
//demo\src\App.vue
 npm i axios

App.vue → 调用 → safe.ts 中的 getHazard() → 调用 → request.ts 中的 http.get()

App.vue

c 复制代码
<template>
  <VScaleScreen width="1920" height="1080" :fullScreen="true">
    <RouterView />
       <AppMap></AppMap>
  </VScaleScreen>
</template>

<script setup lang="ts">
import VScaleScreen from 'v-scale-screen'
import { getHazard } from '@/api/safe'

getHazard({
  companyId:0
}).then(res=>{
  console.log( 111,res )
})

</script>

safe.ts

c 复制代码
//demo\src\api\safe.ts
import http from '@/utils/request'

export const getHazard = ( data:any )=>{
    return http.get('dv3/safe/get-hazard',data);
}

request.ts

c 复制代码
//demo\src\utils\request.ts
import axios from 'axios'

// 请求数据的地址
const request = axios.create({
    baseURL: 'http://39.100.95.39:8089/',
    timeout: 5000
});

// 添加请求拦截器
request.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});

// 添加响应拦截器
request.interceptors.response.use(function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response.data;
}, function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
});

// 封装get和post两个方法,方便灵活应用
const http ={
    get( url:string , data:any ){
        return new Promise((resolve,reject)=>{
            request.get(url,{params:data})
            .then((res)=>{
                resolve(res)
            })
            .catch((error)=>{
                reject(error);
            })
        })
    },
    post( url:string , data:any ){
        return new Promise((resolve,reject)=>{
            request.post(url, data)
            .then((res)=>{
                resolve(res)
            })
            .catch((error)=>{
                reject(error);
            })
        })
    }
}
// 暴露出去
export default http;

得到接口数据

通过接口渲染天气和时间

使用请求回来的数据,进行渲染

c 复制代码
//demo\src\components\AppHeader.vue
<template>
    <div class="app-header">
        <div class="app-header-left">
            <div class="weather">
                <div class="tep">{{ state.weather.temperature_float }}°</div>
                <div class="weater-desc">
                    <p>{{ state.weather.weather }}</p>
                    <p>{{ state.weather.winddirection }}</p>
                </div>
                <div class="text-base">{{ state.currentTime }}</div>
            </div>
            <a class="nav-button">数字孪生</a>
        </div>
        <div class="app-header-center">安全基础</div>
        <div class="app-header-right">
            <div class="nav-button">
                <span class="back-btn">返回</span>
            </div>
        </div>
    </div>
</template>


<script setup lang="ts">
import { onMounted  } from 'vue';
// 引用useFunction.ts的getApiAxios();updateTime();,再触发这个函数
import { useFunction } from '@/hooks/useFunction'
let { state , updateTime , getApiAxios } = useFunction();
onMounted(()=>{
    getApiAxios();
    updateTime();
    setInterval(updateTime,1000);
})
</script>

<style scoped lang="scss">
.app-header{
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: fixed;
    width: 100%;
    height: var(--app-header-height);
    left: 0;
    top: 0;
    color: #ffb432;
    background-image:
        url(../assets/images/顶部导航背景.png),
        linear-gradient(to bottom, rgba(0, 0, 0, .1), rgba(0, 0, 0, .01));
    background-repeat: no-repeat;
    background-position: center 0;
    background-size: auto 100%;
    z-index: 1000;
}
.app-header-left{
    width: 28%;
    height: 68px;
    margin-top: 8px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #fff;
    .weather{
        display: flex;
        align-items: center;
        justify-content: space-around;;
        .tep{
            font-size: 33px;
            padding-left: 72px;
            background-image: url(../assets/images/duoyun.png);
            background-repeat: no-repeat;
            background-position: 24px center;
        }
        .weater-desc{
            font-size: 12px;
            padding-left: 1rem;
            padding-right: 1rem;
        }
        .text-base{
            font-size: 1rem;
            line-height: 1.5rem;
        }
    }
}
.nav-button{
    width: 173px;
    height: 46px;
    line-height: 46px;
    font-size: 16px;
    text-align: center;
    color: #fff;
    background-image: url(../assets/images/导航按钮.png);
    background-position: center;
    background-repeat: no-repeat;
    cursor: pointer;
}
.app-header-center{
    line-height: 72px;
    font-size: 40px;
    background-image: linear-gradient(to bottom, #ffb432, #ff9b2f);
    background-clip: text;
    color: transparent;
    font-family: c-huakang;
}
.app-header-right{
    width: 28%;
    height: 68px;
    margin-top: 8px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .back-btn{
        padding-left: 24px;
        background-image: url(../assets/images/返回.png);
        background-repeat: no-repeat;
        background-position: 0 center;
    }
}
</style>

通过默认get请求,获取接口数据

c 复制代码
//demo\src\hooks\useFunction.ts
import { reactive } from "vue"
import axios from 'axios'
export function useFunction(){


    const getApiAxios = ()=>{
        try {
            axios({
                url:'https://restapi.amap.com/v3/weather/weatherInfo',
                params:{
                    key:'a5613e113fa97e8f6b9903990b124f71',
                    city:'110000'
                }
            }).then(res=>{
                let { data } = res;
                state.weather = data.lives[0];
                console.log( state.weather )
            })
        } catch (error) {
            console.log( error );
        }
    }
    
    //获取时间,时间没有使用接口数据
    function getCurrentDateTime(){
        const now = new Date();
        const year = now.getFullYear();
        const month = String( now.getMonth() + 1 ).padStart(2,'0');
        const day = String(now.getDate()).padStart(2,'0');
        const hours = String(now.getHours()).padStart(2,'0');
        const minutes = String(now.getMinutes()).padStart(2,'0');
        const seconds = String(now.getSeconds()).padStart(2,'0');

        const formattedDate = `${year}-${month}-${day}`;
        const formattedTime = `${hours}-${minutes}-${seconds}`;
        return `${formattedDate} ${formattedTime}`;
    }

    function updateTime(){
        state.currentTime = getCurrentDateTime();
    }

    const state = reactive({
        weather:{},
        currentTime:''
    });

    return {
        state,
        updateTime,
        getApiAxios,
        getCurrentDateTime
    }
}

修改地图位置和添加覆盖物

复制代码
    //获取园区详情数据,useMapConfig是store 实例,挂载触发
await useMapConfig().getPark();


步骤

1,获取园区信息,经纬度等等。

2,覆盖物重构

3,设置多边形覆盖物的位置

4,添加到地图上app-map.vue

c 复制代码
//demo\src\stores\mapConfig.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { getParkInfo } from '@api/safe'
// 创建一个新的 store 实例
export const useMapConfig = defineStore('mapConfig',()=>{

    //园区信息
    const parkInfo = ref();
    async function getPark(){
        let res = await getParkInfo({
            // 支持未来多园区切换
            companyId:0
        })
        parkInfo.value = res.data;
        console.log( parkInfo.value  )
    }

    //园区中心
    let parkCenter = ref<any>();
    //园区边界
    let parkPolygonPath = ref<any>();
    //园区图形
    let parkPolygon = ref<any>();

    function initConfigForMap( map:any ){
        // 园区中心点
        parkCenter.value = new T.LngLat( parkInfo.value?.longitude , parkInfo.value?.latitude );
        //覆盖物数据重构,使数据格式适合使用。
        // 第一次分割:分号分隔多个坐标点
        // 第二次分割:逗号分隔经纬度
        // 坐标对象创建,map((p) => new T.LngLat(...p)) 
        // 原始数据: "116.1,39.1;116.2,39.2;116.3,39.3"
            // → split(';'): ["116.1,39.1", "116.2,39.2", "116.3,39.3"]  
            // → map(split(',')): [["116.1","39.1"], ["116.2","39.2"], ["116.3","39.3"]]
            // → map(T.LngLat): [T.LngLat(116.1,39.1), T.LngLat(116.2,39.2), T.LngLat(116.3,39.3)]
        parkPolygonPath.value = parkInfo.value.boundaries[0].value
            .split(';')           
            .map((p) => p.split(',')) 
            .map((p) => new T.LngLat(...p)) 
        //多边形覆盖物
        parkPolygon.value = new T.Polygon( parkPolygonPath.value ,{
            weight: 3,
            color: parkInfo.value?.boundaries[0].options.sideFillColor,
            opacity: 1,
            fillColor: parkInfo.value?.boundaries[0].options.topFillColor || '#6d9f6a',
            fillOpacity: 0.5
        })
        addParkForMap( map );
    }

    //地图添加园区
    function addParkForMap( map:any ){
      	// 地图中心定位,?. 操作符防止未加载数据时的错误
        map.panTo( new T.LngLat( parkInfo.value?.longitude , parkInfo.value?.latitude ) );
         // 调整地图视野
        map.setViewport( parkPolygonPath.value );
        //将覆盖物添加到地图中
        map.addOverLay( parkPolygon.value );
    }
    return {
        getPark,
        initConfigForMap
    }
})

数据栏布局

建立全局组件

c 复制代码
<template>
    <div class="border-box">
        <div class="border-box-title font-ssr" v-text="title"></div>
        <slot></slot>
    </div>
</template>

<script setup lang="ts">
defineProps<{title:string}>()
</script>

<style scoped lang="scss">
.border-box{
    position: relative;
    width:424px;
    min-height: 160px;
    background-image: 
        url(@/assets/border-box-1/border-title.png),
        url(@/assets/border-box-1/border-bottom.png);
    background-position: 0 0,0 bottom;
    background-repeat: no-repeat;
    background-color: rgba(0,42,64,.4);
    .border-box-title{
        height: 36px;
        line-height: 36px;
        padding-left: 24px;
        color:#fff;
        font-size:16px;
    }
}
</style>

left1.vue

javascript 复制代码
<template>
    <div>
        这是第一个图表
    </div>
</template>

security-management.vue

javascript 复制代码
demo\src\views\security\security-management.vue
<template>
    <div class="layout-left">
        <div class="count-box">
            <span class="font-ssr">装置最大检修总数</span>
            <span class="font-ssb text-white">27</span>
        </div>
        <border-box title="两重点一重大">
            <Left1 />
        </border-box>
        <border-box title="安全三同时报告">
            <Left1 />
        </border-box>
        <border-box title="面积规模">
            <Left1 />
        </border-box>
    </div>
    <div class="layout-right">
        <border-box title="两重点一重大">
            <Left1 />
        </border-box>
        <border-box title="安全三同时报告">
            <Left1 />
        </border-box>
        <border-box title="面积规模">
            <Left1 />
        </border-box>
    </div>
</template>

<script setup lang="ts">
import Left1 from './components/Left1.vue'
</script>

<style scoped lang="scss">
.count-box{
    position: absolute;
    top:-4px;
    left:calc(100% + 14px);
    padding: 14px 32px;
    display: flex;
    align-items: center;
    background-image: url('@/assets/images/总数统计背景.png');
    background-repeat: no-repeat;
    background-position: center;
    background-size: 100% 100%;
    white-space: nowrap;
    .font-ssr{
        font-size:14px;
        color: #a2f4fe;
    }
    .font-ssb{
        padding-left: 12px;
        font-size: 24px;
        color: #fff;
    }

}
</style>

效果

TailwindCSS

Tailwind CSS 是一个功能优先的、低级别的 CSS 框架,它让你能够通过直接在 HTML 中编写预定义的类来快速构建自定义的用户界面。
把它想象成一个巨大的、可复用的 CSS 工具包,而不是预先制作好的组件(如 Bootstrap 的按钮、导航栏)。

安装

复制代码
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init

在 v4 版本中,tailwindcss init 命令已经被移除了,所以要安装版本v3

复制代码
npm install -D tailwindcss@^3.4.0 postcss autoprefixer

安装后会出现一个文件

javascript 复制代码
//demo\tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}

添加

javascript 复制代码
/** @type {import('tailwindcss').Config} */
export default {
	// 扫描 index.html 文件	
	// 扫描 src 目录下所有的 Vue/JS/TS/JSX/TSX 文件
  content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
  theme: {
    extend: {}
  },
  plugins: []
}

新建一个文件,这是官网上的代码

引入

加上组件的间距

这样就有间距了

两重点一重大的内容添加

添加请求获取数据

复制代码
下载引入
	npm install echarts 
	import * as echarts from 'echarts'

安全三同时报告的内容添加

javascript 复制代码
<template>
    <div class="pt-5 px-8 pb-3">
      <app-chart :option="option" height="200px" />
    </div>
</template>
  
<script setup lang="ts">
import { ref , computed } from 'vue';
import { getComBuild } from '@api/safe'
let data = ref();
const getDatas = async ()=>{
    let res = await getComBuild({
        companyId:0
    })
    data.value = res.data;
}
getDatas()
const option = computed(() => {
    return {
        grid: {
            top: '30px',
            left: '0%',
            right: '0%',
            bottom: '0%',
            containLabel: true
        },
        xAxis: {
            data: ['项目资料', '安全三同时', '验收信息'],
            axisLabel: {
            textStyle: {
                color: 'rgba(197,250,255,0.7)', // 这里设置你想要的颜色
                fontSize: '10px',
                fontFamily: 'c-ssr'
            }
            }
        },
        yAxis: {
            name: '总数',
            nameTextStyle: {
                color: 'rgba(197,250,255,0.7)',
                fontSize: 10
            },
            axisLabel: {
                textStyle: {
                    color: 'rgba(197,250,255,0.7)', // 这里设置你想要的颜色
                    fontSize: '10px',
                    fontFamily: 'c-ssr'
                }
            }
        },
        series: [{
            z: 1,
            type: 'bar',
            barWidth: 34,
            barGap: '-100%',
            itemStyle: {
                normal: {
                color: {
                    type: 'linear',
                    x: 0,
                    y: 0,
                    x2: 0,
                    y2: 1,
                    colorStops: [
                    {
                        offset: 0,
                        color: 'rgb(251,184,1)'
                    },
                    {
                        offset: 1,
                        color: 'rgba(31,31,31,1)'
                    }
                    ],
                    global: false
                }
                }
            },
            data: data.value
            },
            {
                z: 2,
                type: 'pictorialBar',
                symbolPosition: 'end',
                data: data.value,
                symbol: 'diamond',
                symbolOffset: [0, '-70%'],
                symbolSize: [34, 17],
                itemStyle: {
                    normal: {
                    color: 'rgb(251,184,1)',
                    borderColor: 'rgba(31,31,31,1)',
                    borderWidth: 10
                    }
                }
            },
            {
                z: 0,
                legendHoverLink: false,
                hoverAnimation: false,
                type: 'pictorialBar',
                data: [0, 0, 0],
                symbol: 'diamond',
                symbolOffset: [0, '50%'],
                symbolSize: [34, 17],
                itemStyle: {
                    normal: {
                        color: 'rgba(31,31,31,1)'
                    }
                }
            }
        ]
    }
})
</script>

面积规模

添加短路径

javascript 复制代码
<template>
    <div class="mjgm-box py-10">
      <div class="mjgm mb-6 basis-4/7 justify-center">
        <img class="left-icon" src="@img/园区总面积.png" alt="" />
        <div class="info left-info">
          <div class="label">园区总面积</div>
          <div>
            <span class="num">{{ yqzmj }}</span
            >平方公里
          </div>
        </div>
      </div>
      <div class="mjgm mb-6 basis-3/7 justify-center">
        <img class="left-icon" src="@img/规上企业.png" alt="" />
        <div class="info">
          <div class="label">规上企业</div>
          <div>
            <span class="num">{{ gsqy }}</span
            >家
          </div>
        </div>
      </div>
      <div class="mjgm basis-4/7 justify-center">
        <img class="left-icon" src="@img/投产面积.png" alt="" />
        <div class="info left-info">
          <div class="label">投产面积</div>
          <div>
            <span class="num">{{ tcmj }}</span
            >平方公里
          </div>
        </div>
      </div>
      <div class="mjgm basis-3/7 justify-center">
        <img class="left-icon" src="@img/化工企业.png" alt="" />
        <div class="info">
          <div class="label">化工企业</div>
          <div>
            <span class="num">{{ hgqy }}</span
            >家
          </div>
        </div>
      </div>
    </div>
</template>
  
<script setup lang="ts">
import { ref } from 'vue'
import { getCompany } from '@api/safe'

const yqzmj = ref('0')
const gsqy = ref('0')
const tcmj = ref('0')
const hgqy = ref('0')
const getDatas = async ()=>{
    let { data } = await getCompany({
        companyId:0
    })
    yqzmj.value = data[0].value;
    gsqy.value = data[1].value;
    tcmj.value = data[2].value;
    hgqy.value = data[3].value;
    console.log( data );
}
getDatas();
</script>
<style scoped lang="scss">
.mjgm-box {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-evenly;
    .left-icon {
      margin-right: 16px;
    }
    .mjgm {
      display: flex;
      .info {
        font-family: c-ssm;
        font-size: 12px;
        color: #7a9496;
        &.left-info {
          width: 140px;
        }
        .label {
          font-size: 14px;
          color: #c5faff;
        }
        .num {
          font-family: c-ssb;
          font-size: 24px;
          color: #c4faff;
          margin-right: 5px;
        }
      }
    }
}
</style>

轮班值守的内容添加

javascript 复制代码
<template>
    <div class="zbks-root px-5">
      <div class="py-5 mb-2">
        <ViewerButton />
      </div>
      <div class="zbks-box pb-10">
        <div class="zbks lxsp">
          <div class="num">{{ lxsp }}</div>
          <div class="label">离线视频</div>
        </div>
        <div class="zbks zxsp">
          <div class="num">{{ zxsp }}</div>
          <div class="label">在线视频</div>
        </div>
        <div class="zbks spyj">
          <div class="num">{{ spyj }}</div>
          <div class="label">视频预警</div>
        </div>
      </div>
    </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { getGuard } from '@api/safe'
const lxsp = ref(0);
const zxsp = ref(0);
const spyj = ref(0);
const getDatas = async ()=>{
    let res = await getGuard({
        companyId:0
    })
    res.data.forEach((item) => {
        switch (item.key) {
            case '离线视频':
                lxsp.value = item.value;
            break
            case '在线视频':
                zxsp.value = item.value;
            break
            case '视频预警':
                spyj.value = item.value;
            break
            default:
            break
        }
    })
}
getDatas();
</script>
  
<style scoped>
.zbks-box {
    display: flex;
    justify-content: space-between;
    .zbks {
      width: 28%;
      color: #ffffff;
      padding-left: 55px;
      background-size: cover;
      background-repeat: no-repeat;
      height: 47px;
      padding-top: 2px;
      .num {
        font-family: c-ssb;
        font-size: 14px;
      }
      .label {
        font-family: c-ssr;
        font-size: 12px;
      }
      &.lxsp {
        background-image: url(@img/离线视频.png);
      }
      &.zxsp {
        background-image: url(@img/在线视频.png);
      }
      &.spyj {
        background-image: url(@img/视频预警.png);
      }
    }
}
</style>
相关推荐
孤客网络科技工作室2 小时前
Python - 100天从新手到大师:第二十七天Python操作PDF文件
开发语言·python·pdf
l1t2 小时前
在duckdb 1.4中编译和使用postgresql协议插件duckdb-pgwire
开发语言·数据库·c++·postgresql·插件·duckdb
m0_652545912 小时前
10.2总结
c语言·开发语言
小高0073 小时前
前端如何优雅地生成唯一标识?——一份跨环境 UUID 工具函数的封装与实战
前端·javascript·vue.js
我是日安3 小时前
从零到一打造 Vue3 响应式系统 Day 24 - Watch:Options
前端·javascript·vue.js
敲码图一乐3 小时前
流量安全——基于Sentinel实现限流,熔断,降级
java·开发语言·数据库
做运维的阿瑞3 小时前
Python原生数据结构深度解析:从入门到精通
开发语言·数据结构·后端·python·系统架构
__XYZ4 小时前
Vala编程语言高级特性-弱引用和所有权
c语言·开发语言·后端·c#
悠哉悠哉愿意4 小时前
【ROS2学习笔记】服务
开发语言·笔记·学习·ros2