Vue3 + TypeScript + Vite + Echarts + DataV

news2024/10/10 1:58:18

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;
}

}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2200721.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【093】基于SpringBoot+Vue实现的精品水果线上销售系统

系统介绍 视频演示 基于SpringBootVue实现的精品水果线上销售系统&#xff08;有文档&#xff09; 基于SpringBootVue实现的精品水果线上销售系统采用前后端分离的架构方式&#xff0c;系统设计了管理员、商家、用户三种角色&#xff0c;实现了公告类型管理、商家信誉类型管理…

网络编程(16)——asio多线程模型IOServicePool

目录 十六、day16 1. 什么是多线程&#xff1f; 2. IOServicePool实现 3. 服务器修改 4. 客户端修改 5. 总结 1. boost::asio::io_context::work的作用&#xff1f; 十六、day16 在之前的设计中&#xff0c;我们对 ASIO 的使用都是采用单线程模式。为了提升网络 I/O 并…

基于多能互补的热电联供型微网优化运行【matlab代码】

目录 1 主要内容 多能互补模型 算例分析 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序基本复现《基于多能互补的热电联供型微网优化运行》&#xff0c;在需求侧对负荷类型进行分类&#xff0c;利用电负荷的弹性和系统供热方式的多样性&#xff0c;构建含电负荷时…

常见的图像处理算法:中值滤波----median filter

一、中值滤波是什么 中值滤波法是一种非线性平滑技术&#xff0c;可用于消除孤立的噪声点。中值滤波在滤除噪声的同时&#xff0c;能够保护信号的边缘&#xff0c;使之不被模糊&#xff0c;这些特性是线性滤波方法所不具有的。 二、中值滤波的原理 中值滤波是将每一像素点的灰度…

数据结构进阶:二叉搜索树_C++

目录 前言&#xff1a; 一、二叉搜索树 1.1二叉搜索树概念 2.2 二叉搜索树操作 1. 二叉搜索树的插入 1.1、插入过程 1.2、代码实现 2、二叉树的删除 2.1、结点删除情况 2.2、替换删除法 1、替换思路 2、代码实现&#xff1a; 3、二叉搜索树的查找 3.1、查找规则 …

LLM - 配置 GraphRAG + Ollama 服务 构建 中文知识图谱

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142795151 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 GraphR…

基于springboot的公司财务管理系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的公司财务管理系统拥有两种角色 管理员&#xff1a;员工管理、部门管理、工资管理、资产管理、经营管理、利润管理等 员工&#xff1a;查看工资、查看公告、登录注册 1.…

OurTV 3.3.0 |流畅电视直播,收藏无忧

OurTV 是一款流畅的电视直播应用&#xff0c;支持电视版和手机版。增加收藏功能&#xff0c;修正了网络问题和潜在内存泄漏&#xff0c;调整最小版本到22&#xff0c;观看体验更佳。 大小&#xff1a;34M 百度网盘&#xff1a;https://pan.baidu.com/s/1UqEBfQx_1ztIUNx4fWopu…

《神经网络》—— 长短期记忆网络(Long Short-Term Memory,LSTM)

文章目录 一、LSTM的简单介绍二、 LSTM的核心组件三、 LSTM的优势四、 应用场景 一、LSTM的简单介绍 传统RNN循环神经网络的局限&#xff1a; 示例&#xff1a;当出现“我的职业是程序员。。。。。。我最擅长的是电脑”。当需要预测最后的词“电脑”。当前的信息建议下一个词可…

iOS Object-C 将数组倒置(倒叙)

使用NSArray自带的对象方法:reverseObjectEnumerator 代码如下: NSArray * tempArray [[NSArray alloc]initWithObjects:"a","b","c","d", nil]; //将tempArray转换成["d","c","b","a"]; …

PasteForm最佳CRUD实践,实际案例PasteTemplate详解之3000问(四)

