Vue3 + TypeScript + Vite + Echarts + DataV

54 篇文章 1 订阅
45 篇文章 2 订阅

Vue3 + TypeScript + Vite + Echarts + DataV

datav

官网:

datav

datav-vue3

1、创建工程

npm create vite@latest
cd datav-app
npm install
npm run dev

2、安装项目依赖模块

npm install @types/node --save-dev

npm install vue-router@4

npm install animate.css --save
npm install gsap --save

npm install fetch --save
npm install axios --save

npm install pinia

npm install less less-loader -D
npm install sass sass-loader --save-dev
npm install scss scss-loader --save-dev

npm install element-plus --save
npm install -D unplugin-vue-components unplugin-auto-import

npm install echarts echarts-wordcloud --save
npm install @kjgl77/datav-vue3

3、配置项目

vite.config.ts

import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import {resolve} from "node:path";

const base = 'http://140.143.190.15:8080'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    host: '0.0.0.0',
    port: 5173,
    open: true,
    proxy: {
      '/api': {
        target: base,  //目标代理接口地址
        secure: false,
        changeOrigin: true,  //开启代理,在本地创建一个虚拟服务器
        PathRewrite: {
          '^/api': '/api'
        }
      }
    }
  },
})

3.1 配置路径别名

vite.config.ts

import {resolve} from "node:path";

resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    },
    // 引入文件的时候,可以忽略掉以下文件后缀
    // extensions: ['.js', '.mjs', '.vue', '.json', '.less', '.css']
  },
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import {resolve} from "node:path";

const base = 'http://140.143.190.15:8080'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    host: '0.0.0.0',
    port: 5173,
    open: true,
    proxy: {
      '/api': {
        target: base,  //目标代理接口地址
        secure: false,
        changeOrigin: true,  //开启代理,在本地创建一个虚拟服务器
        PathRewrite: {
          '^/api': '/api'
        }
      }
    }
  },
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    }
  },
})

ts.config.node.json

/* 路径别名 */
"types": ["node"],
"baseUrl": ".",
"paths": {
  "@/*": ["src/*"]
}
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2023"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,


    /* 路径别名 */
    "types": ["node"],
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["vite.config.ts"]
}

3.2 引入路由

3.2.1 创建路由出口视图并在 app.vue 组件中引入 路由出口视图

DataV.vue

<script setup lang="ts">

</script>

<template>
  <router-view/>
</template>

<style scoped>

</style>

app.vue

<script setup lang="ts">
import HelloEcharts from "@/components/DataV.vue";
</script>

<template>
  <data-v/>
</template>

<style scoped>
</style>

3.2.2 创建路由文件

router.ts

// 1. 定义路由组件.
// 也可以从其他文件导入
import {createMemoryHistory, createRouter, RouteRecordRaw} from 'vue-router'
// 2. 定义一些路由
const routes: Array<RouteRecordRaw> = [
]
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = createRouter({
  // 4. 内部提供了 history 模式的实现。
  // memory 模式。createMemoryHistory
  // hash 模式。createWebHashHistory
  // html5 模式。createWebHistory
  history: createMemoryHistory(),
  routes,
})

export default router
3.2.3 引入路由配置文件

main.ts

import {createApp} from 'vue';
import './style.css';
import App from './App.vue';
import router from "./routers/router.ts";

const app = createApp(App);
app.use(router);
app.mount('#app');

3.3 引入 animate.css 动画库

main.ts

import 'animate.css'
import {createApp} from 'vue';
import './style.css';
import 'animate.css'
import App from './App.vue';
import router from "./routers/router.ts";

const app = createApp(App);
app.use(router);
app.mount('#app');

3.4 引入 pinia

3.4.1 编写状态管理文件strore.ts

store.ts

import {defineStore} from 'pinia'
import {computed, reactive, ref} from "vue";


export const useStore = defineStore('main', () => {
  // ref() 和 reactive() 就是 state 属性
  // computed() 就是 getters
  // function() 就是 actions

  return {}
});
3.4.2 引入 pinia

main.ts

import {createPinia} from "pinia";
// 需要注意的是从pinia中解构出来的createPinia是一个函数,挂载前需要先调用执行
// const pinia = createPinia()
// app.use(pinia)
app.use(createPinia())
import {createApp} from 'vue';
import './style.css';
import 'animate.css'
import App from './App.vue';
import router from "./routers/router.ts";
import {createPinia} from "pinia";
const app = createApp(App);
// 需要注意的是从pinia中解构出来的createPinia是一个函数,挂载前需要先调用执行
// const pinia = createPinia()
// app.use(pinia)
app.use(createPinia())
app.use(router);
app.mount('#app');

