数字孪生监控大屏实战模板:政务服务大数据

  前端数字孪生大屏,使用VUE3+Elementplus+Echarts+TS实现政务服务大数据大屏,数字孪生,监控大屏展示,可下载作为课堂作业、界面模板、扩展开发,个人作品等。

  若想系统学习Echarts开发,我的课程提供了完整的Echarts基础知识讲解并附加大量实战案例,系列课程地址如下:

 1. CSDN课程:https://edu.csdn.net/course/detail/40842

 2. 51学堂课程:https://edu.51cto.com/course/40414.html

 3. B站课程:https://www.bilibili.com/cheese/play/ss456500998

一.效果展示:


二.源码下载:

点击下载

三.开发视频:

https://www.bilibili.com/video/BV17WdoBbEqA/

四.实现明细:

4.1 开发环境

  使用vscode开发,nodejs版本为v24.11.0,其它项目依赖如下:

  1. "dayjs": "^1.11.20"

  2. "echarts": "^6.0.0"

  3. "element-plus": "^2.13.6"

  4. "less": "^4.6.4"

  5. "pinia": "^3.0.4"

  6. "vue": "^3.5.31"

  7. "vue-router": "^5.0.4"

4.2 实现明细

  1. main.ts
javascript 复制代码
import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.use(ElementPlus)

app.mount('#app')
  1. App.vue
javascript 复制代码
<script setup lang="ts"></script>

<template>
  <RouterView></RouterView>
</template>

<style >
@import '@/assets/main.css';

</style>
  1. HomeView.vue
javascript 复制代码
<script setup lang="ts">
import ChartPanel from '@/components/ChartPanel.vue';
import Header from '@/components/Header.vue';
import LeftChartPanel from '@/components/LeftChartPanel.vue';
import RightChartPanel from '@/components/RightChartPanel.vue';
import { onMounted, reactive, ref } from 'vue';
import * as echarts from "echarts"

//中间的背景图
const centerChartBgImg = new URL('@/assets/images/icon-004.png', import.meta.url).href;

//服务总数
const allCount = ref(453425);

