- import Vue from 'vue'
- import VueRouter from 'vue-router'
- const Seller = () => import('@/views/SellerPage')
- const Trend = () => import('@/views/TrendPage')
- const Map = () => import('@/views/MapPage')
- const Rank = () => import('@/views/RankPage')
- const Hot = () => import('@/views/HotPage')
- const Stock = () => import('@/views/StockPage')
- const Screen = () => import('../Screen')
-
- Vue.use(VueRouter)
-
- const routes = [
- {
- path: '/',
- redirect:'/screen'
- },
- {
- path:'/screen',
- component:Screen
- },
- {
- path:'/seller',
- component:Seller
- },
- {
- path:'/trend',
- component:Trend
- },
- {
- path: '/map',
- component:Map
- },
- {
- path: '/rank',
- component:Rank
- },
- {
- path: '/hot',
- component:Hot
- },
- {
- path: '/stock',
- component:Stock
- }
- ]
-
- const router = new VueRouter({
- routes
- })
-
- export default router
到public\static\img 下 各两张 配合明暗两种主图
- <style lang="less" scoped>
- .screen-body {
- width: 100%;
- height: 100%;
- display: flex;
- margin-top: 10px;
- .screen-left {
- height: 100%;
- width: 27.6%;
- #left-top {
- height: 53%;
- position: relative;
- }
- #left-bottom {
- height: 31%;
- margin-top: 25px;
- position: relative;
- }
- }
- .screen-middle {
- height: 100%;
- width: 41.5%;
- margin-left: 1.6%;
- margin-right: 1.6%;
- #middle-top {
- width: 100%;
- height: 56%;
- position: relative;
- }
- #middle-bottom {
- margin-top: 25px;
- width: 100%;
- height: 28%;
- position: relative;
- }
- }
- .screen-right {
- height: 100%;
- width: 27.6%;
- #right-top {
- height: 46%;
- position: relative;
- }
- #right-bottom {
- height: 38%;
- margin-top: 25px;
- position: relative;
- }
- }
- }
- style>
全部的css:
-
- .fullscreen {
- position: fixed!important;
- top: 0 !important;
- left: 0 !important;
- width: 100% !important;
- height: 100% !important;
- margin: 0 !important;
- z-index: 100;
- }
-
- .screen-container {
- width: 100%;
- height: 100%;
- padding: 0 20px;
- background-color: #161522;
- color: #fff;
- box-sizing: border-box;
- }
- .screen-header {
- width: 100%;
- height: 64px;
- font-size: 20px;
- position: relative;
- padding-top: 20px;
- > div {
- img {
- width: 100%;
- }
- }
- .title {
- position: absolute;
- left: 50%;
- top: 50%;
- font-size: 20px;
- transform: translate(-50%, -50%);
- }
- .title-right {
- display: flex;
- align-items: center;
- position:absolute;
- right: 0px;
- top: 50%;
- transform: translateY(-80%);
- }
- .qiehuan {
- width: 28px;
- height: 21px;
- cursor: pointer;
- }
- .datetime {
- font-size: 15px;
- margin-left: 10px;
- }
- .logo {
- position: absolute;
- left: 0px;
- top: 50%;
- transform: translateY(-80%);
- img {
- height: 35px;
- width: 128px;
- }
- }
- }
- .screen-body { ... }
- .resize {
- position: absolute;
- right: 20px;
- top: 20px;
- cursor: pointer;
- }
- import Hot from '@/components/Hot.vue'
- import Map from '@/components/Map.vue'
- import Rank from '@/components/Rank.vue'
- import Seller from '@/components/Seller.vue'
- import Stock from '@/components/Stock.vue'
- import Trend from '@/components/Trend.vue'
-
- components: {
- Hot,
- Map,
- Rank,
- Seller,
- Stock,
- Trend
- },
-
- data(){
- return {
- // 定义每一个图表的全屏状态
- fullScreenStatus:{
- trend:false,
- seller:false,
- map:false,
- rank:false,
- hot:false,
- stock:false,
- },
- // 右上角显示事件的定时器
- time:'',
- timeID:null
- }
- },
- <template>
- <div class="screen-container" :style="containerStyle">
- <header class="screen-header">
- <div>
- <img :src="herderBorderSrc" alt="">
- div>
- <span class="logo">
- <img :src="logoSrc" alt="" />
- span>
- <span class="title">中欣网校数据监控系统span>
- <div class="title-right">
- <img :src="themeSrc" class="qiehuan" @click="handleChangeTheme()">
- <span class="datetime">{{time}}span>
- div>
- header>
- <div class="screen-body">
- <section class="screen-left">
- <div id="left-top" :class="[fullScreenStatus.trend ? 'fullscreen' : '']">
-
- <Trend ref="trend">Trend>
- <div class="resize">
-
- <span @click="changeSize('trend')"
- :class="['iconfont', fullScreenStatus.trend ? 'icon-compress-alt' : 'icon-expand-alt']">span>
- div>
- div>
- <div id="left-bottom" :class="[fullScreenStatus.seller ? 'fullscreen' : '']">
-
- <Seller ref="seller">Seller>
- <div class="resize">
-
- <span @click="changeSize('seller')"
- :class="['iconfont', fullScreenStatus.seller ? 'icon-compress-alt' : 'icon-expand-alt']">span>
- div>
- div>
- section>
- <section class="screen-middle">
- <div id="middle-top" :class="[fullScreenStatus.map ? 'fullscreen' : '']">
-
- <Map ref="map">Map>
- <div class="resize">
- <span
- @click="changeSize('map')"
- :class="['iconfont',fullScreenStatus.map ? 'icon-compress-alt' : 'icon-expand-alt']">span>
- div>
- div>
- <div id="middle-bottom" :class="[fullScreenStatus.rank ? 'fullscreen' : '']">
-
- <Rank ref="rank">Rank>
- <div class="resize">
- <span
- @click="changeSize('rank')"
- :class="['iconfont',fullScreenStatus.rank ? 'icon-compress-alt' : 'icon-expand-alt']">span>
- div>
- div>
- section>
- <section class="screen-right">
- <div id="right-top" :class="[fullScreenStatus.hot ? 'fullscreen' : '']">
-
- <Hot ref="hot">Hot>
- <div class="resize">
- <span
- @click="changeSize('hot')"
- :class="['iconfont',fullScreenStatus.hot ? 'icon-compress-alt' : 'icon-expand-alt']">span>
- div>
- div>
- <div id="right-bottom" :class="[fullScreenStatus.stock ? 'fullscreen' : '']">
-
- <Stock ref="stock">Stock>
- <div class="resize">
- <span
- @click="changeSize('stock')"
- :class="['iconfont',fullScreenStatus.stock ? 'icon-compress-alt' : 'icon-expand-alt']">span>
- div>
- div>
- section>
- div>
- div>
- template>
刚进入组件的时候注册事件+运行定时器
- created() {
- this.$socket.registerCallBack('fullScreen',this.recvData)
- this.$socket.registerCallBack('themeChange',this.recvThemeChange)
- this.dateFormat()
- },
组件销毁时与进入组件操作相反
- destroyed() {
- this.$socket.unRegisterCallBack('fullScreen')
- this.$socket.unRegisterCallBack('themeChange')
- clearInterval(this.timerID)
- },
{{time}}handleChangeTheme(){ this.$socket.send({ action:'themeChange', socketType: 'themeChange', chartName: '', value:'' }) }上篇文章一个路数 handleChangeTheme 发起send 向服务器提交数据 =》action不是getData 服务器就原路返回数据 =》 前端再监听到服务器返回的数据调用进入页面时注册的函数 recvThemeChange =》而这个函数 调用的是Vuex 来改变当前的主题
因为各个组件注册的时候 都引入 vuex 的state来管理主题
监听数据改变 进行重绘操作
recvThemeChange(){ // 修改Vuex中的数据 this.$store.commit('changeTheme') },
store/index.js:
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- Vue.use(Vuex)
-
- export default new Vuex.Store({
- state: {
- theme:'chalk'
- },
- getters: {
- },
- mutations: {
- changeTheme(state){
- if (state.theme === 'chalk'){
- state.theme = 'vintage'
- }else {
- state.theme = 'chalk'
- }
- }
- },
- actions: {
- },
- modules: {
- }
- })
每个组件的公用代码:映射出来 theme 图表初始化的时候 使用 监听theme 改变时进行重绘
- import {mapState} from "vuex";
-
- computed:{
- ...mapState(['theme'])
- },
-
- watch:{
- theme(){
- this.chartsInstance.dispose() //销毁当前的图表
- this.initChart() //重新以最新的主图渲染图表
- this.screenAdapter() // 完成屏幕的适配
- this.updateChart() // 更新图表的展示
- }
- },
-
- this.chartsInstance = this.$echarts.init(this.$refs.rank_1,this.theme)
切换主题时 主页面一些属性也要跟随变化 logo变成反白、字体的颜色、.....
theme_utils.js
- const theme = {
- chalk:{
- // 背景颜色
- backgroundColor:'#161522',
- // 标题的文字颜色
- titleColor:'#ffffff',
- // 左上角logo的图表路径
- logoSrc:'logo_dark.png',
- // 切换主题按钮的图片路径
- themeSrc:'qiehuan_dark.png',
- // 页面顶部的边框图片
- herderBorderSrc:'header_border_dark.png'
- },
- vintage:{
- // 背景颜色
- backgroundColor:'#eee',
- // 标题的文字颜色
- titleColor:'#000000',
- // 左上角logo的图表路径
- logoSrc:'logo_light2.png',
- // 切换主题按钮的图片路径
- themeSrc:'qiehuan_light.png',
- // 页面顶部的边框图片
- herderBorderSrc:'header_border_light.png'
- }
- }
-
- export function getThemeValue(themeName) {
- return theme[themeName]
- }
主页面的计算属性:
- computed:{
- ...mapState(['theme']),
- logoSrc(){
- return '/static/img/' + getThemeValue(this.theme).logoSrc
- },
- herderBorderSrc(){
- return '/static/img/' + getThemeValue(this.theme).herderBorderSrc
- },
- themeSrc(){
- return '/static/img/' + getThemeValue(this.theme).themeSrc
- },
- containerStyle(){
- return{
- backgroundColor:getThemeValue(this.theme).backgroundColor,
- color:getThemeValue(this.theme).titleColor
- }
- },
- },
点击 span 触发changeSize 点击过后就是取反的 fullScreenStatus.具体图表的状态
- <div id="left-bottom" :class="[fullScreenStatus.seller ? 'fullscreen' : '']">
-
- <Seller ref="seller">Seller>
- <div class="resize">
-
- <span @click="changeSize('seller')"
- :class="['iconfont', fullScreenStatus.seller ? 'icon-compress-alt' : 'icon-expand-alt']">span>
- div>
- div>
- changeSize(chartsName){
- /**
- * 正常事件进行单客户端的全屏事件切换
- 取反点击的具体图表 全屏状态的布尔值
- this.fullScreenStatus[chartsName] = !this.fullScreenStatus[chartsName]
- 通过 ref 调用每一个图表 组件内内部 刷新分辨率的方法
- this.$nextTick(() =>{
- this.$refs[chartsName].screenAdapter()
- })
- **/
-
- // 通过webSocket 进行多端联动的效果
- const targetValue = !this.fullScreenStatus[chartsName]
- this.$socket.send({
- action:'fullScreen',
- socketType:'fullScreen',
- chartName:chartsName,
- value:targetValue
- })
- },
走了一圈还是调用 最开始传出去的函数 recvData()
- // 接收到全屏数据之后的处理
- recvData(data){
- // 取出是哪一个图表需要进行切换
- const chartName = data.chartName
- // 取出 切换成什么状态
- const targetValue = data.value
- // 修改数据 根据模板内三元表达式 动态添加 具体图表的全屏事件
- this.fullScreenStatus[chartName] = targetValue
- // 在渲染完毕后重新刷新 具体图表的分辨率事件
- this.$nextTick(() =>{
- this.$refs[chartName].screenAdapter()
- })
- },