3.5 配置 scss

3.5.1 编写scss 变量存储文件 scss_variable.scss
// 单个图表 宽度和高度
$chart-width: 100%;
$chart-height: 100%;

3.5.2 引入 scss 变量配置文件 scss_variable.scss

vite.config.ts

css: {
    preprocessorOptions: {
      scss: {
        // additionalData: '@import "./src/styles/scss_variable.scss";'
        additionalData: `@use "./src/styles/scss_variable.scss" as *;`,
      }
    }
  }
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import {resolve} from "node:path";
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

const base = 'http://140.143.190.15:8080'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    host: '0.0.0.0',
    port: 5173,
    open: true,
    proxy: {
      '/api': {
        target: base,  //目标代理接口地址
        secure: false,
        changeOrigin: true,  //开启代理,在本地创建一个虚拟服务器
        PathRewrite: {
          '^/api': '/api'
        }
      }
    }
  },
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    }
  },
  css: {
    preprocessorOptions: {
      scss: {
        // additionalData: '@import "./src/styles/scss_variable.scss";',
        additionalData: `@use "./src/styles/scss_variable.scss" as *;`,
      }
    }
  }
})

3.6 配置 element plus

完整引入

按需导入

自动导入(本配置使用自动加载)

vite.config.ts

import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import {resolve} from "node:path";
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

const base = 'http://140.143.190.15:8080'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      // resolvers: [ElementPlusResolver({importStyle: "sass"})],
      resolvers: [ElementPlusResolver()],
    }),
  ],
  server: {
    host: '0.0.0.0',
    port: 5173,
    open: true,
    proxy: {
      '/api': {
        target: base,  //目标代理接口地址
        secure: false,
        changeOrigin: true,  //开启代理,在本地创建一个虚拟服务器
        PathRewrite: {
          '^/api': '/api'
        }
      }
    }
  },
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    }
  },
  css: {
    preprocessorOptions: {
      scss: {
        // additionalData: '@import "./src/styles/scss_variable.scss";',
        additionalData: `@use "./src/styles/scss_variable.scss" as *;`,
      }
    }
  }
})

3.7 echarts公共组件

3.7.1 echarts 图表公共组件

ChartLhz.vue

<script setup lang="ts">
import * as echarts from 'echarts';
import 'echarts-wordcloud'
import {onMounted, reactive, ref, useAttrs, useTemplateRef} from "vue";

const chartLhz = ref();

// const chartLhz = useTemplateRef('chartLhz');
// 接受父组件传递的图表的配置项和数据
const props = defineProps(['chart_option'])
const {chart_option} = props;
// 指定图表的配置项和数据
const option = reactive({});

function chartLhzInit() {
  // 基于准备好的dom,初始化echarts实例
  let LhzChart = echarts.init(chartLhz.value, 'dark');
  // 指定图表的配置项和数据
  for (const filed in chart_option) {
    // 将父组件中传递过来的对象属性赋值给本地的对象
    option[filed] = chart_option[filed];
  }
  // 使用刚指定的配置项和数据显示图表。
  LhzChart.setOption(option);
  window.addEventListener('resize', () => {
    LhzChart.resize();
  })
}

onMounted(() => {
  // 在挂载阶段 初始化 echarts 实例
  chartLhzInit();
});
</script>

<template>
  <div id="chartLhz" ref="chartLhz"></div>
</template>

<style scoped lang="scss">
#chartLhz {
  width: 100%;
  height: 100%;
}
</style>
3.7.2 地图公共组件

ChartMap.vue

<script setup>
import * as echarts from 'echarts';
import {ref, reactive, onMounted, useTemplateRef} from "vue";
import china_province from '@/stores/china_province.json'
import china_geo from '@/stores/china_full.json'

const chartMap = ref()
const convertData = function (data) {
  let res = [];
  for (let i = 0; i < data.length; i++) {
    let geoCoord = china_geo.features[i].properties;
    if (geoCoord) {
      res.push({
        name: data[i].name,
        value: geoCoord.center.concat(data[i].value)
      });
    }
  }
  return res;
};