无论100个表还是30个表&#xff0c;在使用PasteForm模式的时候&#xff0c;管理端的页面是一样的&#xff0c;大概4个页面&#xff0c; 利用不同操作模式下的不同dto数据模型&#xff0c;通过后端修改对应的dto可以做到控制前端的UI&#xff0c;在没有特别特殊的需求下可以做到…

【光追模组】雷神之锤4光追mod,调色并修改光影,并且支持光追效果,游戏画质大提升

大家好&#xff0c;今天小编我给大家继续引入一款游戏mod&#xff0c;这次这个模组主要是针对雷神之锤4进行修改&#xff0c;如果你觉得游戏本身光影有缺陷&#xff0c;觉得游戏色彩有点失真的话&#xff0c;或者说你想让雷神之锤4这款游戏增加对光线追踪的支持的话&#xff0c…

在docker中安装并运行mysql8.0.31

第一步&#xff1a;命令行拉取mysql镜像 docker pull mysql:8.0.31查看是否拉取成功 docker images mysql:latest第二步&#xff1a;运行mysql镜像&#xff0c;启动mysql实例 docker run -p 3307:3307 -e MYSQL_ROOT_PASSWORD"123456" -d mysql:8.0.313307:3307前…

FMCW 雷达芯片关键技术学习

CLOCK GENERATION 借助外部晶体产生的 50 MHz 时钟&#xff0c;时钟生成模块为 RF 子系统生成 76 至 81 GHz 时钟信号。时钟生成模块包含内置振荡器电路、参考 PLL、FMCW PLL 和 X4 乘法器。内置振荡器电路与外部晶体一起为参考 PLL 生成 50 MHz 时钟。参考 PLL 为 FMCW PLL 和…

腾讯云SDK项目管理

音视频终端 SDK&#xff08;腾讯云视立方&#xff09;控制台提供项目管理功能&#xff0c;您可参照以下步骤为您的应用快速添加音视频通话能力和多人音视频互动能力。 若需正式开发并上线音视频应用&#xff0c;请在完成创建后&#xff0c;参照 集成指南 进行开发包下载、集成…

fastadmin 列表页表格实现动态列

记录&#xff1a;fastadmin 列表页表格实现动态列 后端代码 /*** 商品库存余额表*/public function kucunbalance(){$houseList (new House)->where([shop_id>SHOP_ID])->order(id desc)->field(name,id)->select();//设置过滤方法$this->request->filte…

Java速成之反射,轻松搞定反射

Hello&#xff0c;大家好&#xff0c;我是Feri&#xff0c;一枚十多年的程序员&#xff0c;同时也是一名在读研究生&#xff0c;关注我&#xff0c;且看一个平凡的程序员如何在自我成长&#xff0c;只为各位小伙伴提供编程相关干货知识&#xff0c;希望在自我蜕变的路上&#x…

记录一次搭建Nacos集群的问题

Java环境&#xff1a;jdk1.8.0_231 Nacos版本&#xff1a;nacos-server-2.2.0.zip 虽然官方推荐的是3个节点&#xff0c;我们还是使用的是2个节点&#xff0c;首先解压创建nacos_config库&#xff0c;导入nacos/conf目录下的mysql-schema.sql SQL文件&#xff0c;如下表&…

ubuntu双系统分区划分

EFI系统分区&#xff08;Windows&#xff09;&#xff1a;自Windows 8起&#xff0c;UEFI模式下的BIOS使用该分区。简单来说&#xff0c;它用于存储已安装系统的EFI引导程序。此分区在资源管理器中无法查看&#xff0c;因为它没有驱动器号&#xff0c;但它必须存在&#xff0c;…

【ISAC】通感算一体化

北京邮电大学冯志勇&#xff1a;面向智能交通的通感算一体化网络技术 香港中文大学&#xff08;深圳&#xff09;许杰&#xff1a;面向通感算融合的无线资源优化 三者逻辑 感知增强: 多个视角的通信&#xff0c;感知其他视角看不到的通信增强&#xff1a;以前做信道估计都是盲的…