疫情统计页面 H5 vue3+TypeScript+Echarts

目录🧰🧰

功能介绍🎨🎨

部分效果展示🌌🌌

全部功能展示效果🗺️🗺️

代码演示🌃🌃

🥰🥰demo目录结构

🍭🍭 DownRefresh.vue 下拉刷新 组件

🪜🪜EpidemicList.vue 数据列表 组件

🏹🏹UpRefreshAndToTop 上拉刷新 一键回到顶部 组件

🗿🗿type index.ts 数据声明

📕📕pageTS index.ts 数据处理

🌃🌃App.vue 疫情页面

📺📺vite.config.ts 代理开通 


功能介绍🎨🎨

下拉刷新🪄  一键回到顶部🚀 echarts中国地图运用🗺️ 数据列表展示🧰 代理🧆

部分效果展示🌌🌌

全部功能展示效果🗺️🗺️

因为功能有点多 所以专门录制了一期视频介绍功能

具体的全部素材 源码也放在评论区 大家可以去看看😁

视频链接地址

代码演示🌃🌃

🥰🥰demo目录结构

🍭🍭 DownRefresh.vue 下拉刷新 组件

<!-- 下拉刷新新数据 -->
<template>
  <div class="box">
    <!-- 内部属性  @scroll 监听滚动条事件 -->
    <div
      @scroll="scrollEvent"
      class="scroll-box"
    >
      <!-- 插槽 -->
      <slot></slot>
      <div class="end-text" v-if="!isScroll">{{ endText }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive, toRefs } from "@vue/reactivity";
const props = defineProps({
  //下拉高度
  distance: Number ,
  //判定是否下拉
  isScroll: Boolean,
  endText: {
    type: String,
    default: "没有更多了",
  },
});
//子传父参数
const $emits = defineEmits(["getList"]);

const data = reactive({
  //离屏幕高度
  scrollTop: 0,
});

let {
  scrollTop,
} = toRefs(data);


//下拉刷新 判定
const scrollEvent = (e: any) => {
  scrollTop = e.srcElement.scrollTop;
  if (!props.isScroll) return;
  if (
    //判定下拉高度
    scrollTop + e.srcElement.offsetHeight >
    e.srcElement.scrollHeight - props.distance!
  ) {
    $emits("getList");
  }
};
</script>

<style lang="scss" scoped>
.box {
  overflow: hidden;
  position: relative;
  width: 100%;
  height: 90vh;
}
.scroll-box {
  height: 90vh;
  width: 100%;
  overflow: auto;
  transition: all 0s ease 0s;
  position: absolute;
  right: 0;
  .end-text {
    text-align: center;
    height: 50px;
    line-height: 50px;
    color: #999;
  }
}
</style>

🪜🪜EpidemicList.vue 数据列表 组件

<!-- 疫情list -->
<template>
  <div class="list-box">
    <div class="info-title info">
      <p>地区</p>
      <p>现有确诊</p>
      <p>确诊</p>
      <p>死亡</p>
      <p>治愈</p>
    </div>
    <div class="list" v-for="item in epideList" :key="item.id">
      <div class="p-box">
        <div @click="getChowChildren(item.id)" class="info">
          <p>{{ item.name }}</p>
          <!-- 确诊病例 计数可能出现负数情况 -->
          <p>
            {{
              item.total.confirm - item.total.dead - item.total.heal >= 0
                ? item.total.confirm - item.total.dead - item.total.heal
                : 0
            }}
          </p>
          <p>
            <span>{{ item.total.confirm }}</span>
            <span>较昨日+{{ item.today.confirm ? item.today.confirm : 0 }}</span>
          </p>
          <p>{{ item.total.dead }}</p>
          <p>{{ item.total.heal }}</p>
        </div>
        <div v-if="showChildren">
          <div>
            <div v-show="data.showChildrenId == item.id" class="children-box">
              <EpidemicList :epideList="item.children" />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<!-- name  组件可以自己调用自己(递归调用) 只能通过name选项来做此事-->