// const chartMap = useTemplateRef('chartMap')
function chartMapInit() {
  // 基于准备好的dom,初始化echarts实例
  const myChart = echarts.init(chartMap.value, 'dark');
  // 注入地图数据 GeoJson 注意第一个参数为 china 才会显示 海南岛缩略图 其它名字不会
  echarts.registerMap('china', china_geo);
  // 指定图表的配置项和数据
  const option = reactive({
    title: {
      text: '',
      left: 'center'
    },
    tooltip: {
      trigger: 'item',
      formatter: function (params) {
        // console.log(params);
        return `${params.data.name}:${params.data.value[2]}`
      }
    },
    // 地图配置
    geo: {
      type: 'map',
      // chinaMap 这个参数 为 echarts.registerMap('chinaMap', response); 参数中第一个参数
      // 注意参数为 china 才会显示 海南岛缩略图 其它名字不会
      map: 'china',
      // 是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
      roam: true,
      // 图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等
      label: {
        // 是否显示标签
        show: true
      },
      // 默认缩放比例
      zoom: 1.1,
      // 地图中心点坐标
      // 当前视角的中心点,默认使用原始坐标(经纬度)。如果设置了projection则用投影后的坐标表示。
      // center: [125.3245, 43.886841]

    },
    series: [
      {
        geoIndex: 0,
        type: 'effectScatter',
        // 配置何时显示特效
        // 'render' 绘制完成后显示特效
        // 'emphasis' 高亮(hover)的时候显示特效。
        showEffectOn: 'render',
        // data: [{ name: '北京市', value: [116.405285, 39.904989, 9] }],
        data: convertData(china_province),
        // 使用地理坐标系,通过 geoIndex 指定相应的地理坐标系组件。
        coordinateSystem: 'geo',
        symbolSize: function (param) {
          // console.log(param[2]);
          return param[2] / 2
        },
      },

    ],
    // 是视觉映射组件,用于进行『视觉编码』,也就是将数据映射到视觉元素(视觉通道
    visualMap: {
      min: 0,
      max: 50,
      // 筛选
      calculable: true
    }
  });

  // 使用刚指定的配置项和数据显示图表。
  myChart.setOption(option);
  window.addEventListener('resize', function () {
    myChart.resize();
  });
}

onMounted(() => {
  chartMapInit()
})
</script>

<template>
  <div id="chartMap" ref="chartMap"></div>
</template>

<style scoped lang="scss">
#chartMap {
  width: 100%;
  height: 100%;
}
</style>

3.8 引入 datav

commons.css

html, body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

main.ts

// 引入 DataV
import DataVVue3 from '@kjgl77/datav-vue3'
import {createApp} from 'vue'
// import './style.css'
import './assets/css/common.css'
import 'animate.css'
import {createPinia} from "pinia"
import App from './App.vue'
import DataVVue3 from '@kjgl77/datav-vue3'
import router from './routers/router.ts'
// import axios from 'axios'
// axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token')
// axios.defaults.baseURL = 'http://localhost:8080'
const app = createApp(App)
// 需要注意的是从pinia中解构出来的createPinia是一个函数,挂载前需要先调用执行
// const pinia = createPinia()
// app.use(pinia)
app.use(createPinia())
app.use(DataVVue3)
app.use(router)
app.mount('#app')

4、页面布局

4.1 大屏页面

Layout.vue

<script setup lang="ts">
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row" style="height: 490px">
            <!-- 第三列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第三列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }
}
</style>

4.2 配置路由

// 1. 定义路由组件.
// 也可以从其他文件导入
import {createMemoryHistory, createRouter, RouteRecordRaw} from 'vue-router'
import Layout from "../views/Layout.vue";
// 2. 定义一些路由
const routes: Array<RouteRecordRaw> = [
  {path: '/', component: Layout},
  // 处理 404
  {path: '/:pathMatch(.*)*', redirect: "/"},
]
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = createRouter({
  // 4. 内部提供了 history 模式的实现。
  // memory 模式。createMemoryHistory
  // hash 模式。createWebHashHistory
  // html5 模式。createWebHistory
  history: createMemoryHistory(),
  routes,
})

export default router

5、 页面组件

5.1 头部组件

TopHeader.vue

<script setup lang="ts">

</script>

