疫情统计页面 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/,'')
      }
    }
  }
})

 完结

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>