const centerChartRef = ref();
const centerChart = ref();
const centerChartOptions = reactive({
  grid: {
        left: '2%',
        top: '20%',
        right: '2%',
        bottom: '20%',
        containLabel: false
    },
    xAxis: {
        type: 'category',
        data: ['房管局', '人社局', '教育局', '交通局', '卫生局', '红十字'],
        show:false
    },
    yAxis: {
        type: 'value',
        show:false
    },
    series: [
      {
            name: '最上层立体圆',
            type: 'pictorialBar',
            symbolSize: [80, 15],
            symbolOffset: [0, -7],
            z: 12,
            itemStyle: {
                normal: {
                    color: {
                      type: 'radial',
                      x: 0.5,
                      y: 0.5,
                      r: 0.5,
                      colorStops: [{
                          offset: 0, color: '#02bfd3' // 0% 处的颜色
                      }, {
                          offset: 1, color: '#02bfd311' // 100% 处的颜色
                      }],
                      global: false // 缺省为 false
                    }
                },
            },
            data: [
                {
                    value: 100,
                    symbolPosition: 'end',
                },
                {
                    value: 100,
                    symbolPosition: 'end',
                },
                {
                    value: 100,
                    symbolPosition: 'end',
                },
                {
                    value: 100,
                    symbolPosition: 'end',
                },
                {
                    value: 100,
                    symbolPosition: 'end',
                },
                {
                    value: 100,
                    symbolPosition: 'end',
                },
            ],
        },
        {
            name: '中间立体圆',
            type: 'pictorialBar',
            symbolSize: [80, 25],
            symbolOffset: [0, -10],
            z: 12,
            itemStyle: {
                normal: {
                    color: () =>
                        new echarts.graphic.LinearGradient(1, 1, 0, 0, [
                            {
                                offset: 0,
                                color: '#05a4df',
                            },
                            {
                                offset: 1,
                                color: '#05a4df11',
                            },
                        ]),
                    shadowColor: '#05a4df',
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowOffsetY: 4,
                },
            },
            data: [
                {
                    value: 40,
                    symbolPosition: 'end',
                },
                {
                    value: 30,
                    symbolPosition: 'end',
                },
                {
                    value: 50,
                    symbolPosition: 'end',
                },
                {
                    value: 80,
                    symbolPosition: 'end',
                },
                {
                    value: 70,
                    symbolPosition: 'end',
                },
                {
                    value: 40,
                    symbolPosition: 'end',
                },
                {
                    value: 90,
                    symbolPosition: 'end',
                },
            ],
        },
        {
            name: '最底部立体圆',
            type: 'pictorialBar',
            symbolSize: [80, 25],
            symbolOffset: [0, 10],
            z: 12,
            itemStyle: {
                normal: {
                    color: () =>
                        new echarts.graphic.LinearGradient(0, 1, 1, 0, [
                            {
                                offset: 0,
                                color: '#05a4df',
                            },
                            {
                                offset: 1,
                                color: '#05a4df11',
                            },
                        ]),
                },
            },
            data: [
                {
                    value: 100-40,
                },
                {
                    value: 100-30,
                },
                {
                    value: 100-50,
                },
                {
                    value: 100-80,
                },
                {
                    value: 100-70,
                },
                {
                    value: 100-40,
                },
                {
                    value: 100-90,
                },
            ],
        },{
            //底部立体柱
            stack: '1',
            type: 'bar',
            itemStyle: {
                normal: {
                    color: () =>
                        new echarts.graphic.LinearGradient(0, 0, 1, 0, [
                            {
                                offset: 0,
                                color: '#05a4dfaa',
                            },
                            {
                                offset: 1,
                                color: '#05a4df55',
                            },
                        ]),
                    opacity: 0.77,
                },
            },
            label:{
                show:true,
                position:'top',
                formatter:'{b}',
                textStyle:{
                    color:"#40e6ff",
                    fontSize:16,
                    fontWeight:600
                }
            },
            silent: true,
            barWidth: 80,
            barGap: '-100%', // Make series be overlap
            data: [40, 30, 50, 80, 70, 40, 90],
        },
        {
            //上部立体柱
            stack: '1',
            type: 'bar',
            itemStyle: {
                normal: {
                    color: () =>
                        new echarts.graphic.LinearGradient(1, 0, 0, 0, [
                            {
                                offset: 0,
                                color: '#47C8FF33',
                            },
                            {
                                offset: 0.05,
                                color: '#47C8FF11',
                            },
                            {
                                offset: 0.15,
                                color: '#47C8FF00',
                            },
                            {
                                offset: 0.85,
                                color: '#47C8FF00',
                            },
                            {
                                offset: 0.95,
                                color: '#47C8FF11',
                            },
                            {
                                offset: 1,
                                color: '#47C8FF33',
                            },
                        ]),
                },
            },
            silent: true,
            barWidth: 80,
            barGap: '-100%', // Make series be overlap
            data: [100-40, 100-30, 100-50, 100-80, 100-70, 100-40, 100-90],
        }
    ]
});

onMounted(() => {
    centerChart.value = echarts.init(centerChartRef.value);
    centerChart.value.setOption(centerChartOptions);

})
</script>

<template>
  <div class="page">
    <Header></Header>
    <el-row :gutter="10" style="width:calc(100vw - 20px);margin-top: 10px;">
      <el-col :span="8">
        <ChartPanel title="某地区事项办理情况">
          <div class="chart-item">
            <LeftChartPanel></LeftChartPanel>
          </div>
        </ChartPanel>
      </el-col>
      <el-col :span="8">
        <div class="center-top">
          <img src="@/assets/images/icon-001.png">
          <div class="center-text">
            <div class="name">服务总数</div>
            <div class="value-panel">
              <div class="empty"></div>
              <div class="value">{{ allCount }}</div>
              <div class="unit">次</div>
              <div class="empty"></div>
            </div>
          </div>
        </div>
        <ChartPanel title="已办理事项排名情况" :bg-img="centerChartBgImg">
          <div class="center-chart-item" ref="centerChartRef">
          </div>
        </ChartPanel>
      </el-col>
      <el-col :span="8">
        <ChartPanel title="办理事项分布情况">
          <div class="chart-item">
            <RightChartPanel></RightChartPanel>
          </div>
        </ChartPanel>
      </el-col>
    </el-row>
  </div>
</template>
<style lang="less" scoped>
.page {
  width: 100vw;
  height: 100vh;
  background: url(@/assets/images/bj.jpg);
  background-size: 100% 100%;

  .chart-item {
    height: calc(100vh - 183px);
  }

  .center-top {
    height: 60vh;
    position: relative;

    img {
      position: absolute;
      left: -3%;
      height: 119%;
    }
    .name{
      color:#fff;
      font-size: 1.4rem;
      font-weight: bold;
      text-align: center;
      padding-top: 29%;
    }
    .value-panel{
      display: flex;
      .value{
        font-size: 3rem;
        color: #40e6ff;
        font-weight: bold;
      }
      .unit{
        color:#fff;
        font-size: 1rem;
        line-height: 90px;
        margin-left: 10px;
      }
      .empty{
        flex:1
      }
    }
  }

  .center-chart-item {
    height: calc(50vh - 273px);
  }
}
</style>
  1. router/index.vue