<template>
  <div id="top-header">
    <!-- 头部左侧 -->
    <dv-decoration-8 class="header-left-decoration" />
    <!-- 头部标题装饰 -->
    <dv-decoration-5 class="header-center-decoration" />"
    <!-- 头部右侧 -->
    <dv-decoration-8 :reverse="true" class="header-right-decoration" />
    <!-- 头部标题 -->
    <div class="center-title">计算机就业数据可视化平台</div>
  </div>
</template>

<style scoped lang="scss">
#top-header{
  width: 100%;
  height: 100px;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  .header-center-decoration {
    width: 40%;
    height: 60px;
    margin-top: 30px;
  }
  .header-left-decoration,.header-right-decoration{
    width: 25%;
    height: 60px;
  }
  .center-title{
    position: absolute;
    font-size: 30px;
    font-weight: bold;
    left: 50%;
    top: 15px;
    transform: translateX(-60%);
  }
}
</style>
<script setup lang="ts">
import TopHeader from "@/views/TopHeader.vue";
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <top-header/>
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
            </div>
          </div>
        </div>
        <div class="col">
           <div class="row" style="height: 490px">
            <!-- 第三列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第三列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }

}
</style>

5.2 全国岗位分布图

CenterMap.vue

<script setup lang="ts">
import axios from "axios";
import * as echarts from 'echarts';
import china_geo from '@/stores/china.json'
import {onMounted, ref, reactive, watch, watchEffect} from "vue";

const chartMap = ref()

function formatCityName(cityName) {
  const replacements = {
    "上海": "上海市",
    "北京": "北京市",
    "天津": "天津市",
    "广州": "广东省",
    "成都": "四川省",
    "杭州": "浙江省",
    "武汉": "湖北省",
    "济南": "山东省",
    "深圳": "广东省",
    "青岛": "山东省",
    // 可以继续添加更多的替换规则
  };
  return replacements[cityName] || cityName;
}

function initChart(data) {
  // 基于准备好的dom,初始化echarts实例
  const myChart = echarts.init(chartMap.value);
  // 注入地图数据 GeoJson 注意第一个参数为 china 才会显示 海南岛缩略图 其它名字不会
  echarts.registerMap('china', china_geo);
  // 指定图表的配置项和数据
  const option = {
    backgroundColor: 'rgba(0,0,0,0)',
    // backgroundColor: 'transparent',
    title: {
      text: '全国岗位分布',
      left: 'center',
      top: '30px',
      textStyle: {
        color: '#fff',
        fontWeight: 'bold',
        fontSize: '30px',
      }
    },
    tooltip: {
      trigger: 'item',
      formatter: function (params) {
        // console.log(params);
        return `${params.data.name}:${params.data.value[2]}`
      },
      backgroundColor: "rgba(0,0,0,.6)",
      borderColor: "rgba(147, 235, 248, .8)",
      textStyle: {
        color: "#FFF",
      },
    },
    // 地图配置
    geo: {
      type: 'map',
      // chinaMap 这个参数 为 echarts.registerMap('chinaMap', response); 参数中第一个参数
      // 注意参数为 china 才会显示 海南岛缩略图 其它名字不会
      map: 'china',
      // 是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
      roam: true,
      // 图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等
      label: {
        // 是否显示标签
        show: true
      },
      // 默认缩放比例
      zoom: 1.1,
      // 地图中心点坐标
      // 当前视角的中心点,默认使用原始坐标(经纬度)。如果设置了projection则用投影后的坐标表示。
      // center: [125.3245, 43.886841]

    },
    series: [
      {
        geoIndex: 0,
        type: 'effectScatter',
        // 配置何时显示特效
        // 'render' 绘制完成后显示特效
        // 'emphasis' 高亮(hover)的时候显示特效。
        showEffectOn: 'render',
        // data: [{ name: '北京市', value: [116.405285, 39.904989, 90] }],
        data: data,
        // 使用地理坐标系,通过 geoIndex 指定相应的地理坐标系组件。
        coordinateSystem: 'geo',
        symbolSize: function (param) {
          // console.log(param[2]);
          return param[2] / 5000
        },
      },

    ],
    // 是视觉映射组件,用于进行『视觉编码』,也就是将数据映射到视觉元素(视觉通道)
    visualMap: {
      left: 20,
      bottom: 20,
      pieces: [
        {gte: 50000, label: "10000个以上"}, // 不指定 max,表示 max 为无限大(Infinity)。
        {gte: 40000, lte: 49999, label: "40000-49999个"},
        {gte: 30000, lte: 39999, label: "30000-39999个"},
        {gte: 20000, lte: 29999, label: "20000-29999个"},
        {gte: 10000, lte: 19999, label: "10000-19999个"},
        {lte: 9999, label: "1-9999个"}, // 不指定 min,表示 min 为无限大(-Infinity)。
      ],
      inRange: {
        // 渐变颜色,从小到大
        color: [
          "#c3d7df",
          "#5cb3cc",
          "#8abcd1",
          "#66a9c9",
          "#2f90b9",
          "#1781b5",
        ],
      },
      textStyle: {
        color: "#fff",
      },
    },
  };
  // 使用刚指定的配置项和数据显示图表。
  myChart.setOption(option, true)
  window.addEventListener('resize', function () {
    myChart.resize();
  });
}