<script name="EpidemicList" setup lang="ts">
// 声明props
import {  reactive } from "vue";
import { IEpidData } from "../type";
//无需引入
const props = defineProps({
  //疫情数据
  epideList:Array<IEpidData>,
  //是否展示子数组 省=>市 区数据
  showChildren: Boolean,
});
//点击展示
const data = reactive({
  showChildrenId: "",
});
//判定 子列表点击是否展示 各个省下面具体的地区
const getChowChildren = (id: string) => {
  //原理:通过id来确定要展示的list 点击第二次则置空 不展示效果
  data.showChildrenId == id ? (data.showChildrenId = ""): (data.showChildrenId = id);
};
//确诊案例 存在
</script>

<style lang="scss" scoped>
.list-box {
  border: 1px solid #d1d1d1;
  margin: 1rem 0;
  .p-box {
    .children-box {
      margin-left: 1rem;
      .list-box {
        border: none;
      }
      .info-title {
        height: 30px;
        line-height: 30px;
      }
      p {
        &:nth-child(1) {
          font-weight: 600;
          color: #999;
        }
      }
    }
  }
}
.info-title {
  font-weight: 600;
  color: #000;
  font-size: 16px;
  height: 50px;
  line-height: 50px;
  background: #d1d1d1;
}

.info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  > p {
    width: 15%;
    text-align: center;
    // white-space: nowrap;
    &:nth-child(1) {
      font-weight: 600;
      color: #000;
    }
    &:nth-child(2) {
      width: 23%;
      color: red;
    }
    &:nth-child(3) {
      width: 23%;
      white-space: nowrap;
      span {
        display: block;
        &:last-child {
          color: #999;
        }
      }
    }
  }
}
.list {
  &:nth-of-type(odd) {
    background: #f6f6f6;
  }
  .info {
    height: 80px;
    line-height: 80px;
    p {
      line-height: 20px;
    }
  }
}
</style>

🏹🏹UpRefreshAndToTop 上拉刷新 一键回到顶部 组件

<!-- 顶部刷新 回退到顶部 -->
<template>
  <div class="box">
    <!-- 内部属性 事件: 触摸开始 @touchstart 触摸移动 @touchmove 触摸结束 @touchend  滚动条滑动 @scroll-->
    <div
      @touchend="touchend"
      @touchmove="touchmove"
      @touchstart="touchstart"
      @scroll="scrollEvent"
      :style="{ top: `${translateY}px` }"
      class="scroll-box"
    >
      <div class="loadingBox" v-if="touchstartTitleShow">释放可刷新...</div>
      <div class="loadingBox" v-if="touchEndTitleShow">加载中...</div>
      <!-- top 回退顶部的定位点 -->
      <div id="top"></div>
      <!-- 插槽 -->
      <slot></slot>
      <div v-show="data.isShowTop" class="back-box" @click="toTop">
      <img src="../assets/toTop.png">
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive, toRefs } from "@vue/reactivity";

const $emits = defineEmits(["refreshFun"]);

const data = reactive({
  startText: "释放即可刷新",
  scrollTop: 0,
  startY: 0,
  translateY: 0,
  touchEndTitleShow: false, //控制手指离开屏幕的title显示
  touchstartTitleShow: false, //控制手指按下屏幕的title显示
  isShowTop:false
});

let {
  touchstartTitleShow,
  touchEndTitleShow,
  translateY,
} = toRefs(data);

