超实用技巧!搭建个性化大屏幕模板,轻松打造专属展示风格

583 阅读3分钟

需求介绍

突然收到领导通知需要紧急重构大屏项目,是这样的,大屏上有很多个模块,比如学校信息,教师信息,学生信息,违纪情况,考勤,打分等等,由多个模块组成。随着模块的增多,学校与学校之间产生了差异,由于不同学校需要展示的模块不同,项目需要进行重构以解决之前项目存在的兼容性问题

拿到这个需求仔细思考了一下,主要有两个难点

  • 自定义模块
  • 自定义布局

自定义模块:每个大屏上展示的模块,需要根据不同的方案展示不同的模块,最好是可以通过一个管理页面控制展示的模块

自定义布局:也就是自定义模块位置和大小:每个模块的大小可能随着展示模块的数量而变化,如果页面中模块展示的多那么每个模块的占用空间就小,每个模块的宽度高度随着占有的空间而改变

实现思路

首先控制整个页面的排版布局,比如模块是纵向排列还是横向排列,考虑到这两个排列方式,计划采用Flex布局

布局方式搞定后就要在布局中插入相应模块,使用Component动态加载组件

经过一番思考后,最后定了一套布局配置方案

{
    type: "layout",
    style: {
        display: 'flex',
        flexDirection: 'column',
        flex: 1
    },
    children: [
        {
            type: "component",
            url: 'Test',
            name: "模块1",
            style: {
              flex: 1,
              background: 'pink'
            }
        },
        {
            type: "layout",
            style: {
                display: 'flex',
                flexDirection: 'row',
                flex: 9
            }, children: [
                {
                    type: "layout",
                    style: {
                        display: 'flex',
                        flexDirection: 'column',
                        flex: 1
                    },
                    children: [
                        {
                            type: "component",
                            url: 'Test',
                            name: "模块2",
                            style: {
                              flex: 1,
                              background: 'pink'
                            }
                        }, {
                            type: "component",
                            url: 'Test',
                            name: "模块3",
                            style: {
                              flex: 1,
                              background: 'pink'
                            }
                        }
                    ]
                },
                {
                    type: "layout",
                    style: {
                        display: 'flex',
                        flexDirection: 'column',
                        flex: 2,
                    },
                    children: [
                        {
                            type: "component",
                            url: 'Test',
                            name: "模块4",
                            style: {
                              flex: 1,
                              background: 'pink'
                            }
                        }, {
                            type: "component",
                            url: 'Test',
                            name: "模块5",
                            style: {
                              flex: 1,
                              background: 'pink'
                            }
                        }, {
                            type: "component",
                            url: 'Test',
                            name: "模块6",
                            style: {
                              flex: 1,
                              background: 'pink'
                            }
                        }
                    ]
                },
                {
                    type: "layout",
                    style: {
                        display: 'flex',
                        flexDirection: 'column',
                        flex: 1
                    },
                    children: [
                        {
                            type: "component",
                            url: 'Test',
                            name: "模块7",
                            style: {
                              flex: 1,
                              background: 'pink'
                            }
                        },
                        {
                            type: "component",
                            url: 'Test',
                            name: "模块8",
                            style: {
                              flex: 1,
                              background: 'pink'
                            }
                        }
                    ]
                },
            ]
        }
    ]
  }  
截图 2024-06-03 21.32.08.png

type的值为layout是控制布局的,style属性控制组件是横向排列还是纵向排列,示例中模块1和下面的模块是纵向排列,模块2和3是一组,模块4,模块5,模块6是一组,模块7,模块8是一组横向排列,里面的组件都是纵向排列

type的值为component是渲染组件(模块)的,url是组件的路径,name是名称,style控制组件的样式,主要是控制组件的大小

通过这样一套布局配置方案,已经可以满足大多数场景了

代码实现

根据上面的分析于是就封装了一个大屏模版组件

// Layout.vue
<template>
  <div style="height:100%" v-if="data.type=='layout'" :style="data.style">
    <Layout v-for="child in data.children" :data="child" />
  </div>
  <component v-else-if="data.type=='component'" :data="data" :is="data.url"></component>
</template>

<script setup lang="ts">
import { defineProps, toRefs } from 'vue';

const props = defineProps({
  data: {
    type: Object, // 类型
    required: true, // 是否必填
    default() { // 默认值
      return {}
    }
  }
})
const { data } = toRefs(props)
</script>
<style scoped>

</style>

考虑到type有两种情况,如果是layout就遍历children属性自己调用自己,向下传递child

如果类型是component就会动态渲染组件,data传递给相应的组件

大部分页面的布局方式都可以通过这个组件实现

截图 2024-06-03 23.36.42.png 截图 2024-06-03 23.28.59.png 截图 2024-06-04 20.19.22.png

总结

通过配置项灵活定制页面布局,利用大屏模板组件实现页面渲染,同时提供后台管理系统,方便修改配置项,确保功能流畅运行。希望这个方案能为大家带来启发,欢迎互相交流学习,共同进步。