function getData() {
  axios.get("/api/ChinaJobCount").then((response) => {
    if (response.data.success) {
      let province_data = response.data.data.chinaJobCountDtos;
      let data = province_data.map((province) => {
        let obj = china_geo.features.find(item => item.properties.name === formatCityName(province.name))
        let rs = {}
        rs.name = obj.properties.name
        rs.value = [obj.properties.center[0], obj.properties.center[1], province.value]
        return rs
      });
      initChart(data)
    }
  })
}

onMounted(() => {
  getData();
})
</script>

<template>
  <dv-border-box-8 style="text-align: center">
    <div ref="chartMap" id="chartMap"/>
  </dv-border-box-8>
</template>

<style scoped lang="scss">
#chartMap {
  width: 100%;
  height: 100%;
}
</style>
<script setup lang="ts">
import TopHeader from "@/views/TopHeader.vue";
import LeftTop from "@/views/LeftTop.vue";
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <top-header/>
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
              <center-map/>
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
            </div>
          </div>
        </div>
        <div class="col">
           <div class="row" style="height: 490px">
            <!-- 第三列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
           <div class="row" style="height: 490px">
            <!-- 第三列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }

}
</style>

5.3 全国岗位需求量占比

CenterPie.vue

<script setup lang="ts">
import axios from "axios";
import {onMounted, reactive} from "vue";

const option = reactive({
  title: {
    text: '全年岗位需求占比',
    style: {
      fill: '#ffffff',
      fontSize: 20,
    }
  },
  series: [
    {
      type: 'pie',
      data: [],
      insideLabel: {
        show: true
      },
      roseType: true
    }
  ]
})
function getData() {
  axios.get("/api/job/findJobByCategory").then((response) => {
    option.series[0].data = response.data;
  })
}
onMounted(() => {
  getData();
})
</script>

<template>
  <dv-border-box-1 style="text-align: center">
    <dv-charts :option="option"/>
  </dv-border-box-1>
</template>

<style scoped lang="scss">

</style>
<script setup lang="ts">
import TopHeader from "@/views/TopHeader.vue";
import LeftTop from "@/views/LeftTop.vue";
import CenterPie from "@/views/CenterPie.vue";
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <top-header/>
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
              <center-map/>
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
              <center-pie/>
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
            </div>
          </div>
        </div>
        <div class="col">
           <div class="row" style="height: 490px">
            <!-- 第三列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
           <div class="row" style="height: 490px">
            <!-- 第三列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }

}
</style>

5.4 web方向不同学历岗位薪资

LeftTop.vue

<script setup lang="ts">
import axios from "axios";
import {onMounted, reactive} from "vue";

const config = reactive({
  data: [],
  showValue: true,
  unit: '千元',
  labelNum: 0,
})

function getData() {
  axios.get("/api/WebDemandSalary").then((response) => {
    config.data = response.data.data.webDemandDtos;
    config.labelNum = response.data.data.webDemandDtos.length;
  })
}

onMounted(() => {
  getData();
})
</script>

<template>
  <dv-border-box-13 style="text-align: center">
    <h1>web岗位平均薪资</h1>
    <dv-capsule-chart :config="config"/>
  </dv-border-box-13>
</template>

<style scoped lang="scss">

</style>
<script setup lang="ts">
import TopHeader from "@/views/TopHeader.vue";
import LeftTop from "@/views/LeftTop.vue";
import CenterPie from "@/views/CenterPie.vue";
import LeftTop from "@/views/LeftTop.vue";  
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <top-header/>
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
              <center-map/>
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
              <center-pie/>
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
              <left-top/>
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
          <div class="row">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
            </div>
          </div>
        </div>
        <div class="col">
           <div class="row" style="height: 490px">
            <!-- 第三列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
           <div class="row" style="height: 490px">
            <!-- 第三列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }
}
</style>