//手指触碰到屏幕
const touchstart = (e: any) => {
  let y = e.targetTouches[0].pageY;
  data.startY = y;
};
const scrollEvent = (e: any) => {
  data.scrollTop = e.srcElement.scrollTop;
  //判定是否展示回退顶部按钮
  data.scrollTop>400? (data.isShowTop=true) : (data.isShowTop=false); 
}
const toTop=()=>{
     //定位到div->top
     let anchor = document.getElementById("top")!;
      anchor.scrollIntoView();
}
//手指开始滑动
const touchmove = (e: any) => {
  let y = e.targetTouches[0].pageY;
  if (y > data.startY && data.scrollTop == 0) {
    data.touchstartTitleShow = true;
    //如果当前移动距离大于初始点击坐标,则视为是下拉。并且要处于顶部才刷新,不能影响正常的列表滑动。
    data.translateY = (y - data.startY) / 2;
  } else {
    data.touchstartTitleShow = false;
  }
};
//手指松开
const touchend = (e: any) => {
  let y = e.changedTouches[0].pageY;
  if (y > data.startY && data.scrollTop == 0) {
    data.translateY = 0;
    data.touchstartTitleShow = false;
    data.touchEndTitleShow = true;
    $emits("refreshFun", () => {
      data.touchEndTitleShow = false;
    });
    data.startY = 0;
  }
};

</script>

<style lang="scss" scoped>
.box {
  overflow: hidden;
  position: relative;
  width: 100%;
  height: 100vh;
  .loadingBox {
    padding: 20px;
    text-align: center;
  }
}
.scroll-box {
  height: 100vh;
  width: 100%;
  overflow: auto;
  transition: all 0s ease 0s;
  position: absolute;
  right: 0;
   .back-box {
    height: 4rem;
    width: 4rem;
    // 如果对小火箭不满意 可以换成阴影盒子 样式也有
    // background-color: #fff;
    // 圆角弧度 添加圆角边框
    // border-radius: 50%;
    //盒子阴影
    // box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.4);
    // position 属性规定元素的定位类型 fixed元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。
    position: fixed;
    bottom: 3rem;
    right: 1rem;
    text-align: center;
    line-height: 4rem;
  }
}
</style>

🗿🗿type index.ts 数据声明

interface IData {
  //全球疫情数据树
  areaTree: IEpidData[];
  chinaDayList: [];
  //全球疫情列表展示
  showList:IEpidData[];
  //全球疫情数组 用来完成分页功能 
  globalEpidemic: Array<IEpidData[]>
  // 疫情 中国总统计
  chinaTotal: IChinaTotal;
  //中国疫情
  china: IEpidData[] | undefined;
  //江西疫情
  jxData: IEpidData | undefined;
  // 进行判定 number 全国 1 江西
  type: number;
  // 判定展示那一个地图 全国现状 全国累计
  mapType: number;
  lineType: number;
  //最新更新时间
  lastUpdateTime: string;
  //下拉刷新判定
  isScroll:Boolean;
}
//疫情数据单位统计
interface IEpidData {
  today: {
    confirm: number;
    suspect: number;
    heal: number;
    dead: number;
    severe: number;
    storeConfirm: number;
  };
  total: {
    confirm: number;
    suspect: number;
    heal: number;
    dead: number;
    severe: number;
    input: number;
  };
  extData: {};
  name: string;
  id: string;
  lastUpdateTime: string;
  children: IEpidData[] | undefined;
}

//疫情 中国总统计
interface IChinaTotal {
  total: {
    confirm: number;
    suspect: number;
    heal: number;
    dead: number;
    severe: number;
    input: number;
  };
  today: {
    input: number;
    storeConfirm: number;
    confirm: number;
    dead: number;
    heal: number;
  };
  extData: {
    noSymptom: number;
    incrNoSymptom: number;
  };
}
//中国地图数值定义
interface IMap{
  name: string,
  value:number
}

export type { IData, IChinaTotal, IEpidData ,IMap};

📕📕pageTS index.ts 数据处理

