本项目是一个基于Vue3+ECharts5+datav打造的一个每日疫情数据大屏可视化开源项目;通过nginx部署在阿里云服务器上

效果展示

在线预览地址http://lj520zz.top/ 服务器已过期
请大家动动手点点star
项目前台源码地址https://github.com/qdfudimo/vue3-screen
项目后台源码地址:https://github.com/qdfudimo/serve-screen

技术栈添加链接描述

前台技术栈

  1. vue3

  2. vite

  3. echarts5 官方社区停用 以下几个社区链接
    社区链接 http://www.ppchart.com/#/
    https://www.isqqw.com/#/homepage
    http://chart.majh.top/
    http://analysis.datains.cn/finance-admin/index.html#/chartLib/all
    https://www.isqqw.com/

  4. datav datav组件库地址

大屏适配方案

案例中采用了css3的缩放transform: scale(X,y)属性,改变分辨率时,scale的值是变化的。 通过获取当前屏幕大小screen和当前窗口大小,我们只要监听浏览器窗口大的小,同时控制变化的比例就可以了。
项目中通过创建一个ScaleBox缩放组件包裹住所有组件
在这里插入图片描述
scalebox组件采用css3的缩放transform: scale(X,y)

const { width, height } = screen
 const w = window.innerWidth / width
 const h = window.innerHeight / height
this.style.transform = 'scale(' + x +"," + y ') translate(-50%, -50%)'

后续添加了屏幕宽度小于800高度小于600时的完整显示

let getScale = () => {
    // const wh = window.innerHeight / height;
    // const ww = window.innerWidth / width;
    // return [wh,ww];
    const w = window.innerWidth / width
    const h = window.innerHeight / height
    if (window.innerWidth <= 800 || window.innerHeight <= 600) {
        let scale = w < h ? w : h;
        return [scale, scale]
    }
    return [h, w]
}
let setScale = (e) => {
    // 缩放比
    scale.h = getScale()[0];
    scale.w = getScale()[1];
}
let reCalc = debounce(setScale)
onMounted(() => {
    setScale();
    window.addEventListener("resize", reCalc);
})
onUnmounted(() => {
    window.removeEventListener("resize", reCalc)
})

在这里插入图片描述
在这里插入图片描述

也可以使用vue3的css样式绑定 https://cn.vuejs.org/api/sfc-css-features.html#v-bind-in-css

<script setup>
const theme = {
  color: 'red'
}
</script>
<style scoped>
p {
  color: v-bind('theme.color');
}
</style>

也使用了阿里的字体图标
通过vite-plugin-svg-icons 使用SVG图片

  1. 安装 vite-plugin-svg-icons
npm i vite-plugin-svg-icons -D
// 或者
yarn add vite-plugin-svg-icons -D
  1. main.js引入
import 'virtual:svg-icons-register';
  1. 创建svg图片文件夹
    在这里插入图片描述
  2. 在vite.config.js中配置
import {
  createSvgIconsPlugin
} from 'vite-plugin-svg-icons'
import path from 'path'
defineConfig({
  server: {
  //反向代理
    proxy: {
      // 选项写法
      // '/api': {
      //   target: 'http://jsonplaceholder.typicode.com',
      //   changeOrigin: true,
      //   rewrite: (path) => path.replace(/^\/api/, '')
      // },
      // // 选项写法
      [config.VITE_API_BASE_URL]: {
        target: config.VITE_APP_BASE_SERVER,
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      },
      // Proxying websockets or socket.io
      // '/socket.io': {
      //   target: 'ws://localhost:3000',
      //   ws: true
      // }
    }
  },
  plugins: [
    createSvgIconsPlugin({
      // Specify the icon folder to be cached
      iconDirs: [path.resolve(process.cwd(), 'src/icons')],
      // Specify symbolId format
      symbolId: 'icon-[dir]-[name]',
    })
  ],
})

5.新建svg组件

<template>
    <svg :class="svgClass" v-bind="$attrs">
        <use :xlink:href="iconName"></use>
    </svg>
</template>

<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps({
    name: {
        type: String,
        required: true
    },
    color: {
        type: String,
        default: '#e6e6e6'
    }
})
const iconName = computed(() => `#icon-${props.name}`)
const svgClass = computed(() => {
    if (props.name) return `svg-icon icon-${props.name}`
    return 'svg-icon'
})
</script>

<style scoped>
.svg-icon {
    width: 1em;
    height: 1em;
    fill: currentColor;
    vertical-align: middle;
}
</style>
  1. main.js全局引入使用
import SvgIcon from '@/components/SvgIcon.vue'
const app = createApp(App)
app.component("svg-icon",SvgIcon)

组件中使用

//name svg文件名
<svg-icon name="empty" style="fontSize:120px"></svg-icon>

后台数据

koa2+axios 将爬取网易新闻的每日接口
通过定时任务每日爬取网易新闻的接口数据,保存为json文件,然后读取文件数据,请求数据时返回给前台。
每天定时下午先判断今日是否有数据,有则删除前一日的json数据,无则不删除

const schedule = require('node-schedule');
const {
    getData
} = require("../api")
const {
    formatBeforetTime,
    formatTime
} = require("../util/moment")
const {
    checkDirFile,
    emptyDir,
} = require("../util/index")
/**
 * 定时任务调接口
 */
function scheduleCronstyle() {
    schedule.scheduleJob('30 0 10 * * *', function () {
        console.log('scheduleCronstyle:' + new Date());
        getData()
    });
    schedule.scheduleJob('30 0 14 * * *', function () {
        console.log('scheduleCronstyle:' + new Date());
        getData()
    });
}
/**
 * 定时任务删除上一天json文件
 */
function scheduleDelFile() {
    schedule.scheduleJob('30 3 16 * * *', function () {
        let fileName = formatBeforetTime();
        let fileNamepre = formatTime();
        if (checkDirFile("areaData", fileNamepre) && checkDirFile("areaData", fileName)) {
            emptyDir("areaData", fileName)
            console.log(`删除文件areaData${fileName}`);
        }else {
            console.log(`没有删除文件areaData`);
        }
        if (checkDirFile("chinaData", fileNamepre) && checkDirFile("chinaData", fileName)) {
            emptyDir("chinaData", fileName)
            console.log(`删除文件chinaData${fileName}`);
        }

    });
Logo

前往低代码交流专区

更多推荐