5.5 Java方向不同学历岗位薪资

LeftCenter.vue

<script setup lang="ts">
import axios from "axios";
import {onMounted, reactive} from "vue";

const config = reactive({
  data: [],
  showValue: true,
  unit: '千元',
  labelNum: 0,
})

function getData() {
  axios.get("/api/JavaDemandSalary").then((response) => {
    config.data = response.data.data.javaDemandDtos;
    config.labelNum = response.data.data.javaDemandDtos.length;
  })
}

onMounted(() => {
  getData();
})
</script>

<template>
  <dv-border-box-13 style="text-align: center ;padding-top: 20px">
    <h1>Java岗位平均薪资</h1>
    <dv-capsule-chart :config="config"/>
  </dv-border-box-13>
</template>

<style scoped lang="scss">

</style>
<script setup lang="ts">
import TopHeader from "@/views/TopHeader.vue";
import LeftTop from "@/views/LeftTop.vue";
import CenterPie from "@/views/CenterPie.vue";
import LeftTop from "@/views/LeftTop.vue";  
import LeftCenter from "@/views/LeftCenter.vue";  
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <top-header/>
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
              <center-map/>
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
              <center-pie/>
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
              <left-top/>
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
              <left-center/>
            </div>
          </div>
          <div class="row">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
            </div>
          </div>
        </div>
        <div class="col">
           <div class="row" style="height: 490px">
            <!-- 第三列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
           <div class="row" style="height: 490px">
            <!-- 第三列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }
}
</style>

5.6 大数据方向不同学历岗位薪资

LeftBottom.vue

<script setup lang="ts">
import axios from "axios";
import {onMounted, reactive} from "vue";

const config = reactive({
  data: [],
  showValue: true,
  unit: '千元',
  labelNum: 0,
})

function getData() {
  axios.get("/api/BigdataDemandSalary").then((response) => {
    config.data = response.data.data.bigdataDemandDtos;
    config.labelNum = response.data.data.bigdataDemandDtos.length;
  })
}

onMounted(() => {
  getData();
})
</script>

<template>
  <dv-border-box-13 style="text-align: center ;padding-top: 20px">
    <h1>大数据岗位平均薪资</h1>
    <dv-capsule-chart :config="config"/>
  </dv-border-box-13>
</template>

<style scoped lang="scss">

</style>
<script setup lang="ts">
import TopHeader from "@/views/TopHeader.vue";
import LeftTop from "@/views/LeftTop.vue";
import CenterPie from "@/views/CenterPie.vue";
import LeftTop from "@/views/LeftTop.vue";  
import LeftCenter from "@/views/LeftCenter.vue";  
import LeftBottom from "@/views/LeftBottom.vue";  
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <top-header/>
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
              <center-map/>
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
              <center-pie/>
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
              <left-top/>
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
              <left-center/>
            </div>
          </div>
          <div class="row">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
              <left-bottom/>
            </div>
          </div>
        </div>
        <div class="col">
           <div class="row" style="height: 490px">
            <!-- 第三列第一行数据分析容器 -->
            <div class="col">
            </div>
          </div>
           <div class="row" style="height: 490px">
            <!-- 第三列第二行数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }
}
</style>

5.8 上海平均薪资排行

RightTop.vue

<script setup lang="ts">
import {onMounted, reactive} from "vue";
import st1_img from "@/assets/img/1st.png"
import st2_img from "@/assets/img/2st.png"
import st3_img from "@/assets/img/3st.png"
import st4_img from "@/assets/img/4st.png"
import st5_img from "@/assets/img/5st.png"
import st6_img from "@/assets/img/6st.png"
import st7_img from "@/assets/img/7st.png"
import axios from "axios";

const config = reactive({
  showValue: true,
  data: [],
  img: [st1_img, st1_img, st2_img, st2_img, st3_img, st4_img, st5_img, st7_img, st6_img],
});

function getData() {
  axios.get("/api/AvgSalary/shanghai").then(response => {
    config.data = response.data.data.salaryRankVos;
  });
}

onMounted(() => {
  getData();
})

</script>

<template>
  <dv-border-box-8 style="text-align: center">
    <h1>上海平均薪资排行</h1>
    <dv-conical-column-chart :config="config" style=" width: 90%;height:350px; position: relative;left: 30px"/>
  </dv-border-box-8>