import { IChinaTotal, IData, IEpidData, IMap } from "../type";
import axios from "axios";
import * as echarts from "echarts";
import chinaJson from "../assets/china.json";
//疫情实时数据
class InfoData implements IData {
  areaTree: IEpidData[] = [];
  chinaDayList: [] = [];
  globalEpidemic:Array<IEpidData[]>=[];
  showList: IEpidData[]=[];
  chinaTotal: IChinaTotal = {
    total: {
      confirm: 0,
      suspect: 0,
      heal: 0,
      dead: 0,
      severe: 0,
      input: 0,
    },
    today: {
      input: 0,
      storeConfirm: 0,
      confirm: 0,
      dead: 0,
      heal: 0,
    },
    extData: {
      noSymptom: 0,
      incrNoSymptom: 0,
    },
  };
  china: IEpidData[] | undefined = [];
  jxData: IEpidData | undefined = {
    today: {
      confirm: 0,
      suspect: 0,
      heal: 0,
      dead: 0,
      severe: 0,
      storeConfirm: 0,
    },
    total: {
      confirm: 0,
      suspect: 0,
      heal: 0,
      dead: 0,
      severe: 0,
      input: 0,
    },
    extData: {},
    name: "",
    id: "",
    lastUpdateTime: "",
    children: ([] = []),
  };
  // 进行判定 0 全国 1 江西
  type = 0;
  mapType = 1;
  lineType = 0;
  lastUpdateTime = "";
  isScroll=true;
}
//数据分页处理 数组[][] 20一页
const getPageList = (list: IEpidData[]) => {
  const arr: Array<IEpidData[]> = [];
  for (let index = 0; index < list.length; index += 20) {
      arr.push(list.slice(index, index + 20))
  }
  return arr
}
const initDataFun = async (data: InfoData) => {
  //疫情地图数据 初始化
  //绑定要渲染的地方
  let nowMapDom: HTMLElement | null = document.getElementById("nowMap");
  let totalmapDom: HTMLElement | null = document.getElementById("totalMap");
  //初始化echarts实例
  let nowMap=echarts.getInstanceByDom(nowMapDom as HTMLElement); //有的话就获取已有echarts实例的DOM节点。
  let totalMap=echarts.getInstanceByDom(totalmapDom as HTMLElement);
  if(nowMap ==null || totalMap == null){ // 如果不存在,就进行初始化。
    nowMap = echarts.init(nowMapDom as HTMLElement);
    totalMap = echarts.init(totalmapDom as HTMLElement);
  } 
  //显示加载圈圈
  nowMap.showLoading();
  totalMap.showLoading();
  //定义两个地图 类型
  let nowMapData: IMap[] = [];
  let totalMapData: IMap[] = [];
  //导入自定义地图数据 registerMap 注册的地图名称。
  echarts.registerMap("china", chinaJson as any);
  //定义 图表 类型
  type EChartsOption = echarts.EChartsOption;
  //定义地图配置
  let series = {
    type: "map",
    map: "china",
    colorBy: "series", //按照系列分配调色盘中的颜色,同一系列中的所有数据都是用相同的颜色
    zoom: 1.3, //当前视角的缩放比例
    top: 80, //组件离容器上侧的距离
    label: {
      show: true,
      color: "#333",
      fontSize: 10,
    },
  };
  //点击地图效果 
  let optionMap: EChartsOption = {
    title: {
      //标题内容
      // text: '中国疫情图',
      subtext: "单击省份可查看病例数",
    },
    tooltip: {
      //提示框组件
      trigger: "item", //触发类型 数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。
      formatter: "现有确诊病例<br/>{b}: {c} ", //提示框浮层内容格式器,支持字符串模板和回调函数两种形式
      //  模板变量有 { a }, { b },{ c },{ d },{ e },分别表示系列名,数据名,数据值等。
      //在 trigger 为 'axis' 的时候,会有多个系列的数据,此时可以通过 { a0 }, { a1 }, { a2 } 这种后面加索引的方式表示系列的索引。 不同图表类型下的 { a },{ b },{ c },{ d } 含义不一样。 其中变量{ a }, { b }, { c }, { d } 在不同图表类型下代表数据含义为:
      // 地图: { a }(系列名称),{ b }(区域名称),{ c }(合并数值), { d }(无)
    },
    visualMap: {
      show: false,
    },
  };
  //获取疫情全部数据接口
  //await是等待的意思,await关键字只能放在async函数里
  //await配合async一起使用,相当于把异步函数变成了同步,await会等待后面表达式的返回结果之后才执行下一步。
  let res=await axios("/prod-api/ug/api/wuhan/app/data/list-total");
    //疫情实时数据处理
    //解构 [[1-30],[31-60],....]
    data.globalEpidemic = getPageList(res.data.data.areaTree);
    data.showList = data.globalEpidemic[0];
    //普通数据赋值
    data.areaTree = res.data.data.areaTree;
    data.chinaDayList = res.data.data.chinaDayList;
    data.chinaTotal = res.data.data.chinaTotal;
    data.lastUpdateTime=res.data.data.lastUpdateTime;
    //获取中国数据
    data.china = data.areaTree.find((v) => v.id === "0")?.children;
    //获取江西疫情数据
    data.jxData = data.china?.find((v) => v.id === "360000");
    //疫情地图数据处理
    data.china?.map((v:IEpidData ) => {
      //对于俩地图赋值
      nowMapData.push({
        name: v.name,
        value: v.total.confirm - v.total.dead - v.total.heal || 0,
      });
      totalMapData.push({
        name: v.name,
        value: v.total.confirm || 0,
      });
    });
    //隐藏加载 圈圈
    nowMap.hideLoading();
    totalMap.hideLoading();
    //数据入地图配置  绘制图表
    nowMap.setOption({
      ...optionMap,
      series: {
        ...series,
        data: nowMapData,
      },
    });
    totalMap.setOption({
      ...optionMap,
      series: {
        ...series,
        data: totalMapData,
      },
    });
};
export { InfoData, initDataFun };