javascript 复制代码
import HomeView from '@/views/HomeView.vue'
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [{
    path:'',
    component:HomeView
  }],
})

export default router
  1. RightChartPanel.vue
javascript 复制代码
<template>
    <div class="chart-item">
        <div class="title">
            <div class="left">
                <img src="@/assets/images/icon-009.png">
            </div>
            <div class="title">
                <div class="text">办理情况</div>
                <div class="title-line"></div>
            </div>
            <div class="right">
                <img src="@/assets/images/icon-009.png">
            </div>
        </div>
        <div class="chart-panel" ref="endChartRef"></div>
    </div>
    <div class="chart-item">
        <div class="title">
            <div class="left">
                <img src="@/assets/images/icon-009.png">
            </div>
            <div class="title">
                <div class="text">办理排名</div>
                <div class="title-line"></div>
            </div>
            <div class="right">
                <img src="@/assets/images/icon-009.png">
            </div>
        </div>
        <div class="chart-panel" ref="scopeChartRef"></div>
    </div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import * as echarts from "echarts"

const endChartRef = ref();
const endChart = ref();
const datas = reactive( [
        { value: 140, name: '决策环节' },
        { value: 238, name: '办理环节' },
        { value: 332, name: '审核环节' },
        { value: 430, name: '未办环节' },
        { value: 128, name: '已办环节' },
        { value: 226, name: '失效环节' },
]);
const endChartOptions = reactive({
    legend: {
        top: 'center',
        right: '20%',
        orient:'vertical',
        textStyle:{
            color:'#fff',
            lineHeight:20,
            rich: {
                a: {
                   color:'#40e6ff',
                   fontWeight:600
                }
            }
        },
        formatter:function(name){
            let max = datas.reduce((current,item)=>{
                return current+item.value;
            },0);
            let item = datas.find(item=>item.name === name);
            if(item){
                let percient = 0;
                if(max>0){
                    percient = parseFloat(((item.value / max)*100).toFixed(2));
                }
                return item.name +'\n{a|'+item.value+'\t'+percient+'%}';
            }
            return '未知'
        }
    },
    series: [
        {
            name: '办理情况',
            type: 'pie',
            radius: [50, 150],
            center: ['30%', '50%'],
            roseType: 'area',
            itemStyle: {
                borderRadius: 8
            },
            label:{
                show:true,
                position:'center',
                textStyle:{
                    color:'#fff',
                    fontSize:18,
                    lineHeight:20,
                    fontWeight:600
                },
                formatter:'{a}\n{c}个'
            },
            labelLine:{
                show:false,
            },
            data:datas
        }
    ]
});

const scopeChartRef = ref();
const scopeChart = ref();
const scopeChartOptions = reactive({
    grid: {
        left: '10%',
        top: '10%',
        right: '5%',
        bottom: '15%',
        containLabel: false
    },
    xAxis: {
        type: 'category',
        data: ['2001', '2002', '2003', '2004', '2005', '2006'],
        axisLine: {
            show: true,
            lineStyle: {
                color: '#0d1b86'
            }
        },
        axisLabel: {
            color: '#fff'
        },
        splitLine: {
            lineStyle: {
                color: '#0d1b8666'
            }
        }
    },
    yAxis: {
        type: 'value',
        axisLine: {
            show: true,
            lineStyle: {
                color: '#0d1b86'
            }
        },
        axisLabel: {
            color: '#fff'
        },
        splitLine: {
            lineStyle: {
                type: 'dashed',
                color: '#0d1b8666'
            }
        }
    },
    series: [
        {
            name: '办理排名',
            data: [120, 200, 150, 80, 70, 110, 130],
            type: 'bar',
            barWidth: 15,
            barGap: '40%',
            label:{
                show:true,
                position:'top',
                textStyle:{
                    color:"#40e6ff"
                }
            },
            itemStyle: {
                color: {
                    type: 'linear',
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 1,
                    colorStops: [{
                        offset: 0, color: '#01b1ff' // 0% 处的颜色
                    }, {
                        offset: 1, color: '#0338ff' // 100% 处的颜色
                    }],
                    global: false // 缺省为 false
                }
            }
        }
    ]
});