</template>

<style scoped lang="scss">

</style>
<script setup lang="ts">
import TopHeader from "@/views/TopHeader.vue";
import CenterMap from "@/views/CenterMap.vue";
import CenterPie from "@/views/CenterPie.vue";
import LeftTop from "@/views/LeftTop.vue";
import LeftCenter from "@/views/LeftCenter.vue";
import LeftBottom from "@/views/LeftBottom.vue";
import RightTop from "@/views/RightTop.vue";
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <top-header/>
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
              <center-map/>
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
              <center-pie/>
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
              <left-top/>
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
              <left-center/>
            </div>
          </div>
           <div class="row" style="height: 490px">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
              <left-bottom/>
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第一行第三列数据分析容器 -->
            <div class="col">
              <right-top/>
            </div>
          </div>
           <div class="row" style="height: 490px">
            <!-- 第二行第三列数据分析容器 -->
            <div class="col">
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }
}
</style>

5.9 各地岗位分布

RightBottom.vue

<script setup lang="ts">
import axios from "axios";
import * as echarts from 'echarts';
import 'echarts-wordcloud'
import {computed, onMounted, reactive, ref, toRaw} from "vue";
import ChartLhz from "@/components/ChartLhz.vue";

const data_list = reactive([]);

// 定义一个用于获取数据的函数
function fetchJobCounts() {
  // 这里创建三个 API 请求的 Promise
  const shanghaiPromise = axios.get("/api/JobCount").then((response) => {
    return response.data.data.shanghaiJobCounts; // 返回上海数据
  });

  const guangzhouPromise = axios.get("/api/JobCount/guangzhou").then((response) => {
    return response.data.data.guangJobCounts; // 返回广州数据
  });

  const chengduPromise = axios.get("/api/JobCount/chengdu").then((response) => {
    return response.data.data.chengJobCountDtos; // 返回成都数据
  });

  // 使用 Promise.all 等待所有请求完成并返回结果
  return Promise.all([shanghaiPromise, guangzhouPromise, chengduPromise]);
}

function getData() {
  //获取数据
  fetchJobCounts().then(([Shanghai_data, Guangzhou_data, Chengdu_data]) => {
    // 封装数据格式 为
    // [
    //   ["DBA", "Java", "Python", "web", "其他后端", "其他职业", "大数据", "数据分析", "算法工程师"],
    //   [99, 17092, 1037, 16200, 583, 4967, 3194, 4403, 3925],
    //   [47, 15870, 584, 13446, 269, 2771, 930, 1873, 606],
    //   [25, 16383, 253, 16352, 102, 928, 645, 1118, 1648]
    // ]
    let tmp = [];
    // 遍历 Shanghai_data
    for (const item of Shanghai_data) {
      tmp.push(item);
    }
    // 遍历 Guangzhou_data
    for (const item of Guangzhou_data) {
      tmp.push(item);
    }
    // 遍历 Chengdu_data
    for (const item of Chengdu_data) {
      tmp.push(item);
    }
    // 使用 reduce 来合并数据
    const result = tmp.reduce((acc, item) => {
      const {name, value} = item;

      // 如果标头数组不存在,则初始化标头数组
      if (!acc.headers.includes(name)) {
        acc.headers.push(name);
      }

      // 将值添加到相应的 name 索引中
      const index = acc.headers.indexOf(name);
      if (!acc.values[index]) {
        acc.values[index] = [];
      }
      acc.values[index].push(value);

      return acc;
    }, {headers: [], values: []});

    // 将最终结果格式化为二维数组
    const finalResult = [result.headers];

    // 确定行数(每个职业的值数量)
    const rowsCount = Math.max(...result.values.map(arr => arr.length));

    // 将值添加到最终结果中
    for (let i = 0; i < rowsCount; i++) {
      const row = [];
      for (const valueArray of result.values) {
        row.push(valueArray[i] || 0); // 如果没有值,则使用 0 填充
      }
      finalResult.push(row);
    }
    // 输出结果
    data_list.value = finalResult;
  }).catch((error) => {
    console.error("Error fetching data:", error);
  });
}