🌃🌃App.vue 疫情页面

<template>
  <UpRefreshAndToTop @refreshFun="refreshFun">
    <div class="box">
      <!-- 疫情实时数据 -->
      <div class="top-box">
        <img class="bg-img" src="./assets/bt.jpg" />
        <div class="title-text">
          <h1>科学防护 共渡难关</h1>
          <h2>肺炎疫情实时动态播报</h2>
          <span>更新时间:{{ lastUpdateTime }}</span>
        </div>
        <div v-if="chinaTotal" class="cover-cards">
          <div class="cover-tab">
            <div @click="changeType(0)" :class="{ active: data.type === 0 }">
              全国疫情数据(含港澳台)
            </div>
            <div @click="changeType(1)" :class="{ active: data.type === 1 }">
              江西疫情数据
            </div>
          </div>
          <!-- 全国疫情 -->
          <div class="cover-info" v-show="data.type === 0">
            <div>
              <h4 class="title">境外输入</h4>
              <p class="number">{{ chinaTotal.total.input }}</p>
              <p class="tip">
                <span>较昨日</span>
                <span>+{{ chinaTotal.today.input }}</span>
              </p>
            </div>
            <div>
              <h4 class="title">无症状感染者</h4>
              <p class="number">{{ chinaTotal.extData.noSymptom }}</p>
              <p class="tip">
                <span>较昨日</span>
                <span>+{{ chinaTotal.extData.incrNoSymptom }}</span>
              </p>
            </div>
            <div>
              <h4 class="title">现有确诊</h4>
              <p class="number">
                {{
                  chinaTotal.total.confirm -
                  chinaTotal.total.dead -
                  chinaTotal.total.heal
                }}
              </p>
              <p class="tip">
                <span>较昨日</span>
                <span>+{{ chinaTotal.today.storeConfirm }}</span>
              </p>
            </div>
            <div>
              <h4 class="title">累计确诊</h4>
              <p class="number">{{ chinaTotal.total.confirm }}</p>
              <p class="tip">
                <span>较昨日</span>
                <span>+{{ chinaTotal.today.confirm }}</span>
              </p>
            </div>
            <div>
              <h4 class="title">累计死亡</h4>
              <p class="number">{{ chinaTotal.total.dead }}</p>
              <p class="tip">
                <span>较昨日</span>
                <span>+{{ chinaTotal.today.dead }}</span>
              </p>
            </div>
            <div>
              <h4 class="title">累计治愈</h4>
              <p class="number">{{ chinaTotal.total.heal }}</p>
              <p class="tip">
                <span>较昨日</span>
                <span>+{{ chinaTotal.today.heal }}</span>
              </p>
            </div>
          </div>
          <!-- 江西疫情 -->
          <div v-if="jxData" v-show="data.type === 1" class="cover-info">
            <div>
              <h4 class="title">累计确诊</h4>
              <p class="number">{{ jxData.total.confirm }}</p>
              <p class="tip">
                较昨日
                <span>+{{ jxData.today.confirm }}</span>
              </p>
            </div>
            <div>
              <h4 class="title">累计死亡</h4>
              <p class="number">{{ jxData.total.dead }}</p>
              <p class="tip">
                较昨日
                <span>+{{ jxData.today.dead }}</span>
              </p>
            </div>
            <div>
              <h4 class="title">累计治愈</h4>
              <p class="number">{{ jxData.total.heal }}</p>
              <p class="tip">
                较昨日
                <span>+{{ jxData.today.heal }}</span>
              </p>
            </div>
          </div>
        </div>
      </div>
      <!-- 疫情地图 -->
      <div class="data-map content">
        <h3>中国疫情</h3>
        <div class="map-box">
          <div
            :class="data.mapType == 1 ? 'to-left' : 'to-right'"
            id="nowMap"
          ></div>
          <div
            :class="data.mapType == 1 ? 'to-left' : 'to-right'"
            id="totalMap"
          ></div>
        </div>
        <div class="map-btn">
          <div @click="mapTypeChange(1)" :class="{ active: data.mapType == 1 }">
            现有确诊
          </div>
          <div @click="mapTypeChange(2)" :class="{ active: data.mapType == 2 }">
            累计确诊
          </div>
        </div>
      </div>
      <!-- 中国疫情列表 -->
      <div class="data-list content">
        <h3>中国病例</h3>
        <span class="hint">温馨提示:点击可展示具体城市</span>
        <EpidemicList :epideList="china" :showChildren="true"></EpidemicList>
      </div>
      <!-- 世界疫情 无点击子模块 -->
      <div v-if="data.showList.length" class="data-list content">
        <h3>世界病例</h3>
        <DownRefresh
          :distance="100"
          :isScroll="data.isScroll"
          @getList="getList"
        >
          <EpidemicList :showChildren="false" :epideList="data.showList" />
        </DownRefresh>
      </div>
    </div>
  </UpRefreshAndToTop>