onMounted(() => {
    endChart.value = echarts.init(endChartRef.value);
    endChart.value.setOption(endChartOptions);

    scopeChart.value = echarts.init(scopeChartRef.value);
    scopeChart.value.setOption(scopeChartOptions);
})
</script>
<style lang="less" scoped>
.chart-item {
    .title {
        line-height: 30px;
        text-align: center;
        display: flex;
        color: #21e7ff;

        .left,
        .right {
            flex: 1;

            img {
                height: 30%;
            }
        }

        .title {
            width: 100px;
            display: block;

            .text {
                width: 100px;
            }

            .title-line {
                height: 2px;
                width: 100%;
                background: linear-gradient(45deg, #2d77f3, #21e7ff);
            }
        }
    }

    .chart-panel {
        height: calc((100vh - 250px) / 2);
    }
}
</style>
  1. LeftChartPanel.vue
javascript 复制代码
<template>
    <div class="baseinfo">
        <div class="item item1">
            <div class="icon icon1">
                <img src="@/assets/images/icon-011.png">
            </div>
            <div class="content">
                <div class="name">待办事项</div>
                <div class="value-content">
                    <div class="value">{{ value1 }}</div>
                    <div class="unit">件</div>
                </div>
            </div>
        </div>
        <div class="item item2">
            <div class="icon icon2">
                <img src="@/assets/images/icon-012.png">
            </div>
            <div class="content">
                <div class="name">已办理事项</div>
                <div class="value-content">
                    <div class="value">{{ value2 }}</div>
                    <div class="unit">件</div>
                </div>
            </div>
        </div>
        <div class="item item3">
            <div class="icon icon3">
                <img src="@/assets/images/icon-013.png">
            </div>
            <div class="content">
                <div class="name">办理中事项</div>
                <div class="value-content">
                    <div class="value">{{ value3 }}</div>
                    <div class="unit">件</div>
                </div>
            </div>
        </div>
        <div class="item item4">
            <div class="icon icon4">
                <img src="@/assets/images/icon-014.png">
            </div>
            <div class="content">
                <div class="name">已结束事项</div>
                <div class="value-content">
                    <div class="value">{{ value4 }}</div>
                    <div class="unit">件</div>
                </div>
            </div>
        </div>
    </div>
    <div class="task-chart" ref="taskChartRef">
    </div>
    <div class="department-chart" ref="departmentChartRef"></div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import * as echarts from "echarts"

const value1 = ref(3435);
const value2 = ref(5436);
const value3 = ref(6547);
const value4 = ref(4365);

const taskChartRef = ref();
const taskChart = ref();
const taskChartOptions = reactive({
    grid:{
        left:'16%',
        top:'3%',
        right:'15%',
        bottom:'3%',
        containLabel:false
    },
    yAxis: {
        type: 'category',
        data: ['已办事项', '未办事项', '待办事项', '完成事项', '超期事项', '审核事项'],
        axisLine:{
            show:false
        },
        axisLabel:{
           color:'#fff'
        }
    },
    xAxis: {
        type: 'value',
        show:false
    },
    series: [
        {
            data: [120, 200, 150, 80, 70, 110, 130],
            type: 'bar',
            barWidth:20,
            itemStyle:{
                color:{
                    type: 'linear',
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 1,
                    colorStops: [{
                        offset: 0, color: '#0338ff' // 0% 处的颜色
                    }, {
                        offset: 1, color: '#01b1ff' // 100% 处的颜色
                    }],
                    global: false // 缺省为 false
                }
            },
            label:{
                show:true,
                position:'right',
                color:'#02afff',
                formatter:'{c} 万个',
                fontSize:16
            }
        }
    ]
});

const departmentChartRef = ref();
const departmentChart = ref();
const departmentChartOptions = reactive({
    grid:{
        left:'5%',
        top:'15%',
        right:'5%',
        bottom:'15%',
        containLabel:false
    },
    legend:{
        left:'center',
        top:'3%',
        textStyle:{
            color:'#fff'
        }
    },
    xAxis: {
        type: 'category',
        data: ['人社局', '卫生局', '教育局', '红十字', '公安局', '交通局'],
        axisLine:{
            show:false
        },
        axisLabel:{
           color:'#fff'
        }
    },
    yAxis: {
        type: 'value',
        show:false
    },
    series: [
        {
            name:'表',
            data: [120, 200, 150, 80, 70, 110, 130],
            type: 'bar',
            barWidth:15,
            barGap:'40%',
            itemStyle:{
                color:{
                    type: 'linear',
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 1,
                    colorStops: [{
                        offset: 0, color: '#0338ff' // 0% 处的颜色
                    }, {
                        offset: 1, color: '#01b1ff' // 100% 处的颜色
                    }],
                    global: false // 缺省为 false
                }
            }
        },
        {
            name:'接口',
            data: [120, 200, 150, 80, 70, 110, 130],
            type: 'bar',
            barWidth:15,
            barGap:'40%',
            itemStyle:{
                color:{
                    type: 'linear',
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 1,
                    colorStops: [{
                        offset: 0, color: '#02948f' // 0% 处的颜色
                    }, {
                        offset: 1, color: '#32fb99' // 100% 处的颜色
                    }],
                    global: false // 缺省为 false
                }
            }
        },{
            name:'文件',
            data: [120, 200, 150, 80, 70, 110, 130],
            type: 'bar',
            barWidth:15,
            barGap:'40%',
            itemStyle:{
                color:{
                    type: 'linear',
                    x: 0,
                    y: 0,
                    x2: 1,
                    y2: 1,
                    colorStops: [{
                        offset: 0, color: '#6842fd' // 0% 处的颜色
                    }, {
                        offset: 1, color: '#2a81af' // 100% 处的颜色
                    }],
                    global: false // 缺省为 false
                }
            }
        }
    ]
});

onMounted(() => {
    taskChart.value = echarts.init(taskChartRef.value);
    taskChart.value.setOption(taskChartOptions);

    departmentChart.value = echarts.init(departmentChartRef.value);
    departmentChart.value.setOption(departmentChartOptions);
})

</script>
<style lang="less" scoped>
.baseinfo {
    display: flex;
    flex-wrap: wrap;

    .item {
        width: 45%;
        margin: 5px;
        display: flex;
        padding: 20px;

        .icon {
            width: 50px;
            height: 50px;
            text-align: center;
            display: flex;
            justify-items: center;
            align-items: center;
            justify-content: center;
            align-content: center;
            border-radius: 50%;
            margin-top: 5px;
        }

        .icon1 {
            background: linear-gradient(45deg, #0337dc, #018ddc);
        }

        .icon2 {
            background: linear-gradient(45deg, #c15e24, #ca9b15);
        }

        .icon3 {
            background: linear-gradient(45deg, #047c82, #29cd8a);
        }

        .icon4 {
            background: linear-gradient(45deg, #4e0aae, #582cb0);
        }

        .content {
            flex: 1;
            padding-top: 0px;
            margin-left: 20px;

            .name {
                line-height: 30px;
                color: #fff;
            }

            .value-content {
                display: flex;

                .value {
                    flex: 1;
                    font-size: 1.2rem;
                    color: #30d7e0;
                    text-align: right;
                    font-weight: bold;
                }

                .unit {
                    font-size: 0.8rem;
                    color: #30d7e0;
                    line-height: 32px;
                    margin-left: 5px;
                }
            }
        }
    }

    .item1 {
        background: url(@/assets/images/icon-005.png);
        background-size: 100% 100%;
    }

    .item2 {
        background: url(@/assets/images/icon-006.png);
        background-size: 100% 100%;
    }

    .item3 {
        background: url(@/assets/images/icon-007.png);
        background-size: 100% 100%;
    }

    .item4 {
        background: url(@/assets/images/icon-008.png);
        background-size: 100% 100%;
    }
}

.task-chart {
    border-top: 1px dotted #5544c7;
    border-bottom: 1px dotted #5544c7;
    height: 32vh;
}
.department-chart {
    height: 23vh;
}
</style>
  1. Header.vue
javascript 复制代码
<script setup lang="ts">
</script>

<template>
    <div class="header">
        <div class="left"></div>
        <div class="title">军军君政务服务大数据</div>
        <div class="left"></div>
    </div>
</template>
<style lang="less" scoped>
    .header{
        background: url(@/assets/images/icon-002.png);
        background-size: 100% 100%;
        height: 118px;
        display: flex;

        .left,.right{
            flex:1
        }
        .title{
            line-height: 100px;
            color: #fff;
            font-size: 2rem;
            font-weight: bold;
            letter-spacing: 10px;
            text-shadow: -5px 2px 8px #00BCD4;
        }
    }
</style>
  1. ChartPanel.vue
javascript 复制代码
<template>
    <div class="chart-panel" :style="{ 'background-image':' url('+ bgImg +')' }">
        <div class="title">{{ title }}</div>
        <div class="content">
            <slot></slot>
        </div>
    </div>
</template>
<script setup lang="ts">

const props = defineProps({
    title:String,
    bgImg:{
        type:String,
        default:new URL('@/assets/images/icon-003.png', import.meta.url).href
    }
});
</script>
<style lang="less" scoped>
    .chart-panel{
        background-size: 100% 100%;

        .title{
            line-height: 40px;
            text-align: center;
            color: #2fd5ff;
        }
    }
</style>
  1. main.css
javascript 复制代码
@import './base.css';

#app {
  font-weight: normal;
}

a,
.green {
  text-decoration: none;
  color: hsla(160, 100%, 37%, 1);
  transition: 0.4s;
}

@media (hover: hover) {
  a:hover {
    background-color: hsla(160, 100%, 37%, 0.2);
  }
}

@media (min-width: 1024px) {
  body {
  }

  #app {
  }
}
  1. base.css
javascript 复制代码
/* color palette from <https://github.com/vuejs/theme> */
:root {
  --vt-c-white: #ffffff;
  --vt-c-white-soft: #f8f8f8;
  --vt-c-white-mute: #f2f2f2;

  --vt-c-black: #181818;
  --vt-c-black-soft: #222222;
  --vt-c-black-mute: #282828;

  --vt-c-indigo: #2c3e50;

  --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
  --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
  --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
  --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);

  --vt-c-text-light-1: var(--vt-c-indigo);
  --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
  --vt-c-text-dark-1: var(--vt-c-white);
  --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}

/* semantic color variables for this project */
:root {
  --color-background: var(--vt-c-white);
  --color-background-soft: var(--vt-c-white-soft);
  --color-background-mute: var(--vt-c-white-mute);

  --color-border: var(--vt-c-divider-light-2);
  --color-border-hover: var(--vt-c-divider-light-1);

  --color-heading: var(--vt-c-text-light-1);
  --color-text: var(--vt-c-text-light-1);

  --section-gap: 160px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-background: var(--vt-c-black);
    --color-background-soft: var(--vt-c-black-soft);
    --color-background-mute: var(--vt-c-black-mute);

    --color-border: var(--vt-c-divider-dark-2);
    --color-border-hover: var(--vt-c-divider-dark-1);

    --color-heading: var(--vt-c-text-dark-1);
    --color-text: var(--vt-c-text-dark-2);
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  font-weight: normal;
}

body {
  color: var(--color-text);
  background: var(--color-background);
  transition:
    color 0.5s,
    background-color 0.5s;
  line-height: 1.6;
  font-family:
    Inter,
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    Roboto,
    Oxygen,
    Ubuntu,
    Cantarell,
    'Fira Sans',
    'Droid Sans',
    'Helvetica Neue',
    sans-serif;
  font-size: 15px;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  margin: 0;
  padding: 0;
}
  1. index.html
javascript 复制代码
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <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.ts"></script>
  </body>
</html>
  1. package.json
javascript 复制代码
{
  "name": "government-service",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "run-p type-check \"build-only {@}\" --",
    "preview": "vite preview",
    "build-only": "vite build",
    "type-check": "vue-tsc --build"
  },
  "dependencies": {
    "echarts": "^6.0.0",
    "element-plus": "^2.13.7",
    "pinia": "^3.0.4",
    "vue": "^3.5.31",
    "vue-router": "^5.0.4"
  },
  "devDependencies": {
    "@tsconfig/node24": "^24.0.4",
    "@types/node": "^24.12.0",
    "@vitejs/plugin-vue": "^6.0.5",
    "@vue/tsconfig": "^0.9.1",
    "less": "^4.6.4",
    "npm-run-all2": "^8.0.4",
    "typescript": "~6.0.0",
    "vite": "^8.0.3",
    "vite-plugin-vue-devtools": "^8.1.1",
    "vue-tsc": "^3.2.6"
  },
  "engines": {
    "node": "^20.19.0 || >=22.12.0"
  }
}
相关推荐
To_OC7 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
To_OC7 小时前
LC 17 电话号码的字母组合:我的回溯算法,就是从这道题开窍的
javascript·算法·leetcode
vipbic7 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy7 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志8 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble9 小时前
c端系统,其实更像一个信息展示平台
前端
你怎么知道我是队长9 小时前
JavaScript的变量和数据类型介绍
开发语言·javascript·ecmascript
李姆斯10 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜10 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司10 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能