// 配置项
const chart_option = computed(() => {
  let option = {
    title: {
      text: '主要城市岗位需求数量',
      left: 'center',
      textStyle: {
        color: '#fff',
      }
    },
    legend: {
      data: ['上海', '广州', '成都'],
      left: 'center',
      top: 'bottom',
      textStyle: {
        color: '#fff',
      }
    },
    radar: {
      // shape: 'circle',
      indicator: ["DBA","Java","Python","web","其他后端","其他职业","大数据","数据分析","算法工程师"],
      // axisName: {
      //   color: '#fff'
      // },
    },
    series: [
      {
        name: '主要城市岗位需求数量',
        type: 'radar',
        data: [],
      }
    ]
  };
  if (data_list.value) {
    option.radar.indicator = [];
    console.log(JSON.stringify(data_list.value[0]));
    for (const item of data_list.value[0]) {
      option.radar.indicator.push({name:item});
    }
    option.series[0].data[0] = {value: JSON.parse(JSON.stringify(data_list.value[1])), name: '上海'};
    option.series[0].data[1] = {value: JSON.parse(JSON.stringify(data_list.value[2])), name: '广州'};
    option.series[0].data[2] = {value: JSON.parse(JSON.stringify(data_list.value[3])), name: '成都'};
  }
  return option;
});
onMounted(() => {
  getData();
})
</script>

<template>
  <dv-border-box-1 style="text-align: center">
    <chart-lhz :chart_option="chart_option"  v-if="data_list.value"/>
  </dv-border-box-1>
</template>

<style scoped lang="scss">

</style>
<script setup lang="ts">
import TopHeader from "@/views/TopHeader.vue";
import CenterMap from "@/views/CenterMap.vue";
import CenterPie from "@/views/CenterPie.vue";
import LeftTop from "@/views/LeftTop.vue";
import LeftCenter from "@/views/LeftCenter.vue";
import LeftBottom from "@/views/LeftBottom.vue";
import RightTop from "@/views/RightTop.vue";
import RightBottom from "@/views/RightBottom.vue";
</script>

<template>
  <div id="data-view">
    <!-- 全屏容器 -->
    <dv-full-screen-container>
      <!-- 头部标题组件 -->
      <top-header/>
      <!-- 数据分析容器 -->
      <div class="row" style="position: relative; top: -20px">
        <div class="col" style="flex: 1">
          <div class="row" style="height: 490px">
            <!-- 第一列 top 数据分析容器 -->
            <div class="col" style="flex: 1">
              <center-map/>
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第一列 bottom 数据分析容器 -->
            <div class="col">
              <center-pie/>
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row">
            <!-- 第二列第一行数据分析容器 -->
            <div class="col">
              <left-top/>
            </div>
          </div>
          <div class="row">
            <!-- 第二列第二行数据分析容器 -->
            <div class="col">
              <left-center/>
            </div>
          </div>
          <div class="row">
            <div class="col">
              <!-- 第二列第三行数据分析容器 -->
              <left-bottom/>
            </div>
          </div>
        </div>
        <div class="col">
          <div class="row" style="height: 490px">
            <!-- 第三列第一行数据分析容器 -->
            <div class="col">
              <right-top/>
            </div>
          </div>
          <div class="row" style="height: 490px">
            <!-- 第三列第二行数据分析容器 -->
            <div class="col">
              <right-bottom/>
            </div>
          </div>
        </div>
      </div>
    </dv-full-screen-container>
  </div>
</template>
<style lang="scss" scoped>
#data-view {
  width: 100vw;
  height: 100vh;
  background-color: #030409;
  color: #fff;

  #dv-full-screen-container {
    background-image: url('@/assets/img/bg.png');
    background-size: 100% 100%;
    box-shadow: 0 0 3px blue;
    display: flex;
    flex-direction: column;
  }

  .row, .col {
    width: 100%;
    height: 100%;
    display: flex;
    flex: 1;
    justify-content: space-between;
  }

  .row {
    flex-direction: row;
  }

  .col {
    flex-direction: column;
  }

}
</style>

v-full-screen-container>





















































#dv-full-screen-container {
background-image: url(‘@/assets/img/bg.png’);
background-size: 100% 100%;
box-shadow: 0 0 3px blue;
display: flex;
flex-direction: column;
}

.row, .col {
width: 100%;
height: 100%;
display: flex;
flex: 1;
justify-content: space-between;
}

.row {
flex-direction: row;
}

.col {
flex-direction: column;
}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

李昊哲小课

桃李不言下自成蹊

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

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

打赏作者

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

抵扣说明:

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

余额充值