</template>

<script setup lang="ts">
import { onMounted, reactive, toRefs } from "vue";
import { InfoData, initDataFun } from "./pageTs/index";
import EpidemicList from "./components/EpidemicList.vue";
import UpRefreshAndToTop from "./components/UpRefreshAndToTop.vue";
import DownRefresh from "./components/DownRefresh.vue";
const data = reactive(new InfoData());
onMounted(() => {
  initDataFun(data);
});
//解构数据
const { chinaTotal, jxData, china, lastUpdateTime } = toRefs(data);

//切换 疫情实时数据 全国 江西
const changeType = (toType: number) => {
  data.type = toType;
};
//地图 切换
const mapTypeChange = (type: number) => {
  console.log(type);
  data.mapType = type;
};
//下拉效果 全球疫情列表
let page: number = 0;
const getList = () => {
  if (page === data.globalEpidemic.length - 1) {
    data.isScroll = false;
    return;
  }
  console.log("加载下一页");

  // 子组件触发,加载下一页数据
  page++;
  data.showList.push(...data.globalEpidemic[page]);
};
//重新加载数据
const refreshFun = (fun: Function) => {
  initDataFun(data).then(() => {
    //疫情实时数据切换成全国数据
    data.type = 0;
    //重置全球疫情下拉功能
    page = 0;
    data.isScroll = true;
    //控制手指按下屏幕的title显示 去除
    fun();
  });
};
</script>

<style lang="scss" scoped>
// 滑动动画
@keyframes toRight {
  from {
    left: 0;
  }

  to {
    left: calc(0px - 100vw + 1rem);
  }
}

@keyframes toLeft {
  from {
    left: calc(0px - 100vw + 1rem);
  }

  to {
    left: 0;
  }
}
.bg-img {
  width: 100%;
}
//疫情实时数据样式
.top-box {
  position: relative;

  .title-text {
    position: absolute;
    z-index: 2;
    color: #fff;
    top: 20px;
    left: 1rem;
    span {
      color: #000;
    }
  }

  .cover-cards {
    position: absolute;
    top: 12rem;
    background: #fff;
    border-radius: 20px;
    width: calc(100% - 2rem);
    left: 1rem;
    overflow: hidden;
    box-shadow: 0 2px 20px rgb(0 0 0 / 10%);

    > div {
      display: flex;
      justify-content: space-between;
      align-items: center;
      flex-wrap: wrap;

      &.cover-tab {
        > div {
          width: 50%;
          background: #efefef;
          text-align: center;
          height: 40px;
          line-height: 40px;

          &.active {
            background: #fff;
          }
        }
      }

      &.cover-info {
        > div {
          width: 33%;
          text-align: center;
          margin: 10px 0;

          &:nth-child(2) {
            .number,
            span {
              color: #ffa352;
            }
          }

          &:nth-child(3) {
            .number,
            span {
              color: #791618;
            }
          }

          &:nth-child(4) {
            .number,
            span {
              color: #e44a3d;
            }
          }

          &:nth-child(5) {
            .number,
            span {
              color: #333;
            }
          }

          &:nth-child(6) {
            .number,
            span {
              color: #34aa70;
            }
          }

          .title {
            font-size: 12px;
          }

          .number {
            font-size: 1.5rem;
            font-weight: 600;
            margin: 5px 0;
            color: #a31d13;

            span {
              color: #a31d13;
            }
          }

          .tip {
            font-size: 12px;
          }
        }
      }
    }
  }
}
//疫情地图 数组样式
.content {
  padding: 0 1rem;
}

.data-map,
.data-list {
  margin-top: 300px;
  overflow: hidden;

  h3 {
    border-left: 8px solid #e10000;
    padding-left: 1rem;
  }
  .hint{
   font-size: 0.5rem;
   color: coral;
  }
}

.map-box {
  display: flex;
  width: 200%;
}

#nowMap,
#totalMap {
  height: 350px;
  width: 50%;
  animation-fill-mode: forwards;
  left: 0;
}

#nowMap {
  margin-right: 1rem;
}

#totalMap {
  margin-left: 1rem;
}

.to-left {
  animation: toLeft 1s;
}

.to-right {
  animation: toRight 1s;
}

.map-btn,
.line-btn {
  display: flex;
  justify-content: space-between;
  align-items: center;

  > div {
    width: 45%;
    height: 40px;
    line-height: 40px;
    border: 1px solid #d2d2d2;
    box-shadow: 0 5px 7px 1px rgb(0 0 0 / 5%);
    border-radius: 5px;
    text-align: center;

    &.active {
      border-color: #ce4733;
      background-color: #fef7f7;
      color: #ce2c1e;
    }
  }
}

.line-btn {
  > div {
    width: 30%;
    height: 55px;
    line-height: 25px;
    padding-top: 5px;
  }
}

.data-list {
  margin-top: 20px;
}
</style>

📺📺vite.config.ts 代理开通 

温馨提示:数据来源 网易云🤭

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    proxy: {
       //网易代理
      '/prod-api':
       {
        target: "https://c.m.163.com",
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/prod-api/,'')
      }
    }
  }
})

 完结

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新生代农民工-小王八

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值